Upgrade & Secure Your Future with DevOps, SRE, DevSecOps, MLOps!

We spend hours scrolling social media and waste money on things we forget, but won’t spend 30 minutes a day earning certifications that can change our lives.
Master in DevOps, SRE, DevSecOps & MLOps by DevOpsSchool!

Learn from Guru Rajesh Kumar and double your salary in just one year.


Get Started Now!

AWS Load Balancer Controller for Kubernetes: A Comprehensive Guide

The AWS Load Balancer Controller is a Kubernetes controller that manages Elastic Load Balancers for Amazon EKS clusters. It provides a native way to expose Kubernetes services to external traffic by automatically provisioning and configuring AWS Application Load Balancers (ALB) and Network Load Balancers (NLB) based on Kubernetes Ingress and Service resources.

Understanding the AWS Load Balancer Controller

The AWS Load Balancer Controller operates by watching for Kubernetes Ingress and Service resources, then automatically creating and managing corresponding AWS load balancer infrastructure. When you create an Ingress resource, the controller provisions an ALB; when you create a Service of type LoadBalancer with appropriate annotations, it can provision either an ALB or NLB.

Key Components:

  • Application Load Balancer (ALB): Layer 7 load balancer for HTTP/HTTPS traffic with advanced routing capabilities
  • Network Load Balancer (NLB): Layer 4 load balancer for high-performance TCP/UDP traffic
  • Target Groups: AWS resources that route requests to registered targets
  • Listeners: Components that check for connection requests on specified ports
  • Rules: Define how traffic is routed based on conditions

How It Works

The controller follows a specific workflow when managing load balancers:

  1. Monitoring: The controller watches for Ingress and Service events from the Kubernetes API server
  2. Resource Creation: When it finds resources that satisfy its requirements, it begins creating AWS resources
  3. Load Balancer Provisioning: An ALB or NLB is created in AWS based on the resource type and annotations
  4. Target Group Management: Target groups are created for each unique Kubernetes service
  5. Listener Configuration: Listeners are created for specified ports with appropriate certificates
  6. Rule Creation: Rules are established for path-based routing to correct services

The controller supports two traffic modes:

  • Instance Mode: Traffic flows from ALB to Kubernetes nodes via NodePort services
  • IP Mode: Traffic flows directly from ALB to Kubernetes pods (requires compatible CNI)

Prerequisites and Setup Requirements

Before installing the AWS Load Balancer Controller, ensure you have:

  • AWS CLI v2.18.10 or higher
  • eksctl v0.193.0 or higher
  • EKS Cluster v1.30 or higher
  • Pod Identity Agent v1.3.2-eksbuild.2 or higher
  • Amazon VPC CNI plugin
  • kubectl v1.31 or higher
  • Helm v3.16.2 or higher

Sequence for Installing AWS Load Balancer Controller with Best Practices

1. OIDC Identity Provider

  • Enables secure trust between Kubernetes service accounts and AWS IAM roles.
  • Needed so you can use IRSA (IAM Roles for Service Accounts).

2. IAM Policy

  • Write or download the official AWS Load Balancer Controller policy (JSON file).
  • This policy defines what permissions the controller gets (e.g., create/manage load balancers, security groups, etc.).

3. IAM Role

  • Create an IAM role with the trust policy for the OIDC provider (so only your specific K8s service account can assume it).
  • Attach the policy from step 2 to this role.

4. Kubernetes Service Account (linked to IAM Role)

  • Create (or update) a Kubernetes service account (e.g., aws-load-balancer-controller in kube-system namespace).
  • Annotate this service account with the IAM Role ARN from step 3.

5. Install AWS Load Balancer Controller

  • Install via Helm (recommended), specifying that it should use your service account.
  • Controller pods will automatically assume the right IAM role, get temporary AWS credentials, and have the required permissions.

IAM Permissions Configuration

The controller requires specific IAM permissions to manage AWS resources. You have two options for configuring these permissions:

Option A: IAM Roles for Service Accounts (IRSA) – Recommended

First, create an IAM OIDC provider for your cluster:

eksctl utils associate-iam-oidc-provider \
--region <region-code> \
--cluster <your-cluster-name> \
--approve

Download the appropriate IAM policy based on your region:

bash# For standard AWS regions
curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.13.2/docs/install/iam_policy.json

# For US Gov Cloud regions
curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.13.2/docs/install/iam_policy_us-gov.json

# For China regions
curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.13.2/docs/install/iam_policy_cn.json

Create the IAM policy:

bashaws iam create-policy \
  --policy-name AWSLoadBalancerControllerIAMPolicy \
  --policy-document file://iam-policy.json

