FlaskScaleHub: Boosting a Two-Tier Flask-MySQL App to Handle 10,000 Users on Kubernetes and EKS
Create an AWS t2.micro Instance:
Log into your AWS Management Console.
Navigate to the EC2 Dashboard and launch a new instance.
Select the
t2.micro
instance type, which is eligible for the free tier.Configure the instance details, storage, and tags as required.
Configure the security group to allow inbound traffic on the ports you will use (e.g., SSH on port 22, HTTP on port 80, and other ports as per your requirement).
Review and launch the instance.
Create a new key pair or select an existing one, then download it to be able to SSH into the instance.
Connect to Your Instance:
Clone the code on your server.
Sudo apt update
update your server.
sudo apt install docker.io
install docker.
docker ps
this command shows running containers on your server.
you will see permission denied error.
sudo chown $USER /var/run/docker.sock
in order to change permissions, use this command.
Now, create a docker file according app.py. the code given by developer.
Vim Dockerfile
# Use an official Python runtime as the base image
FROM python:3.9-slim
# Set the working directory in the container
WORKDIR /app
# install required packages for system
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y gcc default-libmysqlclient-dev pkg-config \
&& rm -rf /var/lib/apt/lists/*
# Copy the requirements file into the container
COPY requirements.txt .
# Install app dependencies
RUN pip install mysqlclient
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application code
COPY . .
# Specify the command to run your application
CMD ["python", "app.py"]
create vim requirements.txt
file: all the required libraries.
Flask==2.0.1
Flask-MySQLdb==0.2.0
requests==2.26.0
Werkzeug==2.0.1
cannot connect o server error. Kill the mysql conatiner and again run it.
Because i have create two containers but they are not connected. so, to connect them create anetwork and place both of them in same network.
Again run conatiners, this time they are in same network.
In order to understand network, inspect that network twotier:
Here, are two conatiners with the name of "youthful_gould" and "ecstatic_beaver". so change thier names with "flask-app" and "mysql" resp.
Kill old conatiners and rename them.
The error message displayed on your screen is a MySQL database connection issue:
MySQLdb.OperationalError: (1044, "Access denied for user 'admin'@'%' to database 'default_db'")
This suggests that the user admin
does not have the necessary permissions to access the default_db
database. Here are some steps to address the issue.
As database is already exist but there is command type error in container run command.
now i kill containers and again run it , just to check if data entered is mysql is persist or not.
data is deleted, have to create table again and add data.
in order to persist data in conatiner attach a volume to mysql container. kill mysql container and add volume to it.
docker volume create mysql_data
docker run -d -p 3306:3306 --network=twotier -e MYSQL_ROOT_PASSWORD=admin -e MYSQL_DATABASE=myDb -e MYSQL_USER=admin -e MYSQL_PASSWORD=admin --name=mysql -v mysql_data:/var/lib/mysql mysql:5.7
Docker-compose
Kubernetes: now deploy the same project on kuberenetes:
first need to set up kubenetes cluster b using kubeadm: follow link
worker nodejoined the cluster.
On master node:
now master and worker nodes are set.
now, create manifest files for pod, deployment, service, mysql-deployment, mysql-service, persistent volume, persistent volume claim.
First create poad file:
vim two-tier-app-pod.yml
kubectl apply -f two-tier-app-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: two-tier-app-pod
spec:
containers:
- name: two-tier-app-pod
image: pardeepkaur/two-tier-flask-app:latest
env:
- name: MYSQL_HOST
value: "mysql"
- name: MYSQL_PASSWORD
value: "admin"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_DB
value: "mydb"
ports:
- containerPort: 5000
imagePullPolicy: Always
second create deployment file: Deployment is use to scale the pods according to application requirements.
vim two-tier-app-deployment.yml
kubectl apply -f two-tier-app-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: two-tier-app-deployment
labels:
app: two-tier-app
spec:
replicas: 1
selector:
matchLabels:
app: two-tier-app
template:
metadata:
labels:
app: two-tier-app
spec:
containers:
- name: two-tier-app
image: pardeepkaur/two-tier-flask-app:latest
env:
- name: MYSQL_HOST
value: "mysql" # this is your mysql's service clusture IP, Make sure to change it with yours
- name: MYSQL_PASSWORD
value: "admin"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_DB
value: "mydb"
ports:
- containerPort: 5000
imagePullPolicy: Always
On worker node: because conatiners are running on worker nodes.
docker ps
to check the running containers.
sudo chown $USER /var/run/docker.sock
to change the permissions of currect user. give permissions of docker to current user.
whoami
to check current user.
now one container is up and running. make a service file so that this conatiner able to connect with externel user.
vim two-tier-app-svc.yml
kubectl apply -f two-tier-app-svc.yml
apiVersion: v1
kind: Service
metadata:
name: two-tier-app-service
spec:
selector:
app: two-tier-app
ports:
- protocol: TCP
port: 80
targetPort: 5000
nodePort: 30007
type: NodePort
Now, output will be: as mysql conatiner is not up and running therefore, it shows error there.
Now, create a mysql conatiner:
vim mysql-deployment.yml
kubectl apply -f mysql-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:latest
env:
- name: MYSQL_ROOT_PASSWORD
value: "admin"
- name: MYSQL_DATABASE
value: "mydb"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_PASSWORD
value: "admin"
ports:
- containerPort: 3306
kubectl get pods
to check running pods
for auto scaling of pods: kubectl scale deployment mysql-deployment --replicas=2
kubectl scale deployment two-tier-app-deployemnt --replicas=2
the error crashLoopBackoff shows because i have created mysql pod but till now i didnt gave service to mysql pod. first create volume file then create claim file that will claim that volume and then give service to mysql pod.
vim mysql-pv.yml
kubectl apply -f mysql-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 256Mi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /home/ubuntu/two-tier-flask-app/mysqldata #This is your host path where your data will be stored. Make sure to create mysqldata directory in mentioned path
vim mysql-pvc.yml
kubectl apply -f mysql-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 256Mi
after create volume configure mysql-deployment file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:latest
env:
- name: MYSQL_ROOT_PASSWORD
value: "admin"
- name: MYSQL_DATABASE
value: "mydb"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_PASSWORD
value: "admin"
ports:
- containerPort: 3306
volumeMounts:
- name: mysqldata
mountPath: /var/lib/mysql # this is your container path from where your data will be stored
volumes:
- name: mysqldata
persistentVolumeClaim:
claimName: mysql-pvc # PVC claim name
due to some identation i got this error- CrashLoopBackOff error.
on worder node:
I corrected some identation and mysql-deployment is up and running.
Auto healing
on worker node: if one of pod is deleted
if one of pod is deleted, automatically a new pod will be generated, see in restarts.
now, create service for mysql:
vim mysql-svc.yml
kubectl apply -f mysql-svc.yml
then, output will be:
because, two-tier-flask-app pod not able to connect to mysql conatiner. so configure vim two-tier-flask-app-deployment.yml
paste the mysql-service clusterIp.
apiVersion: apps/v1
kind: Deployment
metadata:
name: two-tier-app
labels:
app: two-tier-app
spec:
replicas: 1
selector:
matchLabels:
app: two-tier-app
template:
metadata:
labels:
app: two-tier-app
spec:
containers:
- name: two-tier-app
image: pardeepkaur/two-tier-flask-app
env:
- name: MYSQL_HOST
value: "10.110.24.236" # this is your mysql's service clusture IP, Make sure to change it with yours
- name: MYSQL_PASSWORD
value: "admin"
- name: MYSQL_USER
value: "root"
- name: MYSQL_DB
value: "mydb"
ports:
- containerPort: 5000
imagePullPolicy: Always
then output will be: