Introduction

The AWS Load Balancer Controller creates ALBs and NLBs for Kubernetes Ingress and Service resources. When the controller fails to provision load balancers, services remain pending and applications are unreachable from outside the cluster.

Symptoms

Ingress not getting address:

```bash $ kubectl get ingress my-ingress

NAME CLASS HOSTS ADDRESS PORTS AGE my-ingress alb * 80 10m # ADDRESS field remains empty ```

Service pending:

```bash $ kubectl get svc my-service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-service LoadBalancer 10.100.100.10 <pending> 80:30000/TCP 10m ```

Controller logs showing errors:

```bash $ kubectl logs -n kube-system deployment/aws-load-balancer-controller

E0115 10:00:00.000000 controller.go:123] "msg"="failed to create load balancer" "error"="AccessDenied: User is not authorized" ```

Common Causes

  1. 1.IAM role not configured - Controller lacks AWS permissions
  2. 2.IRSA not set up - Service account missing IAM role annotation
  3. 3.Subnet tagging missing - Subnets not tagged for auto-discovery
  4. 4.Incorrect annotations - Wrong or missing Ingress annotations
  5. 5.Controller not installed - Helm deployment missing or failed
  6. 6.Cluster name mismatch - Controller using wrong cluster name
  7. 7.VPC configuration issues - Public/private subnet confusion

Step-by-Step Fix

  1. 1.Check logs for specific error messages
  2. 2.Verify configuration settings
  3. 3.Test network connectivity
  4. 4.Review recent changes
  5. 5.Apply corrective action
  6. 6.Verify the fix

Step 1: Check Controller Installation

```bash # Check if controller is running kubectl get deployment -n kube-system aws-load-balancer-controller

# Check pod status kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller

# If not installed, install via Helm helm repo add eks https://aws.github.io/eks-charts helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=my-cluster \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller ```

Step 2: Verify IAM Role (IRSA)

```bash # Check service account annotation kubectl get serviceaccount aws-load-balancer-controller -n kube-system -o yaml

# Should have annotation: # eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/AmazonEKSLoadBalancerControllerRole

# If missing, create service account with annotation kubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: aws-load-balancer-controller namespace: kube-system annotations: eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/AmazonEKSLoadBalancerControllerRole EOF ```

Create IAM role with required policy:

```bash # Create IAM policy document cat > lb-controller-policy.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:CreateServiceLinkedRole", "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeInternetGateways", "ec2:DescribeVpcs", "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", "ec2:DescribeInstances", "ec2:DescribeNetworkInterfaces", "ec2:DescribeTags", "ec2:GetCoipPoolUsage", "ec2:DescribeCoipPools", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeLoadBalancerAttributes", "elasticloadbalancing:DescribeListeners", "elasticloadbalancing:DescribeListenerCertificates", "elasticloadbalancing:DescribeSSLPolicies", "elasticloadbalancing:DescribeRules", "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:DescribeTargetGroupAttributes", "elasticloadbalancing:DescribeTargetHealth", "elasticloadbalancing:DescribeTags", "elasticloadbalancing:CreateLoadBalancer", "elasticloadbalancing:CreateTargetGroup", "elasticloadbalancing:CreateListener", "elasticloadbalancing:DeleteLoadBalancer", "elasticloadbalancing:DeleteTargetGroup", "elasticloadbalancing:DeleteListener", "elasticloadbalancing:ModifyLoadBalancerAttributes", "elasticloadbalancing:ModifyTargetGroup", "elasticloadbalancing:ModifyTargetGroupAttributes", "elasticloadbalancing:RegisterTargets", "elasticloadbalancing:DeregisterTargets", "elasticloadbalancing:SetSecurityGroups", "elasticloadbalancing:SetSubnets", "elasticloadbalancing:SetIpAddressType", "cognito-idp:DescribeUserPoolClient", "acm:ListCertificates", "acm:DescribeCertificate", "waf-regional:GetWebACL", "waf-regional:GetWebACLForResource", "waf-regional:AssociateWebACL", "waf-regional:DisassociateWebACL", "wafv2:GetWebACL", "wafv2:GetWebACLForResource", "wafv2:AssociateWebACL", "wafv2:DisassociateWebACL", "shield:GetSubscriptionState", "shield:DescribeProtection", "shield:CreateProtection", "shield:DeleteProtection" ], "Resource": "*" } ] } EOF

# Create policy aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://lb-controller-policy.json

# Create role with trust policy for IRSA aws iam create-role \ --role-name AmazonEKSLoadBalancerControllerRole \ --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Federated": "arn:aws:iam::ACCOUNT:oidc-provider/OIDC_PROVIDER"}, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": {"StringEquals": {"OIDC_PROVIDER:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"}} }] }'

# Attach policy to role aws iam attach-role-policy \ --role-name AmazonEKSLoadBalancerControllerRole \ --policy-arn arn:aws:iam::ACCOUNT:policy/AWSLoadBalancerControllerIAMPolicy ```

Step 3: Verify Subnet Tagging

```bash # Subnets must be tagged for controller auto-discovery # Get cluster VPC and subnets aws eks describe-cluster --name my-cluster \ --query 'cluster.resourcesVpcConfig.[vpcId,subnetIds]'

# Check subnet tags aws ec2 describe-subnets --subnet-ids subnet-12345 \ --query 'Subnets[*].Tags'

# Required tags: # For public subnets (ALB): # kubernetes.io/role/elb: 1 # For private subnets (internal ALB): # kubernetes.io/role/internal-elb: 1 # Also tag with cluster name: # kubernetes.io/cluster/my-cluster: shared ```

