SSL Terminated Kubernetes Load Balancers in AWS

Launching services in Kubernetes that utilize an AWS Elastic Load Balancer has long been fairly simple - just launch a service with type: LoadBalancer. Where it becomes more complicated and not nearly as well documented is when you want to do SSL termination at the ELB level, a common practice when using ELBs. Luckily, there are a few annotations you can use on your service to make this happen.

The first annotation is service.beta.kubernetes.io/aws-load-balancer-ssl-ports. This tells the ELB which port to listen on for https traffic. It will almost always be set to "443".

Second, we have the service.beta.kubernetes.io/aws-load-balancer-ssl-cert annotation. This annotation is used to provide the arn (Amazon identifier) for the SSL certificate you have stored in AWS Certificate Manager. It should look something like arn:aws:acm:region:accountNumber:certificate/certificateName.

Last but not least, we have service.beta.kubernetes.io/aws-load-balancer-backend-protocol. This is the bread and butter of this, which tells the ELB that the servers it is balancing the load between is expecting the traffic to come in as http traffic.

Here's what this looks like all put together:

kind: Service
apiVersion: v1
metadata:
  name: my-deployment-name
  namespace: my-namespace
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:us-west-2:accountNumber:certificate/certificateName"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
spec:
  selector:
    deployment: my-deployment-name
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
    - name: https
      protocol: TCP
      port: 443
      targetPort: 80
  type: LoadBalancer

For more information, see the source.