AWS EKS and TLS terminated Load Balancer

ismail yenigül
Feb 26 · 4 min read

At this time, TLS termination with AWS Network Load Balancer(NLB) is not supported by Kubernetes. Also AWS NLB support is a new feature in Kubernetes that is currently in Alpha version and for that reason AWS does not recommend using it on production environments.

We have two options: Classical Load Balancer or AWS ALB Ingress Controller for Kubernetes.

AWS ALB Ingress Controller is a 3rd party resource and therefore out of AWS support scope. It uses a different approach to deploy an Application Load Balancer by using ingress resources instead of the LoadBalancer service type from Kubernetes.

I will give sample yaml files for Classical LoadBalancer and AWS ALB Ingress Controller here.

AWS Classical Load Balancer

apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:eu-west-1:xxx:certificate/xxx
labels:
app: myapp
name: myapp
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 443
targetPort: 8080
selector:
app: myapp

Replace service.beta.kubernetes.io/aws-load-balancer-ssl-cert value with your SSL certificate ARN. You can get the ARN from AWS Certificate Manager Console.

If your backend is HTTP and if you need to get X-Forwarded-Proto headers in your backend service, you need to set backend as http. to set the backend protocol as HTTP add the following lines in the annotations

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http

From https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go

// ServiceAnnotationLoadBalancerBEProtocol is the annotation used on the service                       
// to specify the protocol spoken by the backend (pod) behind a listener.
// If `http` (default) or `https`, an HTTPS listener that terminates
// the connection and parses headers is created. // If set to `ssl` or `tcp`, a "raw" SSL listener is used. // If set to `http` and `aws-load-balancer-ssl-cert` is not used // then
// a HTTP listener is used. const ServiceAnnotationLoadBalancerBEProtocol = "service.beta.kubernetes.io/aws-load-balancer-backend-protocol"

HTTP/HTTPS Listener

If you want to listen port 80 too in the Load balancer, you can change the service as following.

  1. You must give a name to all ports.
  2. You must configure service.beta.kubernetes.io/aws-load-balancer-ssl-ports Otherwise, The load balancer will listen port 80 as HTTPS
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:eu-west-1:xxx:certificate/xxx
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
labels:
app: myapp
name: myapp
spec:
type: LoadBalancer
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
- name: https
protocol: TCP
port: 443
targetPort: 8080
selector:
app: myapp

AWS ALB Ingress Controller

To use AWS ALB Ingress Controller at https://github.com/kubernetes-sigs/aws-alb-ingress-controller/ I assume that you deployed AWS ALB Ingress Controller correctly.

If you are trying to deploy v.1.1 please use iam-policy.json from master branch. v1.1.1 does not contain the following permissions to get SSL certs from ACM.

"elasticloadbalancing:DescribeListenerCertificates",
"elasticloadbalancing:AddListenerCertificates",
"elasticloadbalancing:RemoveListenerCertificates"

Also don’t forget to add tag kubernetes.io/role/elb for your subnets

kubernetes.io/role/elb should be set to 1 or an empty tag value for internet-facing load balancers.

Create a service with NodePort type, replace targetPort with your Pod exposed port.

apiVersion: v1
kind: Service
metadata:
labels:
app: myapp
name: myapp
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: NodePort
selector:
app: myapp

Then create an Ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapp
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
alb.ingress.kubernetes.io/group: myapp
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-west-1:xxx:certificate/xxx
spec:
rules:
- host: app.mydomain.com
http:
paths:
- path: /*
backend:
serviceName: myapp
servicePort: 80

servicePort in Ingress must match with port value in service yaml. Your HTTP and HTTPS will be forwarded to myapp service’s port 80

Now you can create your loadbalancer with kubectl

Ismail YENIGUL

Devops Engineer at Feedstock Inc.

Follow us on Twitter 🐦 and Facebook 👥 and join our Facebook Group 💬.

To join our community Slack 🗣️ and read our weekly Faun topics 🗞️, click here⬇

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author! ⬇

Faun

The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts

ismail yenigül

Written by

Linux and Cloud

Faun

Faun

The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade