Ingress
Overview
To enable us to process external requests in Kubernetes four main components need to be in place. They are:
- DNS - This is the external server which links our domain name to the custer's IP address
- Ingress - Terminates the external connection and routes the request to the appropriate service from its hostname
- Service - Forwards the request to the apppropriate pods to be actioned
- 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.