Ingress

Overview

To enable us to process external requests in Kubernetes four main components need to be in place. They are:

  1. DNS - This is the external server which links our domain name to the custer's IP address
  2. Ingress - Terminates the external connection and routes the request to the appropriate service from its hostname
  3. Service - Forwards the request to the apppropriate pods to be actioned
  4. Pod - These are the actual virtual machines which will action the request

So in the following article, we will be going through the steps required to implement these phases.

MetalLB

If you are using a provisioned Kubernetes cluster such as EKS which automatically assigns an external IP address you do not need this step.

MetalLB provides external IP addresses to bare metal Kubernetes clusters.

The following are the steps I took from the MetalLB site.

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml

Check the status of the metalLB namespace with the following command:

kubectl get all -n metallb-system

All going well we are now ready to configure which IP addresses metalLB can assign.

nano ipaddresspool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - [address]

The addresses list can contain individual IP addresses or CIDR ranges. eg.

spec:
  addresses:
  - 62.191.175.12/32 
  - 192.168.10.0/24
  - 192.168.9.1-192.168.9.5
  - fc00:f853:0ccd:e799::/124

Check the address pool has been assigned.

kubectl describe IPAddressPool --all-namespaces

DNS

The Domain Name Server is like an old phone book: it takes a hostname and finds the corresponding IP address for the host and forwards the traffic to that address.

Not to go too much into detail there are millions of nameservers all connected, normally a router within your home internet connection acts as a private nameserver for the devices connected to your home network. For our purposes, we need a public nameserver so the world can send our cluster requests.

I use domain.com as my name server but most of them act in very much the same way. For this exercise, I created the following "A" DNS record.

With the above DNS record requests to ingress-test.james-blog.tech will be forwarded to my new cluster.

Ingress Controller

As mentioned above, the ingress controller handles requests from outside the Kubernetes cluster.
The most widely used ingress controller is Nginx. Full details of its workings can be found on the site https://kubernetes.github.io/ingress-nginx/deploy/ but the cliff notes version is that it listens at ports 80 and 443 and directs HTTP traffic depending on the hostname within the HTTP header.

To install Nginx enter the following command:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml

Check the ingress controller is ready:

kubectl get pods --selector=app.kubernetes.io/component=controller  --namespace=ingress-nginx

Let's test it out!

If you have the demo namespace still in place from the previous article you just need to alter the service as shown:

kubectl create namespace demo
nano demo-deploy.yaml

Copy the following configuration:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: demo
  name: demo
  namespace: demo
spec:
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - image: httpd
        imagePullPolicy: Always
        name: httpd
        ports:
        - containerPort: 80
          protocol: TCP

Deploy the configuration:

kubectl apply -f demo-deploy.yaml

Now we need to create our cluster service:

nano demo-cluster-svc.yaml

Copy and paste the following:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: demo
  name: demo
  namespace: demo
spec:
  type: ClusterIP
  selector:
    app: demo
  ports:
    - name: demo
      protocol: TCP
      port: 80
      targetPort: 80

Create / update the service:

kubectl apply -f demo-cluster-svc.yaml

Now we need to get onto the ingress itself:

nano demo-ingress.yaml

Copy and paste the following:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
  namespace: demo
spec:
  ingressClassName: nginx
  rules:
  - host: ingress-test.james-blog.tech
    http:
      paths:
      - backend:
          service:
            name: demo
            port:
              number: 80
        path: /
        pathType: Exact

Finally, create the ingress:

kubectl apply -f demo-ingress.yaml

Try it out!

curl -v ingress-test.james-blog.tech

If you try to connect through a browser to this site, you will see an invalid certificate showing, don't worry about this for now, we sort it out in the next article.