Ingress

Ingress is a routing mechanism to services running inside kubernetes cluster. It is natively handled as kubernetes resource object using yaml files.

Tip

Ingress is a Layer 7 Load balancer which means it works on application layer (that is obvious as ingress is an application in the end).

Consists of ingress controller and ingress resources.

Just to add some back story of this two division, if we want to add something like this what we would do? We would have some proxy services such as nginx and a set of configuration for routing rules. Similarly, kubernetes have implemented ingress where ingress controllers are deployed applications and ingress resources are configurations.

Ingress Controller

Ingress controller are pods such nginx. Ingress controllers are not deployed by default by kubernetes. We need to do that manually.

There are several ingress controller that can be used such as nginx, Contour, happroxy, traefik, istio, and GCP HTTP(s) load balancer (GCE). Nginx and GCP HTTP(s) load balancer (GCE) are maintained by kubernetes.

These being used as controllers have more functionality than just Nginx server. In other words, nginx controller is made by using nginx and extra functionalities of monitor kubernetes cluster such as identifying new ingress resources and definitions and updating ingress controller accordingly.

Defining ingress controller

apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx-ingress-controller
spec:
    replicas: 1
    selector:
        matchLabels:
            app: nginx-ingress
    template:
        metadata:
            name: nginx-ingress
            labels:
                app: nginx-ingress
        spec:
            containers:
                - name: nginx-ingress-controller
                  image: registry.k8s.io/ingress-nginx/controller:v1.12.1@sha256:d2fbc4ec70d8aa2050dd91a91506e998765e86c96f32cffb56c503c9c34eed5b
                  args: 
                    - /nginx-ingress-controller
                    - --configmap=$(POD_NAMESPACE)/nginx-controller-cm
                  env:
                    - name: POD_NAME
                      valueFrom:
                          fieldRef:
                              fieldPath: metadata.name
                    - name: POD_NAMESPACE
                          valueFrom:
                              fieldRef:
                                  fieldPath: metadata.namespace
                  ports:
                    - name: http
                      containerPort: 80
                    - name: https
                      containerPort: 443
        

This ingress controller requires some nginx configuration that we can provide using configmap and mention that inside container command using args field.

apiVersion: v1
kind: ConfigMap
metadata:
    name: nginx-controller-cm

At this point, config map can be empty as default can be used.

To expose ingress controller, we need NodePort Service as defined below.

apiVersion: v1
kind: Service
metadata:
    name: ingress-controller
spec:
    selector:
        app: nginx-ingress
    type: NodePort
    ports:
        - name: http
          targetPort: 80
          port: 80
          protocol: TCP
        - name: https
          targetPort: 443
          port: 443
          protocol: TCP
        

As ingress controller requires to monitor kubernetes cluster, it requires to have permissions to do so. To achieve that, we need service account with appropriate roles and permissions. Minimal service account is shown below.

apiVersion: v1
kind: ServiceAccount
metadata:
    name: nginx-controller-sa

Ingress Resources

Ingress resources are rules which specify the routes.

A minimal example of ingress resource that redirects request to service of a pod. In this example, there is a pod entertainment and with service entertainment-svc. entertainment pod serves requests for music, videos, games etc entertainment.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: ingress-entertainment
spec:
    backend:
        service:
            name: entertainment-svc
            port: 
                number: 80

For a more complex scenario where there exists different pods for different entertainment media such as music, videos and games, instead of a single pod and we want to route requests coming for different media with paths something.com/music, something.com/video and something.com/games.

We can achieve this using following ingress resource file,

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: ingress-entertainment
spec:
    rules:
        - http:
              paths:
                - path: /music
                  pathType: Prefix
                  backend:
                      service:
                          name: music-svc
                          port:
                             number: 80
                - path: /video
                  pathType: Prefix
                  backend:
                      service:
                          name: video-svc
                          port:
                             number: 80
                - path: /games
                  pathType: Prefix
                  backend:
                      service:
                          name: games-svc
                          port:
                             number: 80

Sometimes sub domains are also used for these types of operations. For example, music.something.com, video.something.com, games.something.com.

To support these type of configuration, the ingress resource file looks like,

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: ingress-entertainment
spec:
    rules:
        - host: music.something.com
          http:
              paths:
                - backend:
                      service:
                          name: video-svc
                          port:
                             number: 80
        - host: video.something.com
          http:
              paths:
                - backend:
                      service:
                          name: video-svc
                          port:
                             number: 80

On HOLD. It will be updated.