TechAnek

When deploying applications on Amazon EKS, many developers prefer to expose using the Application Load Balancer (ALB) due to its robust security features, integrated routing capabilities, and native support for modern web-based applications. ALB stands out with features like path-based routing, SSL termination, and seamless integration with AWS Web Application Firewall (WAF), offering a comprehensive security layer. This makes it a go-to choice for teams seeking tighter security controls and flexible routing configurations. However, a common issue arises when using the LoadBalancer service type on EKS — by default, EKS provisions a Classic Load Balancer (CLB). While CLB might suffice for basic needs, it falls short in comparison to ALB, particularly in terms of security features and integration support. CLB lacks advanced routing features and offers limited capabilities for modern workloads, making it an unsuitable choice for production environments that demand high availability, security, and compliance.

This limitation can be frustrating for developers who want to leverage ALB’s advanced capabilities. The main challenge, then, is how to integrate the superior ALB with an Ingress controller like Nginx on EKS to fully benefit from ALB’s security and performance features. In this post, we will explore how to overcome this challenge by deploying Ingress Nginx with ALB Controller on an EKS cluster.

Prerequisites:

Before starting with AWS Load Balancer Controller, make sure the following components are set up:

  • Existing EKS cluster
  • AWS CLI installed and configured to access EKS
  • Familiarity with AWS Elastic Load Balancing. For more information, see the Elastic Load Balancing User Guide.
  • Familiarity with Kubernetes service and ingress concepts.
  • Make sure that Amazon VPC CNI plugin for Kubernetes, kube-proxy, and CoreDNS add-ons are at the minimum versions listed in Cluster add-ons.

Upon completion of the prerequisites – such as AWS CLI installation and EKS cluster – the next task involves creating and attaching an IAM policy to the EKS node role. This action enables the AWS Load Balancer Controller to interact with AWS APIs and manage Application Load Balancers.

Step 1: Attach IAM Policy to AWS IAM Assume Role

Create an IAM policy:
To allow the AWS Load Balancer Controller to interact with AWS APIs, we first need to create and attach an IAM policy to your EKS node role.

  • Download the IAM policy for the AWS Load Balancer Controller:
				
					curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/docs/install/iam_policy.json

				
			
  • Create the IAM policy:
				
					aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json
				
			
Attach this policy to your EKS node role, granting the controller the necessary permissions to create and manage ALBs.
Step 2: Tag Subnets required ALB Creation

The AWS Load Balancer Controller needs to identify which subnets to use when creating ALBs. To ensure this, tag the subnets with the appropriate key-value pairs.

  • You can use the following script to tag subnets:
				
					for NODEGROUP in $(aws eks list-nodegroups --cluster-name "${CLUSTER_NAME}" --query 'nodegroups' --output text); do
    aws ec2 create-tags \
        --tags "Key=kubernetes.io/role/elb,Value=1" \
        --resources $(aws eks describe-nodegroup --cluster-name "${CLUSTER_NAME}" \
        --nodegroup-name "${NODEGROUP}" --query 'nodegroup.subnets' --output text )
done
				
			
  • Verify the tags on your subnets using the AWS CLI:
				
					aws ec2 describe-subnets --filters "Name=tag:kubernetes.io/role/elb,Values=1"
				
			
Step 3: Installing AWS Load Balancer Controller
Next, install the AWS Load Balancer Controller in your cluster using Helm.
  • Add the Helm chart repository:
				
					helm repo add eks https://aws.github.io/eks-charts
				
			
				
					helm install [RELEASE_NAME] eks/aws-load-balancer-controller \
--namespace alb \
--set clusterName=clusterName \
--set serviceAccount.name=sa-name \
--set ingressClass=ingressClass-name
				
			
Note: If you’re deploying to EC2 nodes with restricted access or to Fargate, also include the following flags:
				
					--set region=region-code \
--set vpcId=vpc-xxxxxxxx
				
			
Step 4: Installing Ingress NGINX Controller
Now, we will install the Ingress NGINX Controller to manage routing inside the cluster.
  • Add the Ingress NGINX Helm chart repository:
				
					helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
				
			
  • Install the Ingress NGINX controller:
				
					helm install [RELEASE_NAME] ingress-nginx/ingress-nginx \
--set controller.service.type=NodePort
				
			
Note: Setting the service type to NodePort is crucial as it enables routing traffic from the ALB to the Ingress NGINX service running on the cluster nodes.
Step 5: Create an Ingress Resource to Set Up ALB

With both controllers (AWS Load Balancer Controller and Ingress NGINX Controller) installed, you can now create an Ingress resource to configure an ALB with your desired settings. Ensure that the Ingress backend points to the Ingress NGINX service. Since the service type is set to NodePort, the ALB will forward traffic seamlessly to the NGINX service running on the node.

Below is an example Ingress YAML file that sets up an ALB with custom configurations:

				
					apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/load-balancer-attributes: deletion_protection.enabled=true
    alb.ingress.kubernetes.io/load-balancer-name: alb-with-ingress-nginx #Alb name
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/security-groups: sg-id #custom security-group ID 
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    alb.ingress.kubernetes.io/success-codes: 200,404
    alb.ingress.kubernetes.io/target-type: instance
    alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:region:account-id:regional/webacl/waf-name/id #AWS WAF ARN
  name: ingress-nginx
  namespace: kube-system
spec:
  ingressClassName: alb
  rules:
  - host: 'example.com'
    http:
      paths:
      - backend:
          service:
            name: ingress-nginx-controller #Ingress-nginx service name
            port:
              number: 80
        path: /
        pathType: Prefix
				
			
This Ingress configuration will create an ALB with SSL redirection, WAF protection, custom security groups, and more. Apply this configuration, and you can check the created ALB in the AWS console.

Conclusion

By following these steps, you can successfully integrate Ingress NGINX with an ALB using AWS Load Balancer Controller. This setup allows you to benefit from the advanced load balancing features of ALB while maintaining the flexibility of Ingress NGINX for routing and traffic management.