Deploy Your Flask App to Kubernetes Using EKS
Source code: vnk8071/server_deployment_containerization
Template Pipeline: vnk8071/pipeline-deploy-kubernetes-on-aws
Prerequisites
- Docker Desktop - Installation instructions for all OSes can be found here.
- Git: Download and install Git for your system.
- Code editor: You can download and install VS code here.
- AWS Account
- Python version between 3.7 and 3.9. Check the current version using:
# Mac/Linux/Windows
python --version
You can download a specific release version from here.
- Python package manager - PIP 19.x or higher. PIP is already installed in Python 3 >=3.4 downloaded from python.org . However, you can upgrade to a specific version, say 20.2.3, using the command:
# Mac/Linux/Windows Check the current version
pip --version
# Mac/Linux
pip install --upgrade pip==20.2.3
# Windows
python -m pip install --upgrade pip==20.2.3
- Terminal
- Mac/Linux users can use the default terminal.
- Windows users can use either the GitBash terminal or WSL.
- Command line utilities:
- AWS CLI installed and configured using the
aws configure
command. Another important configuration is the region. Do not use the us-east-1 because the cluster creation may fails mostly in us-east-1. Let's change the default region to:
Ensure to create all your resources in a single region.aws configure set region us-east-2
- EKSCTL installed in your system. Follow the instructions available here or here to download and install
eksctl
utility. - The KUBECTL installed in your system. Installation instructions for kubectl can be found here.
- AWS CLI installed and configured using the
Installation
Install AWS CLI
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
Reference: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
AWS Configure
aws configure
export AWS_CONFIG_FILE=~/.aws/config
export AWS_SHARED_CREDENTIALS_FILE=~/.aws/credentials
Install Eksctl
brew tap weaveworks/tap
brew install weaveworks/tap/eksctl
Install Kubectl
brew install kubectl
Monitoring Kubernetes Cluster
brew install k9s
Install packages
pip install -r requirements.txt
Build Application
Run locally
python main.py
Request method POST
:
export TOKEN=`curl --data '{"email":"khoivn@email.com","password":"mypwd"}' --header "Content-Type: application/json" -X POST localhost:8080/auth | jq -r '.token'`
Response: echo $TOKEN
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTc5NjUyNjcsIm5iZiI6MTY5Njc1NTY2NywiZW1haWwiOiJraG9pdm5AZW1haWwuY29tIn0.hZr2RQqnroNdly_j9yRKpO7Z6yEwx7pNleFfB25IjHs
Request method GET
:
curl --request GET 'http://localhost:8080/contents' -H "Authorization: Bearer ${TOKEN}" | jq .
Response:
{
"email": "khoivn@email.com",
"exp": 1697965267,
"nbf": 1696755667
}
Run Pytest
pytest test_main.py --disable-pytest-warnings
Result:
=================================================================================== test session starts ====================================================================================
platform darwin -- Python 3.8.18, pytest-6.2.2, py-1.11.0, pluggy-0.13.1
rootdir: /Users/macos/projects/Kelvin/pipeline-deploy-kubernetes-on-aws
collected 2 items
test_main.py .. [100%]
============================================================================== 2 passed, 5 warnings in 0.22s ===============================================================================
Build Docker Image
docker build -t token-flask-app .
Run Docker Container
docker run --detach --publish 80:8080 --env-file=.env_file token-flask-app
Test Docker Container
export TOKEN=`curl --data '{"email":"khoivn@email.com","password":"mypwd"}' --header "Content-Type: application/json" -X POST localhost:80/auth | jq -r '.token'`
Result:
curl --request GET 'http://localhost:80/contents' -H "Authorization: Bearer ${TOKEN}" | jq .
Result"
{
"email": "khoivn@email.com",
"exp": 1697977237,
"nbf": 1696767637
}
Push Docker Image to Docker Hub
docker tag token-flask-app:latest vnk8071/token-flask-app:latest
docker push vnk8071/token-flask-app:latest
Deploy Application to Kubernetes Cluster
Create EKS Cluster
eksctl create cluster --name eksctl-demo-flask-token --nodes=2 --instance-types=t2.medium --region=us-east-1
Get cluster information:
kubectl get nodes
Get current AWS account
aws sts get-caller-identity --query Account --output text
Result: 993324276116
Create IAM Role and attach policy
aws iam create-role --role-name UdacityFlaskDeployCBKubectlRole --assume-role-policy-document file://trust.json --output text --query 'Role.Arn'
Result: arn:aws:iam::993324276116:role/UdacityFlaskDeployCBKubectlRole
aws iam put-role-policy --role-name UdacityFlaskDeployCBKubectlRole --policy-name eks-describe --policy-document file://iam-role-policy.json
Set Environment Variables
aws ssm put-parameter --name JWT_SECRET --value "KhoiVN-secret" --type SecureString --region us-east-1
Create Kubernetes ConfigMap
kubectl get -n kube-system configmap/aws-auth -o yaml > /tmp/aws-auth-patch.yml
kubectl patch configmap/aws-auth -n kube-system --patch "$(cat /tmp/aws-auth-patch.yml)"
Result: configmap/aws-auth patched
Get GitHub Access Token
In GitHub, go to Settings > Developer settings > Personal access tokens > Generate new token
Create CloudFormation Stack
- Modify
ci-cd-codepipeline.cfn.yaml
file - Review the resources
- Create stack
Create CodePipeline
Details in buildspec.yml
file
Check CodePipeline Deployment
Test Endpoint
kubectl get services simple-jwt-api -o wide
Request method POST
:
export TOKEN=`curl -d '{"email":"khoivn@email.com","password":"mypwd"}' -H "Content-Type: application/json" -X POST ad4d5c8ff64e142a7b7adba1b35a5b56-2013205018.us-east-1.elb.amazonaws.com/auth | jq -r '.token'`
Request method GET
:
curl --request GET 'ad4d5c8ff64e142a7b7adba1b35a5b56-2013205018.us-east-1.elb.amazonaws.com/contents' -H "Authorization: Bearer ${TOKEN}" | jq
Result:
{
"email": "khoivn@email.com",
"exp": 1698029355,
"nbf": 1696819755
}
Delete CloudFormation Stack
aws cloudformation delete-stack --stack-name <stack-name>
Delete EKS Cluster
eksctl delete cluster --name <eksname> --region=us-east-1