From b847151e1d2490b86ba449c479dcf8bb75e2c8c8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 16 Apr 2025 11:02:37 +0200 Subject: [PATCH] hafzalk --- z1/z2/Dockerfile | 9 ++++ z1/z2/README.md | 32 ++++++++++++ z1/z2/app/main.py | 81 ++++++++++++++++++++++++++++++ z1/z2/app/requirements.txt | 5 ++ z1/z2/k8s/deployment.yaml | 32 ++++++++++++ z1/z2/k8s/migrate-job.yaml | 12 +++++ z1/z2/k8s/namespace.yaml | 4 ++ z1/z2/k8s/postgres-deployment.yaml | 57 +++++++++++++++++++++ z1/z2/k8s/service.yaml | 13 +++++ z1/z2/prepare-app.sh | 10 ++++ z1/z2/start-app.sh | 18 +++++++ z1/z2/stop-app.sh | 18 +++++++ 12 files changed, 291 insertions(+) create mode 100644 z1/z2/Dockerfile create mode 100644 z1/z2/README.md create mode 100644 z1/z2/app/main.py create mode 100644 z1/z2/app/requirements.txt create mode 100644 z1/z2/k8s/deployment.yaml create mode 100644 z1/z2/k8s/migrate-job.yaml create mode 100644 z1/z2/k8s/namespace.yaml create mode 100644 z1/z2/k8s/postgres-deployment.yaml create mode 100644 z1/z2/k8s/service.yaml create mode 100755 z1/z2/prepare-app.sh create mode 100755 z1/z2/start-app.sh create mode 100755 z1/z2/stop-app.sh diff --git a/z1/z2/Dockerfile b/z1/z2/Dockerfile new file mode 100644 index 0000000..a7e0bc1 --- /dev/null +++ b/z1/z2/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY app/ . + +RUN pip install --no-cache-dir -r requirements.txt + +CMD ["python", "main.py"] diff --git a/z1/z2/README.md b/z1/z2/README.md new file mode 100644 index 0000000..413be49 --- /dev/null +++ b/z1/z2/README.md @@ -0,0 +1,32 @@ +# Flask + PostgreSQL Kubernetes Deployment + +This project deploys a Flask web application with a PostgreSQL backend using Kubernetes. + +## 🛠 Structure + +- `app/`: Flask source code (`main.py`, `requirements.txt`) +- `k8s/`: Kubernetes manifests for deployments, services, namespace, etc. +- `Dockerfile`: Builds the Flask app image +- `prepare-app.sh`: Builds Docker image and prepares volumes +- `start-app.sh`: Applies all Kubernetes objects +- `stop-app.sh`: Deletes all Kubernetes resources +- `statefulset.yaml`: Defines StatefulSet, PV, and PVC + +## 🚀 Steps to Deploy + +1. **Prepare the application:** + ```bash + ./prepare-app.sh + + +hafzal03@LAPTOP-ELUS3HGM:~/mypro/z2$ kubectl get pods -n webapp-namespace +NAME READY STATUS RESTARTS AGE +flask-app-6b844bf6-cq9t6 1/1 Running 0 8m37s +postgres-644fc4c86d-l9h4f 1/1 Running 0 14m +hafzal03@LAPTOP-ELUS3HGM:~/mypro/z2$ minikube service flask-service -n webapp-namespace + +minikube service flask-service -n webapp-namespace + +kubectl get pods -n webapp-namespace + +kubectl rollout restart deployment flask-app -n webapp-namespace diff --git a/z1/z2/app/main.py b/z1/z2/app/main.py new file mode 100644 index 0000000..74c109e --- /dev/null +++ b/z1/z2/app/main.py @@ -0,0 +1,81 @@ +from flask import Flask, request, jsonify, render_template_string +import psycopg2 +import os + +app = Flask(__name__) + +def get_db_connection(): + return psycopg2.connect( + host=os.environ.get("POSTGRES_HOST"), + database=os.environ.get("POSTGRES_DB"), + user=os.environ.get("POSTGRES_USER"), + password=os.environ.get("POSTGRES_PASSWORD"), + port=os.environ.get("POSTGRES_PORT", 5432), + ) + +def init_db(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute(""" + CREATE TABLE IF NOT EXISTS students ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + room_number TEXT NOT NULL, + faculty TEXT NOT NULL + ); + """) + conn.commit() + cur.close() + conn.close() + +@app.route("/") +def index(): + return "

Welcome!

Go to /add to add a student, /students to view all.

" + +# HTML Form + POST Submission +@app.route("/add", methods=["GET", "POST"]) +def add_student(): + if request.method == "POST": + name = request.form.get("name") + room_number = request.form.get("room_number") + faculty = request.form.get("faculty") + + if not name or not room_number or not faculty: + return "All fields are required!", 400 + + conn = get_db_connection() + cur = conn.cursor() + cur.execute("INSERT INTO students (name, room_number, faculty) VALUES (%s, %s, %s)", (name, room_number, faculty)) + conn.commit() + cur.close() + conn.close() + return "

Student added successfully!

Add another" + + # HTML form + return render_template_string(""" +

Add Student

