The AWS ecosystem for Kubernetes load balancing spans two closely related surfaces: the AWS Load Balancer Controller that reconciles Kubernetes Service, Ingress and Gateway resources into Elastic Load Balancers, and the Terraform AWS ALB module that provisions Application and Network Load Balancer resources with declarative configuration. Both converge on the awslb resource and its supporting listener, target group and security group constructs, and both expose configuration through annotations and module variables that must be understood together to operate awslb safely in production.
The AWS Load Balancer Controller is a controller to help manage Elastic Load Balancers for a Kubernetes cluster. It satisfies Kubernetes Ingress resources by provisioning Application Load Balancers. It satisfies Kubernetes Service resources by provisioning Network Load Balancers. It satisfies Kubernetes Gateway resources by provisioning Network Load Balancers and Application Load Balancers. This project was formerly known as "AWS ALB Ingress Controller", we rebranded it to be "AWS Load Balancer Controller".
The Terraform module which creates Application and Network Load Balancer resources on AWS provides a Terraform wrapper around the aws_lb resource and related AWS resources. When you're using ALB Listener rules, make sure that every rule's actions block ends in a forward, redirect, or fixed-response action so that every rule will resolve to some sort of an HTTP response.
AWS Load Balancer Controller Overview
AWS Load Balancer Controller is a controller to help manage Elastic Load Balancers for a Kubernetes cluster.
The controller's primary reconciliation targets are:
- Kubernetes Ingress resources by provisioning Application Load Balancers
- Kubernetes Service resources by provisioning Network Load Balancers
- Kubernetes Gateway resources by provisioning Network Load Balancers and Application Load Balancers
This project was formerly known as "AWS ALB Ingress Controller", we rebranded it to be "AWS Load Balancer Controller".
Origin and governance
AWS ALB Ingress Controller was originated by Ticketmaster and CoreOS as part of Ticketmaster's move to AWS and CoreOS Tectonic. Learn more about Ticketmaster's Kubernetes initiative from Justin Dean's video at Tectonic Summit.
AWS ALB Ingress Controller was donated to Kubernetes SIG-AWS to allow AWS, CoreOS, Ticketmaster and other SIG-AWS contributors to officially maintain the project. SIG-AWS reached this consensus on June 1, 2018.
The controller is open for contributions. We welcome contributions! For non-trivial changes (new features, API changes, refactors), please open an issue or discussion before submitting a PR so the maintainers can provide early feedback. See CONTRIBUTING.md for full details.
Terraform AWS ALB Module Overview
The module referenced in the reference material is terraform-aws-modules/alb/aws. Terraform module which creates Application and Network Load Balancer resources on AWS.
Version constraints captured in the reference material:
| Name | Version |
|---|---|
| terraform | >= 1.5.7 |
| aws | >= 6.28 |
The module creates the following resources as documented:
| Name | Type |
|---|---|
| awslambdapermission.this | resource |
| aws_lb.this | resource |
| awslblistener.this | resource |
| awslblistener_certificate.this | resource |
| awslblistener_rule.this | resource |
| awslbtarget_group.this | resource |
| awslbtargetgroupattachment.additional | resource |
| awslbtargetgroupattachment.this | resource |
| awsroute53record.this | resource |
| awssecuritygroup.this | resource |
| awsvpcsecuritygroupegress_rule.this | resource |
| awsvpcsecuritygroupingress_rule.this | resource |
| awswafv2webaclassociation.this | resource |
| aws_partition.current | data source |
Module Configuration Example
A representative module invocation is shown in the reference facts:
hcl
module "alb" {
source = "terraform-aws-modules/alb/aws"
name = "my-alb"
vpc_id = "vpc-abcde012"
subnets = ["subnet-abcde012", "subnet-bcde012a"]
security_group_ingress_rules = {
all_http = {
from_port = 80
to_port = 80
ip_protocol = "tcp"
description = "HTTP web traffic"
cidr_ipv4 = "0.0.0.0/0"
}
all_https = {
from_port = 443
to_port = 443
ip_protocol = "tcp"
description = "HTTPS web traffic"
cidr_ipv4 = "0.0.0.0/0"
}
}
security_group_egress_rules = {
all = {
ip_protocol = "-1"
cidr_ipv4 = "10.0.0.0/16"
}
}
access_logs = {
bucket = "my-alb-logs"
}
listeners = {
ex-http-https-redirect = {
port = 80
protocol = "HTTP"
redirect = {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
ex-https = {
port = 443
protocol = "HTTPS"
certificate_arn = "arn:aws:iam::123456789012:server-certificate/test_cert-123456789012"
forward = {
target_group_key = "ex-instance"
}
}
}
target_groups = {
ex-instance = {
name_prefix = "h1"
protocol = "HTTP"
port = 80
target_type = "instance"
target_id = "i-0f6d38a07d50d080f"
}
}
tags = {
Environment = "Development"
Project = "Example"
}
}
A second partial example shows the same listener pattern with an ex-cognito listener on port 444 with protocol HTTPS and certificate_arn.
The module documentation notes: When you're using ALB Listener rules, make sure that every rule's actions block ends in a forward, redirect, or fixed-response action so that every rule will resolve to some sort of an HTTP response.
Module Input Variables
The reference facts list the following input variables with partial descriptions.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| access_logs | Map containing access logging configuration for load balancer | object | null | no |
| additionaltargetgroup_attachments | Map of additional target group attachments to create. Use targetgroupkey to attach to the target group created in target_groups | map(object) | null | no |
| associatewebacl | Indicates whether a Web Application Firewall (WAF) ACL should be associated with the load balancer | bool | false | no |
| clientkeepalive | Client keep alive value in seconds. The valid range is 60-604800 seconds. Only valid for Load Balancers of type application. Default: 60 | number | null | no |
| internal | If true, the LB will be internal. Defaults to false | bool | null | no |
| ipaddresstype | The type of IP addresses used by the subnets for your load balancer. The possible values are ipv4 and dualstack | string | null | no |
| ipam_pools | The IPAM pools to use with the load balancer | object | null | no |
| listeners | Map of listener configurations to create | map(object) | {} | no |
| loadbalancertype | The type of load balancer to create. Possible values are application, gateway, or network. The default value is application | string | "application" | no |
| minimumloadbalancer_capacity | Minimum capacity for a load balancer. Only valid for Load Balancers of type application or network | object | null | no |
| name | The name of the LB. This name must be unique within your AWS account, can have a maximum of 32 characters, must contain only alphanumeric characters or hyphens, and must not begin or end with a hyphen | string | null | no |
| name_prefix | Creates a unique name beginning with the specified prefix. Conflicts with name | string | null | no |
| preservehostheader | Indicates whether the Application Load Balancer should preserve the Host header in the HTTP request and send it to the target without any change | - | - | - |
The module also documents:
- Only valid for Load Balancers of type application. Default: 60
- preserve client IP is disabled by default for IP targets - preserve client IP is enabled by default for instance targets
Kubernetes Service Annotations for AWS Load Balancer Controller
The AWS Load Balancer Controller manages Kubernetes Services in a compatible way with the legacy aws cloud provider. The annotation service.beta.kubernetes.io/aws-load-balancer-type is used to determine which controller reconciles the service. If the annotation value is nlb-ip or external, legacy cloud provider ignores the service resource (provided it has the correct patch) so that the AWS Load Balancer controller can take over. For all other values of the annotation, the legacy cloud provider will handle the service. All other types below must be string-encoded, for example:- boolean: "true"
- integer: "42"
- stringList: "s1,s2,s3"
- stringMap: "k1=v1,k2=v2"
- json: "{ \"key\": \"value\" }"
- boolean:
| Name | Type | Default | Notes | |
|---|---|---|---|---|
| service.beta.kubernetes.io/load-balancer-source-ranges | stringList | |||
| service.beta.kubernetes.io/aws-load-balancer-type | string | |||
| service.beta.kubernetes.io/aws-load-balancer-nlb-target-type | string | |||
| service.beta.kubernetes.io/aws-load-balancer-name | string | |||
| service.beta.kubernetes.io/aws-load-balancer-internal | boolean | false | deprecated, in favor of aws-load-balancer-scheme | |
| service.beta.kubernetes.io/aws-load-balancer-scheme | string | internal | ||
| service.beta.kubernetes.io/aws-load-balancer-proxy-protocol | string | Set to "*" to enable | ||
| service.beta.kubernetes.io/aws-load-balancer-ip-address-type | string | ipv4 | ipv4 | dualstack |
| service.beta.kubernetes.io/aws-load-balancer-access-log-enabled | boolean | false | ||
| service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name | string | |||
| service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix | string | |||
| service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled | boolean | false | ||
| service.beta.kubernetes.io/aws-load-balancer-ssl-cert | stringList | |||
| service.beta.kubernetes.io/aws-load-balancer-ssl-ports | stringList | |||
| service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy |
- service.beta.kubernetes.io/load-balancer-source-ranges: 10.0.0.0/24
- service.beta.kubernetes.io/aws-load-balancer-scheme specifies whether the NLB will be internet-facing or internal. Valid values are internal, internet-facing. If not specified, default is internal.
Example service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing" - service.beta.kubernetes.io/aws-load-balancer-internal specifies whether the NLB will be internet-facing or internal. deprecation note This annotation is deprecated starting v2.2.0 release in favor of the new aws-load-balancer-scheme annotation. It will will be supported, but in case of ties, the aws-load-balancer-scheme gets precedence.
Example service.beta.kubernetes.io/aws-load-balancer-internal: "true"
Annotation Encoding and Legacy Compatibility
The annotation documentation notes that all other types below must be string-encoded. The reference facts illustrate encoding examples for boolean, integer, stringList, stringMap, json, and boolean. The legacy Cloud Provider interaction is explicitly handled through service.beta.kubernetes.io/aws-load-balancer-type. The controller takes over when the value is nlb-ip or external.Integration Patterns Between Terraform Module and Controller
The Terraform module creates aws_lb.this and related aws_lb_listener, aws_lb_target_group resources directly via Terraform. The AWS Load Balancer Controller creates and manages aws_lb resources via Kubernetes reconciliation based on Service, Ingress and Gateway objects. When both are used in the same environment, separation of concerns is important:- Use the Terraform module for statically provisioned, infrastructure owned Application Load Balancers and Network Load Balancers with explicit listeners, target groups, security groups, access logs and WAF association.
- Use the AWS Load Balancer Controller for dynamically provisioned load balancers driven by Kubernetes workloads, with configuration expressed through service annotations and Ingress/Gateway manifests.
Operational Notes
- The Terraform module supports loadbalancertype values application, gateway, or network with default application.
- Security group ingress rules can be defined per port and protocol as shown in the example with allhttp and allhttps.
- Security group egress rules can be defined with ipprotocol "-1" and cidripv4 range.
- Access logging is configured via accesslogs bucket.
- Listener redirect actions must terminate in forward, redirect, or fixed-response to resolve to an HTTP response.
- Target group configuration includes nameprefix, protocol, port, targettype and targetid as demonstrated.