Why do we need Ingress
Almost every time in production we need to expose multiple k8s services or api endpoints which are running as microservices to user. Like /login, /checkout,
/cart needs to communicated seperately as they are running on different k8s deployment or simply using seperete k8s service. In this case if you open each endpoints to user the loadbalancer need to be created for each of them. That is costly as well very tedious to maintain.
What is Ingress
So the solution is to create some kind of object inside the cluster which will act as a single point of contact to each external request and direct the requests to the specific k8s services. Now we need only one loadbalancer on front of it and let this object send the requests to the specific services on based of either subdomains(foo.bar.com) or endpoints(bar.com/foo). That object is Ingress.
Ingress controller
Ingress controller is the actual service that will run on the cluster as a deployment and route the trafic to the specific services. You can install multiple types of them, and they are known as ingress class. Previously K8s community was maintaing Nginx-ingress controller as a open source project now the repo is a public archive so no support and future updates. Traefik is also one more popular choice these days, and it works pretty good. You can deploy them with helm charts as well.
Ingress configuration file
To configure the Ingress controller we need a configuration file, because that is the controller which will route the requests but we need to configure it using a manifest file. In this file you specify the class-name(which controller), multiple endpoints or subdomains which route to multiple k8s services also tls decryption. This one interesting, so you can deal with the https traffic as well. Need to specify the k8s certificate object where the private key and certificate will stored and ingress controller will decrypt the traffic and forward the request to services which will eventually go to pods.
Demo
Time to open the terminal. So we will first create a Nginx deployment, expose it as a cluster ip service, then we will install the ingress controller on the server and then apply the ingress configuration manifest file and test it.
Creating deployment
kubectl create deployment nginx --image=nginxCreating service
kubectl expose deployment nginx --name=nginx --port=8080 --target-port=80Installing Ingress controller
- Opensource Nginx controller
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx- Traefik Controller
helm install traefik oci://ghcr.io/traefik/helm/traefikIngress configuration file
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
spec:
ingressClassName: nginx
rules:
- host: ingress.nginx.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 8080Ingress configuration file with tls termination
- create a self signed certificate
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout nginxtls.key \
-out nginxtls.crt \
-subj "/CN=local.nginx.com/O=nginx"- creating a secret for it
kubectl create secret tls nginx-tls --key=nginxtls.key --cert=nginxtls.crt- manifest file with tls termination
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress-tls
spec:
ingressClassName: nginx
tls:
- hosts:
- tls.ingress.nginx.com
secretName: nginx-tls
rules:
- host: tls.ingress.nginx.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 8080- Apply with
kubectl apply -f INGRESS-FILE-NAME.yamlNote
You can create multiple configuration file which will configure multiple installed ingress controller for a same same service. It's very unusal and rare to do that but as long as you change the class-name of the ingress controller you can play around with this.
GatewayAPI
Creating a gateway-api resource with tls termination.
Installing Envoy gateway controller
helm install envoy-gateway-controller oci://docker.io/envoyproxy/gateway-helm --version v1.9.1
kubectl wait --timeout=5m deployment/envoy-gateway --for=condition=AvailableCreating gateway class
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy-gateway-controller
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controllersave it as
gatewayclass.yamlCreating gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: non-tls-gateway
namespace: default
spec:
gatewayClassName: envoy-gateway-controller
listeners:
- name: http
protocol: HTTP
port: 80
hostname: gateway.nginx.com
allowedRoutes:
namespaces:
from: Samesave it as
gateway.yamlCreating httproute
aapiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: nginx-route-non-tls
namespace: default
spec:
hostnames:
- gateway.nginx.com
parentRefs:
- name: non-tls-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: nginx
port: 8080save it with
httproute.yamlWith TLS termination
- generating selfsigned certificate
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout nginxtls.key \
-out nginxtls.crt \
-subj "/CN=local.nginx.com/O=nginx"- creating a secret for it
kubectl create secret tls nginx-tls --key=nginxtls.key --cert=nginxtls.crtModify gateway.yaml
add tls section
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tls-gateway
namespace: default
spec:
gatewayClassName: envoy-gateway-controller
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: tls.gateway.nginx.com
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: nginx-tls
allowedRoutes:
namespaces:
from: Samesave gateway.yaml file.
Modify httproute.yaml
add sectionName: https
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: nginx-route-tls
namespace: default
spec:
parentRefs:
- name: tls-gateway
sectionName: https
hostnames:
- tls.gateway.nginx.com
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: nginx
port: 8080save it as httproute.yaml
- Apply all the files with
kubectl apply -f filenames.yaml