Playing with EKS Fargate

Playing with EKS Fargate

The purpose of this tutorial is to deploy a ‘simple’ application to EKS Fargate. In this tutorial, I will try to be practical as possible and deploy ‘httpbin’ application to EKS Fargate.

First, a regular EKS cluster with node groups will be created, then I will add the Fargate profile as ‘play-with-fargate’ namespace and every application deployed to this namespace will use Fargate.

AWS Fargate

AWS Fargate is a technology that provides on-demand, right-sized compute capacity for containers. With AWS Fargate, you don’t have to provision, configure, or scale groups of virtual machines on your own to run containers. You also don’t need to choose server types, decide when to scale your node groups, or optimize cluster packing. You can control which pods start on Fargate and how they run with Fargate profiles. Fargate profiles are defined as part of your Amazon EKS cluster.

httpbin

A simple HTTP Request & Response Service.

https://httpbin.org

Prerequisites

  • AWS account with all needed permissions to create EKS cluster
  • Installed kubectl and eksctl
  • Installed AWS CLI

Let’s provision the EKS cluster

Provision EKS cluster with eksctl to the region: eu-west-3, name: fargate-cluster

eksctl create cluster \
 --name fargate-cluster \
 --region eu-west-3

kubectl get pods -A
kubectl get nodes

Add Fargate profile to an existing EKS cluster

eksctl create fargateprofile \
 --cluster fargate-cluster \
 --name play-with-fargate \
 --namespace play-with-fargate \
 --region eu-west-3

That is what you need to see in AWS Console -> Amazon Container Services, you need to be in the eu-west-3 region.

Let’s test we can deploy applications to EKS Fargate

I will deploy Nginx to ‘play-with-fargate’ namespace:

kubectl create ns play-with-fargate
kubectl create deployment nginx --image=nginx -n play-with-fargate

Took some time to spin up the pod, almost 1 minute to be more precise before deployment status become ‘ContainerCreated’. hmm, I feel some improvements are needed here:-)

Fargate node provisioned on the fly.

We can see Nginx indeed provisioned on Fargate node

Let’s delete the Nginx

kubectl delete deployments nginx -n play-with-fargate

Next, I will deploy AWS Load Balancer Controller, to use ALB ingress with our application and make it externally accessible.

Install AWS Load Balancer Controller to EKS

Based on this workshop: https://www.eksworkshop.com/beginner/180_fargate/prerequisites-for-alb/

Create IAM OIDC provider

This step is required to give IAM permissions to a Fargate pod running in the cluster using the IAM for Service Accounts feature.

eksctl utils associate-iam-oidc-provider \
    --region eu-west-3 \
    --cluster fargate-cluster \
    --approve

Create an IAM policy

The next step is to create the IAM policy that will be used by the AWS Load Balancer Controller. This policy will be later associated to the Kubernetes Service Account and will allow the controller pods to create and manage the ELB’s resources in your AWS account for you.

curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.2.0/docs/install/iam_policy.json
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json
rm iam_policy.json

Create an IAM role and ServiceAccount for the Load Balancer controller

First, change ${ACCOUNT_ID} to your account, which you can find in the AWS console on the top -> right side

eksctl create iamserviceaccount \
  --cluster fargate-cluster \
  --region eu-west-3 \
  --namespace kube-system \
  --name aws-load-balancer-controller \
  --attach-policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \
  --override-existing-serviceaccounts \
  --approve

The above command deploys a CloudFormation template that creates an IAM role and attaches the IAM policy to it.

Install the TargetGroupBinding CRDs

kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller//crds?ref=master"

Install the AWS Load Balancer Controller

You need your VPC ID first:

aws eks describe-cluster \
  --name fargate-cluster \
  --region eu-west-3 \
  --query "cluster.resourcesVpcConfig.vpcId" \
  --output text

Change vpcId before executing the next command.

helm repo add eks https://aws.github.io/eks-charts
helm upgrade -i aws-load-balancer-controller eks/aws-load-balancer-controller \
--set clusterName=fargate-cluster \
--set serviceAccount.create=false \
--set region=eu-west-3 \
--set vpcId=vpc-xxxxx \
--set serviceAccount.name=aws-load-balancer-controller -n kube-system

Verify that the AWS Load Balancer Controller is installed

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

Let’s deploy our application: httpbin

‘httpbin’ will be deployed to ‘play-with-fargate’ namespace

All manifests combined in all-resources.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
  namespace: play-with-fargate
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: play-with-fargate
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: play-with-fargate
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        name: httpbin
        ports:
        - containerPort: 80

You can find gist with all commands and manifests here: https://gist.github.com/warolv/e982ccce78a6b78c40cea4227c13912f

kubectl apply -f all-resources.yaml

Let’s connect to httpbin using the port-forwarding

Will use ‘kubectl port-forward’ to get access to httpbin

Looks good:-)

The only thing left is to access this application externally, will use ‘AWS Load Balancer Controller’ we installed and ‘ingress’ manifest.

‘AWS Load Balancer Controller’ will provision ALB on AWS behind the scenes.

Ingress for httpbin

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
  name: httpbin-ingress
spec:
  rules:
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: httpbin
            port:
              number: 8000

Provision ALB may take a couple of minutes, be patient.

Success! :-)

annotations: ‘kubernetes.io/ingress.class: alb’ instructs AWS Load Balancer Controller to create ALB on AWS for this application.

alb.ingress.kubernetes.io/scheme: internet-facing instructs AWS Load Balancer Controller to create external LB for this application and not internal.

You can find gist with all commands and manifests here: https://gist.github.com/warolv/e982ccce78a6b78c40cea4227c13912f

In this tutorial, I explained how to add a Fargate profile to an existing EKS cluster, how to deploy ‘httpbin’ application, and to provision AWS Load Balancer Controller to make the application accessible externally.

Thank you for reading, I hope you enjoyed it, see you in the next post.

Please subscribe to my YT channel

If you want to be notified when the next post of this tutorial is published, please follow me on Twitter @warolv.

My medium account: warolv.medium.com