Create the IAM role and service account:

eksctl create iamserviceaccount \
--cluster=<cluster-name> \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::<AWS_ACCOUNT_ID>:policy/AWSLoadBalancerControllerIAMPolicy \
--override-existing-serviceaccounts \
--region <region-code> \
--approve

Option B: Attach IAM Policies to Worker Nodes

If not using IRSA, attach the IAM policy directly to your worker node roles. However, this approach is less secure and not recommended for production environments.

Installation Methods

Method 1: Helm Installation (Recommended)

Add the EKS Helm repository:

bashhelm repo add eks https://aws.github.io/eks-charts
helm repo update eks

Install the controller:

bashhelm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=<cluster-name> \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  --version 1.13.0

Method 2: YAML Manifests

Install cert-manager first:

bashkubectl apply --validate=false -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.3/cert-manager.yaml

Download and apply the controller manifest:

bashwget https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.13.2/v2_13_2_full.yaml

Edit the YAML file to set your cluster name:

textapiVersion: apps/v1
kind: Deployment
metadata:
  name: aws-load-balancer-controller
  namespace: kube-system
spec:
  template:
    spec:
      containers:
        - args:
            - --cluster-name=<your-cluster-name>

Apply the manifest:

bashkubectl apply -f v2_13_2_full.yaml

Verification and Troubleshooting

Verify the installation:

bashkubectl get deployment -n kube-system aws-load-balancer-controller
kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller

Check the controller version:

bashkubectl get deploy aws-load-balancer-controller -n=kube-system -o yaml | grep image:

Verify Custom Resource Definitions:

bashkubectl get crds | grep -iE "elbv2"
kubectl get ingressclass

Configuring Application Load Balancer (ALB) with Ingress

Basic ALB Ingress Configuration

Create a basic Ingress resource for ALB:

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: example-alb
spec:
  ingressClassName: alb
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: example-service
                port:
                  number: 80

Advanced ALB Configuration with Multiple Services

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-service-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/healthcheck-path: /health
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: '30'
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
    alb.ingress.kubernetes.io/healthy-threshold-count: '2'
    alb.ingress.kubernetes.io/unhealthy-threshold-count: '3'
spec:
  ingressClassName: alb
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /api/v1
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080
          - path: /api/v2
            pathType: Prefix
            backend:
              service:
                name: api-v2-service
                port:
                  number: 8080
    - host: web.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80

Configuring Network Load Balancer (NLB) with Services

Basic NLB Service Configuration

textapiVersion: v1
kind: Service
metadata:
  name: nlb-service
  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: example-app
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP

Advanced NLB Configuration with Security Groups

textapiVersion: v1
kind: Service
metadata:
  name: advanced-nlb-service
  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
    service.beta.kubernetes.io/aws-load-balancer-security-groups: sg-12345678
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: '2'
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: '10'
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: '2'
    service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: preserve_client_ip.enabled=true
spec:
  type: LoadBalancer
  selector:
    app: example-app
  ports:
    - port: 443
      targetPort: 8443
      protocol: TCP
      name: https
    - port: 80
      targetPort: 8080
      protocol: TCP
      name: http

SSL/HTTPS Configuration

SSL Termination at ALB

Configure HTTPS with SSL certificates:

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:region:account:certificate/cert-id
    alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
  ingressClassName: alb
  rules:
    - host: secure.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: secure-service
                port:
                  number: 80

Multiple SSL Certificates

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-cert-ingress
  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:region:account:certificate/cert-id-1,
      arn:aws:acm:region:account:certificate/cert-id-2
spec:
  ingressClassName: alb
  rules:
    - host: app1.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app1-service
                port:
                  number: 80
    - host: app2.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app2-service
                port:
                  number: 80

DNS Configuration with Route 53

To configure DNS routing to your load balancer, create Route 53 alias records:

  1. Create an Alias Record: In Route 53, create an alias record that points to your ALB or NLB
  2. Configure the Record: Set the record type to A (for IPv4) or AAAA (for IPv6)
  3. Select the Load Balancer: Choose your load balancer from the dropdown list
  4. Set Routing Policy: Configure appropriate routing policies (simple, weighted, latency-based, etc.)

Example Route 53 configuration:

  • Record Name: api.example.com
  • Record Type: A – IPv4 address
  • Alias: Yes
  • Route Traffic To: Alias to Application Load Balancer
  • Region: Your ALB region
  • Load Balancer: Select your ALB from the list

Advanced Routing and Traffic Management

Weighted Routing for Blue/Green Deployments

