SSL Termination and Load Balancing in Kubernetes Clusters
February 6, 2018
In the past, acquiring SSL certificates, setting up domain names and load balancing HTTP traffic were labor-intensive tasks. With Let’s Encrypt, Nginx and Kubernetes, you can automate a lot of this.
(If you’re just getting started with Kubernetes, read this setup guide.)
kube-lego is a daemon that runs in a cluster. When you deploy an HTTP application into that cluster,
kube-lego notices. It requests a new SSL certificate from Let’s Encrypt. This certificate is used for traffic into the HTTP application. Client applications can then connect to your application over HTTPS; which is a necessity for web traffic.
kube-lego only needs to be set up once per cluster. To add
kube-lego, grab the files from this repository. Replace
<ADMIN_EMAIL> with your email address in
configmap.yaml, and apply the directory with
kubectl apply -f kube-lego/
That’s it; the
kube-lego daemon will now be running in your cluster.
Nginx Ingress Controller
Ingress object routes traffic into your cluster to the correct application. By default, an ingress enables a Google Cloud Load Balancer. These are some badass, globally available load balancers that can handle an outrageous amount of traffic. You probably don’t need that for most applications, especially development environments.
The Nginx ingress controller is a substitute. Its an application that runs in your cluster and handles routing and load balancing traffic. It’s simple to add an nginx ingress controller; apply the files in this repository.
kubectl apply -f nginx-ingress-controller/
It will take a moment for
nginx-ingress-lb to acquire an IP address. During that time, running the command
kubectl get services -n kube-system will show something like the following:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE default-http-backend 10.55.241.224 <nodes> 80:32516/TCP 11d heapster 10.55.255.208 <none> 80/TCP 11d kube-dns 10.55.240.11 <none> 53/UDP,53/TCP 11d kubernetes-dashboard 10.55.240.50 <none> 80/TCP 11d nginx-ingress-lb 10.55.249.186 <pending> 80:32005/TCP,443:31623/TCP 6s
<pending>. Once that
<pending> flips to an IP address, note the IP address. Navigate to
VPC Network->External IP adresses in the Google Cloud console. Locate the IP address in that list and change it’s type from
Static. (You’ll be prompted for a name which can be whatever you like.)
Using kube-lego and nginx-ingress-controller
To tell Kubernetes that you want to use the Nginx ingress controller instead of the default load balancers, you add an annotation to your ingress object. Likewise, to tell
kube-lego that an SSL certificate should be generated, you add another annotation. To enable HTTPS, include the
tls field in your ingress object.
Here’s an example:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: api-ingress namespace: my-app annotations: kubernetes.io/tls-acme: "true" kubernetes.io/ingress.class: "nginx" spec: tls: - hosts: - my-app.myhost.com secretName: api-ingress-tls rules: - host: my-app.myhost.com http: paths: - path: / backend: serviceName: api-service servicePort: 80
For each application you deploy, create a new ingress including both annotations. The
spec.tls.secretName name can be anything, but it must be different for each ingress.