This commit is contained in:
Muhammed Tariq Ali Razvi 2025-04-09 06:48:50 +02:00
parent 7806001c1d
commit f16847f1fd
18 changed files with 330 additions and 0 deletions

BIN
z1/minikube-linux-amd64 Normal file

Binary file not shown.

69
z2/README.md Normal file
View File

@ -0,0 +1,69 @@
# Visitor Counter Application
## Description of the Application
This application is designed to count the number of visits to a webpage. It utilizes Flask for the backend, Apache for serving static web content, and Redis for storing visitor counts.
## List of Containers Used
- **Backend Container**: Built using Flask, this container handles API requests and updates visitor counts in Redis.
- **Web Container**: Built using Apache, this container serves static HTML content.
- **Redis Container**: Uses the official Redis image to store visitor counts persistently.
## List of Kubernetes Objects
- **Deployments**:
- **Backend Deployment**: Manages the backend Flask application.
- **Web Deployment**: Manages the web Apache server.
- **Services**:
- **Backend Service**: Exposes the backend application on a specific port.
- **Web Service**: Exposes the web server on a specific port.
- **Redis Service**: Provides access to the Redis database.
- **StatefulSet**:
- **Redis StatefulSet**: Ensures persistent storage for Redis data.
- **PersistentVolumeClaim (PVC)** and **PersistentVolume (PV)**:
- Used for providing persistent storage to Redis.
## Virtual Networks and Named Volumes
- **Virtual Networks**: Kubernetes automatically manages pod-to-pod communication within a cluster.
- **Named Volumes**: Used for persistent storage in Redis, ensuring data is retained across pod restarts.
## Container Configuration
- **Backend Container**: Configured to listen on port 5000 and connect to Redis for storing visitor counts.
- **Web Container**: Configured to serve static HTML content on port 80.
- **Redis Container**: Configured to store data persistently using a PersistentVolumeClaim.
## Instructions to Prepare, Run, Pause, and Delete the Application
1. **Prepare the Application**:
Run the `prepare-app.sh` script to build Docker images and load them into Minikube.
./prepare-app.sh
2. **Run the Application**:
Run the `start-app.sh` script to create all necessary Kubernetes objects and start the application.
./start-app.sh
3. **Pause the Application**:
You can pause the application by scaling down deployments to zero replicas:
kubectl scale deployment backend-deployment --replicas=0
kubectl scale deployment web-deployment --replicas=0
4. **Delete the Application**:
Run the `stop-app.sh` script to delete all Kubernetes objects and stop the application.
./stop-app.sh
## Instructions to View the Application on the Web
1. **Access the Web Service**:
Use Minikube to access the web service:
minikube service web-service --url
This will output a URL that you can use to view the application in your web browser by ctrl+clicking on the link.

11
z2/backend/Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM python:3.9-slim
WORKDIR /app
COPY app.py /app/
RUN pip install flask redis flask-cors
EXPOSE 5000
CMD ["python", "app.py"]

18
z2/backend/app.py Normal file
View File

@ -0,0 +1,18 @@
from flask import Flask, jsonify
from flask_cors import CORS
import redis
app = Flask(__name__)
CORS(app)
# Connect to Redis (running in a separate container and foldr)
redis_client = redis.StrictRedis(host='redis', port=6379, decode_responses=True)
@app.route('/counter', methods=['GET'])
def counter():
# Increment visitor count in Redis
visits = redis_client.incr('visits')
return jsonify({"visits": visits})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

23
z2/check.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
# list all namespaces
echo "Namespaces:"
kubectl get namespaces
# list all statefulsets
echo "\nStatefulSets:"
kubectl get statefulsets
# list all services
echo "\nServices:"
kubectl get services
# list all deployments
echo "\nDeployments:"
kubectl get deployments
# list all pods
echo "\nPods:"
kubectl get pods

28
z2/compose.yaml Normal file
View File