The AWS Load Balancer Controller supports advanced traffic splitting for blue/green deployments:

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: blue-green-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/actions.weighted-routing: |
      {
        "type": "forward",
        "forwardConfig": {
          "targetGroups": [
            {
              "serviceName": "blue-service",
              "servicePort": 80,
              "weight": 80
            },
            {
              "serviceName": "green-service", 
              "servicePort": 80,
              "weight": 20
            }
          ]
        }
      }
spec:
  ingressClassName: alb
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: weighted-routing
                port:
                  name: use-annotation

Header-Based Routing

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: header-routing-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/conditions.api-v1: |
      [{"field":"http-header","httpHeaderConfig":{"httpHeaderName":"X-API-Version","values":["v1"]}}]
    alb.ingress.kubernetes.io/conditions.api-v2: |
      [{"field":"http-header","httpHeaderConfig":{"httpHeaderName":"X-API-Version","values":["v2"]}}]
spec:
  ingressClassName: alb
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-v1
                port:
                  number: 80
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-v2
                port:
                  number: 80

Target Group Bindings

Target Group Binding allows you to expose pods using existing ALB or NLB target groups:

textapiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  name: example-tgb
  namespace: default
spec:
  serviceRef:
    name: example-service
    port: 80
  targetGroupARN: arn:aws:elasticloadbalancing:region:account:targetgroup/example-tg/1234567890abcdef
  targetType: ip
  nodeSelector:
    matchLabels:
      kubernetes.io/arch: amd64

Security Best Practices

Security Group Management

The controller supports both frontend and backend security groups:

Frontend Security Groups control access to load balancers:

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/security-groups: sg-frontend-12345678
    alb.ingress.kubernetes.io/inbound-cidrs: 10.0.0.0/8,192.168.0.0/16
spec:
  ingressClassName: alb
  rules:
    - host: secure.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: secure-service
                port:
                  number: 80

Backend Security Groups control load balancer to target communication:

textapiVersion: v1
kind: Service
metadata:
  name: secure-nlb-service
  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-security-groups: sg-backend-87654321
spec:
  type: LoadBalancer
  selector:
    app: secure-app
  ports:
    - port: 443
      targetPort: 8443
      protocol: TCP

WAF Integration

Integrate AWS WAF with ALB for additional security:

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: waf-protected-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:region:account:regional/webacl/example-waf/12345678-1234-1234-1234-123456789012
spec:
  ingressClassName: alb
  rules:
    - host: protected.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: protected-service
                port:
                  number: 80

Monitoring and Logging

Access Logs Configuration

Enable ALB access logs for monitoring and troubleshooting:

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: logged-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-attributes: |
      access_logs.s3.enabled=true,
      access_logs.s3.bucket=my-access-logs-bucket,
      access_logs.s3.prefix=alb-logs
spec:
  ingressClassName: alb
  rules:
    - host: monitored.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: monitored-service
                port:
                  number: 80

CloudWatch Metrics

Monitor key metrics:

  • RequestCount: Number of requests processed
  • TargetResponseTime: Response time from targets
  • HTTPCode_Target_2XX_Count: Successful responses
  • HTTPCode_Target_4XX_Count: Client errors
  • HTTPCode_Target_5XX_Count: Server errors
  • HealthyHostCount: Number of healthy targets
  • UnHealthyHostCount: Number of unhealthy targets

Managing Multiple Load Balancers

IngressClass Parameters

Create custom IngressClass configurations for different environments:

textapiVersion: elbv2.k8s.aws/v1beta1
kind: IngressClassParams
metadata:
  name: dev-class-params
spec:
  namespaceSelector:
    matchLabels:
      kubernetes.io/metadata.name: dev
  scheme: internet-facing
  ipAddressType: ipv4
  loadBalancerAttributes:
    - key: deletion_protection.enabled
      value: "true"
    - key: idle_timeout.timeout_seconds
      value: "120"
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: dev-alb
spec:
  controller: ingress.k8s.aws/alb
  parameters:
    apiGroup: elbv2.k8s.aws
    kind: IngressClassParams
    name: dev-class-params

Ingress Grouping

Group multiple Ingress resources to share a single ALB:

textapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app1-ingress
  annotations:
    alb.ingress.kubernetes.io/group.name: shared-alb
    alb.ingress.kubernetes.io/group.order: '10'
spec:
  ingressClassName: alb
  rules:
    - host: app1.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app1-service
                port:
                  number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app2-ingress
  annotations:
    alb.ingress.kubernetes.io/group.name: shared-alb
    alb.ingress.kubernetes.io/group.order: '20'
spec:
  ingressClassName: alb
  rules:
    - host: app2.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app2-service
                port:
                  number: 80

