EKS Application Loadbalancer

Pre-Requisite:

1.Create the underlying infrastructure (VPC, subnets, route tables, internet gateway, nat gateway, security groups) AWS VPC infrastructure.

2.Create EKS cluster role with policies - AmazonEKSClusterPolicy, AmazonEKSVPCResourceController.

3.Create EKS node group role with policies - AmazonEKSWorkerNodePolicy,AmazonEC2ContainerRegistryReadOnly,AmazonEKS_CNI_Policy.

4.Create the EKS cluster.
5.Create the node group.

Steps to load balance (internet facing) the above application

1.Tag the public subnets with Tag name: kubernetes.io/role/elb; Tag value: 1.

eks subnet tag

If you want more information about subnet tag refer aws documentation sunbet tag for public and private.

Create IAM OIDC identity provider for your cluster.

  1. Copy OpenID Connect provider URL from your cluster - overview section.

  2. Open → IAM Console → Identity providers → paste openID Connect provider URL → select openID Connect → provider URL → Get thumbprint → add audience.
    As show in below figure

eks openidconnect

Create load balancer controller policy and load balancer trust policy.

  1. Create an IAM policy.

    1. Download an IAM policy for the AWS Load Balancer Controller that allows it to make calls to AWS APIs on your behalf.

curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json
eks loadbalancer controller policy

2.Create an IAM policy using the policy downloaded in the previous step.

Create IAM role for load balancer controller

  1. Create an IAM role. Create a Kubernetes service account named aws-load-balancer-controller in the kube-system namespace for the AWS Load Balancer Controller and annotate the Kubernetes service account with the name of the IAM role.

    1. Attach policy that you have created in previous step.

    2. Add the below code to trust relationships and replace with your <accountId> and <oidcId> ensure the correct value.
      As shown in the below figure.

      {
         "Version":"2012-10-17",
         "Statement":[
            {
               "Effect":"Allow",
               "Principal":{
                  "Federated":"arn:aws:iam::<accountId>:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/<oidcId>"
               },
               "Action":"sts:AssumeRoleWithWebIdentity",
               "Condition":{
                  "StringEquals":{
                     "oidc.eks.<region>.amazonaws.com/id/<oidcId>:aud":"sts.amazonaws.com",
                     "oidc.eks.<region>.amazonaws.com/id/<oidcId>:sub":"system:serviceaccount:kube-system:aws-load-balancer-controller"
                  }
               }
            }
         ]
      }
eks role for application loadbalancer

Create service account.

1.Create the Kubernetes service account on your cluster. The Kubernetes service account named aws-load-balancer-controller is annotated with the IAM role that you created named AmazonEKSLoadBalancerControllerRole.

cat >aws-load-balancer-controller-service-account.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: aws-load-balancer-controller
  name: aws-load-balancer-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<accountId>:role/<eks_role_for_application_loadbalancer>
EOF

replace with your <accountId123> and <eks_role_for_application_loadbalancer>.

kubectl apply -f aws-load-balancer-controller-service-account.yaml

2.Install the AWS Load Balancer Controller using Helm V3

  1. Add the eks-charts repository.

  2. Install load balancer controller using helm. using below commands

    helm repo add eks https://aws.github.io/eks-charts
  3. Update your local repo to make sure that you have the most recent charts.

    helm repo update eks
  4. Apply the ingress.yaml

helm install load balancer

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=<clustername> \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller

add your <clustername>.

3.Verify that the controller is installed.

kubectl get deployment -n kube-system aws-load-balancer-controller

An example output is as follows.

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           84s

Create alb ingress for external loadbalancer

ex:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: eks-alb-public-ingress
  namespace: istio-system
  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: /healthz/ready
    alb.ingress.kubernetes.io/healthcheck-port: status-port
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: "30"
    alb.ingress.kubernetes.io/healthy-threshold-count: "3"
    alb.ingress.kubernetes.io/unhealthy-threshold-count: "3"
    alb.ingress.kubernetes.io/loadbalancer: istio-public-alb
    alb.ingress.kubernetes.io/backend-protocol: HTTPS
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-FS-1-2-Res-2020-10
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '443'
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-south-1:948930947331:certificate/b2ab6c06-f3d4-4658-9dee-172b28b86e8e
  labels:
    ingress.kind: external
    istio: istio-ingressgateway
spec:
  ingressClassName: alb
  rules:
  - host: "*"
  - http:
      paths:
      - backend:
          service:
            name: ssl-redirect
            port:
              name: use-annotation
        path: /
        pathType: Prefix
      - backend:
          service:
            name: istio-ingressgateway
            port:
              number: 15021
        path: /
        pathType: Prefix
      - backend:
          service:
            name: istio-ingressgateway
            port:
              number: 443
        path: /
        pathType: Prefix