+
+ Name:
+ Room Number:
+ Faculty:
+ +
+ """) + +# View all students +@app.route("/students", methods=["GET"]) +def get_students(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT id, name, room_number, faculty FROM students") + rows = cur.fetchall() + cur.close() + conn.close() + + return jsonify([ + {"id": row[0], "name": row[1], "room_number": row[2], "faculty": row[3]} for row in rows + ]) + +if __name__ == "__main__": + init_db() + app.run(host="0.0.0.0", port=8000) diff --git a/z1/z2/app/requirements.txt b/z1/z2/app/requirements.txt new file mode 100644 index 0000000..3a4074c --- /dev/null +++ b/z1/z2/app/requirements.txt @@ -0,0 +1,5 @@ +Flask==2.0.1 +Werkzeug==2.0.3 +psycopg2-binary==2.9.1 +python-dotenv==0.19.0 +Jinja2==3.0.3 diff --git a/z1/z2/k8s/deployment.yaml b/z1/z2/k8s/deployment.yaml new file mode 100644 index 0000000..0dd90fc --- /dev/null +++ b/z1/z2/k8s/deployment.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flask-app + namespace: webapp-namespace +spec: + replicas: 1 + selector: + matchLabels: + app: flask + template: + metadata: + labels: + app: flask + spec: + containers: + - name: flask + image: flask-app:latest + imagePullPolicy: Never + ports: + - containerPort: 8000 + env: + - name: POSTGRES_HOST + value: postgres + - name: POSTGRES_DB + value: mydatabase + - name: POSTGRES_USER + value: myuser + - name: POSTGRES_PASSWORD + value: mypassword + - name: POSTGRES_PORT + value: "5432" diff --git a/z1/z2/k8s/migrate-job.yaml b/z1/z2/k8s/migrate-job.yaml new file mode 100644 index 0000000..b7d81d8 --- /dev/null +++ b/z1/z2/k8s/migrate-job.yaml @@ -0,0 +1,12 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: migrate +spec: + template: + spec: + containers: + - name: migrator + image: myapp:latest + command: ["python", "manage.py", "migrate"] + restartPolicy: Never diff --git a/z1/z2/k8s/namespace.yaml b/z1/z2/k8s/namespace.yaml new file mode 100644 index 0000000..2ef198a --- /dev/null +++ b/z1/z2/k8s/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: webapp-namespace diff --git a/z1/z2/k8s/postgres-deployment.yaml b/z1/z2/k8s/postgres-deployment.yaml new file mode 100644 index 0000000..aaf3c1d --- /dev/null +++ b/z1/z2/k8s/postgres-deployment.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres-pvc + namespace: webapp-namespace +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: webapp-namespace +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:13 + env: + - name: POSTGRES_DB + value: mydatabase + - name: POSTGRES_USER + value: myuser + - name: POSTGRES_PASSWORD + value: mypassword + ports: + - containerPort: 5432 + volumeMounts: + - name: postgres-storage + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-storage + persistentVolumeClaim: + claimName: postgres-pvc +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: webapp-namespace +spec: + selector: + app: postgres + ports: + - port: 5432 diff --git a/z1/z2/k8s/service.yaml b/z1/z2/k8s/service.yaml new file mode 100644 index 0000000..2d83fc9 --- /dev/null +++ b/z1/z2/k8s/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: flask-service + namespace: webapp-namespace +spec: + selector: + app: flask + type: NodePort + ports: + - port: 8000 + targetPort: 8000 + nodePort: 30080 # <-- Changed this diff --git a/z1/z2/prepare-app.sh b/z1/z2/prepare-app.sh new file mode 100755 index 0000000..2090316 --- /dev/null +++ b/z1/z2/prepare-app.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo "Building Docker image for Flask app..." +docker build -t flask-app:latest . + +echo "Creating Minikube image cache (if using Minikube)..." +eval $(minikube docker-env) +docker build -t flask-app:latest . + +echo "Preparation complete." diff --git a/z1/z2/start-app.sh b/z1/z2/start-app.sh new file mode 100755 index 0000000..a869e7a --- /dev/null +++ b/z1/z2/start-app.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +echo "Creating Namespace..." +kubectl apply -f k8s/namespace.yaml + +echo "Creating Persistent Volumes and StatefulSet..." +kubectl apply -f k8s/statefulset.yaml -n webapp-namespace + +echo "Deploying PostgreSQL..." +kubectl apply -f k8s/postgres-deployment.yaml -n webapp-namespace + +echo "Deploying Flask App..." +kubectl apply -f k8s/deployment.yaml -n webapp-namespace + +echo "Creating Service..." +kubectl apply -f k8s/service.yaml -n webapp-namespace + +echo "All resources have been applied." diff --git a/z1/z2/stop-app.sh b/z1/z2/stop-app.sh new file mode 100755 index 0000000..22a14d6 --- /dev/null +++ b/z1/z2/stop-app.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +echo "Deleting Flask App Deployment..." +kubectl delete -f k8s/deployment.yaml -n webapp-namespace + +echo "Deleting Flask Service..." +kubectl delete -f k8s/service.yaml -n webapp-namespace + +echo "Deleting PostgreSQL Deployment and PVC..." +kubectl delete -f k8s/postgres-deployment.yaml -n webapp-namespace + +echo "Deleting StatefulSet and PVs..." +kubectl delete -f k8s/statefulset.yaml -n webapp-namespace + +echo "Deleting Namespace..." +kubectl delete -f k8s/namespace.yaml + +echo "All resources have been deleted."