AWS Load Balancer Controller Install on AWS EKS
Learn to install AWS Load Balancer Controller for Ingress Implementation on AWS EKS
Step-00: Introduction
Create IAM Policy and make a note of Policy ARN
Create IAM Role and k8s Service Account and bound them together
Install AWS Load Balancer Controller using HELM3 CLI
Understand IngressClass Concept and create a default Ingress Class
Step-01: Pre-requisites
Pre-requisite-1: eksctl & kubectl Command Line Utility
- Should be the latest eksctl version
# Verify eksctl version
eksctl version
# For installing or upgrading latest eksctl version
https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html
# Verify EKS Cluster version
kubectl version --short
kubectl version
Important Note: You must use a kubectl version that is within one minor version difference of your Amazon EKS cluster control plane. For example, a 1.20 kubectl client works with Kubernetes 1.19, 1.20 and 1.21 clusters.
# For installing kubectl cli
https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html
Pre-requisite-2: Create EKS Cluster and Worker Nodes (if not created)
# Create Cluster (Section-01-02)
eksctl create cluster --name=eksdemo1 \
--region=us-east-1 \
--zones=us-east-1a,us-east-1b \
--version="1.21" \
--without-nodegroup
# Get List of clusters (Section-01-02)
eksctl get cluster
# Template (Section-01-02)
eksctl utils associate-iam-oidc-provider \
--region region-code \
--cluster <cluter-name> \
--approve
# Replace with region & cluster name (Section-01-02)
eksctl utils associate-iam-oidc-provider \
--region us-east-1 \
--cluster eksdemo1 \
--approve
# Create EKS NodeGroup in VPC Private Subnets (Section-07-01)
eksctl create nodegroup --cluster=eksdemo1 \
--region=us-east-1 \
--name=eksdemo1-ng-private1 \
--node-type=t3.medium \
--nodes-min=2 \
--nodes-max=4 \
--node-volume-size=20 \
--ssh-access \
--ssh-public-key=kube-demo \
--managed \
--asg-access \
--external-dns-access \
--full-ecr-access \
--appmesh-access \
--alb-ingress-access \
--node-private-networking
Pre-requisite-3: Verify Cluster, Node Groups and configure kubectl cli if not configured
EKS Cluster
EKS Node Groups in Private Subnets
# Verfy EKS Cluster
eksctl get cluster
# Verify EKS Node Groups
eksctl get nodegroup --cluster=eksdemo1
# Verify if any IAM Service Accounts present in EKS Cluster
eksctl get iamserviceaccount --cluster=eksdemo1
Observation:
1. No k8s Service accounts as of now.
# Configure kubeconfig for kubectl
eksctl get cluster # TO GET CLUSTER NAME
aws eks --region <region-code> update-kubeconfig --name <cluster_name>
aws eks --region us-east-1 update-kubeconfig --name eksdemo1
# Verify EKS Nodes in EKS Cluster using kubectl
kubectl get nodes
# Verify using AWS Management Console
1. EKS EC2 Nodes (Verify Subnet in Networking Tab)
2. EKS Cluster
Step-02: Create IAM Policy
Create IAM policy for the AWS Load Balancer Controller that allows it to make calls to AWS APIs on your behalf.
As on today
2.3.1
is the latest Load Balancer ControllerWe will download always latest from main branch of Git Repo
# Change Directroy
cd 08-NEW-ELB-Application-LoadBalancers/
cd 08-01-Load-Balancer-Controller-Install
# Delete files before download (if any present)
rm iam_policy_latest.json
# Download IAM Policy
## Download latest
curl -o iam_policy_latest.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
## Verify latest
ls -lrta
## Download specific version
curl -o iam_policy_v2.3.1.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.3.1/docs/install/iam_policy.json
# Create IAM Policy using policy downloaded
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam_policy_latest.json
## Sample Output
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$ aws iam create-policy \
> --policy-name AWSLoadBalancerControllerIAMPolicy \
> --policy-document file://iam_policy_latest.json
{
"Policy": {
"PolicyName": "AWSLoadBalancerControllerIAMPolicy",
"PolicyId": "ANPASUF7HC7S52ZQAPETR",
"Arn": "arn:aws:iam::180789647333:policy/AWSLoadBalancerControllerIAMPolicy",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 0,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"CreateDate": "2022-02-02T04:51:21+00:00",
"UpdateDate": "2022-02-02T04:51:21+00:00"
}
}
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$
- Important Note: If you view the policy in the AWS Management Console, you may see warnings for ELB. These can be safely ignored because some of the actions only exist for ELB v2. You do not see warnings for ELB v2.
Make a note of Policy ARN
- Make a note of Policy ARN as we are going to use that in next step when creating IAM Role.
# Policy ARN
Policy ARN: arn:aws:iam::180789647333:policy/AWSLoadBalancerControllerIAMPolicy
Step-03: Create an IAM role for the AWS LoadBalancer Controller and attach the role to the Kubernetes service account
Applicable only with
eksctl
managed clustersThis command will create an AWS IAM role
This command also will create Kubernetes Service Account in k8s cluster
In addition, this command will bound IAM Role created and the Kubernetes service account created
Step-03-01: Create IAM Role using eksctl
# Verify if any existing service account
kubectl get sa -n kube-system
kubectl get sa aws-load-balancer-controller -n kube-system
Obseravation:
1. Nothing with name "aws-load-balancer-controller" should exist
# Template
eksctl create iamserviceaccount \
--cluster=my_cluster \
--namespace=kube-system \
--name=aws-load-balancer-controller \ #Note: K8S Service Account Name that need to be bound to newly created IAM Role
--attach-policy-arn=arn:aws:iam::111122223333:policy/AWSLoadBalancerControllerIAMPolicy \
--override-existing-serviceaccounts \
--approve
# Replaced name, cluster and policy arn (Policy arn we took note in step-02)
eksctl create iamserviceaccount \
--cluster=eksdemo1 \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::180789647333:policy/AWSLoadBalancerControllerIAMPolicy \
--override-existing-serviceaccounts \
--approve
- Sample Output
# Sample Output for IAM Service Account creation
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$ eksctl create iamserviceaccount \
> --cluster=eksdemo1 \
> --namespace=kube-system \
> --name=aws-load-balancer-controller \
> --attach-policy-arn=arn:aws:iam::180789647333:policy/AWSLoadBalancerControllerIAMPolicy \
> --override-existing-serviceaccounts \
> --approve
2022-02-02 10:22:49 [ℹ] eksctl version 0.82.0
2022-02-02 10:22:49 [ℹ] using region us-east-1
2022-02-02 10:22:52 [ℹ] 1 iamserviceaccount (kube-system/aws-load-balancer-controller) was included (based on the include/exclude rules)
2022-02-02 10:22:52 [!] metadata of serviceaccounts that exist in Kubernetes will be updated, as --override-existing-serviceaccounts was set
2022-02-02 10:22:52 [ℹ] 1 task: {
2 sequential sub-tasks: {
create IAM role for serviceaccount "kube-system/aws-load-balancer-controller",
create serviceaccount "kube-system/aws-load-balancer-controller",
} }2022-02-02 10:22:52 [ℹ] building iamserviceaccount stack "eksctl-eksdemo1-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2022-02-02 10:22:53 [ℹ] deploying stack "eksctl-eksdemo1-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2022-02-02 10:22:53 [ℹ] waiting for CloudFormation stack "eksctl-eksdemo1-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2022-02-02 10:23:10 [ℹ] waiting for CloudFormation stack "eksctl-eksdemo1-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2022-02-02 10:23:29 [ℹ] waiting for CloudFormation stack "eksctl-eksdemo1-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2022-02-02 10:23:32 [ℹ] created serviceaccount "kube-system/aws-load-balancer-controller"
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$
Step-03-02: Verify using eksctl cli
# Get IAM Service Account
eksctl get iamserviceaccount --cluster eksdemo1
# Sample Output
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$ eksctl get iamserviceaccount --cluster eksdemo1
2022-02-02 10:23:50 [ℹ] eksctl version 0.82.0
2022-02-02 10:23:50 [ℹ] using region us-east-1
NAMESPACE NAME ROLE ARN
kube-system aws-load-balancer-controller arn:aws:iam::180789647333:role/eksctl-eksdemo1-addon-iamserviceaccount-kube-Role1-1244GWMVEAKEN
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$
Step-03-03: Verify CloudFormation Template eksctl created & IAM Role
Goto Services -> CloudFormation
CFN Template Name: eksctl-eksdemo1-addon-iamserviceaccount-kube-system-aws-load-balancer-controller
Click on Resources tab
Click on link in Physical Id to open the IAM Role
Verify it has eksctl-eksdemo1-addon-iamserviceaccount-kube-Role1-WFAWGQKTAVLR associated
Step-03-04: Verify k8s Service Account using kubectl
# Verify if any existing service account
kubectl get sa -n kube-system
kubectl get sa aws-load-balancer-controller -n kube-system
Obseravation:
1. We should see a new Service account created.
# Describe Service Account aws-load-balancer-controller
kubectl describe sa aws-load-balancer-controller -n kube-system
Observation: You can see that newly created Role ARN is added in
Annotations
confirming that AWS IAM role bound to a Kubernetes service accountOutput
## Sample Output
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$ kubectl describe sa aws-load-balancer-controller -n kube-system
Name: aws-load-balancer-controller
Namespace: kube-system
Labels: app.kubernetes.io/managed-by=eksctl
Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::180789647333:role/eksctl-eksdemo1-addon-iamserviceaccount-kube-Role1-1244GWMVEAKEN
Image pull secrets: <none>
Mountable secrets: aws-load-balancer-controller-token-5w8th
Tokens: aws-load-balancer-controller-token-5w8th
Events: <none>
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$
Step-04: Install the AWS Load Balancer Controller using Helm V3
Step-04-01: Install Helm
Install Helm if not installed
# Install Helm (if not installed) MacOS
brew install helm
# Verify Helm version
helm version
Step-04-02: Install AWS Load Balancer Controller
- Important-Note-1: If you're deploying the controller to Amazon EC2 nodes that have restricted access to the Amazon EC2 instance metadata service (IMDS), or if you're deploying to Fargate, then add the following flags to the command that you run:
--set region=region-code
--set vpcId=vpc-xxxxxxxx
Important-Note-2: If you're deploying to any Region other than us-west-2, then add the following flag to the command that you run, replacing account and region-code with the values for your region listed in Amazon EKS add-on container image addresses.
--set image.repository=account.dkr.ecr.region-code.amazonaws.com/amazon/aws-load-balancer-controller
# Add the eks-charts repository.
helm repo add eks https://aws.github.io/eks-charts
# Update your local repo to make sure that you have the most recent charts.
helm repo update
# Install the AWS Load Balancer Controller.
## Template
helm 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 \
--set region=<region-code> \
--set vpcId=<vpc-xxxxxxxx> \
--set image.repository=<account>.dkr.ecr.<region-code>.amazonaws.com/amazon/aws-load-balancer-controller
## Replace Cluster Name, Region Code, VPC ID, Image Repo Account ID and Region Code
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=eksdemo1 \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set region=us-east-1 \
--set vpcId=vpc-0165a396e41e292a3 \
--set image.repository=602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon/aws-load-balancer-controller
- Sample output for AWS Load Balancer Controller Install steps
## Sample Ouput for AWS Load Balancer Controller Install steps
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$ helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
> -n kube-system \
> --set clusterName=eksdemo1 \
> --set serviceAccount.create=false \
> --set serviceAccount.name=aws-load-balancer-controller \
> --set region=us-east-1 \
> --set vpcId=vpc-0570fda59c5aaf192 \
> --set image.repository=602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon/aws-load-balancer-controller
NAME: aws-load-balancer-controller
LAST DEPLOYED: Wed Feb 2 10:33:57 2022
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$
Step-04-03: Verify that the controller is installed and Webhook Service created
# Verify that the controller is installed.
kubectl -n kube-system get deployment
kubectl -n kube-system get deployment aws-load-balancer-controller
kubectl -n kube-system describe deployment aws-load-balancer-controller
# Sample Output
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$ kubectl get deployment -n kube-system aws-load-balancer-controller
NAME READY UP-TO-DATE AVAILABLE AGE
aws-load-balancer-controller 2/2 2 2 27s
Kalyans-MacBook-Pro:08-01-Load-Balancer-Controller-Install kdaida$
# Verify AWS Load Balancer Controller Webhook service created
kubectl -n kube-system get svc
kubectl -n kube-system get svc aws-load-balancer-webhook-service
kubectl -n kube-system describe svc aws-load-balancer-webhook-service
# Sample Output
Kalyans-MacBook-Pro:aws-eks-kubernetes-masterclass-internal kdaida$ kubectl -n kube-system get svc aws-load-balancer-webhook-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
aws-load-balancer-webhook-service ClusterIP 10.100.53.52 <none> 443/TCP 61m
Kalyans-MacBook-Pro:aws-eks-kubernetes-masterclass-internal kdaida$
# Verify Labels in Service and Selector Labels in Deployment
kubectl -n kube-system get svc aws-load-balancer-webhook-service -o yaml
kubectl -n kube-system get deployment aws-load-balancer-controller -o yaml
Observation:
1. Verify "spec.selector" label in "aws-load-balancer-webhook-service"
2. Compare it with "aws-load-balancer-controller" Deployment "spec.selector.matchLabels"
3. Both values should be same which traffic coming to "aws-load-balancer-webhook-service" on port 443 will be sent to port 9443 on "aws-load-balancer-controller" deployment related pods.
Step-04-04: Verify AWS Load Balancer Controller Logs
# List Pods
kubectl get pods -n kube-system
# Review logs for AWS LB Controller POD-1
kubectl -n kube-system logs -f <POD-NAME>
kubectl -n kube-system logs -f aws-load-balancer-controller-86b598cbd6-5pjfk
# Review logs for AWS LB Controller POD-2
kubectl -n kube-system logs -f <POD-NAME>
kubectl -n kube-system logs -f aws-load-balancer-controller-86b598cbd6-vqqsk
Step-04-05: Verify AWS Load Balancer Controller k8s Service Account - Internals
# List Service Account and its secret
kubectl -n kube-system get sa aws-load-balancer-controller
kubectl -n kube-system get sa aws-load-balancer-controller -o yaml
kubectl -n kube-system get secret <GET_FROM_PREVIOUS_COMMAND - secrets.name> -o yaml
kubectl -n kube-system get secret aws-load-balancer-controller-token-5w8th
kubectl -n kube-system get secret aws-load-balancer-controller-token-5w8th -o yaml
## Decoce ca.crt using below two websites
https://www.base64decode.org/
https://www.sslchecker.com/certdecoder
## Decode token using below two websites
https://www.base64decode.org/
https://jwt.io/
Observation:
1. Review decoded JWT Token
# List Deployment in YAML format
kubectl -n kube-system get deploy aws-load-balancer-controller -o yaml
Observation:
1. Verify "spec.template.spec.serviceAccount" and "spec.template.spec.serviceAccountName" in "aws-load-balancer-controller" Deployment
2. We should find the Service Account Name as "aws-load-balancer-controller"
# List Pods in YAML format
kubectl -n kube-system get pods
kubectl -n kube-system get pod <AWS-Load-Balancer-Controller-POD-NAME> -o yaml
kubectl -n kube-system get pod aws-load-balancer-controller-65b4f64d6c-h2vh4 -o yaml
Observation:
1. Verify "spec.serviceAccount" and "spec.serviceAccountName"
2. We should find the Service Account Name as "aws-load-balancer-controller"
3. Verify "spec.volumes". You should find something as below, which is a temporary credentials to access AWS Services
CHECK-1: Verify "spec.volumes.name = aws-iam-token"
- name: aws-iam-token
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: sts.amazonaws.com
expirationSeconds: 86400
path: token
CHECK-2: Verify Volume Mounts
volumeMounts:
- mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
name: aws-iam-token
readOnly: true
CHECK-3: Verify ENVs whose path name is "token"
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
Step-04-06: Verify TLS Certs for AWS Load Balancer Controller - Internals
# List aws-load-balancer-tls secret
kubectl -n kube-system get secret aws-load-balancer-tls -o yaml
# Verify the ca.crt and tls.crt in below websites
https://www.base64decode.org/
https://www.sslchecker.com/certdecoder
# Make a note of Common Name and SAN from above
Common Name: aws-load-balancer-controller
SAN: aws-load-balancer-webhook-service.kube-system, aws-load-balancer-webhook-service.kube-system.svc
# List Pods in YAML format
kubectl -n kube-system get pods
kubectl -n kube-system get pod <AWS-Load-Balancer-Controller-POD-NAME> -o yaml
kubectl -n kube-system get pod aws-load-balancer-controller-65b4f64d6c-h2vh4 -o yaml
Observation:
1. Verify how the secret is mounted in AWS Load Balancer Controller Pod
CHECK-2: Verify Volume Mounts
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
CHECK-3: Verify Volumes
volumes:
- name: cert
secret:
defaultMode: 420
secretName: aws-load-balancer-tls
Step-04-07: UNINSTALL AWS Load Balancer Controller using Helm Command (Information Purpose - SHOULD NOT EXECUTE THIS COMMAND)
This step should not be implemented.
This is just put it here for us to know how to uninstall aws load balancer controller from EKS Cluster
# Uninstall AWS Load Balancer Controller
helm uninstall aws-load-balancer-controller -n kube-system
Step-05: Ingress Class Concept
Understand what is Ingress Class
Understand how it overrides the default deprecated annotation
#
kubernetes.io/ingress.class
: "alb"
Step-06: Review IngressClass Kubernetes Manifest
File Location:
08-01-Load-Balancer-Controller-Install/kube-manifests/01-ingressclass-resource.yaml
Understand in detail about annotation
ingressclass.kubernetes.io/is-default-class
: "true"
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: my-aws-ingress-class
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: ingress.k8s.aws/alb
## Additional Note
# 1. You can mark a particular IngressClass as the default for your cluster.
# 2. Setting the ingressclass.kubernetes.io/is-default-class annotation to true on an IngressClass resource will ensure that new Ingresses without an ingressClassName field specified will be assigned this default IngressClass.
# 3. Reference: https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.3/guide/ingress/ingress_class/
Step-07: Create IngressClass Resource
# Navigate to Directory
cd 08-01-Load-Balancer-Controller-Install
# Create IngressClass Resource
kubectl apply -f kube-manifests
# Verify IngressClass Resource
kubectl get ingressclass
# Describe IngressClass Resource
kubectl describe ingressclass my-aws-ingress-class