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.
A lot of people seem confused about how Ingress works in Kubernetes and questions come up almost daily in Slack. It’s…medium.com
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.
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:
- a configMap for the Nginx loadbalancer.
- the nginx-ingress-controller.
- a service that exposes a default Nginx backend pod for handling unmapped requests.
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.
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.
You should be able to access the exposed endpoints via https.
Adding the annotation
ingress.kubernetes.io/ssl-redirect: “true” to the
ingress.yaml config enables traffic through HTTP and HTTPS.
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.
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.