FlaskScaleHub: Boosting a Two-Tier Flask-MySQL App to Handle 10,000 Users on Kubernetes and EKS

  1. 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.

  2. 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: