new z2 and old z2-failed
This commit is contained in:
parent
f16847f1fd
commit
52444ad27d
69
z2-failed/README.md
Normal file
69
z2-failed/README.md
Normal 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.
|
22
z2-failed/backend/app.py
Normal file
22
z2-failed/backend/app.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
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-service', port=6379, decode_responses=True)
|
||||||
|
|
||||||
|
@app.route('/counter', methods=['GET'])
|
||||||
|
def counter():
|
||||||
|
try:
|
||||||
|
visits = redis_client.incr('visits')
|
||||||
|
print(f"[INFO] Visit count: {visits}")
|
||||||
|
return jsonify({"visits": visits})
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Redis connection failed: {e}")
|
||||||
|
return jsonify({"error": "Could not connect to Redis"}), 500
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True, host='0.0.0.0', port=80)
|
@ -2,6 +2,7 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: backend-deployment
|
name: backend-deployment
|
||||||
|
namespace: visitor-app
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
4
z2-failed/namespace.yaml
Normal file
4
z2-failed/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: visitor-app
|
9
z2-failed/prepare-app.sh
Executable file
9
z2-failed/prepare-app.sh
Executable 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
|
@ -2,6 +2,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: redis-service
|
name: redis-service
|
||||||
|
namespace: visitor-app
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: redis-app # This must match the pod label in StatefulSet.
|
app: redis-app # This must match the pod label in StatefulSet.
|
@ -2,6 +2,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: backend-service
|
name: backend-service
|
||||||
|
namespace: visitor-app
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: backend-app
|
app: backend-app
|
18
z2-failed/start-app.sh
Executable file
18
z2-failed/start-app.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# start minikube
|
||||||
|
minikube start
|
||||||
|
|
||||||
|
#create namespace
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
|
||||||
|
# apply all Kubernetes YAML files
|
||||||
|
kubectl apply -f deployment.yaml -n visitor-app
|
||||||
|
kubectl apply -f web-deployment.yaml -n visitor-app
|
||||||
|
kubectl apply -f statefulset.yaml -n visitor-app
|
||||||
|
kubectl apply -f service.yaml -n visitor-app
|
||||||
|
kubectl apply -f web-service.yaml -n visitor-app
|
||||||
|
kubectl apply -f redis-service.yaml -n visitor-app
|
||||||
|
|
||||||
|
# Output web service URL
|
||||||
|
#minikube service web-service --url
|
@ -2,6 +2,7 @@ apiVersion: apps/v1
|
|||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
metadata:
|
metadata:
|
||||||
name: redis-statefulset
|
name: redis-statefulset
|
||||||
|
namespace: visitor-app
|
||||||
spec:
|
spec:
|
||||||
serviceName: "redis-service"
|
serviceName: "redis-service"
|
||||||
replicas: 1
|
replicas: 1
|
7
z2-failed/stop-app.sh
Executable file
7
z2-failed/stop-app.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# delete the whole namespace since it will deleat all resoruces inside it
|
||||||
|
kubectl delete namespace visitor-app
|
||||||
|
|
||||||
|
# stop minikube
|
||||||
|
minikube stop
|
@ -2,6 +2,7 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: web-deployment
|
name: web-deployment
|
||||||
|
namespace: visitor-app
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
@ -2,6 +2,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: web-service
|
name: web-service
|
||||||
|
namespace: visitor-app
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: web-app
|
app: web-app
|
20
z2-failed/web/Dockerfile
Normal file
20
z2-failed/web/Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM httpd:2.4
|
||||||
|
|
||||||
|
# Enable mod_proxy and mod_proxy_http
|
||||||
|
RUN sed -i '/^#LoadModule proxy_module/s/^#//' /usr/local/apache2/conf/httpd.conf && \
|
||||||
|
sed -i '/^#LoadModule proxy_http_module/s/^#//' /usr/local/apache2/conf/httpd.conf
|
||||||
|
|
||||||
|
# Copy the HTML file
|
||||||
|
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 && \
|
||||||
|
# echo "ProxyPassReverse /counter http://backend-service:5000/counter" >> /usr/local/apache2/conf/httpd.conf
|
||||||
|
|
||||||
|
|
||||||
|
#Add a proxy configuration for /counter
|
||||||
|
RUN echo "ProxyPass /counter http://backend-service.visitor-app.svc.cluster.local:5000/counter" >> /usr/local/apache2/conf/httpd.conf && \
|
||||||
|
echo "ProxyPassReverse /counter http://backend-service.visitor-app.svc.cluster.local:5000/counter" >> /usr/local/apache2/conf/httpd.conf
|
||||||
|
|
||||||
|
|
||||||
|
EXPOSE 80
|
@ -8,7 +8,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>Welcome to the Visitor Counter App!</h1>
|
<h1>Welcome to the Visitor Counter App!</h1>
|
||||||
<h2>Made by ALI</h2>
|
<h2>Made by ALI</h2>
|
||||||
<h3>Also made for assinment 1</h3>
|
<h3>Also copied from assinemnt 1 to make assinment 2</h3>
|
||||||
<p>This page has been visited <span id="counter">0</span> times.</p>
|
<p>This page has been visited <span id="counter">0</span> times.</p>
|
||||||
|
|
||||||
<script>
|
<script>
|
136
z2/README.md
136
z2/README.md
@ -1,69 +1,105 @@
|
|||||||
# Visitor Counter Application
|
# Web Form Application with PostgreSQL on Kubernetes
|
||||||
|
|
||||||
## Description of the Application
|
## 📌 Application Description
|
||||||
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
|
This project is a simple web application built with Flask that provides a form for user input. The form collects the following data:
|
||||||
|
- Name
|
||||||
|
- Middle name
|
||||||
|
- Surname
|
||||||
|
- Age
|
||||||
|
|
||||||
- **Backend Container**: Built using Flask, this container handles API requests and updates visitor counts in Redis.
|
Upon submission, the data is stored in a PostgreSQL database. A confirmation message is displayed once the data is successfully inserted.
|
||||||
- **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**:
|
## 🐳 Containers Used
|
||||||
- **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
|
1. **web-app**
|
||||||
|
- A Python Flask-based container serving the HTML form and handling form submission.
|
||||||
|
- Connects to the PostgreSQL container using environment variables.
|
||||||
|
|
||||||
- **Virtual Networks**: Kubernetes automatically manages pod-to-pod communication within a cluster.
|
2. **postgres**
|
||||||
- **Named Volumes**: Used for persistent storage in Redis, ensuring data is retained across pod restarts.
|
- Official PostgreSQL container used as the backend database.
|
||||||
|
- Uses a named volume to persist data.
|
||||||
|
- Initializes the database and the `users` table using a custom `init.sql` script.
|
||||||
|
|
||||||
## Container Configuration
|
---
|
||||||
|
|
||||||
- **Backend Container**: Configured to listen on port 5000 and connect to Redis for storing visitor counts.
|
## 🕸 Kubernetes Objects
|
||||||
- **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
|
| Object | Description |
|
||||||
|
|--------------------|-----------------------------------------------------------------------------|
|
||||||
|
| `Namespace` | Isolates the application under `webform-app`. |
|
||||||
|
| `Deployment` | Manages the Flask web app, ensuring high availability. |
|
||||||
|
| `StatefulSet` | Manages the PostgreSQL database pod with persistent identity and storage. |
|
||||||
|
| `Service` | Exposes both the web app and PostgreSQL internally via DNS. |
|
||||||
|
| `PersistentVolume` | Provides physical storage for PostgreSQL data. |
|
||||||
|
| `PersistentVolumeClaim` | Requests storage for the StatefulSet. |
|
||||||
|
|
||||||
1. **Prepare the Application**:
|
---
|
||||||
Run the `prepare-app.sh` script to build Docker images and load them into Minikube.
|
|
||||||
|
|
||||||
./prepare-app.sh
|
## 🌐 Virtual Networks & Volumes
|
||||||
|
|
||||||
|
- **Virtual Networking**: Kubernetes Services provide internal DNS-based networking. The Flask app communicates with PostgreSQL using the service name `postgres` within the same namespace.
|
||||||
|
|
||||||
|
- **Named Volumes**:
|
||||||
|
- A named volume is mounted at `/var/lib/postgresql/data` in the PostgreSQL container to persist database data across pod restarts.
|
||||||
|
|
||||||
|
---
|
||||||
|
## ⚙️ Container Configuration
|
||||||
|
|
||||||
|
- Flask container:
|
||||||
|
- Dockerized using `python:3.11-slim` as the base image.
|
||||||
|
- `flask` and `psycopg2-binary` installed.
|
||||||
|
- `app.py` and `index.html` are copied into the container.
|
||||||
|
- Uses port `5000`.
|
||||||
|
|
||||||
|
- PostgreSQL container:
|
||||||
|
- Uses `docker-entrypoint-initdb.d/init.sql` to initialize the database (`userdb`) and create the `users` table on first run.
|
||||||
|
- Uses environment variables for default credentials and database name.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
2. **Run the Application**:
|
## 🛠️ Instructions
|
||||||
Run the `start-app.sh` script to create all necessary Kubernetes objects and start the application.
|
|
||||||
./start-app.sh
|
### ✅ Prepare the Application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create namespace
|
||||||
|
kubectl apply -f kubi/namespace.yaml
|
||||||
|
|
||||||
|
# Create persistent volume and claim
|
||||||
|
kubectl apply -f kubi/pv.yaml
|
||||||
|
kubectl apply -f kubi/pvc.yaml
|
||||||
|
|
||||||
|
# Deploy PostgreSQL StatefulSet and Service
|
||||||
|
kubectl apply -f kubi/postgres-statefulset.yaml
|
||||||
|
kubectl apply -f kubi/postgres-service.yaml
|
||||||
|
|
||||||
|
# Deploy Flask web app and Service
|
||||||
|
kubectl apply -f kubi/webapp-deployment.yaml
|
||||||
|
kubectl apply -f kubi/webapp-service.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
3. **Pause the Application**:
|
# Run the Application
|
||||||
You can pause the application by scaling down deployments to zero replicas:
|
kubectl get pods -n webform-app
|
||||||
|
|
||||||
kubectl scale deployment backend-deployment --replicas=0
|
# You can pause the app using:
|
||||||
kubectl scale deployment web-deployment --replicas=0
|
kubectl scale deployment web-app --replicas=0 -n webform-app
|
||||||
|
|
||||||
|
# Delete the app
|
||||||
|
kubectl delete -f kubi/ --recursive
|
||||||
|
|
||||||
|
# to view the app in browser
|
||||||
|
# find the NodePort exposed by the web app
|
||||||
|
kubectl get svc -n webform-app
|
||||||
|
|
||||||
|
# Then open broswerr and go to
|
||||||
|
http://<your-node-ip>:<node-port>
|
||||||
|
|
||||||
|
# Since its minikube use
|
||||||
|
minikube service web-app-service -n webform-app
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
15
z2/app/Dockerfile
Normal file
15
z2/app/Dockerfile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dependencies directly
|
||||||
|
RUN pip install flask psycopg2-binary
|
||||||
|
|
||||||
|
#checking flask version
|
||||||
|
RUN python -c "import flask; print(flask.__version__)"
|
||||||
|
#copy app files
|
||||||
|
COPY app.py .
|
||||||
|
COPY index.html .
|
||||||
|
|
||||||
|
# start app
|
||||||
|
CMD ["python3", "app.py"]
|
60
z2/app/app.py
Normal file
60
z2/app/app.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
from flask import Flask, request, render_template
|
||||||
|
import psycopg2
|
||||||
|
import os
|
||||||
|
|
||||||
|
app = Flask(__name__, template_folder=".")
|
||||||
|
|
||||||
|
# This function runs before the first request to create the users table if it doesn't exist
|
||||||
|
#@app.before_first_request
|
||||||
|
def init_db():
|
||||||
|
conn = psycopg2.connect(
|
||||||
|
host=os.environ.get("DB_HOST", "db-service"),
|
||||||
|
database=os.environ.get("DB_NAME", "userdb"),
|
||||||
|
user=os.environ.get("DB_USER", "user"),
|
||||||
|
password=os.environ.get("DB_PASS", "pass")
|
||||||
|
)
|
||||||
|
cur = conn.cursor()
|
||||||
|
# Ensure the users table exists
|
||||||
|
cur.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
surname TEXT,
|
||||||
|
middlename TEXT,
|
||||||
|
age INT
|
||||||
|
);
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET', 'POST'])
|
||||||
|
def index():
|
||||||
|
if request.method == 'POST':
|
||||||
|
name = request.form['name']
|
||||||
|
surname = request.form['surname']
|
||||||
|
middlename = request.form['middlename']
|
||||||
|
age = request.form['age']
|
||||||
|
|
||||||
|
conn = psycopg2.connect(
|
||||||
|
host=os.environ.get("DB_HOST", "db-service"),
|
||||||
|
database=os.environ.get("DB_NAME", "userdb"),
|
||||||
|
user=os.environ.get("DB_USER", "user"),
|
||||||
|
password=os.environ.get("DB_PASS", "pass")
|
||||||
|
)
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("INSERT INTO users (name, surname, middlename, age) VALUES (%s, %s, %s, %s)",
|
||||||
|
(name, surname, middlename, age))
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return f"Hi I am {name}, my middle name is {middlename}, and surname is {surname}, who's {age} years old."
|
||||||
|
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host='0.0.0.0', port=5000)
|
18
z2/app/index.html
Normal file
18
z2/app/index.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>User Form</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Enter Your Details</h2>
|
||||||
|
<form method="POST">
|
||||||
|
Name: <input name="name"><br>
|
||||||
|
Surname: <input name="surname"><br>
|
||||||
|
middle Name: <input name="middlename"><br>
|
||||||
|
Age: <input name="age"><br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
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)
|
|
9
z2/db/init.sql
Normal file
9
z2/db/init.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-- Create the users tabl
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
surname TEXT,
|
||||||
|
middlename TEXT,
|
||||||
|
age INT
|
||||||
|
);
|
||||||
|
|
10
z2/init.sql
Normal file
10
z2/init.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE DATABASE userdb;
|
||||||
|
\c userdb;
|
||||||
|
CREATE TABLE users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
surname TEXT,
|
||||||
|
middlename TEXT,
|
||||||
|
age INT
|
||||||
|
);
|
||||||
|
|
31
z2/kubi/deployment.yaml
Normal file
31
z2/kubi/deployment.yaml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: web-app
|
||||||
|
namespace: webform-app
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: web-app
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: web-app
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: web-app
|
||||||
|
image: web-app:latest
|
||||||
|
imagePullPolicy: Never
|
||||||
|
ports:
|
||||||
|
- containerPort: 5000
|
||||||
|
env:
|
||||||
|
- name: DB_HOST
|
||||||
|
value: db-service
|
||||||
|
- name: DB_NAME
|
||||||
|
value: userdb
|
||||||
|
- name: DB_USER
|
||||||
|
value: user
|
||||||
|
- name: DB_PASS
|
||||||
|
value: pass
|
||||||
|
|
4
z2/kubi/namespace.yaml
Normal file
4
z2/kubi/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: webform-app
|
25
z2/kubi/service.yaml
Normal file
25
z2/kubi/service.yaml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: web-app
|
||||||
|
namespace: webform-app
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: web-app
|
||||||
|
type: NodePort
|
||||||
|
ports:
|
||||||
|
- port: 5000
|
||||||
|
targetPort: 5000
|
||||||
|
nodePort: 30008
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: db-service
|
||||||
|
namespace: webform-app
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: db
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
targetPort: 5432
|
74
z2/kubi/statefulset.yaml
Normal file
74
z2/kubi/statefulset.yaml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: db-pv
|
||||||
|
namespace: webform-app
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 1Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
hostPath:
|
||||||
|
path: "/data/db"
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: db-pvc
|
||||||
|
namespace: webform-app
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
namespace: webform-app
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: db
|
||||||
|
serviceName: "db-service"
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: db
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:14
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: userdb
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
value: user
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
value: pass
|
||||||
|
volumeMounts:
|
||||||
|
- name: db-storage
|
||||||
|
mountPath: /var/lib/postgresql/data
|
||||||
|
- name: db-init
|
||||||
|
mountPath: /docker-entrypoint-initdb.d
|
||||||
|
volumes:
|
||||||
|
- name: db-init
|
||||||
|
configMap:
|
||||||
|
name: db-init-script
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: db-storage
|
||||||
|
spec:
|
||||||
|
accessModes: [ "ReadWriteOnce" ]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
|
@ -1,9 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
docker build -t web-app:latest ./app
|
||||||
# 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
|
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
kubectl apply -f kubi/namespace.yaml
|
||||||
|
kubectl apply -f kubi/statefulset.yaml
|
||||||
|
kubectl create configmap db-init-script --from-file=db/init.sql -n webform-app
|
||||||
|
kubectl apply -f kubi/deployment.yaml
|
||||||
|
kubectl apply -f kubi/service.yaml
|
||||||
|
|
||||||
# start minikube
|
# Get url
|
||||||
minikube start
|
minikube service web-app -n webform-app --url
|
||||||
|
|
||||||
# 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
|
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
kubectl delete -f kubi/service.yaml
|
||||||
|
kubectl delete -f kubi/deployment.yaml
|
||||||
|
kubectl delete -f kubi/statefulset.yaml
|
||||||
|
kubectl delete configmap db-init-script -n webform-app
|
||||||
|
kubectl delete -f kubi/namespace.yaml
|
||||||
|
|
||||||
# delete all Kubernetes objects
|
# stop the minikube
|
||||||
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
|
minikube stop
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
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
|
|
Loading…
Reference in New Issue
Block a user