In the first two posts in this series, SSL Options with Kubernetes – Part 1 and SSL Options with Kubernetes – Part 2, we saw how to use the Kubernetes LoadBalancer service type to terminate SSL for your application deployed on a Kubernetes cluster in AWS and Azure, respectively. In this post, we will see how this can be done for a Kubernetes cluster anywhere using an Ingress resource.
Rather than using an external load balancer as the AWS and Azure cloud providers do for the
LoadBalancer service type, an ingress uses an Ingress Controller to provide load balancing, SSL termination and other services within a Kubernetes cluster. A big advantage of using an ingress is its portability across all clusters regardless of the underlying infrastructure, i.e. cloud, virtualized or bare metal. Until recently, a disadvantage was an ingress only supported HTTP and HTTPS and you would need to use a
NodePort service type for other protocols. However, NGINX has added support for other protocols to their ingress controller.
Deploying an Ingress Controller
As always, in building our Kubernetes cluster, we will use Docker Enterprise. Docker is the leader in the enterprise container platform space, (https://www.docker.com/resources/report/the-forrester-wave-enterprise-container-platform-software-suites-2018), and makes it very easy to setup a highly available container cluster on (almost) any infrastructure with Kubernetes (and Swarm) orchestration.
Once you have your Kubernetes cluster up, the first choice you will have to make is what ingress controller to use. There are a wide range of ingress controllers available. Contour from Heptio (now VMware), NGINX from NGINX, Inc. (now F5) and Traefik from Containous are popular choices. And, you can use multiple ingress controllers if you find the need to take advantage of some unique capabilities each might provide. For this post, we are going to use the open source nginx ingress controller supported and maintained within the Kubernetes project itself.
To setup our nginx ingress controller, we’ll use Nicola Kabar’s excellent blog post, Production Ingress Deployment in Docker Enterprise UCP 3.1, as a starting point.
Another option for deploying the ingress controller is the nginx-ingress Helm chart.
Creating a Secret for our TLS Certificate
In our previous examples we’ve used a wildcard certificate for *.lab.capstonec.net issued by GoDaddy. We’ll use that same certificate in this example. First, we’ll create a Kubernetes secret, default-tls-certficate, in our ingress controller’s namespace, ingress in this example.
$ kubectl -n ingress create secret tls default-ssl-certificate --key key.pem --cert cert.pem secret/default-ssl-certificate created
Update the Deployment to Specify the Secret
Once we have a secret with certificate we want to use, we need to update containers spec in the ingress controller’s deployment to include the
--default-ssl-certificate command line option.
... containers: - name: nginx-ingress-controller image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.24.1 args: - /nginx-ingress-controller - --default-backend-service=$(POD_NAMESPACE)/default-http-backend - --default-ssl-certificate=$(POD_NAMESPACE)/default-ssl-certificate - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --annotations-prefix=nginx.ingress.kubernetes.io ...
Specifying the Default SSL Certificate when using a Helm Chart
If you use the nginx-ingress Helm chart to deploy your NGINX ingress controller, you can specify the Kubernetes secret to use for the default SSL certificate when you install it.
You can pass it via the command line, i.e.
$ helm install --name nginx-ingress --set controller.extraArgs.default-ssl-certificate=default/default-ssl-certificate stable/nginx-ingress
Or you can pass it through an additional extraArgs.yaml file, i.e.
controller: extraArgs: default-ssl-certificate: "default/default-ssl-certificate"
$ helm install --name nginx-ingress --values=extraArgs.yaml stable/nginx-ingress
Deploying Our Application
As in our previous posts, we’ll use the nginx official image as our example web server. First, we create a deployment YAML file, kens-deployment.yaml.
kind: Deployment apiVersion: apps/v1 metadata: name: kens-deployment spec: selector: matchLabels: app: kens-app replicas: 2 template: metadata: labels: app: kens-app spec: containers: - name: nginx image: nginx:1.15 ports: - containerPort: 80
Then, we apply it using kubectl.
$ kubectl apply -f kens-deploment.yaml deployment.apps/kens-deployment created
Next, we create a service manifest, kens-service.yaml.
kind: Service apiVersion: v1 metadata: name: kens-service spec: type: ClusterIP selector: app: kens-app ports: - name: http protocol: TCP port: 80 targetPort: 80
And, apply it using kubectl.
$ kubectl apply -f kens-service.yaml service/kens-service created
Creating an Ingress for Our Application
Finally, we need to create an Ingress manifest, kens-ingress.yaml. We want to access our service, kens-service, using the URL https://ken-nginx.lab.capstonec.net. In our manifest, we specify that TLS should be used for that host and we specify a rule that directs traffic for that host to our service.
kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx labels: app: kens-app name: kens-ingress spec: tls: - hosts: - ken-nginx.lab.capstonec.net rules: - host: ken-nginx.lab.capstonec.net http: paths: - backend: serviceName: kens-service servicePort: 80 path: /
We then apply this manifest using kubectl.
$ kubectl apply -f kens-ingress.yaml ingress.extensions/kens-ingress created
Now, when we browse to our site, https://ken-nginx.lab.capstonec.net, we see a secure connection to our default web page.
Overriding the Default SSL Certificate
If you don’t want to use the default SSL certificate for your application, you can create another secret, for example my-ssl-certificate, using your certifcate and key files. Then you would specify it in your ingress manifest as below.
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx labels: app: kens-app name: kens-ingress spec: tls: - hosts: - ken-nginx.lab.capstonec.net secretName: my-ssl-certificate rules: - host: ken-nginx.lab.capstonec.net http: paths: - backend: serviceName: kens-service servicePort: 80 path: /
Want to know more?
In this series of posts we’ve looked at various options for terminating SSL for applications running in a Kubernetes cluster. The option you choose will depend upon your infrastructure and your application requirements. Capstone IT is a Docker Premier Consulting Partner as well as being an Azure Gold and AWS Select partner. If you are interested in finding out more and getting help with your Container, Cloud and DevOps transformation, please Contact Us.