@ -0,0 +1,28 @@
version: '3.8'
services:
web:
build: ./web
ports:
- "5000:80"
depends_on:
- backend
restart: always
backend:
build: ./backend
ports:
- "5001:5000"
depends_on:
- redis
restart: always
redis:
image: redis:alpine
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_data:/data
restart: always
volumes:
redis_data:

20
z2/deployment.yaml Normal file
View File

@ -0,0 +1,20 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-deployment
spec:
replicas: 1
selector:
matchLabels:
app: backend-app
template:
metadata:
labels:
app: backend-app
spec:
containers:
- name: backend-container
image: backend:latest
imagePullPolicy: IfNotPresent #uses local images if available
ports:
- containerPort: 5000

BIN
z2/minikube-linux-amd64 Normal file

Binary file not shown.

9
z2/prepare-app.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
# build Docker images for backend and web
docker build -t backend:latest ./backend
docker build -t web:latest ./web
# load images into minikube
minikube image load backend:latest
minikube image load web:latest

11
z2/redis-service.yaml Normal file
View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis-app # This must match the pod label in StatefulSet.
ports:
- name: redis-port
port: 6379 # External port for Redis.
targetPort: 6379 # Internal container port.

12
z2/service.yaml Normal file
View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend-app
ports:
- name: http
port: 5000
targetPort: 5000
type: NodePort

15
z2/start-app.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# start minikube
minikube start
# apply all Kubernetes YAML files
kubectl apply -f backend-deployment.yaml
kubectl apply -f web-deployment.yaml
kubectl apply -f statefulset.yaml
kubectl apply -f backend-service.yaml
kubectl apply -f web-service.yaml
kubectl apply -f redis-service.yaml
# Output web service URL
minikube service web-service --url

31
z2/statefulset.yaml Normal file
View File

@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-statefulset
spec:
serviceName: "redis-service"
replicas: 1
selector:
matchLabels:
app: redis-app
template:
metadata:
labels:
app: redis-app
spec:
containers:
- name: redis-container
image: redis:alpine # Redis image.
ports:
- containerPort: 6379 # Redis default port.
volumeMounts:
- name: redis-storage-volume # Mount persistent volume.
mountPath: /data # Redis data directory.
volumeClaimTemplates:
- metadata:
name: redis-storage-volume # Persistent Volume Claim.
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi # Persistent storage size.

12
z2/stop-app.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
# delete all Kubernetes objects
kubectl delete -f backend-deployment.yaml
kubectl delete -f web-deployment.yaml
kubectl delete -f statefulset.yaml
kubectl delete -f backend-service.yaml
kubectl delete -f web-service.yaml
kubectl delete -f redis-service.yaml
# stop minikube
minikube stop

20
z2/web-deployment.yaml Normal file
View File

@ -0,0 +1,20 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 1
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-container
image: web:latest
imagePullPolicy: IfNotPresent #same thing uses local image if any
ports:
- containerPort: 80

12
z2/web-service.yaml Normal file
View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web-app
ports:
- name: http
port: 80
targetPort: 80
type: NodePort

11
z2/web/Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM httpd:2.4
# Copies your static HTML file into the Apache document root
COPY index.html /usr/local/apache2/htdocs/
# Add a proxy configuration for /counter
RUN echo "ProxyPass /counter http://backend-service:5000/counter" >> /usr/local/apache2/conf/httpd.conf
RUN echo "ProxyPassReverse /counter http://backend-service:5000/counter" >> /usr/local/apache2/conf/httpd.conf
EXPOSE 80

28
z2/web/index.html Normal file
View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Visitor Counter</title>
</head>
<body>
<h1>Welcome to the Visitor Counter App!</h1>
<h2>Made by ALI</h2>
<h3>Also made for assinment 1</h3>
<p>This page has been visited <span id="counter">0</span> times.</p>
<script>
async function updateCounter() {
try {
const response = await fetch('/counter');
const data = await response.json();
document.getElementById('counter').textContent = data.visits;
} catch (error) {
console.error('Error fetching counter:', error);
}
}
updateCounter();
</script>
</body>
</html>