Add missing tags:

```bash # Tag public subnets aws ec2 create-tags --resources subnet-public-1 subnet-public-2 \ --tags Key=kubernetes.io/role/elb,Value=1 Key=kubernetes.io/cluster/my-cluster,Value=shared

# Tag private subnets aws ec2 create-tags --resources subnet-private-1 subnet-private-2 \ --tags Key=kubernetes.io/role/internal-elb,Value=1 Key=kubernetes.io/cluster/my-cluster,Value=shared ```

Step 4: Check Ingress Annotations

```bash # Required annotations for ALB Ingress kubectl get ingress my-ingress -o yaml

# Minimum annotations: # kubernetes.io/ingress.class: alb # alb.ingress.kubernetes.io/scheme: internet-facing # or internal # alb.ingress.kubernetes.io/target-type: ip # or instance ```

Example Ingress with correct annotations:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/healthcheck-path: /health
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

Step 5: Check Service Annotations (NLB)

```bash # For NLB services, use specific annotations kubectl get svc my-service -o yaml

# Required annotations for NLB: # 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 ```

Example NLB Service:

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-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
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: my-app

Step 6: Check Controller Logs

```bash # View controller logs for errors kubectl logs -n kube-system deployment/aws-load-balancer-controller --tail=100

# Common errors: # - AccessDenied: IAM permissions issue # - SubnetNotFound: Subnet tagging issue # - InvalidConfiguration: Annotation error # - ResourceNotFound: Target group or security group issue

# Enable debug logging kubectl set env deployment/aws-load-balancer-controller -n kube-system LOG_LEVEL=debug ```

Step 7: Verify Cluster Name Configuration

```bash # Check controller cluster name matches actual cluster kubectl get deployment -n kube-system aws-load-balancer-controller \ -o jsonpath='{.spec.template.spec.containers[0].args}'

# Should include: --cluster-name=my-cluster

# If mismatch, update Helm values helm upgrade aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=my-cluster ```

Step 8: Check Security Groups

```bash # For ALB, controller creates security group # For NLB, uses node security group

# Check if security group allows traffic aws ec2 describe-security-groups \ --filters Name=tag:kubernetes.io/cluster/my-cluster,Values=owned \ --query 'SecurityGroups[*].[GroupId,IpPermissions]'

# Ensure port 80/443 allowed from appropriate sources ```

Step 9: Test with Simple Deployment

```bash # Deploy test application kubectl apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: nginx-test spec: replicas: 2 selector: matchLabels: app: nginx-test template: metadata: labels: app: nginx-test spec: containers: - name: nginx image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-test spec: ports: - port: 80 targetPort: 80 selector: app: nginx-test --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-test annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: nginx-test port: number: 80 EOF

# Wait for ALB provisioning (takes 1-2 minutes) kubectl get ingress nginx-test -w ```

Step 10: Common Error Resolution

ErrorCauseFix
AccessDeniedIAM permissionsAttach required policy
No subnets foundMissing tagsTag subnets correctly
TargetGroupNotFoundController timingWait or restart controller
CertificateNotFoundACM issueVerify ACM certificate
SecurityGroupLimitExceededAWS quotaRequest limit increase

Verification

```bash # Check ingress gets address kubectl get ingress my-ingress

# Should show ADDRESS after 1-2 minutes NAME CLASS HOSTS ADDRESS PORTS AGE my-ingress alb * k8s-mycluster-myingr-abc123.region.elb.amazonaws.com 80 2m

# Test access curl http://k8s-mycluster-myingr-abc123.region.elb.amazonaws.com

# Check ALB in AWS console aws elbv2 describe-load-balancers \ --query 'LoadBalancers[?contains(LoadBalancerName, k8s)]' ```

  • [Fix AWS EKS Node Not Joining](/articles/fix-aws-eks-node-not-joining)
  • [Fix AWS EKS Cluster Autoscaler Not Scaling](/articles/fix-aws-eks-cluster-autoscaler-not-scaling)
  • [Fix AWS ELB Health Check Failing](/articles/fix-aws-elb-health-check-failing)
  • [AWS troubleshooting: Fix IAM Permission Denied - Complete Tro](fix-iam-permission-denied)
  • [AWS cloud troubleshooting: AWS ACM Certificate Pending Validation Because the](aws-acm-certificate-pending-validation-wrong-route53-zone)
  • [AWS cloud troubleshooting: AWS ALB Returns 502 Because the Target Closed the ](aws-alb-502-target-closed-connection-keepalive-timeout-mismatch)
  • [AWS cloud troubleshooting: Fix AWS ALB CreateListener TargetGroupNotFound Err](aws-alb-createlistener-targetgroupnotfound)
  • [AWS cloud troubleshooting: Fix Aws Alb Lambda 502 Bad Gateway Issue in AWS](aws-alb-lambda-502-bad-gateway)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix AWS EKS Load Balancer Controller Failed", "description": "Troubleshoot EKS Load Balancer Controller failures. Fix IAM roles, service annotations, and subnet tagging for ALB/NLB provisioning.", "url": "https://www.fixwikihub.com/fix-aws-eks-load-balancer-controller-failed", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-01T23:13:21.305Z", "dateModified": "2026-04-01T23:13:21.305Z" } </script>