https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.10/deploy/installation/
Configure IAM role and k8s Service Account for the controller:
Setup an IAM OpenID Connect provider for the cluster:
# From the bastion host
eksctl utils associate-iam-oidc-provider --cluster eks-demo-cluster --region us-east-1 --approve
Copy the policy from https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.10.0/docs/install/iam_policy.json, then add it as an IAM policy AWSLoadBalancerControllerIAMPolicy
through the console or AWS CLI (from the local machine).
Copy the ARN of the policy, then create an IAM role and a k8s service account:
eksctl create iamserviceaccount \\
--cluster=eks-demo-cluster \\
--namespace=kube-system \\
--name=aws-load-balancer-controller \\
--attach-policy-arn=arn:aws:iam::<AWS_ACCOUNT_ID>:policy/AWSLoadBalancerControllerIAMPolicy \\
--override-existing-serviceaccounts \\
--region us-east-1 \\
--approve
Install the cert-manager
(resolving SSL/TLS certificates from Load Balancer):
<aside> ☝
Since the EKS cluster is private and has no access to the internet, you cannot simply apply the manifest file like this:
kubectl apply -f <https://github.com/cert-manager/cert-manager/releases/download/v1.12.3/cert-manager.yaml
>
The images in the manifest file is not from your AWS ECR private repository: For example, quay.io/jetstack/cert-manager-cainjector:v1.12.3
</aside>
Download the manifest file: https://github.com/cert-manager/cert-manager/releases/download/v1.12.3/cert-manager.yaml
Create 3 private ECR repositories called:
jetstack/cert-manager-webhook
jetstack/cert-manager-cainjector
jetstack/cert-manager-controller
From the local machine pull the images from what the manifest file indicated, then push to your own repository:
docker pull --platform linux/arm64 quay.io/jetstack/cert-manager-webhook:v1.12.3
docker tag quay.io/jetstack/cert-manager-webhook:v1.12.3 <aws_id>.dkr.ecr.us-east-1.amazonaws.com/jetstack/cert-manager-webhook:v1.12.3
docker push <aws_id>.dkr.ecr.us-east-1.amazonaws.com/jetstack/cert-manager-webhook:v1.12.3
# Do the same for the other images
Modify the cert-manager.yaml
manifest file:
# cert-manager.yaml
# Change the images to the private ECR images
image: <aws_id>.dkr.ecr.us-east-1.amazonaws.com/jetstack/cert-manager-webhook:v1.12.3
image: <aws_id>.dkr.ecr.us-east-1.amazonaws.com/jetstack/cert-manager-cainjector:v1.12.3
image: <aws_id>.dkr.ecr.us-east-1.amazonaws.com/jetstack/cert-manager-controller:v1.12.3
Then apply the Certification Manager to the cluster:
# From bastion host
mkdir helpers
# From local machine, copy the file through SCP to the bastion host
scp -i <path_to_access_key> ./cert-manager.yaml ec2-user@<instance_id>:/home/ec2-user/helpers
# From bastion host
kubectl apply -f ./helpers/cert-manager.yaml
# Verify the certification manager server
kubectl get deployment -n cert-manager
Install the Load Balancer Controller:
Download the manifest files:
Create a private ECR repository called: eks/aws-load-balancer-controller
(v2_10_0_full.yaml)
From the local machine pull the images from what the manifest file indicated, then push to your own repository:
docker pull --platform linux/arm64 public.ecr.aws/eks/aws-load-balancer-controller:v2.10.0
docker tag public.ecr.aws/eks/aws-load-balancer-controller:v2.10.0 <aws_id>.dkr.ecr.us-east-1.amazonaws.com/eks/aws-load-balancer-controller:v2.10.0
docker push <aws_id>.dkr.ecr.us-east-1.amazonaws.com/eks/aws-load-balancer-controller:v2.10.0
Modify the v2_10_0_full.yaml
manifest file:
# v2_10_0_full.yaml
# Change the cluster name and the images to the private ECR images
containers:
- args:
- --cluster-name=eks-demo-cluster
...
image: <aws_id>.dkr.ecr.us-east-1.amazonaws.com/eks/aws-load-balancer-controller:v2.10.0
# Remove the ServiceAccount from the manifest
---
apiVersion: v1
kind: ServiceAccount
metadata:
...
name: aws-load-balancer-controller
...
---
Then apply the LBC to the cluster:
# From local machine, copy the file through SCP to the bastion host
scp -i <path_to_access_key> ./v2_10_0_full.yaml ec2-user@<instance_id>:/home/ec2-user/helpers/aws-lbc-full.yaml
scp -i <path_to_access_key> ./v2_10_0_ingclass.yaml ec2-user@<instance_id>:/home/ec2-user/helpers/aws-lbc-ingclass.yaml
# From bastion host
kubectl apply -f ./helpers/aws-lbc-full.yaml
kubectl apply -f ./helpers/aws-lbc-ingclass.yaml # Wait a minute before applying
# Verify the metrics server
kubectl get deployment -n kube-system aws-load-balancer-controller
Create a VPC Endpoint to connect the AWS ELB service to the private cluster:
Create an ACM certificate to redirect your HTTP (80) traffic from your cluster to the internet with HTTPS (443), using SSL redirect:
Request a public certificate from AWS Certificate Manager:
eks-demo.bachhv.com
After request, ACM will give a CNAME record requiring validation. Go to whatever your domain registrar, and add the CNAME record (e.g. Route 53). Because my domain is registered in Cloudflare, I will add the record there.
When the certificate is validated and issued, copy the certificate’s ARN.
Creating the manifest to deploy the service for each app:
# svc-frontend.yaml
apiVersion: v1
kind: Service
metadata:
name: coffeeshop-frontend-svc
spec:
selector:
app: coffeeshop-frontend
ports:
- protocol: TCP
port: 8080
targetPort: 8080
Creating the manifest to deploy the ingress:
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: coffeeshop-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/load-balancer-name: eks-demo-alb
alb.ingress.kubernetes.io/subnets: <subnet_alb_1_id>,<subnet_alb_2_id>
alb.ingress.kubernetes.io/certificate-arn: <certificate_arn>
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
ingressClassName: alb
rules:
- host: eks-demo.bachhv.com # Domain that will eventually be used
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: coffeeshop-frontend-svc
port:
number: 8080
- path: /api/customer
pathType: Prefix
backend:
service:
name: coffeeshop-customer-svc
port:
number: 4000
- path: /api/shopping
pathType: Prefix
backend:
service:
name: coffeeshop-shopping-svc
port:
number: 4000
Applying the manifests. When the ingress is created, the Load Balancer Controller will also create an ALB on AWS based on the rules of the ingress manifest. It should take 5-10 minutes for the controller to create:
# From local machine, copy all deployment and HPA manifests
scp -i <path_to_access_key> ./svc-*.yaml ./ingress.yaml ec2-user@<instance_id>:/home/ec2-user/manifests
# From bastion host
kubectl apply -f './manifests/svc-*.yaml'
kubectl apply -f './manifests/ingress.yaml'