{"id":49894,"date":"2025-07-01T01:54:58","date_gmt":"2025-07-01T01:54:58","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=49894"},"modified":"2025-07-01T02:11:51","modified_gmt":"2025-07-01T02:11:51","slug":"aws-load-balancer-controller-for-kubernetes-a-comprehensive-guide","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/aws-load-balancer-controller-for-kubernetes-a-comprehensive-guide\/","title":{"rendered":"AWS Load Balancer Controller for Kubernetes: A Comprehensive Guide"},"content":{"rendered":"\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"understanding-the-aws-load-balancer-controller\">Understanding the AWS Load Balancer Controller<\/h2>\n\n\n\n<p>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.<\/p>\n\n\n\n<p><strong>Key Components:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Application Load Balancer (ALB)<\/strong>: Layer 7 load balancer for HTTP\/HTTPS traffic with advanced routing capabilities<\/li>\n\n\n\n<li><strong>Network Load Balancer (NLB)<\/strong>: Layer 4 load balancer for high-performance TCP\/UDP traffic<\/li>\n\n\n\n<li><strong>Target Groups<\/strong>: AWS resources that route requests to registered targets<\/li>\n\n\n\n<li><strong>Listeners<\/strong>: Components that check for connection requests on specified ports<\/li>\n\n\n\n<li><strong>Rules<\/strong>: Define how traffic is routed based on conditions<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-it-works\">How It Works<\/h2>\n\n\n\n<p>The controller follows a specific workflow when managing load balancers:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Monitoring<\/strong>: The controller watches for Ingress and Service events from the Kubernetes API server<\/li>\n\n\n\n<li><strong>Resource Creation<\/strong>: When it finds resources that satisfy its requirements, it begins creating AWS resources<\/li>\n\n\n\n<li><strong>Load Balancer Provisioning<\/strong>: An ALB or NLB is created in AWS based on the resource type and annotations<\/li>\n\n\n\n<li><strong>Target Group Management<\/strong>: Target groups are created for each unique Kubernetes service<\/li>\n\n\n\n<li><strong>Listener Configuration<\/strong>: Listeners are created for specified ports with appropriate certificates<\/li>\n\n\n\n<li><strong>Rule Creation<\/strong>: Rules are established for path-based routing to correct services<\/li>\n<\/ol>\n\n\n\n<p>The controller supports two traffic modes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Instance Mode<\/strong>: Traffic flows from ALB to Kubernetes nodes via NodePort services<\/li>\n\n\n\n<li><strong>IP Mode<\/strong>: Traffic flows directly from ALB to Kubernetes pods (requires compatible CNI)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"prerequisites-and-setup-requirements\">Prerequisites and Setup Requirements<\/h2>\n\n\n\n<p>Before installing the AWS Load Balancer Controller, ensure you have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>AWS CLI v2.18.10 or higher<\/li>\n\n\n\n<li>eksctl v0.193.0 or higher<\/li>\n\n\n\n<li>EKS Cluster v1.30 or higher<\/li>\n\n\n\n<li>Pod Identity Agent v1.3.2-eksbuild.2 or higher<\/li>\n\n\n\n<li>Amazon VPC CNI plugin<\/li>\n\n\n\n<li>kubectl v1.31 or higher<\/li>\n\n\n\n<li>Helm v3.16.2 or higher<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Sequence for Installing AWS Load Balancer Controller with Best Practices<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. OIDC Identity Provider<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Enables secure trust between Kubernetes service accounts and AWS IAM roles.<\/li>\n\n\n\n<li>Needed so you can use <strong>IRSA<\/strong> (IAM Roles for Service Accounts).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. IAM Policy<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Write or download the official AWS Load Balancer Controller policy (JSON file).<\/li>\n\n\n\n<li>This policy defines <em>what<\/em> permissions the controller gets (e.g., create\/manage load balancers, security groups, etc.).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. IAM Role<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create an IAM role with the <strong>trust policy<\/strong> for the OIDC provider (so only your specific K8s service account can assume it).<\/li>\n\n\n\n<li>Attach the policy from step 2 to this role.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Kubernetes Service Account (linked to IAM Role)<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create (or update) a Kubernetes service account (e.g., <code>aws-load-balancer-controller<\/code> in <code>kube-system<\/code> namespace).<\/li>\n\n\n\n<li>Annotate this service account with the <strong>IAM Role ARN<\/strong> from step 3.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. Install AWS Load Balancer Controller<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install via Helm (recommended), specifying that it should use your service account.<\/li>\n\n\n\n<li>Controller pods will automatically assume the right IAM role, get temporary AWS credentials, and have the required permissions.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"iam-permissions-configuration\">IAM Permissions Configuration<\/h2>\n\n\n\n<p>The controller requires specific IAM permissions to manage AWS resources. You have two options for configuring these permissions:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Option A: IAM Roles for Service Accounts (IRSA) &#8211; Recommended<\/h2>\n\n\n\n<p>First, create an IAM OIDC provider for your cluster:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>eksctl utils associate-iam-oidc-provider \\<br>  --region &lt;region-code&gt; \\<br>  --cluster &lt;your-cluster-name&gt; \\<br>  --approve<br><\/code><\/pre>\n\n\n\n<p>Download the appropriate IAM policy based on your region:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code><em># For standard AWS regions<\/em>\ncurl -o iam-policy.json https:\/\/raw.githubusercontent.com\/kubernetes-sigs\/aws-load-balancer-controller\/v2.13.2\/docs\/install\/iam_policy.json\n\n<em># For US Gov Cloud regions<\/em>\ncurl -o iam-policy.json https:\/\/raw.githubusercontent.com\/kubernetes-sigs\/aws-load-balancer-controller\/v2.13.2\/docs\/install\/iam_policy_us-gov.json\n\n<em># For China regions<\/em>\ncurl -o iam-policy.json https:\/\/raw.githubusercontent.com\/kubernetes-sigs\/aws-load-balancer-controller\/v2.13.2\/docs\/install\/iam_policy_cn.json\n<\/code><\/pre>\n\n\n\n<p>Create the IAM policy:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>aws iam create-policy \\\n  --policy-name AWSLoadBalancerControllerIAMPolicy \\\n  --policy-document file:\/\/iam-policy.json\n<\/code><\/pre>\n\n\n\n<p>Create the IAM role and service account:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>eksctl create iamserviceaccount \\<br>  --cluster=&lt;cluster-name&gt; \\<br>  --namespace=kube-system \\<br>  --name=aws-load-balancer-controller \\<br>  --attach-policy-arn=arn:aws:iam::&lt;AWS_ACCOUNT_ID&gt;:policy\/AWSLoadBalancerControllerIAMPolicy \\<br>  --override-existing-serviceaccounts \\<br>  --region &lt;region-code&gt; \\<br>  --approve<br><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Option B: Attach IAM Policies to Worker Nodes<\/h2>\n\n\n\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"installation-methods\">Installation Methods<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Method 1: Helm Installation (Recommended)<\/h2>\n\n\n\n<p>Add the EKS Helm repository:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>helm repo add eks https:\/\/aws.github.io\/eks-charts\nhelm repo update eks\n<\/code><\/pre>\n\n\n\n<p>Install the controller:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>helm install aws-load-balancer-controller eks\/aws-load-balancer-controller \\\n  -n kube-system \\\n  --set clusterName=&lt;cluster-name&gt; \\\n  --set serviceAccount.create=false \\\n  --set serviceAccount.name=aws-load-balancer-controller \\\n  --version 1.13.0\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Method 2: YAML Manifests<\/h2>\n\n\n\n<p>Install cert-manager first:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>kubectl apply --validate=false -f https:\/\/github.com\/cert-manager\/cert-manager\/releases\/download\/v1.12.3\/cert-manager.yaml\n<\/code><\/pre>\n\n\n\n<p>Download and apply the controller manifest:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>wget https:\/\/github.com\/kubernetes-sigs\/aws-load-balancer-controller\/releases\/download\/v2.13.2\/v2_13_2_full.yaml\n<\/code><\/pre>\n\n\n\n<p>Edit the YAML file to set your cluster name:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: aws-load-balancer-controller\n  namespace: kube-system\nspec:\n  template:\n    spec:\n      containers:\n        - args:\n            - --cluster-name=&lt;your-cluster-name&gt;\n<\/code><\/pre>\n\n\n\n<p>Apply the manifest:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>kubectl apply -f v2_13_2_full.yaml\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"verification-and-troubleshooting\">Verification and Troubleshooting<\/h2>\n\n\n\n<p>Verify the installation:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>kubectl get deployment -n kube-system aws-load-balancer-controller\nkubectl get pods -n kube-system -l app.kubernetes.io\/name=aws-load-balancer-controller\n<\/code><\/pre>\n\n\n\n<p>Check the controller version:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>kubectl get deploy aws-load-balancer-controller -n=kube-system -o yaml | grep image:\n<\/code><\/pre>\n\n\n\n<p>Verify Custom Resource Definitions:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code>kubectl get crds | grep -iE \"elbv2\"\nkubectl get ingressclass\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"configuring-application-load-balancer-alb-with-ing\">Configuring Application Load Balancer (ALB) with Ingress<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Basic ALB Ingress Configuration<\/h2>\n\n\n\n<p>Create a basic Ingress resource for ALB:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: example-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/load-balancer-name: example-alb\nspec:\n  ingressClassName: alb\n  rules:\n    - host: example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: example-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Advanced ALB Configuration with Multiple Services<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: multi-service-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/healthcheck-path: \/health\n    alb.ingress.kubernetes.io\/healthcheck-interval-seconds: '30'\n    alb.ingress.kubernetes.io\/healthcheck-timeout-seconds: '5'\n    alb.ingress.kubernetes.io\/healthy-threshold-count: '2'\n    alb.ingress.kubernetes.io\/unhealthy-threshold-count: '3'\nspec:\n  ingressClassName: alb\n  rules:\n    - host: api.example.com\n      http:\n        paths:\n          - path: \/api\/v1\n            pathType: Prefix\n            backend:\n              service:\n                name: api-service\n                port:\n                  number: 8080\n          - path: \/api\/v2\n            pathType: Prefix\n            backend:\n              service:\n                name: api-v2-service\n                port:\n                  number: 8080\n    - host: web.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: web-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"configuring-network-load-balancer-nlb-with-service\">Configuring Network Load Balancer (NLB) with Services<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Basic NLB Service Configuration<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: v1\nkind: Service\nmetadata:\n  name: nlb-service\n  annotations:\n    service.beta.kubernetes.io\/aws-load-balancer-type: external\n    service.beta.kubernetes.io\/aws-load-balancer-nlb-target-type: ip\n    service.beta.kubernetes.io\/aws-load-balancer-scheme: internet-facing\nspec:\n  type: LoadBalancer\n  selector:\n    app: example-app\n  ports:\n    - port: 80\n      targetPort: 8080\n      protocol: TCP\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Advanced NLB Configuration with Security Groups<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: v1\nkind: Service\nmetadata:\n  name: advanced-nlb-service\n  annotations:\n    service.beta.kubernetes.io\/aws-load-balancer-type: external\n    service.beta.kubernetes.io\/aws-load-balancer-nlb-target-type: ip\n    service.beta.kubernetes.io\/aws-load-balancer-scheme: internet-facing\n    service.beta.kubernetes.io\/aws-load-balancer-security-groups: sg-12345678\n    service.beta.kubernetes.io\/aws-load-balancer-backend-protocol: tcp\n    service.beta.kubernetes.io\/aws-load-balancer-healthcheck-healthy-threshold: '2'\n    service.beta.kubernetes.io\/aws-load-balancer-healthcheck-interval: '10'\n    service.beta.kubernetes.io\/aws-load-balancer-healthcheck-unhealthy-threshold: '2'\n    service.beta.kubernetes.io\/aws-load-balancer-target-group-attributes: preserve_client_ip.enabled=true\nspec:\n  type: LoadBalancer\n  selector:\n    app: example-app\n  ports:\n    - port: 443\n      targetPort: 8443\n      protocol: TCP\n      name: https\n    - port: 80\n      targetPort: 8080\n      protocol: TCP\n      name: http\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sslhttps-configuration\">SSL\/HTTPS Configuration<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">SSL Termination at ALB<\/h2>\n\n\n\n<p>Configure HTTPS with SSL certificates:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: https-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/listen-ports: '[{\"HTTP\": 80}, {\"HTTPS\": 443}]'\n    alb.ingress.kubernetes.io\/certificate-arn: arn:aws:acm:region:account:certificate\/cert-id\n    alb.ingress.kubernetes.io\/ssl-redirect: '443'\nspec:\n  ingressClassName: alb\n  rules:\n    - host: secure.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: secure-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Multiple SSL Certificates<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: multi-cert-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/listen-ports: '[{\"HTTPS\": 443}]'\n    alb.ingress.kubernetes.io\/certificate-arn: |\n      arn:aws:acm:region:account:certificate\/cert-id-1,\n      arn:aws:acm:region:account:certificate\/cert-id-2\nspec:\n  ingressClassName: alb\n  rules:\n    - host: app1.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: app1-service\n                port:\n                  number: 80\n    - host: app2.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: app2-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"dns-configuration-with-route-53\">DNS Configuration with Route 53<\/h2>\n\n\n\n<p>To configure DNS routing to your load balancer, create Route 53 alias records:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Create an Alias Record<\/strong>: In Route 53, create an alias record that points to your ALB or NLB<\/li>\n\n\n\n<li><strong>Configure the Record<\/strong>: Set the record type to A (for IPv4) or AAAA (for IPv6)<\/li>\n\n\n\n<li><strong>Select the Load Balancer<\/strong>: Choose your load balancer from the dropdown list<\/li>\n\n\n\n<li><strong>Set Routing Policy<\/strong>: Configure appropriate routing policies (simple, weighted, latency-based, etc.)<\/li>\n<\/ol>\n\n\n\n<p>Example Route 53 configuration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Record Name<\/strong>: api.example.com<\/li>\n\n\n\n<li><strong>Record Type<\/strong>: A &#8211; IPv4 address<\/li>\n\n\n\n<li><strong>Alias<\/strong>: Yes<\/li>\n\n\n\n<li><strong>Route Traffic To<\/strong>: Alias to Application Load Balancer<\/li>\n\n\n\n<li><strong>Region<\/strong>: Your ALB region<\/li>\n\n\n\n<li><strong>Load Balancer<\/strong>: Select your ALB from the list<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"advanced-routing-and-traffic-management\">Advanced Routing and Traffic Management<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Weighted Routing for Blue\/Green Deployments<\/h2>\n\n\n\n<p>The AWS Load Balancer Controller supports advanced traffic splitting for blue\/green deployments:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: blue-green-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/actions.weighted-routing: |\n      {\n        \"type\": \"forward\",\n        \"forwardConfig\": {\n          \"targetGroups\": [\n            {\n              \"serviceName\": \"blue-service\",\n              \"servicePort\": 80,\n              \"weight\": 80\n            },\n            {\n              \"serviceName\": \"green-service\", \n              \"servicePort\": 80,\n              \"weight\": 20\n            }\n          ]\n        }\n      }\nspec:\n  ingressClassName: alb\n  rules:\n    - host: app.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: weighted-routing\n                port:\n                  name: use-annotation\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Header-Based Routing<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: header-routing-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/conditions.api-v1: |\n      [{\"field\":\"http-header\",\"httpHeaderConfig\":{\"httpHeaderName\":\"X-API-Version\",\"values\":[\"v1\"]}}]\n    alb.ingress.kubernetes.io\/conditions.api-v2: |\n      [{\"field\":\"http-header\",\"httpHeaderConfig\":{\"httpHeaderName\":\"X-API-Version\",\"values\":[\"v2\"]}}]\nspec:\n  ingressClassName: alb\n  rules:\n    - host: api.example.com\n      http:\n        paths:\n          - path: \/api\n            pathType: Prefix\n            backend:\n              service:\n                name: api-v1\n                port:\n                  number: 80\n          - path: \/api\n            pathType: Prefix\n            backend:\n              service:\n                name: api-v2\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"target-group-bindings\">Target Group Bindings<\/h2>\n\n\n\n<p>Target Group Binding allows you to expose pods using existing ALB or NLB target groups:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: elbv2.k8s.aws\/v1beta1\nkind: TargetGroupBinding\nmetadata:\n  name: example-tgb\n  namespace: default\nspec:\n  serviceRef:\n    name: example-service\n    port: 80\n  targetGroupARN: arn:aws:elasticloadbalancing:region:account:targetgroup\/example-tg\/1234567890abcdef\n  targetType: ip\n  nodeSelector:\n    matchLabels:\n      kubernetes.io\/arch: amd64\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"security-best-practices\">Security Best Practices<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Security Group Management<\/h2>\n\n\n\n<p>The controller supports both frontend and backend security groups:<\/p>\n\n\n\n<p><strong>Frontend Security Groups<\/strong> control access to load balancers:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: secure-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/security-groups: sg-frontend-12345678\n    alb.ingress.kubernetes.io\/inbound-cidrs: 10.0.0.0\/8,192.168.0.0\/16\nspec:\n  ingressClassName: alb\n  rules:\n    - host: secure.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: secure-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<p><strong>Backend Security Groups<\/strong> control load balancer to target communication:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: v1\nkind: Service\nmetadata:\n  name: secure-nlb-service\n  annotations:\n    service.beta.kubernetes.io\/aws-load-balancer-type: external\n    service.beta.kubernetes.io\/aws-load-balancer-nlb-target-type: ip\n    service.beta.kubernetes.io\/aws-load-balancer-security-groups: sg-backend-87654321\nspec:\n  type: LoadBalancer\n  selector:\n    app: secure-app\n  ports:\n    - port: 443\n      targetPort: 8443\n      protocol: TCP\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">WAF Integration<\/h2>\n\n\n\n<p>Integrate AWS WAF with ALB for additional security:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: waf-protected-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/wafv2-acl-arn: arn:aws:wafv2:region:account:regional\/webacl\/example-waf\/12345678-1234-1234-1234-123456789012\nspec:\n  ingressClassName: alb\n  rules:\n    - host: protected.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: protected-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"monitoring-and-logging\">Monitoring and Logging<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Access Logs Configuration<\/h2>\n\n\n\n<p>Enable ALB access logs for monitoring and troubleshooting:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: logged-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/load-balancer-attributes: |\n      access_logs.s3.enabled=true,\n      access_logs.s3.bucket=my-access-logs-bucket,\n      access_logs.s3.prefix=alb-logs\nspec:\n  ingressClassName: alb\n  rules:\n    - host: monitored.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: monitored-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">CloudWatch Metrics<\/h2>\n\n\n\n<p>Monitor key metrics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>RequestCount<\/strong>: Number of requests processed<\/li>\n\n\n\n<li><strong>TargetResponseTime<\/strong>: Response time from targets<\/li>\n\n\n\n<li><strong>HTTPCode_Target_2XX_Count<\/strong>: Successful responses<\/li>\n\n\n\n<li><strong>HTTPCode_Target_4XX_Count<\/strong>: Client errors<\/li>\n\n\n\n<li><strong>HTTPCode_Target_5XX_Count<\/strong>: Server errors<\/li>\n\n\n\n<li><strong>HealthyHostCount<\/strong>: Number of healthy targets<\/li>\n\n\n\n<li><strong>UnHealthyHostCount<\/strong>: Number of unhealthy targets<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"managing-multiple-load-balancers\">Managing Multiple Load Balancers<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">IngressClass Parameters<\/h2>\n\n\n\n<p>Create custom IngressClass configurations for different environments:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: elbv2.k8s.aws\/v1beta1\nkind: IngressClassParams\nmetadata:\n  name: dev-class-params\nspec:\n  namespaceSelector:\n    matchLabels:\n      kubernetes.io\/metadata.name: dev\n  scheme: internet-facing\n  ipAddressType: ipv4\n  loadBalancerAttributes:\n    - key: deletion_protection.enabled\n      value: \"true\"\n    - key: idle_timeout.timeout_seconds\n      value: \"120\"\n---\napiVersion: networking.k8s.io\/v1\nkind: IngressClass\nmetadata:\n  name: dev-alb\nspec:\n  controller: ingress.k8s.aws\/alb\n  parameters:\n    apiGroup: elbv2.k8s.aws\n    kind: IngressClassParams\n    name: dev-class-params\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Ingress Grouping<\/h2>\n\n\n\n<p>Group multiple Ingress resources to share a single ALB:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: app1-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/group.name: shared-alb\n    alb.ingress.kubernetes.io\/group.order: '10'\nspec:\n  ingressClassName: alb\n  rules:\n    - host: app1.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: app1-service\n                port:\n                  number: 80\n---\napiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: app2-ingress\n  annotations:\n    alb.ingress.kubernetes.io\/group.name: shared-alb\n    alb.ingress.kubernetes.io\/group.order: '20'\nspec:\n  ingressClassName: alb\n  rules:\n    - host: app2.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: app2-service\n                port:\n                  number: 80\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"troubleshooting-guide\">Troubleshooting Guide<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Common Issues and Solutions<\/h2>\n\n\n\n<p><strong>1. Controller Not Installing<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify IAM permissions are correctly configured<\/li>\n\n\n\n<li>Check that OIDC provider is associated with the cluster<\/li>\n\n\n\n<li>Ensure service account has proper annotations<\/li>\n<\/ul>\n\n\n\n<p><strong>2. Load Balancer Not Created<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Check controller logs: <code>kubectl logs -n kube-system deployment\/aws-load-balancer-controller<\/code><\/li>\n\n\n\n<li>Verify subnet tags are correct<\/li>\n\n\n\n<li>Ensure security groups allow necessary traffic<\/li>\n<\/ul>\n\n\n\n<p><strong>3. Health Check Failures<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify health check path is accessible<\/li>\n\n\n\n<li>Check target group health check configuration<\/li>\n\n\n\n<li>Ensure pods are running and ready<\/li>\n<\/ul>\n\n\n\n<p><strong>4. SSL Certificate Issues<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify certificate ARN is correct and in the same region<\/li>\n\n\n\n<li>Check certificate validation status in ACM<\/li>\n\n\n\n<li>Ensure certificate covers all hostnames<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Debugging Commands<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">bash<code><em># Check controller status<\/em>\nkubectl get deployment -n kube-system aws-load-balancer-controller\n\n<em># View controller logs<\/em>\nkubectl logs -n kube-system deployment\/aws-load-balancer-controller\n\n<em># Check Ingress status<\/em>\nkubectl describe ingress &lt;ingress-name&gt;\n\n<em># View target group bindings<\/em>\nkubectl get targetgroupbindings -n &lt;namespace&gt; -o wide\n\n<em># Check service annotations<\/em>\nkubectl describe service &lt;service-name&gt;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Version Compatibility<\/h2>\n\n\n\n<p>Always use the latest compatible version of the controller. Check the compatibility matrix:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>EKS 1.21+ requires AWS Load Balancer Controller 2.4.x+<\/li>\n\n\n\n<li>Kubernetes 1.22+ requires controller versions that support <code>networking.k8s.io\/v1<\/code> API<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"real-world-use-cases\">Real-World Use Cases<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">E-commerce Platform<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code># Frontend ALB for web traffic\napiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: ecommerce-web\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/certificate-arn: arn:aws:acm:region:account:certificate\/web-cert\n    alb.ingress.kubernetes.io\/listen-ports: '[{\"HTTPS\": 443}]'\n    alb.ingress.kubernetes.io\/ssl-redirect: '443'\n    alb.ingress.kubernetes.io\/wafv2-acl-arn: arn:aws:wafv2:region:account:regional\/webacl\/ecommerce-waf\/12345\nspec:\n  ingressClassName: alb\n  rules:\n    - host: shop.example.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: frontend-service\n                port:\n                  number: 80\n          - path: \/api\n            pathType: Prefix\n            backend:\n              service:\n                name: api-service\n                port:\n                  number: 8080\n---\n# Internal NLB for database connections\napiVersion: v1\nkind: Service\nmetadata:\n  name: database-nlb\n  annotations:\n    service.beta.kubernetes.io\/aws-load-balancer-type: external\n    service.beta.kubernetes.io\/aws-load-balancer-nlb-target-type: ip\n    service.beta.kubernetes.io\/aws-load-balancer-scheme: internal\n    service.beta.kubernetes.io\/aws-load-balancer-security-groups: sg-database-access\nspec:\n  type: LoadBalancer\n  selector:\n    app: database-proxy\n  ports:\n    - port: 5432\n      targetPort: 5432\n      protocol: TCP\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Microservices Architecture<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code># API Gateway ALB with path-based routing\napiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: microservices-gateway\n  annotations:\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/target-type: ip\n    alb.ingress.kubernetes.io\/healthcheck-path: \/health\n    alb.ingress.kubernetes.io\/load-balancer-attributes: |\n      routing.http2.enabled=true,\n      idle_timeout.timeout_seconds=60\nspec:\n  ingressClassName: alb\n  rules:\n    - host: api.company.com\n      http:\n        paths:\n          - path: \/users\n            pathType: Prefix\n            backend:\n              service:\n                name: user-service\n                port:\n                  number: 8080\n          - path: \/orders\n            pathType: Prefix\n            backend:\n              service:\n                name: order-service\n                port:\n                  number: 8080\n          - path: \/payments\n            pathType: Prefix\n            backend:\n              service:\n                name: payment-service\n                port:\n                  number: 8080\n          - path: \/inventory\n            pathType: Prefix\n            backend:\n              service:\n                name: inventory-service\n                port:\n                  number: 8080\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"summary\">Summary<\/h2>\n\n\n\n<p>The AWS Load Balancer Controller provides a powerful, native way to manage load balancers in Amazon EKS. Key benefits include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Automatic Management<\/strong>: Automatically provisions and configures AWS load balancers based on Kubernetes resources<\/li>\n\n\n\n<li><strong>Advanced Features<\/strong>: Supports SSL termination, WAF integration, and advanced routing capabilities<\/li>\n\n\n\n<li><strong>Cost Optimization<\/strong>: Enables sharing of load balancers across multiple services<\/li>\n\n\n\n<li><strong>Security<\/strong>: Provides fine-grained security group management and integration with AWS security services<\/li>\n\n\n\n<li><strong>Monitoring<\/strong>: Integrates with CloudWatch for comprehensive monitoring and logging<\/li>\n<\/ul>\n\n\n\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"frequently-asked-questions\">Frequently Asked Questions<\/h2>\n\n\n\n<p><strong>Q: Can the AWS Load Balancer Controller work with Classic Load Balancers?<\/strong><br>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.<\/p>\n\n\n\n<p><strong>Q: How do I migrate from the ALB Ingress Controller to the AWS Load Balancer Controller?<\/strong><br>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.<\/p>\n\n\n\n<p><strong>Q: Can I use the same load balancer for multiple Ingress resources?<\/strong><br>A: Yes, use the <code>alb.ingress.kubernetes.io\/group.name<\/code> annotation to group multiple Ingress resources that should share the same ALB.<\/p>\n\n\n\n<p><strong>Q: What&#8217;s the difference between Instance mode and IP mode?<\/strong><br>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.<\/p>\n\n\n\n<p><strong>Q: How do I handle SSL certificates?<\/strong><br>A: Use AWS Certificate Manager (ACM) to provision certificates and reference them in your Ingress annotations using the <code>alb.ingress.kubernetes.io\/certificate-arn<\/code> annotation.<\/p>\n\n\n\n<p><strong>Q: Can I use the controller with private subnets?<\/strong><br>A: Yes, set the scheme to <code>internal<\/code> using the <code>alb.ingress.kubernetes.io\/scheme: internal<\/code> annotation for internal load balancers.<\/p>\n\n\n\n<p><strong>Q: How do I troubleshoot load balancer creation issues?<\/strong><br>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.<\/p>\n\n\n\n<p><strong>Q: What happens to my load balancers if I delete the Ingress resource?<\/strong><br>A: The controller automatically deletes the associated AWS load balancer resources when you delete the corresponding Kubernetes Ingress or Service resource.<\/p>\n\n\n\n<p>Absolutely! <strong>IAM Roles for Service Accounts (IRSA)<\/strong> is the AWS-recommended way to securely give Kubernetes pods permissions to call AWS APIs\u2014<em>without<\/em> using long-lived static credentials.<\/p>\n\n\n\n<p>C<strong>reating an IAM policy, an IAM role, and connecting it to your EKS service account using IRSA<\/strong> for the AWS Load Balancer Controller.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1. Why Do This?<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The AWS Load Balancer Controller running inside your EKS cluster needs AWS permissions to create ALBs\/NLBs, manage security groups, etc.<\/li>\n\n\n\n<li>Using IRSA, we \u201clink\u201d a Kubernetes service account with an IAM role that has the needed permissions.<\/li>\n\n\n\n<li><strong>Result:<\/strong> The controller pod automatically gets temporary AWS credentials for that IAM role.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2. Steps Overview<\/strong><\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Create an IAM Policy<\/strong> (permissions for the controller)<\/li>\n\n\n\n<li><strong>Create an IAM Role with a trust policy for EKS<\/strong><\/li>\n\n\n\n<li><strong>Create a Kubernetes Service Account and annotate it with the IAM role ARN<\/strong><\/li>\n\n\n\n<li><strong>Install the AWS Load Balancer Controller using that service account<\/strong><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3. Step-by-Step Guide<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>A. Create the IAM Policy<\/strong><\/h3>\n\n\n\n<p>Save this policy to a file (e.g., <code>aws-load-balancer-controller-policy.json<\/code>).<br>(You can copy the policy from <a href=\"https:\/\/raw.githubusercontent.com\/kubernetes-sigs\/aws-load-balancer-controller\/main\/docs\/install\/iam_policy.json\" target=\"_blank\" rel=\"noopener\">here in AWS docs<\/a> or use the one in the previous answer.)<\/p>\n\n\n\n<p><strong>Command:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">aws iam create-policy \\\n  --policy-name AWSLoadBalancerControllerIAMPolicy \\\n  --policy-<span class=\"hljs-built_in\">document<\/span> file:<span class=\"hljs-comment\">\/\/aws-load-balancer-controller-policy.json<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><em>Copy the Policy ARN from the output (e.g., <code>arn:aws:iam::123456789012:policy\/AWSLoadBalancerControllerIAMPolicy<\/code>).<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>B. Create an IAM Role for Service Account (using eksctl is easiest)<\/strong><\/h3>\n\n\n\n<p><strong>Recommended:<\/strong> Use <a href=\"https:\/\/eksctl.io\/\" target=\"_blank\" rel=\"noopener\"><code>eksctl<\/code><\/a>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">eksctl create iamserviceaccount \\\n  --cluster <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">your-cluster-name<\/span>&gt;<\/span> \\\n  --namespace kube-system \\\n  --name aws-load-balancer-controller \\\n  --attach-policy-arn arn:aws:iam::<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">your-account-id<\/span>&gt;<\/span>:policy\/AWSLoadBalancerControllerIAMPolicy \\\n  --approve\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li><code>--namespace kube-system<\/code> is where you\u2019ll install the controller (can be different if you use a separate namespace).<\/li>\n\n\n\n<li>This will <strong>create an IAM role<\/strong> and a Kubernetes service account named <code>aws-load-balancer-controller<\/code> in the <code>kube-system<\/code> namespace, annotated to use that role.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Don\u2019t want to use <code>eksctl<\/code>?<\/strong><\/h4>\n\n\n\n<p>Do it manually:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Create IAM role<\/strong> with this trust policy (replace <code>&lt;OIDC_PROVIDER_URL&gt;<\/code> and <code>&lt;YOUR_ACCOUNT_ID&gt;<\/code>): <code>{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \"Principal\": { \"Federated\": \"arn:aws:iam::&lt;YOUR_ACCOUNT_ID&gt;:oidc-provider\/&lt;OIDC_PROVIDER_URL&gt;\" }, \"Action\": \"sts:AssumeRoleWithWebIdentity\", \"Condition\": { \"StringEquals\": { \"&lt;OIDC_PROVIDER_URL&gt;:sub\": \"system:serviceaccount:kube-system:aws-load-balancer-controller\" } } } ] }<\/code><\/li>\n\n\n\n<li><strong>Attach the IAM policy<\/strong> from step A to this role.<\/li>\n\n\n\n<li><strong>Annotate your K8s service account:<\/strong> <code>kubectl annotate serviceaccount -n kube-system aws-load-balancer-controller \\ eks.amazonaws.com\/role-arn=arn:aws:iam::&lt;your-account-id&gt;:role\/&lt;your-role-name&gt;<\/code><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>C. Install the AWS Load Balancer Controller Using That Service Account<\/strong><\/h3>\n\n\n\n<p>When you install via Helm, set:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">--<span class=\"hljs-keyword\">set<\/span> serviceAccount.create=false \\\n--<span class=\"hljs-keyword\">set<\/span> serviceAccount.name=aws-load-balancer-controller\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This tells Helm to use your existing, IRSA-enabled service account.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Summary Table<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Step<\/th><th>What You Do<\/th><th>AWS CLI \/ Tool<\/th><\/tr><\/thead><tbody><tr><td>Create policy<\/td><td>Write permissions for controller<\/td><td><code>aws iam create-policy<\/code><\/td><\/tr><tr><td>Create IAM role<\/td><td>Trust OIDC from EKS, allow K8s ServiceAccount<\/td><td><code>eksctl<\/code> or AWS console\/CLI<\/td><\/tr><tr><td>Attach policy<\/td><td>Attach policy to role<\/td><td><code>aws iam attach-role-policy<\/code><\/td><\/tr><tr><td>Annotate SvcAcct<\/td><td>Link K8s service account to role<\/td><td><code>eksctl<\/code> or <code>kubectl annotate<\/code><\/td><\/tr><tr><td>Install controller<\/td><td>Use that service account<\/td><td>Helm<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Helpful Links<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/aws-load-balancer-controller.html\" target=\"_blank\" rel=\"noopener\">Official AWS Docs: IRSA for AWS Load Balancer Controller<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/raw.githubusercontent.com\/kubernetes-sigs\/aws-load-balancer-controller\/main\/docs\/install\/iam_policy.json\" target=\"_blank\" rel=\"noopener\">Full IAM Policy Example<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/enable-iam-roles-for-service-accounts.html\" target=\"_blank\" rel=\"noopener\">EKS OIDC Provider Setup<\/a><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-49894","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49894","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=49894"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49894\/revisions"}],"predecessor-version":[{"id":49898,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49894\/revisions\/49898"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=49894"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=49894"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=49894"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}