K8's Assignment Deploying Flask-Microservices and Reddit Clone Application

K8's Assignment Deploying Flask-Microservices and Reddit Clone Application


📍Task 1:

1. Deployment of a Microservices Application on K8s

- Do Mongo Db Deployment

- Do Flask App Deployment

- Connect both using Service Discovery

📍Flask-microservice app

Step 1: Installing minikube on AWS EC2 instance visit this GitHub URL for the guide:

https://github.com/LondheShubham153/kubestarter/blob/main/minikube_installation.md

Step 2: Create a projects directory inside the home directory:

Step 3: Clone this GitHub repository: https://github.com/Varunmargam/microservices-k8s

Inside the project folder:

Step 4: Change the directory to k8s inside the microservices-k8s folder:

It contains the following 6 files:

Deployment Manifest file for the backend: taskmaster.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: taskmaster
  namespace: flask
  labels:
    app: taskmaster
spec:
  replicas: 1
  selector:
    matchLabels:
      app: taskmaster
  template:
    metadata:
      namespace: flask
      labels:
        app: taskmaster
    spec:
      containers:
        - name: taskmaster
          image: trainwithshubham/taskmaster-python:latest
          ports:
            - containerPort: 5000
          imagePullPolicy: Always

Service Manifest file for the backend: taskmaster-svc.yml

apiVersion: v1
kind: Service
metadata:
  name: taskmaster-svc
  namespace: flask
spec:
  selector:
    app: taskmaster
  ports:
    - port: 80
      targetPort: 5000
      nodePort: 30007
  type: NodePort

MongoDB Database Deployment Manifest file: mongo.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongo
  namespace: flask
  labels:
      app: mongo
spec:
  selector:
    matchLabels:
      app: mongo
  template:
    metadata:
      namespace: flask
      labels:
        app: mongo
    spec:
      containers:
        - name: mongo
          image: mongo
          ports:
            - containerPort: 27017
          volumeMounts:
            - name: storage
              mountPath: /data/db
      volumes:
        - name: storage
          persistentVolumeClaim:
            claimName: mongo-pvc

MongoDB Database Service Manifest file: mongo-svc.yml

apiVersion: v1
kind: Service
metadata:
  namespace: flask
  labels:
    app: mongo
  name: mongo
spec:
  ports:
    - port: 27017
      targetPort: 27017
  selector:
    app: mongo

MongoDB Database PersistentVolume Manifest file: mongo-pv.yml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongo-pv
  namespace: flask
spec:
  capacity:
    storage: 256Mi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/db

MongoDB Database PersistentVolumeClaim Manifest file: mongo-pvc.yml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongo-pvc
  namespace: flask
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 256Mi

Step 5: Create a namespace named flask :

Step 6: Executing the kubectl apply commands in this order following the best practice:

Verifying the mongo deployment and the service created:

Step 7: Executing inside the mongo pod to see if we can access it:

kubectl exec -it <pod_name> -n <namespace> -- bash
# If successfully entered the pod then to login to the mongo database do
mongosh

Type exit to exit from the Mongo database.

Step 8: Applying the backend deployment file and verifying it:

Applying the backend service deployment file and verifying it:

Step 8: Verify both pods are running:

Step 9: Testing the application on the minikube ip:

# command to access the service ip:
minikube service taskmaster-svc -n flask --url

# test the application on minikube:
curl -L http://minikube_ip:30007 
# the link that we got from the fiest command

You can see our application is running!

To list the tasks:

curl -L http://minikube_ip:30007/tasks
curl -L http://minikube_ip:30007/task

Step 10: To run the application in our browser we have to expose the deployment and the app service:

# command to expose deployment
kubectl expose deployment taskmaster -n flask --type=NodePort

Exposing the service:

kubectl port-forward svc/taskmaster-svc -n flask 30007:80 --address 0.0.0.0

Before that, we have to expose the port 30007 in the security group of our instance running the minikube.

Now execute the above command:

Now go to your browser and type the link ec2_ip:30007:

I tried to add some data using the command:

curl -d '{"task":"completed the assignment"}' -H "Content-Type: application/json" -X POST http://ec2_ip:30007/task

ISSUE: But, suddenly the connection was refused and the connection in my browser was also refused don't know why? I would appreciate it if you could give some possible solutions or reasons in the comments.


📍Task 2:

2. Deployment of a Reddit-Clone Application

- Do Deployment of the Reddit Clone app

- Write an ingress controller for the same to give a custom route

📍Deployment of a Reddit-Clone Application using Ingress

Step 1: Install minikube on AWS EC2 instance.

Step 2: Inside the projects directory clone using the git clone <HTTP_URL> command this GitHub repository: https://github.com/Varunmargam/reddit-clone-k8s-ingress

It contains 3 manifest files:

Deployment manifest file for the Reddit app: deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: reddit-clone-deployment
  namespace: reddit
  labels:
    app: reddit-clone
spec:
  replicas: 2
  selector:
    matchLabels:
      app: reddit-clone
  template:
    metadata:
      namespace: reddit
      labels:
        app: reddit-clone
    spec:
      containers:
      - name: reddit-clone
        image: rohanrustagi18/redditclone
        ports:
        - containerPort: 3000

