diff --git a/z1/minikube-linux-amd64 b/z1/minikube-linux-amd64 new file mode 100644 index 0000000..af25bb2 Binary files /dev/null and b/z1/minikube-linux-amd64 differ diff --git a/z2/README.md b/z2/README.md new file mode 100644 index 0000000..2dade06 --- /dev/null +++ b/z2/README.md @@ -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. diff --git a/z2/backend/Dockerfile b/z2/backend/Dockerfile new file mode 100644 index 0000000..be27c94 --- /dev/null +++ b/z2/backend/Dockerfile @@ -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"] diff --git a/z2/backend/app.py b/z2/backend/app.py new file mode 100644 index 0000000..dbfb451 --- /dev/null +++ b/z2/backend/app.py @@ -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) diff --git a/z2/check.sh b/z2/check.sh new file mode 100755 index 0000000..c50591c --- /dev/null +++ b/z2/check.sh @@ -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 + diff --git a/z2/compose.yaml b/z2/compose.yaml new file mode 100644 index 0000000..b2c82d1 --- /dev/null +++ b/z2/compose.yaml @@ -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: diff --git a/z2/deployment.yaml b/z2/deployment.yaml new file mode 100644 index 0000000..53efc0f --- /dev/null +++ b/z2/deployment.yaml @@ -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 diff --git a/z2/minikube-linux-amd64 b/z2/minikube-linux-amd64 new file mode 100644 index 0000000..af25bb2 Binary files /dev/null and b/z2/minikube-linux-amd64 differ diff --git a/z2/prepare-app.sh b/z2/prepare-app.sh new file mode 100755 index 0000000..71b6da2 --- /dev/null +++ b/z2/prepare-app.sh @@ -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 diff --git a/z2/redis-service.yaml b/z2/redis-service.yaml new file mode 100644 index 0000000..35eedea --- /dev/null +++ b/z2/redis-service.yaml @@ -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. diff --git a/z2/service.yaml b/z2/service.yaml new file mode 100644 index 0000000..c02b7ed --- /dev/null +++ b/z2/service.yaml @@ -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 diff --git a/z2/start-app.sh b/z2/start-app.sh new file mode 100755 index 0000000..307b9c0 --- /dev/null +++ b/z2/start-app.sh @@ -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 diff --git a/z2/statefulset.yaml b/z2/statefulset.yaml new file mode 100644 index 0000000..f2f3587 --- /dev/null +++ b/z2/statefulset.yaml @@ -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. diff --git a/z2/stop-app.sh b/z2/stop-app.sh new file mode 100755 index 0000000..e966df5 --- /dev/null +++ b/z2/stop-app.sh @@ -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 diff --git a/z2/web-deployment.yaml b/z2/web-deployment.yaml new file mode 100644 index 0000000..11bf383 --- /dev/null +++ b/z2/web-deployment.yaml @@ -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 diff --git a/z2/web-service.yaml b/z2/web-service.yaml new file mode 100644 index 0000000..39584bf --- /dev/null +++ b/z2/web-service.yaml @@ -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 diff --git a/z2/web/Dockerfile b/z2/web/Dockerfile new file mode 100644 index 0000000..107f355 --- /dev/null +++ b/z2/web/Dockerfile @@ -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 diff --git a/z2/web/index.html b/z2/web/index.html new file mode 100644 index 0000000..d63b496 --- /dev/null +++ b/z2/web/index.html @@ -0,0 +1,28 @@ + + +
+ + +This page has been visited 0 times.
+ + + +