Using Application Load Balancers with Kubernetes
Introduction
Using the AWS Application Load Balancer (ALB) offers an easy way to provide flexible, secure, and scalable load balancing for applications running in Kubernetes.
AWS Application Load Balancers provide the following features:
- Layer 7 (HTTP/HTTPS)
- TLS termination
- Path-based routing
- Integrates with AWS WAF and AWS Shield
The AWS Load Balancer Controller allows application owners to configure a load balancer for their application using the Kubernetes Ingress API. The load balancer configuration can be saved in source control alongside the application code and deployed with a Helm chart or other methods of deploying to Kubernetes.
This guide will focus on common use cases for providing load balancing functionality for applications which are deployed to Kubernetes.
What are the benefits of the AWS Load Balancer Controller?
- Declarative configuration management
Load balancer configuration is managed by Kubernetes Ingress API which allows application owners to define a load balancer for their application in source control without requiring permissions to AWS. - Integration with pod readiness gates
Kubernetes pod readiness gates can be used to ensure pods have passed load balancer health checks prior to being considered ready in Kubernetes. - Multiple applications supported with a single load balancer
Multiple applications can share a single load balancer and hostname. Path-based routing rules are used to determine which application will receive requests. - Slow start mode
Slow-start mode ensures new pods are warmed up prior to receiving a full share of traffic. - Integration with AWS Certificate Manager
Certificates managed by AWS Certificate Manager (ACM) can be used by the load balancer. If encryption is enabled but no certificate is specified, then a certificate which matches the hostname of the listener will be automatically selected.
Controller Installation
Installing the AWS Load Balancer Controller requires configuring IAM, security groups, and deployment of the controller via Helm or YAML. Refer to the Installation Guide for step by step details on how to complete installation and initial configuration for the controller.
Application Load Balancing
Declarative Configuration Management
Ingress Resource
A load balancer is configured by deploying an ingress resource in Kubernetes which has the appropriate ingressClassName
specified. A minimal ingress resource for an AWS ALB may look like this:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-service annotations: alb.ingress.kubernetes.io/target-type: ip spec: ingressClassName: alb rules: - host: example-service.example.com http: paths: - backend: service: name: example-service port: number: 443 path: /* pathType: ImplementationSpecific
You can use kubectl to create or update the load balancer:
kubectl apply -f ingress.yaml
Configuration Parameters
Load balancer functionality can be customized by adding annotations to the ingress resource.
The following table describes a few of the most commonly used annotations which may be required. For a complete list, see the Ingress Annotations page in the official documentation.
Configuration | Annotation | Example Value |
---|---|---|
Target Type | alb.ingress.kubernetes.io/target-type | ip |
Backend Protocol | alb.ingress.kubernetes.io/backend-protocol | HTTPS |
Listen Ports | alb.ingress.kubernetes.io/listen-ports | [{"HTTPS": 443}] |
Healthcheck Protocol | alb.ingress.kubernetes.io/healthcheck-protocol | HTTPS |
Healthcheck Path | alb.ingress.kubernetes.io/healthcheck-path | /healthcheck/ready |
SSL Policy | alb.ingress.kubernetes.io/ssl-policy | ELBSecurityPolicy-TLS-1-2-2017-01 |
Scheme | alb.ingress.kubernetes.io/scheme | internet-facing |
Pod Readiness Gate
The AWS Load Balancer controller supports integration with Kubernetes pod readiness gates. This is useful to ensure that the load balancer considers a new target healthy before the pod is considered ready by Kubernetes. Without the pod readiness gate, a rolling deployment could terminate all pods in a replica set before any pods in a new replica set are ready to receive traffic from the load balancer which can result in performance impacts or HTTP 503 (service unavailable) errors.
Rolling update to a deployment with Pod Readiness Gate enabled (assuming maxSurge: 100% and maxUnavailable: 0%).
In the above example, without the pod readiness gate, the 2nd pod in the v1 ReplicaSet would be terminated before the 2nd pod in the v2 ReplicaSet is receiving traffic from the load balancer.
The Pod Readiness Gate integration is enabled on a per-namespace basis. To enable, add the following label to the namespace where the Kubernetes service is deployed:
elbv2.k8s.aws/pod-readiness-gate-inject: enabled
End-to-End Encryption
By default, an application load balancer will use unencrypted HTTP for backend connections to targets. However, end-to-end encryption may be required if the environment is in scope for PCI DSS, HIPAA, or other regulatory frameworks.
The Setting up end-to-end TLS encryption on Amazon EKS with the new AWS Load Balancer Controller article describes how to configure end-to-end encryption using an AWS Certificate Manager Private CA. However, this solution incurs additional cost and may not be necessary since the certificate on the target does not have to be trusted by the load balancer.
Configure the following attribute to enable HTTPS on back-end targets:
alb.ingress.kubernetes.io/backend-protocol: HTTPS
If you opt to use self-signed certificates, they can be generated when building application containers:
Windows:
Import-Module WebAdministration New-SelfSignedCertificate -CertStoreLocation cert:\LocalMachine\My -DnsName <DNS Hostname> | New-Item IIS:\SslBindings\0.0.0.0!443 $certHash = (Get-ChildItem cert:\LocalMachine\My | Where-Object {$_.Subject -match "CN=<DNS Hostname>"}).GetCertHashString() Get-WebBinding -Name <IIS Website> -Protocol https | $_.AddSslCertificate($certHash, "My")
Linux:
openssl req -new -newkey rsa -x509 -subj '/CN=' -nodes -out MyCertificate.crt -keyout MyKey.key
Once a certificate is generated, you will need to configure the web server application to use it
Ingress Groups
The IngressGroup feature allows you to deploy multiple applications which share a single load balancer and hostname. The AWS Load Balancer Controller will automatically merge path-based routing rules for each Ingress into a single Application Load Balancer.
Source: amazon.com
To use ingress groups, ensure that all ingress resources use the same alb.ingress.kubernetes.io/group.name value. If you need to control the order in which rules are merged, use the alb.ingress.kubernetes.io/group.order annotation
The following example demonstrates the use of a simple IngressGroup using two ingress resources:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-service-a alb.ingress.kubernetes.io/group.name: example-service spec: rules: - host: example-service.example.com http: paths: - backend: service: name: example-service-a port: number: 443 path: /example-service-a/* pathType: ImplementationSpecific --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-service-b alb.ingress.kubernetes.io/group.name: example-service spec: rules: - host: example-service.example.com http: paths: - backend: service: name: example-service-b port: number: 443 path: /example-service-b/* pathType: ImplementationSpecific
For more information, see the IngressGroup section of the official documentation.
Slow Start Mode
Often, new containers process requests more slowly for a period of time until they are “warmed up”. Slow start mode allows new targets to receive less than their full share of requests until the slow start duration period has ended. Traffic will be gradually increased over the slow start duration.
To enable slow start mode, use the alb.ingress.kubernetes.io/target-group-attributes attribute:
alb.ingress.kubernetes.io/target-group-attributes: slow_start.duration_seconds=30
Conclusion
In this article, I’ve discussed the benefits of using AWS Application Load Balancers and the AWS Load Balancer Controller in a Kubernetes environment. I also described how to configure pod readiness gates, end-to-end encryption, ingress groups, and slow start mode.
In a future article, we’ll cover load balancer monitoring and access logs.
References
https://aws.amazon.com/blogs/containers/introducing-aws-load-balancer-controller/
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html
https://www.eksworkshop.com/beginner/180_fargate/prerequisites-for-alb/
https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/how-it-works/
https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller