Nginx Ingress setup for kubernetes

Recently I decided to give Kubernetes a try. I was avoiding it just for the reason of writing several long YAML files. I know I am a lazy guy. But once you get used to writing Kubernetes code, you discover the power of it. You do have to write a docker-compose file in the world of Docker but I have found writing YAML for Kubernetes more tedious but it might be worth it once you understand what more you can do with Kubernetes.

Like everyone the first thing I learned in Kubernetes is to create a deployment that serves a website and created a service around it. The first question that came in my mind afterward is how I can host 2 websites and route the traffic to them based on hostnames. Traditionally you would install something like NGINX and configure it to serve different websites or forward the requests to some other service. We can still use Nginx to route our request in Kubernetes but in a different way, by using Ingress.

In this article, we will have a look at Nginx Ingress Controller. Using this we can easily divert traffic based on hostnames inside our Kubernetes cluster essentially allowing us to host multiple projects on a single cluster. Isn’t it cool? Let me know in the comments if I am overselling it.

To test it out we will need to install and enable Nginx Ingress Controller. We will be using Minikiube to test on our local machine.

1
$ minikube addons enable ingress

Before we set up our Ingress controller we will need to set up deployments with corresponding services. Let’s Create a sample deployment and a service.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
apiVersion: apps/v1
kind: Deployment
metadata:
name: first-deployment
spec:
replicas: 3
selector:
matchLabels:
app: first-deployment
template:
metadata:
labels:
app: first-deployment
spec:
containers:
- name: hello-kubernetes
image: paulbouwer/hello-kubernetes:1.5
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: Hello from first Deployment
---
apiVersion: v1
kind: Service
metadata:
name: first-deployment
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
selector:
app: first-deployment

Similarly, let’s create one more deployment just by replacing the word first in the above text with the word second. Being lazy sometimes does save some time. If you are too lazy to type that also, then you can find the code in my repo https://github.com/suyashmohan/simple_kubernetes_ingress_sample

In case you are new to Kubernetes, you can deploy above YAML by using

1
2
kubectl apply -f first-deployment.yml
kubectl apply -f second-deployement.yml

You can check if everything is running fine by using

1
2
3
kubectl get pods
kubectl get deployments
kubectl get services

If everything is looking fine let’s continue and setup our Ingress controllers. If you are stuck at any error, you can comment below and I will try to help you out.

Setting up Ingress is pretty easily

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: first.info
http:
paths:
- path: /
backend:
serviceName: first-deployment
servicePort: 8080
- host: second.info
http:
paths:
- path: /
backend:
serviceName: second-deployment
servicePort: 8080

Here we have defined a resource with kind of Ingress. The specifications for this resource includes rules which defines how traffic should be diverted to different services based on host. For e.g. if a request comes for first.info with root path, we will forward the request to first-deployment at port 8080. Same goes for second.info

Apply the above ingress resource

1
$ kubectl apply -f ingress.yml

Get the address for Ingress controller as following

1
2
3
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
test-ingress first.info,second.info 192.168.39.98 80 57s

One advantage of Ingress is that it exposes the controller, so you don’t have to expose the services to the world. Testing this setup is also pretty easy.

We can either set up these hosts in /etc/host/ pointing to local address or we can just Host header in curl to test it out.

1
2
$ curl -H 'Host:first.info' http://192.168.39.98
$ curl -H 'Host:second.info' http://192.168.39.98

That’s it we have set up 2 services that get traffic based on Hostnames using Nginx Ingress Controller. I hope this article was helpful. Please share your thoughts and doubts using the comments below.