Troubleshooting Guide

Common Issues and Solutions

1. Controller Not Installing

  • Verify IAM permissions are correctly configured
  • Check that OIDC provider is associated with the cluster
  • Ensure service account has proper annotations

2. Load Balancer Not Created

  • Check controller logs: kubectl logs -n kube-system deployment/aws-load-balancer-controller
  • Verify subnet tags are correct
  • Ensure security groups allow necessary traffic

3. Health Check Failures

  • Verify health check path is accessible
  • Check target group health check configuration
  • Ensure pods are running and ready

4. SSL Certificate Issues

  • Verify certificate ARN is correct and in the same region
  • Check certificate validation status in ACM
  • Ensure certificate covers all hostnames

Debugging Commands

bash# Check controller status
kubectl get deployment -n kube-system aws-load-balancer-controller

# View controller logs
kubectl logs -n kube-system deployment/aws-load-balancer-controller

# Check Ingress status
kubectl describe ingress <ingress-name>

# View target group bindings
kubectl get targetgroupbindings -n <namespace> -o wide

# Check service annotations
kubectl describe service <service-name>

Version Compatibility

Always use the latest compatible version of the controller. Check the compatibility matrix:

  • EKS 1.21+ requires AWS Load Balancer Controller 2.4.x+
  • Kubernetes 1.22+ requires controller versions that support networking.k8s.io/v1 API

Real-World Use Cases

E-commerce Platform

text# Frontend ALB for web traffic
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ecommerce-web
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:region:account:certificate/web-cert
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: '443'
    alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:region:account:regional/webacl/ecommerce-waf/12345
spec:
  ingressClassName: alb
  rules:
    - host: shop.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080
---
# Internal NLB for database connections
apiVersion: v1
kind: Service
metadata:
  name: database-nlb
  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: internal
    service.beta.kubernetes.io/aws-load-balancer-security-groups: sg-database-access
spec:
  type: LoadBalancer
  selector:
    app: database-proxy
  ports:
    - port: 5432
      targetPort: 5432
      protocol: TCP

Microservices Architecture

text# API Gateway ALB with path-based routing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: microservices-gateway
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/healthcheck-path: /health
    alb.ingress.kubernetes.io/load-balancer-attributes: |
      routing.http2.enabled=true,
      idle_timeout.timeout_seconds=60
spec:
  ingressClassName: alb
  rules:
    - host: api.company.com
      http:
        paths:
          - path: /users
            pathType: Prefix
            backend:
              service:
                name: user-service
                port:
                  number: 8080
          - path: /orders
            pathType: Prefix
            backend:
              service:
                name: order-service
                port:
                  number: 8080
          - path: /payments
            pathType: Prefix
            backend:
              service:
                name: payment-service
                port:
                  number: 8080
          - path: /inventory
            pathType: Prefix
            backend:
              service:
                name: inventory-service
                port:
                  number: 8080

Summary

The AWS Load Balancer Controller provides a powerful, native way to manage load balancers in Amazon EKS. Key benefits include:

  • Automatic Management: Automatically provisions and configures AWS load balancers based on Kubernetes resources
  • Advanced Features: Supports SSL termination, WAF integration, and advanced routing capabilities
  • Cost Optimization: Enables sharing of load balancers across multiple services
  • Security: Provides fine-grained security group management and integration with AWS security services
  • Monitoring: Integrates with CloudWatch for comprehensive monitoring and logging

The controller supports both ALB for Layer 7 traffic and NLB for Layer 4 traffic, with extensive customization options through annotations. Proper IAM configuration, security group management, and monitoring are essential for production deployments.

Frequently Asked Questions

Q: Can the AWS Load Balancer Controller work with Classic Load Balancers?
A: No, the AWS Load Balancer Controller only supports Application Load Balancers (ALB) and Network Load Balancers (NLB). Classic Load Balancers are managed by the legacy AWS cloud controller manager.

Q: How do I migrate from the ALB Ingress Controller to the AWS Load Balancer Controller?
A: Follow the official migration guide, which involves uninstalling the old controller, updating CRDs, and installing the new controller. Existing load balancers will be preserved during the migration.

Q: Can I use the same load balancer for multiple Ingress resources?
A: Yes, use the alb.ingress.kubernetes.io/group.name annotation to group multiple Ingress resources that should share the same ALB.

Q: What’s the difference between Instance mode and IP mode?
A: Instance mode routes traffic through NodePort services to worker nodes, while IP mode routes traffic directly to pod IPs. IP mode requires a compatible CNI plugin and is generally more efficient.

