Lesson 08 of 18 · Operate
Ingress
Expose EKS workloads with the AWS Load Balancer Controller: ALBs from Ingress, NLBs from Services, IP targets straight to pods, shared ALBs with IngressGroups, TLS from ACM, and where Gateway API fits.
The AWS Load Balancer Controller
The AWS Load Balancer Controller (LBC) watches Kubernetes objects and manages AWS load balancers for them:
| Kubernetes object | AWS result |
|---|---|
Ingress (class alb) |
ALB with listeners, rules and target groups |
Service type: LoadBalancer (with LBC annotations) |
NLB |
| Gateway API resources (newer controller versions) | ALB/NLB from Gateways and Routes |
Install it with Helm, giving its ServiceAccount an IAM role (AWS publishes the required policy) via Pod Identity or IRSA.
The controller is a stage manager: when an app says "I need a front door" (Ingress or Service), the stage manager orders the right door from AWS (an ALB or NLB), wires it straight to the actors (pods), and removes it when the show ends.
ALB from an Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
namespace: shop
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-west-1:111122223333:certificate/abcd-1234
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
alb.ingress.kubernetes.io/healthcheck-path: /healthz
alb.ingress.kubernetes.io/group.name: public-web # share one ALB across Ingresses
spec:
ingressClassName: alb
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
target-type: ipregisters pod IPs in the target group: no NodePort hop, and health checks see real pods.- IngressGroups (
group.name) put many Ingresses behind one ALB, saving money. Only group apps that share a trust boundary. - TLS from ACM certificates; attach AWS WAF with the
wafv2-acl-arnannotation for public apps.
NLB from a Service
apiVersion: v1
kind: Service
metadata:
name: gateway
namespace: infra
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: external
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
type: LoadBalancer
selector: { app: gateway }
ports:
- { name: https, port: 443, targetPort: 8443 }
Use NLBs for TCP/UDP services, static IPs (Elastic IP annotations), extreme throughput, or to put your own L7 proxy (an in-cluster Gateway API implementation) behind a simple L4 edge.
Choosing an edge
| Pattern | When |
|---|---|
| ALB per app group (IngressGroup) | AWS-native: ACM, WAF, OIDC auth on the ALB |
| NLB → in-cluster gateway (Envoy Gateway, Istio, Traefik…) | Portable Gateway API config, advanced L7 features, one LB for everything |
| LBC with Gateway API | Gateway API resources, backed by AWS load balancers |
Try it: ALB and NLB on EKS (sandbox account)
- Tag your VPC subnets (
kubernetes.io/role/elb/internal-elb), create the controller's IAM role and install it with Helm. - Deploy
weband apply the Ingress above (use an ACM certificate for a domain you control, or an HTTP listener for the lab). Wait for the ALB and curl it. - Look at the target group in the console: which IPs are registered? Scale
weband watch targets change. - Create a second Ingress with the same
group.namefor another path, and confirm it reuses the ALB. - Expose a Service as an internet-facing NLB with IP targets. Delete everything (and check the load balancers are gone).
Going deeper: edges on EKS in production
- Readiness gates: the controller can inject pod readiness gates so pods only count as Ready once they're healthy in the ALB target group, which gives zero-downtime rollouts.
- Set deregistration delay and a
preStopsleep so in-flight requests finish during rollouts. - Keep internet-facing and internal load balancers separate, and restrict who can create internet-facing ones (admission policy on the scheme annotation).
- Use ExternalDNS to create Route 53 records from Ingress/Service hostnames automatically.
Recap
- The AWS Load Balancer Controller turns Ingresses into ALBs and Services into NLBs (and supports Gateway API in newer versions).
target-type: ipsends traffic straight to pods; IngressGroups share ALBs.- TLS from ACM, WAF on public ALBs, subnet tags for discovery.
- Choose between AWS-native ALBs and NLB + in-cluster gateway by features and portability.
This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.