Service Manifest file: service.yml

apiVersion: v1
# Indicates this as a service
kind: Service
metadata:
  # Service name
  name: reddit-clone-service
  namespace: reddit
spec:
  selector:
    # Selector for Pods
    app: reddit-clone
  ports:
    # Port Map
  - port: 3000
    targetPort: 3000
    protocol: TCP
  type: LoadBalancer

Ingress Manifest file: ingress.yml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-reddit-app
  namespace: reddit
spec:
  rules:
  - host: "domain.com"
    http:
      paths:
      - pathType: Prefix
        path: "/test"
        backend:
          service:
            name: reddit-clone-service
            port:
              number: 3000
  - host: "*.domain.com"
    http:
      paths:
      - pathType: Prefix
        path: "/test"
        backend:
          service:
            name: reddit-clone-service
            port:
              number: 3000

Step 3: Create a namespace named reddit:

Step 4: Apply the deployment file:

Verifying the pods are running:

Step 5: Apply the service file and verify it:

Step 6: Apply the ingress file and verify it:

Step 7: Exposing the deployment:

Step 8: Exposing the service:

Step 9: Go to the security group of your instance and add the port 3000:

Step 10: Go to your browser and access the application at ec2_ip:3000:


📍Basic Flask-QA Application

The previous 2 assignments had the deployment and the service file inside the GitHub repository. Therefore, I thought of writing a deployment and the service file and tried to deploy a basic Question and Answer Flask application that I got from ChatGPT.

Step 1: Inside the projects directory make a directory named flask-qa:

Step 2: Go inside the flask-qa directory and create a Python file app.py:

Step 3: Copy the below Python code inside this file, then save and quit the Vim editor:

Application code:

from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)

# Mock data for questions and answers
questions = [
    {"id": 1, "title": "What is your favorite programming language?", "answers": []},
    {"id": 2, "title": "How do you deploy a Flask app?", "answers": []},
]

@app.route("/")
def index():
    return render_template("index.html", questions=questions)

@app.route("/ask", methods=["GET", "POST"])
def ask():
    if request.method == "POST":
        title = request.form["title"]
        new_question = {"id": len(questions) + 1, "title": title, "answers": []}
        questions.append(new_question)
        return redirect(url_for("index"))
    return render_template("ask.html")

@app.route("/question/<int:question_id>", methods=["GET", "POST"])
def question(question_id):
    question = next((q for q in questions if q["id"] == question_id), None)
    if not question:
        return redirect(url_for("index"))

    if request.method == "POST":
        answer_text = request.form["answer"]
        question["answers"].append(answer_text)
    return render_template("question.html", question=question)

if __name__ == "__main__":
    app.run(debug=True)

Step 4: Create a requirements.txt file open it in the Vim editor and copy the below content inside the file.

Requirements file:

Flask==2.1.0

Step 5: Create a Dockerfile and copy the below content in it.

Dockerfile:

FROM python:3.8-slim-buster

WORKDIR /app

COPY . /app

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 5000

CMD ["python", "app.py"]

Step 6: Build a Docker image from the Dockerfile with the tag <dockerhub_username>/flask-qa:latest

The below output image shows that the build has been successful:

The docker image has been created:

Now, we will upload this docker image to our DockerHub account.

Step 7: Log in to your DockerHub account:

docker login -u <dockerhub_username>

Step 8: Push this docker image to our DockerHub Account:

docker push <image_name>

Step 9: Go to your DockerHub account and see if the image has been uploaded:

The flask-qa image has been uploaded:

Now, let's start creating the Deployment and Service manifest file.

Step 10: Create a namespace flask-qa:

Step 11: Create a file named deployment.yml and write the deployment manifest file.

(📝Note: Try to write the manifest files on your own and then compare them with the below deployment file)

Deployment Manifest file: deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: qa-deployment
  namespace: flask-qa
  labels:
    app: qa
spec:
  replicas: 1
  selector:
    matchLabels:
      app: qa
  template:
    metadata:
      namespace: flask-qa
      labels:
        app: qa
    spec:
      containers:
      - name: qa-app
        image: varunmargam/flask-qa:latest
        ports:
        - containerPort: 5000

Step 12: Apply the created deployment.yml file by kubectl apply:

Verifying the pods are running:

Step 13: Create a service.yml file and write the Service Manifest file:

Service Manifest file: service.yml

apiVersion: v1
kind: Service
metadata:
  name: qa-svc
  namespace: flask-qa
spec:
  selector:
    app: qa
  type: NodePort
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 5000
    nodePort: 30001

Step 14: Apply service.yml file and verify if the service has been created:

Step 15: Exposing the deployment and service:

Added the port 30001 in the Ec2 Instance security groups inbound rules:

However I was unable to access the application on my browser at port 30001, I would appreciate it if anyone could share what can be the issue with this in the comments.

Shubham Londhe I kindly request your advice on the issues I am facing in the k8s-microservice app and the above flask-qa app.