Deploy a python app (Docker Image) to Kubernetes cluster via AWS EKS
Tags: beginners, tutorial, eks, kubernetes
Published: 2023-09-20 06:49:02

This post will help you to deploy a python game app into a highly available cluster via AWS EKS (a Managed control plane service from AWS). 

### Pre-requisites

1. [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
2. [Install Kubectl ](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/)
3. [Install eksctl ](https://eksctl.io/introduction/#installation)
4. [Install Heml] (https://helm.sh/docs/intro/install/)

### Step 1 : Configure AWS root account
```
PS C:\WINDOWS\system32> AWS configure
AWS Access Key ID [****************FINA]:
AWS Secret Access Key [****************R6U5]:
Default region name [us-east-1]:
Default output format [json]:
PS C:\WINDOWS\system32>
```
### Step 2 : Create EKS cluster

- Create EKS cluster via CLI 
`eksctl create cluster --name demo-cluster --region us-east-1 --fargate`
- Output: It should take ~5 to 15 mins to create cluster in AWS
```
PS C:\WINDOWS\system32> eksctl create cluster --name demo-cluster --region us-east-1 --fargate
2023-09-19 23:43:58 [ℹ]  eksctl version 0.157.0
2023-09-19 23:43:58 [ℹ]  using region us-east-1
2023-09-19 23:43:58 [ℹ]  setting availability zones to [us-east-1a us-east-1d]
2023-09-19 23:43:58 [ℹ]  subnets for us-east-1a - public:192.168.0.0/19 private:192.168.64.0/19
2023-09-19 23:43:58 [ℹ]  subnets for us-east-1d - public:192.168.32.0/19 private:192.168.96.0/19
2023-09-19 23:43:58 [ℹ]  using Kubernetes version 1.25
2023-09-19 23:43:58 [ℹ]  creating EKS cluster "demo-cluster" in "us-east-1" region with Fargate profile
2023-09-19 23:43:58 [ℹ]  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-east-1 --cluster=demo-cluster'
2023-09-19 23:43:58 [ℹ]  Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "demo-cluster" in "us-east-1"
2023-09-19 23:43:58 [ℹ]  CloudWatch logging will not be enabled for cluster "demo-cluster" in "us-east-1"
2023-09-19 23:43:58 [ℹ]  you can enable it with 'eksctl utils update-cluster-logging --enable-types={SPECIFY-YOUR-LOG-TYPES-HERE (e.g. all)} --region=us-east-1 --cluster=demo-cluster'
2023-09-19 23:43:58 [ℹ]
2 sequential tasks: { create cluster control plane "demo-cluster",
    2 sequential sub-tasks: {
        wait for control plane to become ready,
        create fargate profiles,
    }
}
2023-09-19 23:43:58 [ℹ]  building cluster stack "eksctl-demo-cluster-cluster"
2023-09-19 23:43:59 [ℹ]  deploying stack "eksctl-demo-cluster-cluster"
2023-09-19 23:44:29 [ℹ]  waiting for CloudFormation stack "eksctl-demo-cluster-cluster"
2023-09-19 23:45:00 [ℹ]  waiting for CloudFormation stack "eksctl-demo-cluster-cluster"
2023-09-19 23:46:00 [ℹ]  waiting for CloudFormation stack "eksctl-demo-cluster-cluster"
```
- Output : AWS console 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n6zy7x90h9orpi3515jj.jpg) 
- Download Kubeconfig
`aws eks update-kubeconfig --name demo-cluster --region us-east-1`
- output: 
```
PS C:\WINDOWS\system32> aws eks update-kubeconfig --name demo-cluster --region us-east-1
Added new context arn:aws:eks:us-east-1:21344354364:cluster/demo-cluster to C:\Users\Jasper\.kube\config
```
### Step 3 : Create custom fargate-profile
- To Create custom fargate-profile use below snippet
```
$ eksctl create fargateprofile \
    --cluster demo-cluster \
    --region us-east-1 \
    --name alb-sample-app \
    --namespace game-2048
2023-09-20 00:17:40 [ℹ]  creating Fargate profile "alb-sample-app" on EKS cluster "demo-cluster"
2023-09-20 00:19:50 [ℹ]  created Fargate profile "alb-sample-app" on EKS cluster "demo-cluster"
- output : 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ncyy3edj3wkt7ekb48s4.jpg)
```
### Step 4 : Deploy using deployment.yml file 
- Deploy via deployment.yaml , service and Ingress (Note: Please attach Ingress controller to this to create a ALB for traffic to flow through)
```
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/examples/2048/2048_full.yaml
namespace/game-2048 created
deployment.apps/deployment-2048 created
service/service-2048 created
ingress.networking.k8s.io/ingress-2048 created
```
- Get pods `kubectl get pods -n game-2048`
```
$ kubectl get pods -n game-2048
NAME                               READY   STATUS    RESTARTS   AGE
deployment-2048-5686bb4958-22w8c   1/1     Running   0          7m24s
deployment-2048-5686bb4958-2jvnh   1/1     Running   0          7m25s
deployment-2048-5686bb4958-94dgg   1/1     Running   0          7m25s
deployment-2048-5686bb4958-fqxmg   1/1     Running   0          7m24s
deployment-2048-5686bb4958-lndww   1/1     Running   0          7m25s
```
- search for service `$ kubectl get svc -n game-2048` 
- Note: The service has CLUSTER_IP with NodePort but no EXTERNAL-IP: ie., Anyone that has access to VPC can talk to the pod using nodeIP address followed by name of port `10.100.219.219:80:30929`
```
$ kubectl get svc -n game-2048
NAME           TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service-2048   NodePort   10.100.219.219   <none>        80:30929/TCP   10m
```
- Get Ingress : We use this ingress to make someone outside the AWS VPC access the pod. `kubectl get ingress -n game-2048`
- Output: Note: There is no Address associated to ingress. There has to be an ingress controller. once we deploy ingress controller 
```
$ kubectl get ingress -n game-2048
NAME           CLASS   HOSTS   ADDRESS   PORTS   AGE
ingress-2048   alb     *                 80      16m
```
### Step 5 : Pre-requisite to Step #6 (create ALB Ingress-Controller )
- This will read from .yaml file <ingress section> and it will read 'ingress-2048' and configure ALB - example: target group
## Pre-requisite: Configure/Associate OIDC connector
- we need IAM OIDC connector because the ALB controller (K8s pod) needs to access Application load balancer (ALB)
- to talk to ALB it needs IAM OIDC provider. 
```
eksctl utils associate-iam-oidc-provider --cluster demo-cluster --approve
2023-09-20 01:02:21 [ℹ]  will create IAM Open ID Connect provider for cluster "demo-cluster" in "us-east-1"
2023-09-20 01:02:22 [✔]  created IAM Open ID Connect provider for cluster "demo-cluster" in "us-east-1"
```
- Install ALB controller (Its a K8s pod ): It needs the following
- Architecture flow: ALB controller --> (K8s Pod) --> Need access to AWS services such as ALB

1. Download IAM policy `curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json`
2. Create IAM Policy for Pod to access AWS Service/ALB 
3. Create IAM Role for Pod : an EKS LB Controller Role and attach this role to service account to Pod.  

- Output 1 : 
```
$ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8386  100  8386    0     0   5093      0  0:00:01  0:00:01 --:--:--  5144
```
- Output 2 : 
```
$ aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json
{
    "Policy": {
        "PolicyName": "AWSLoadBalancerControllerIAMPolicy",
        "PolicyId": "ASADF23423SDFG",
        "Arn": "arn:aws:iam::123435234:policy/AWSLoadBalancerControllerIAMPolicy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2023-09-20T06:13:14+00:00",
        "UpdateDate": "2023-09-20T06:13:14+00:00"
    }
}
```
- Output 3: `eksctl create iamserviceaccount   --cluster=demo-cluster   --namespace=kube-system   --name=aws-load-balancer-controller   --role-name AmazonEKSLoadBalancerControllerRole   --attach-policy-arn=arn:aws:iam::342523452346:p
olicy/AWSLoadBalancerControllerIAMPolicy   --approve`
```
$ eksctl create iamserviceaccount   --cluster=demo-cluster   --namespace=kube-system   --name=aws-load-balancer-controller   --role-name AmazonEKSLoadBalancerControllerRole   --attach-policy-arn=arn:aws:iam::342523452346:p
olicy/AWSLoadBalancerControllerIAMPolicy   --approve
2023-09-20 01:19:19 [ℹ]  1 iamserviceaccount (kube-system/aws-load-balancer-controller) was included (based on the include/exclude rules)
2023-09-20 01:19:19 [!]  serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
2023-09-20 01:19:19 [ℹ]  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",
    } }2023-09-20 01:19:19 [ℹ]  building iamserviceaccount stack "eksctl-demo-cluster-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2023-09-20 01:19:19 [ℹ]  deploying stack "eksctl-demo-cluster-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2023-09-20 01:19:19 [ℹ]  waiting for CloudFormation stack "eksctl-demo-cluster-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2023-09-20 01:19:49 [ℹ]  waiting for CloudFormation stack "eksctl-demo-cluster-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2023-09-20 01:19:50 [ℹ]  created serviceaccount "kube-system/aws-load-balancer-controller"
```
Step 6 : Create ALB Ingress-Controller via helm chart
- Add helm repo
`helm repo add eks https://aws.github.io/eks-charts`
```
$ helm repo add eks https://aws.github.io/eks-charts
"eks" has been added to your repositories
```
- Get VPC ID = `vpc-0b8ke79b820c877c0`, Region= 'us-east-2' 
```
$ helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=demo-cluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  --set region=us-east-2 \
  --set vpcId=vpc-0b8ke79b820c877c0
NAME: aws-load-balancer-controller
LAST DEPLOYED: Wed Sep 20 01:32:34 2023
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!
```
- Verify Load balancer is created and at least 2 replicas of it. 
`kubectl get deployment -n kube-system aws-load-balancer-controller`
- output : 
```
$ 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           114s
```
- Get deployment : available repicas is 2/2
```
$ kubectl get deploy -n kube-system
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           5m18s
coredns                        2/2     2            2           108m
```
### Step 7: Verify if "ALB controller - K8s Pod " created ALB 
- Verify if "ALB controller - K8s Pod created via ingress resources" created ALB or not in AWS console 
- AWS console --> EC2 --> ALB 
- Output: 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3e3olygltx99gg5gmux.jpg)
```
$ kubectl get ingress -n game-2048
NAME           CLASS   HOSTS   ADDRESS                                                                  PORTS   AGE
ingress-2048   alb     *       k8s-game2048-ingress2-bacc1c6c73-234532456.us-east-1.elb.amazonaws.com   80      76m
```
### Step 8 : Verify Load balancer DNS/ IP in browser
-Output: Congratulations. I was able to deploy python app which is accessible via Load balancer. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3d5uvpy1cn6fywtci6jg.jpg)

### Note: 

> Usually, DevOps engineers use deployment.yml, service.yaml, ingress.yaml & ingress controller (One time responsibility: for EKS we have to create service account --> Then attach servicde account with IAM role) with On-prem: One can assign ingress controller service account with proper RBAC

Credits: 
- [Abhishek.Veeramalla] (https://www.youtube.com/watch?v=RRCrY12VY_s&list=PLdpzxOOAlwvLNOxX0RfndiYSt1Le9azze&index=24)
- [Git Hub] (https://github.com/iam-veeramalla)