Applying a Single AWS ALB to Multiple Namespaces in AWS EKS

When deploying your application on EKS, using ALB to expose it is the most cloud-native approach. The AWS Load Balancer Controller simplifies the process of converting Kubernetes-native Ingress into AWS-native ALB automatically.

The Ingress objects are namespace-scoped. What happens if your applications are deployed in multiple namespaces? By default, the AWS Load Balancer Controller will create a separate ALB for each ingress object. Even if there are multiple Ingress objects in the same namespace, you will end up having an individual ALB for each of them. And that's perfectly fine.

However, if you have 50 or 100 namespaces, and your application needs to be deployed in multiple namespaces, you will incur higher costs because each ALB will charge you for the number of hours they remain active, even if you do not use them.

There is a simple trick to consolidate all Ingress objects into a single ALB, where all those routes will be combined into ALB rule groups. All you need to do is annotate each Ingress with the following labels.

alb.ingress.kubernetes.io/group.name: myapp

For all matching group.name labels in all namespaces, the AWS Load Balancer Controller will create a single ALB with multiple rules inside it. Here is a detailed example:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol: HTTP
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-1:987654321:certificate/37c33c94-e3be-41cc-9ec8-fd16b2873bd4
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/load-balancer-name: myapp
    alb.ingress.kubernetes.io/group.name: myapp
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    alb.ingress.kubernetes.io/success-codes: "200"
    alb.ingress.kubernetes.io/target-type: instance
    kubernetes.io/ingress.class: alb
  name: myapp-dev
  namespace: myapp-dev
spec:
  rules:
  - host: myapp-dev.example.com
    http:
      paths:
      - backend:
          service:
            name: app
            port:
              number: 80
        path: /
        pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol: HTTP
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-1:987654321:certificate/37c33c94-e3be-41cc-9ec8-fd16b2873bd4
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/load-balancer-name: myapp
    alb.ingress.kubernetes.io/group.name: myapp
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    alb.ingress.kubernetes.io/success-codes: "200"
    alb.ingress.kubernetes.io/target-type: instance
    kubernetes.io/ingress.class: alb
  name: myapp-stage
  namespace: myapp-prstageod
spec:
  rules:
  - host: myapp-stage.example.com
    http:
      paths:
      - backend:
          service:
            name: app
            port:
              number: 80
        path: /
        pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol: HTTP
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-1:987654321:certificate/37c33c94-e3be-41cc-9ec8-fd16b2873bd4
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/load-balancer-name: myapp
    alb.ingress.kubernetes.io/group.name: myapp
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    alb.ingress.kubernetes.io/success-codes: "200"
    alb.ingress.kubernetes.io/target-type: instance
    kubernetes.io/ingress.class: alb
  name: myapp-prod
  namespace: myapp-prod
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - backend:
          service:
            name: app
            port:
              number: 80
        path: /
        pathType: Prefix

You can find all available annotations here: https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.6/guide/ingress/annotations/