Setting up Nginx Ingress on Kubernetes

September 23rd 2017

Hey there, setting up an Ingress Controller on your Kubernetes cluster? After reading through many articles and the official docs, I was still having a hard time setting up Ingress. But after numerous attempts I managed to setup an nginx-ingress-controller to forward outside traffic to my in-cluster services, handling HTTP and HTTPS. This writeup is a step by step guide to do this.

Pssst… incase you are a newbie to Kubernetes like me, here is a nice writeup that explains Ingresses.

The Scene

We will setup a simple “hello-world” api and expose the api using the nginx-ingress-controller on a local cluster using Minikube.

TL;DR — Here is a boilerplate that reflects what is explained.

Steps

Step 1: Creating the service to be exposed

Assuming that you already have Kubectl and Minikube setup, let’s deploy our hello-world api and expose it within our cluster as a NodePort Service. We will be using a simple api for the purpose of the demo. The source code can be found here.

The config file consists of the deployment and the service. Normally we separate them into individual files.

kubectl create -f hello-world.yaml

Now you should be able to see the created resources when you run

kubectl get all | grep hello-world

Step 2: Creating a default backend to be used by the nginx-ingress-controller

We need to provide a default backend for the ingress-controller. The default backend is the default service that Nginx falls backs to if it cannot route a request successfully. The default backend needs to satisfy the following two requirements :

  • serves a 404 page at /
  • serves 200 on a /healthz

The nginx-ingress-controller project has an example default backend.

kubectl create -f default-backend.yaml

Step 3: Creating secrets to specify the SSL certificate for Nginx

Create a self-signed certificate using OpenSSL. The common name specified while generating the SSL certificate should be used as the host in your ingress config. We create secrets for the given key, certificate and dhparam files. Use corresponding file names for the key, certificate and dhparam.

kubectl create secret tls tls-certificate --key <key-file>.key --cert <certificate-file>.crt
kubectl create secret generic tls-dhparam --from-file=<dhparam-file>.pem

Step 4: Enable ingress on Minikube

Minikube versions > v0.14.0 ships with Nginx ingress setup as an add-on. It can be enabled by simply running:

minikube addons enable ingress

Enabling the add-on provisions the following:

Step 5: Setting up the nginx-ingress-controller

Now we create a service for the controller. The service is of type LoadBalancer so that it is exposed outside the cluster.

The config consists of the deployment and service for the nginx-ingress. The following can be observed from the config :

  • The secret for the default SSL certificate and default-backend-service are passed as args.
  • The image nginx-ingress-controller:0.9.0-beta.5 is used. I have tried the later beta releases. This seems to be a more stable for our usecase.
  • The tls-dhparam secret is mounted on a volume to be used by the controller.

Create the controller by running:

kubectl create -f nginx-controller.yaml

We should be able to see the created resources with the exposed IP address after a few seconds. To get the IP on Minikube run.

minikube service nginx-ingress --url

Running a Curl request to the exposed endpoint should give us a response from the default-backend as we still haven’t configured our ingress to point to our hello-world api.

curl http://<nginx-service-IP>:<port>
default backend - 404%

Step 6: Configure Ingress rules

Coming to the part where we will be spending most of our time. We provide the forwarding rules to the ingress.

We use annotations here to pass configuration params to the underlying ingress-controller, Nginx in our case. You can find more about annotations here.

  • nginx.org/ssl-services is used to specify the service that is to be load balanced using HTTPS
  • We specify the hosts, paths and their corresponding service handlers.
kubectl create -f ingress.yaml

We now have an Nginx web server configured that routes traffic for api.sample.com to our configured hello-world-svc. It falls back to the default-backend service for unhandled requests.

Also you might want to update /etc/hosts file to resolve your host to your minikube IP. Assuming your Minikube IP is 192.168.99.101 Your entry should look like.

192.168.99.101 api.sample.com

You should be able to access the exposed endpoints via https.

GET api.sample.com/:name
POST api.sample.com/:name
PUT api.sample.com/:name

Adding the annotation ingress.kubernetes.io/ssl-redirect: “true” to the ingress.yaml config enables traffic through HTTP and HTTPS.

Conclusion

Ingress does allow you to configure multiple Virtual Hosts, Sticky sessions, Path rewrites and also custom configs, providing a powerful, flexible routing mechanism for Kubernetes.

For more info on nginx-ingress-controller visit https://github.com/nginxinc/kubernetes-ingress

A similar procedure can be used to deploy to AWS, GKE instead of Minikube.

Kubernetes and Ingress in particular is constantly evolving I will try my best to keep this updated. Boy Scout Oath.

Good Reads

Hope you enjoyed reading this as much as I enjoyed writing it. 
If you think this will be of help to someone? Do not hesitate to share. If you liked it, tap the clap below so other people will see this here on Medium. Don’t forget to show some love by following the blog!

*Update on 11 November 2018* Added RBAC in the example setup. Thanks to Jens Madsen for his contribution.

More by Gokul Chandrasekaran

More Related Stories