Q: How do I handle SSL certificates?
A: Use AWS Certificate Manager (ACM) to provision certificates and reference them in your Ingress annotations using the alb.ingress.kubernetes.io/certificate-arn annotation.

Q: Can I use the controller with private subnets?
A: Yes, set the scheme to internal using the alb.ingress.kubernetes.io/scheme: internal annotation for internal load balancers.

Q: How do I troubleshoot load balancer creation issues?
A: Check controller logs, verify IAM permissions, ensure proper subnet tagging, and validate security group configurations. The controller logs provide detailed information about any issues encountered during resource creation.

Q: What happens to my load balancers if I delete the Ingress resource?
A: The controller automatically deletes the associated AWS load balancer resources when you delete the corresponding Kubernetes Ingress or Service resource.

Absolutely! IAM Roles for Service Accounts (IRSA) is the AWS-recommended way to securely give Kubernetes pods permissions to call AWS APIs—without using long-lived static credentials.

Creating an IAM policy, an IAM role, and connecting it to your EKS service account using IRSA for the AWS Load Balancer Controller.


1. Why Do This?

  • The AWS Load Balancer Controller running inside your EKS cluster needs AWS permissions to create ALBs/NLBs, manage security groups, etc.
  • Using IRSA, we “link” a Kubernetes service account with an IAM role that has the needed permissions.
  • Result: The controller pod automatically gets temporary AWS credentials for that IAM role.

2. Steps Overview

  1. Create an IAM Policy (permissions for the controller)
  2. Create an IAM Role with a trust policy for EKS
  3. Create a Kubernetes Service Account and annotate it with the IAM role ARN
  4. Install the AWS Load Balancer Controller using that service account

3. Step-by-Step Guide

A. Create the IAM Policy

Save this policy to a file (e.g., aws-load-balancer-controller-policy.json).
(You can copy the policy from here in AWS docs or use the one in the previous answer.)

Command:

aws iam create-policy \
  --policy-name AWSLoadBalancerControllerIAMPolicy \
  --policy-document file://aws-load-balancer-controller-policy.json
Code language: JavaScript (javascript)

Copy the Policy ARN from the output (e.g., arn:aws:iam::123456789012:policy/AWSLoadBalancerControllerIAMPolicy).


B. Create an IAM Role for Service Account (using eksctl is easiest)

Recommended: Use eksctl.

eksctl create iamserviceaccount \
  --cluster <your-cluster-name> \
  --namespace kube-system \
  --name aws-load-balancer-controller \
  --attach-policy-arn arn:aws:iam::<your-account-id>:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve
Code language: HTML, XML (xml)
  • --namespace kube-system is where you’ll install the controller (can be different if you use a separate namespace).
  • This will create an IAM role and a Kubernetes service account named aws-load-balancer-controller in the kube-system namespace, annotated to use that role.

Don’t want to use eksctl?

Do it manually:

  1. Create IAM role with this trust policy (replace <OIDC_PROVIDER_URL> and <YOUR_ACCOUNT_ID>): { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<YOUR_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER_URL>" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "<OIDC_PROVIDER_URL>:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller" } } } ] }
  2. Attach the IAM policy from step A to this role.
  3. Annotate your K8s service account: kubectl annotate serviceaccount -n kube-system aws-load-balancer-controller \ eks.amazonaws.com/role-arn=arn:aws:iam::<your-account-id>:role/<your-role-name>

C. Install the AWS Load Balancer Controller Using That Service Account

When you install via Helm, set:

--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller
Code language: JavaScript (javascript)

This tells Helm to use your existing, IRSA-enabled service account.


Summary Table

StepWhat You DoAWS CLI / Tool
Create policyWrite permissions for controlleraws iam create-policy
Create IAM roleTrust OIDC from EKS, allow K8s ServiceAccounteksctl or AWS console/CLI
Attach policyAttach policy to roleaws iam attach-role-policy
Annotate SvcAcctLink K8s service account to roleeksctl or kubectl annotate
Install controllerUse that service accountHelm

Helpful Links


Subscribe
Notify of
guest
0 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments

Certification Courses

DevOpsSchool has introduced a series of professional certification courses designed to enhance your skills and expertise in cutting-edge technologies and methodologies. Whether you are aiming to excel in development, security, or operations, these certifications provide a comprehensive learning experience. Explore the following programs:

DevOps Certification, SRE Certification, and DevSecOps Certification by DevOpsSchool

Explore our DevOps Certification, SRE Certification, and DevSecOps Certification programs at DevOpsSchool. Gain the expertise needed to excel in your career with hands-on training and globally recognized certifications.

0
Would love your thoughts, please comment.x
()
x