Téléverser les fichiers vers "z2"
This commit is contained in:
parent
16aa94ff55
commit
b91eb63711
12
z2/Dockerfile
Normal file
12
z2/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM python:3.9-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY app.py .
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
|
107
z2/README.md
Normal file
107
z2/README.md
Normal file
@ -0,0 +1,107 @@
|
||||
# Shopping List Web Application on Kubernetes
|
||||
|
||||
## Overview
|
||||
This project deploys a Python shopping list web application using Flask and PostgreSQL on a Kubernetes cluster. The application allows users to create, track, and manage their shopping items in a persistent way. The deployment includes a Namespace, Deployments for both the web application and PostgreSQL database, a StatefulSet (with PersistentVolume and PersistentVolumeClaim), and Service.
|
||||
|
||||
## Application Description
|
||||
- Simple shopping list application that allows users to add, mark as purchased, and delete items
|
||||
- Each item can have a quantity associated with it
|
||||
- All data is stored in PostgreSQL for persistence between application restarts
|
||||
- The application uses a Flask web framework with a minimalist interface
|
||||
|
||||
## Containers
|
||||
- **simple-web-app**: Runs the Python Flask application on port 5000
|
||||
- **postgres**: Runs PostgreSQL database to store shopping list items
|
||||
|
||||
## Kubernetes Objects
|
||||
- **Namespace**: Isolates all the resources under `my-app`
|
||||
- **Deployment (Web App)**: Manages the stateless web application pods with 2 replicas for high availability
|
||||
- **Deployment (PostgreSQL)**: Manages the PostgreSQL database with persistent storage
|
||||
- **StatefulSet**: Manages stateful application pods that require persistent storage
|
||||
- **PersistentVolume (PV)**: Provides persistent storage from the host (1GB)
|
||||
- **PersistentVolumeClaim (PVC)**: Claims the PV for storage
|
||||
- **Service (Web App)**: Exposes the web application externally via LoadBalancer
|
||||
- **Service (PostgreSQL)**: Headless service for internal database access
|
||||
|
||||
## Networking and Storage
|
||||
- Internal service discovery allows the web application to connect to PostgreSQL
|
||||
- PostgreSQL uses persistent storage to maintain shopping list data even if pods are restarted
|
||||
- The web application is exposed externally using a LoadBalancer service
|
||||
|
||||
## Container Configuration
|
||||
- The web app container is based on Python and includes Flask and psycopg2
|
||||
- PostgreSQL container uses the official PostgreSQL image
|
||||
- Resource limits and readiness probes are configured for better stability
|
||||
|
||||
## How to Prepare, Run, Pause, and Delete the Application
|
||||
|
||||
1. **Prepare the application:**
|
||||
```bash
|
||||
./prepare-app.sh
|
||||
```
|
||||
This script builds the Docker image and creates the directory for persistent volume.
|
||||
|
||||
2. **Start the application:**
|
||||
```bash
|
||||
./start-app.sh
|
||||
```
|
||||
This script creates all necessary Kubernetes objects in the correct order, including PostgreSQL.
|
||||
|
||||
3. **Pause or delete the application:**
|
||||
```bash
|
||||
./stop-app.sh
|
||||
```
|
||||
This script removes all Kubernetes objects created by `start-app.sh`.
|
||||
|
||||
## Accessing the Application
|
||||
To access the application:
|
||||
|
||||
1. Find the IP address of your Kubernetes node:
|
||||
```bash
|
||||
kubectl get nodes -o wide
|
||||
```
|
||||
|
||||
2. Access the application in your browser at:
|
||||
```
|
||||
http://<NODE_IP>:80
|
||||
```
|
||||
Where `<NODE_IP>` is the IP address of any of your Kubernetes nodes.
|
||||
|
||||
## Application Features
|
||||
- Add items with quantity
|
||||
- Mark items as purchased/unpurchased
|
||||
- Delete items
|
||||
- Items list is separated into "to buy" and "purchased" sections
|
||||
- Data persists between sessions and application restarts
|
||||
|
||||
## Database Schema
|
||||
The application uses a simple PostgreSQL schema:
|
||||
- Table: `shopping_items`
|
||||
- Fields:
|
||||
- `id`: Serial primary key
|
||||
- `item`: Text (item name)
|
||||
- `quantity`: Integer (defaults to 1)
|
||||
- `purchased`: Boolean flag (defaults to false)
|
||||
|
||||
## Troubleshooting
|
||||
If you encounter issues:
|
||||
|
||||
1. Check pod status:
|
||||
```bash
|
||||
kubectl get pods -n my-app
|
||||
```
|
||||
|
||||
2. View pod logs:
|
||||
```bash
|
||||
kubectl logs <pod-name> -n my-app
|
||||
```
|
||||
|
||||
3. Check service status:
|
||||
```bash
|
||||
kubectl get svc -n my-app
|
||||
```
|
||||
|
||||
4. Check database connectivity:
|
||||
```bash
|
||||
kubectl exec -it <web-app-pod-name> -n my-app -- python -c "import psycopg2; conn = psycopg2.connect(host='postgres', dbname='postgres', user='postgres', password='postgres'); print('Connection successful')"
|
||||
```
|
173
z2/app.py
Normal file
173
z2/app.py
Normal file
@ -0,0 +1,173 @@
|
||||
from flask import Flask, request, redirect, url_for, render_template_string
|
||||
import os
|
||||
import psycopg2
|
||||
from psycopg2 import pool
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
DB_HOST = os.environ.get('DB_HOST', 'localhost')
|
||||
DB_PORT = os.environ.get('DB_PORT', '5432')
|
||||
DB_NAME = os.environ.get('DB_NAME', 'postgres')
|
||||
DB_USER = os.environ.get('DB_USER', 'postgres')
|
||||
DB_PASS = os.environ.get('DB_PASS', 'postgres')
|
||||
|
||||
connection_pool = psycopg2.pool.SimpleConnectionPool(
|
||||
1, 10,
|
||||
host=DB_HOST,
|
||||
port=DB_PORT,
|
||||
database=DB_NAME,
|
||||
user=DB_USER,
|
||||
password=DB_PASS
|
||||
)
|
||||
|
||||
def init_db():
|
||||
conn = connection_pool.getconn()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute('''
|
||||
CREATE TABLE IF NOT EXISTS shopping_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
item TEXT NOT NULL,
|
||||
quantity INTEGER DEFAULT 1,
|
||||
purchased BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
''')
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'initialisation de la base de données: {e}")
|
||||
conn.rollback()
|
||||
finally:
|
||||
connection_pool.putconn(conn)
|
||||
|
||||
HTML_TEMPLATE = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Liste de Courses</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Ma Liste de Courses</h1>
|
||||
|
||||
<form action="/add" method="post">
|
||||
<input type="text" name="item" placeholder="Article" required>
|
||||
<input type="number" name="quantity" value="1" min="1">
|
||||
<button type="submit">Ajouter</button>
|
||||
</form>
|
||||
|
||||
<h2>Articles à acheter</h2>
|
||||
<ul>
|
||||
{% for item in items %}
|
||||
{% if not item[3] %}
|
||||
<li>
|
||||
{{ item[1] }} ({{ item[2] }})
|
||||
<form action="/toggle/{{ item[0] }}" method="post" style="display:inline">
|
||||
<button type="submit">Acheté</button>
|
||||
</form>
|
||||
<form action="/delete/{{ item[0] }}" method="post" style="display:inline">
|
||||
<button type="submit">Supprimer</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h2>Articles achetés</h2>
|
||||
<ul>
|
||||
{% for item in items %}
|
||||
{% if item[3] %}
|
||||
<li>
|
||||
{{ item[1] }} ({{ item[2] }})
|
||||
<form action="/toggle/{{ item[0] }}" method="post" style="display:inline">
|
||||
<button type="submit">Non acheté</button>
|
||||
</form>
|
||||
<form action="/delete/{{ item[0] }}" method="post" style="display:inline">
|
||||
<button type="submit">Supprimer</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
conn = connection_pool.getconn()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("SELECT id, item, quantity, purchased FROM shopping_items ORDER BY purchased, id")
|
||||
items = cur.fetchall()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de la récupération des articles: {e}")
|
||||
items = []
|
||||
finally:
|
||||
connection_pool.putconn(conn)
|
||||
|
||||
return render_template_string(HTML_TEMPLATE, items=items)
|
||||
|
||||
@app.route('/add', methods=['POST'])
|
||||
def add_item():
|
||||
item = request.form.get('item')
|
||||
quantity = request.form.get('quantity', 1, type=int)
|
||||
|
||||
conn = connection_pool.getconn()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO shopping_items (item, quantity) VALUES (%s, %s)",
|
||||
(item, quantity)
|
||||
)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'ajout d'un article: {e}")
|
||||
conn.rollback()
|
||||
finally:
|
||||
connection_pool.putconn(conn)
|
||||
|
||||
return redirect(url_for('index'))
|
||||
|
||||
@app.route('/toggle/<int:item_id>', methods=['POST'])
|
||||
def toggle_item(item_id):
|
||||
conn = connection_pool.getconn()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"UPDATE shopping_items SET purchased = NOT purchased WHERE id = %s",
|
||||
(item_id,)
|
||||
)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors du basculement du statut: {e}")
|
||||
conn.rollback()
|
||||
finally:
|
||||
connection_pool.putconn(conn)
|
||||
|
||||
return redirect(url_for('index'))
|
||||
|
||||
@app.route('/delete/<int:item_id>', methods=['POST'])
|
||||
def delete_item(item_id):
|
||||
conn = connection_pool.getconn()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("DELETE FROM shopping_items WHERE id = %s", (item_id,))
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de la suppression d'un article: {e}")
|
||||
conn.rollback()
|
||||
finally:
|
||||
connection_pool.putconn(conn)
|
||||
|
||||
return redirect(url_for('index'))
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
init_db()
|
||||
except Exception as e:
|
||||
print(f"Impossible d'initialiser la base de données: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
port = int(os.environ.get("PORT", 5000))
|
||||
app.run(host='0.0.0.0', port=port, debug=True)
|
51
z2/deployment.yaml
Normal file
51
z2/deployment.yaml
Normal file
@ -0,0 +1,51 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web-app-deployment
|
||||
namespace: my-app
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web-app
|
||||
spec:
|
||||
containers:
|
||||
- name: web-app-container
|
||||
image: antonin193/simple-web-app:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
env:
|
||||
- name: DB_HOST
|
||||
value: postgres
|
||||
- name: DB_PORT
|
||||
value: "5432"
|
||||
- name: DB_NAME
|
||||
value: postgres
|
||||
- name: DB_USER
|
||||
value: postgres
|
||||
- name: DB_PASS
|
||||
value: postgres
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "200m"
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 5000
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 5000
|
||||
initialDelaySeconds: 20
|
||||
periodSeconds: 20
|
7
z2/namespace.yaml
Normal file
7
z2/namespace.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: my-app
|
||||
labels:
|
||||
name: my-app
|
||||
environment: development
|
29
z2/persistent-storage.yaml
Normal file
29
z2/persistent-storage.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: data-pv
|
||||
namespace: my-app
|
||||
labels:
|
||||
type: local
|
||||
spec:
|
||||
capacity:
|
||||
storage: 1Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: manual
|
||||
hostPath:
|
||||
path: /data/stateful
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: data-pvc
|
||||
namespace: my-app
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: manual
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
44
z2/postgres-deployment.yaml
Normal file
44
z2/postgres-deployment.yaml
Normal file
@ -0,0 +1,44 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: my-app
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:14
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_PASSWORD
|
||||
value: postgres
|
||||
- name: POSTGRES_USER
|
||||
value: postgres
|
||||
- name: POSTGRES_DB
|
||||
value: postgres
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
volumeMounts:
|
||||
- name: postgres-storage
|
||||
mountPath: /var/lib/postgresql/data
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "200m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
- name: postgres-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: data-pvc
|
15
z2/postgres-service.yaml
Normal file
15
z2/postgres-service.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: my-app
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
selector:
|
||||
app: postgres
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
targetPort: 5432
|
||||
clusterIP: None
|
22
z2/prepare-app.sh
Normal file
22
z2/prepare-app.sh
Normal file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
# Script to prepare the application environment
|
||||
|
||||
export REGION="local"
|
||||
echo "Preparing deployment for region: $REGION"
|
||||
|
||||
# Make sure scripts are executable
|
||||
chmod +x start-app.sh stop-app.sh
|
||||
|
||||
# Build and tag Docker image
|
||||
docker build -t simple-web-app:latest .
|
||||
docker tag simple-web-app:latest antonin193/simple-web-app:latest
|
||||
|
||||
# Push to Docker Hub if needed
|
||||
echo "Pushing image to Docker Hub..."
|
||||
docker push antonin193/simple-web-app:latest
|
||||
|
||||
# Create directory for persistent volume (Docker Desktop supports hostPath)
|
||||
sudo mkdir -p /data/stateful
|
||||
sudo chmod 777 /data/stateful
|
||||
|
||||
echo "Preparation complete: Docker image built, tagged, and volume directory created."
|
4
z2/requirements.txt
Normal file
4
z2/requirements.txt
Normal file
@ -0,0 +1,4 @@
|
||||
Flask>=2.0.0
|
||||
Werkzeug>=2.0.0
|
||||
gunicorn>=20.1.0
|
||||
psycopg2-binary>=2.9.3
|
16
z2/service.yaml
Normal file
16
z2/service.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web-app-service
|
||||
namespace: my-app
|
||||
labels:
|
||||
app: web-app
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
selector:
|
||||
app: web-app
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 5000
|
||||
sessionAffinity: None
|
82
z2/start-app.sh
Normal file
82
z2/start-app.sh
Normal file
@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
# Script to deploy the app locally using Docker Desktop + Kubernetes
|
||||
|
||||
# Set default region (optional but kept for consistency)
|
||||
if [ -z "$REGION" ]; then
|
||||
export REGION="local"
|
||||
echo "No region specified. Using default region: $REGION"
|
||||
else
|
||||
echo "Deploying to region: $REGION"
|
||||
fi
|
||||
|
||||
# Build Docker image
|
||||
echo "Building Docker image..."
|
||||
docker build -t antonin193/simple-web-app:latest .
|
||||
|
||||
# Push to Docker Hub (optional for local, but kept if needed across machines)
|
||||
echo "Pushing image to Docker Hub..."
|
||||
docker push antonin193/simple-web-app:latest
|
||||
|
||||
# Create Kubernetes Namespace
|
||||
echo "Creating namespace..."
|
||||
kubectl apply -f namespace.yaml
|
||||
|
||||
# Create PersistentVolume and PersistentVolumeClaim
|
||||
echo "Creating persistent storage..."
|
||||
kubectl apply -f persistent-storage.yaml
|
||||
|
||||
# Wait briefly for resources to be established
|
||||
sleep 2
|
||||
|
||||
# Deploy PostgreSQL first
|
||||
echo "Creating PostgreSQL Deployment and Service..."
|
||||
kubectl apply -f postgres-deployment.yaml
|
||||
kubectl apply -f postgres-service.yaml
|
||||
|
||||
# Wait for PostgreSQL to be ready
|
||||
echo "Waiting for PostgreSQL to be ready..."
|
||||
kubectl wait --for=condition=ready pod -l app=postgres -n my-app --timeout=120s
|
||||
|
||||
# Deploy application
|
||||
echo "Creating Deployment..."
|
||||
kubectl apply -f deployment.yaml
|
||||
|
||||
echo "Creating StatefulSet..."
|
||||
kubectl apply -f statefulset.yaml
|
||||
|
||||
echo "Creating Service..."
|
||||
kubectl apply -f service.yaml
|
||||
|
||||
# Wait for LoadBalancer IP (Docker Desktop uses host network so it's usually localhost)
|
||||
echo "Waiting for LoadBalancer to obtain an external IP (or localhost for Docker Desktop)..."
|
||||
external_ip=""
|
||||
attempt=0
|
||||
max_attempts=4
|
||||
|
||||
while [ -z "$external_ip" ] && [ $attempt -lt $max_attempts ]; do
|
||||
sleep 10
|
||||
attempt=$((attempt+1))
|
||||
external_ip=$(kubectl get svc web-app-service -n my-app --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}" 2>/dev/null)
|
||||
|
||||
if [ -z "$external_ip" ]; then
|
||||
echo "Waiting for external IP... Attempt $attempt of $max_attempts"
|
||||
fi
|
||||
done
|
||||
|
||||
# Fallback to localhost if no external IP is found (common in Docker Desktop)
|
||||
if [ -z "$external_ip" ]; then
|
||||
external_ip="localhost"
|
||||
echo ""
|
||||
echo "=========================================================="
|
||||
echo "Could not get external IP from LoadBalancer. Defaulting to localhost."
|
||||
echo "You can try accessing your app at: http://localhost:80"
|
||||
echo "Or check service status manually with:"
|
||||
echo "kubectl get svc web-app-service -n my-app"
|
||||
echo "=========================================================="
|
||||
else
|
||||
echo ""
|
||||
echo "=========================================================="
|
||||
echo "Application deployed successfully!"
|
||||
echo "You can try accessing your app at: http://localhost:80"
|
||||
echo "=========================================================="
|
||||
fi
|
59
z2/statefulset.yaml
Normal file
59
z2/statefulset.yaml
Normal file
@ -0,0 +1,59 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: stateful-app
|
||||
namespace: my-app
|
||||
spec:
|
||||
serviceName: "stateful-app"
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: stateful-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: stateful-app
|
||||
spec:
|
||||
containers:
|
||||
- name: stateful-app-container
|
||||
image: antonin193/simple-web-app:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
env:
|
||||
- name: DB_HOST
|
||||
value: postgres
|
||||
- name: DB_PORT
|
||||
value: "5432"
|
||||
- name: DB_NAME
|
||||
value: postgres
|
||||
- name: DB_USER
|
||||
value: postgres
|
||||
- name: DB_PASS
|
||||
value: postgres
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "200m"
|
||||
volumeMounts:
|
||||
- name: app-storage
|
||||
mountPath: /data
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 5000
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: app-storage
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: manual
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
55
z2/stop-app.sh
Normal file
55
z2/stop-app.sh
Normal file
@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# Delete Kubernetes objects in reverse order
|
||||
|
||||
# Check if REGION environment variable is set
|
||||
if [ -z "$REGION" ]; then
|
||||
# Default region if not set
|
||||
export REGION="westeurope"
|
||||
echo "No region specified. Using default region: $REGION"
|
||||
else
|
||||
echo "Stopping application in region: $REGION"
|
||||
fi
|
||||
|
||||
# For AKS deployments, make sure we're connected to the right cluster
|
||||
if command -v az &> /dev/null; then
|
||||
echo "Checking AKS connection for region $REGION..."
|
||||
# You might need to adjust these parameters based on your specific Azure setup
|
||||
RESOURCE_GROUP="flask-rg-$REGION"
|
||||
CLUSTER_NAME="flask-aks-$REGION"
|
||||
|
||||
# Try to connect to the Azure cluster
|
||||
if ! az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --overwrite-existing 2>/dev/null; then
|
||||
echo "Warning: Could not connect to AKS cluster in $REGION. Continuing with current kubectl context."
|
||||
else
|
||||
echo "Successfully connected to AKS cluster in $REGION"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Stopping application..."
|
||||
|
||||
# Delete Service first to stop incoming traffic
|
||||
kubectl delete -f service.yaml 2>/dev/null || echo "Service could not be deleted or does not exist."
|
||||
|
||||
# Delete StatefulSet and wait for pods to terminate
|
||||
kubectl delete -f statefulset.yaml 2>/dev/null || echo "StatefulSet could not be deleted or does not exist."
|
||||
|
||||
# Delete Deployment
|
||||
kubectl delete -f deployment.yaml 2>/dev/null || echo "Deployment could not be deleted or does not exist."
|
||||
|
||||
# Delete PostgreSQL objects
|
||||
kubectl delete -f postgres-service.yaml 2>/dev/null || echo "PostgreSQL service could not be deleted or does not exist."
|
||||
kubectl delete -f postgres-deployment.yaml 2>/dev/null || echo "PostgreSQL deployment could not be deleted or does not exist."
|
||||
|
||||
# Wait for pods to terminate
|
||||
echo "Waiting for pods to terminate..."
|
||||
kubectl wait --for=delete pod --selector=app=web-app -n my-app --timeout=60s 2>/dev/null || true
|
||||
kubectl wait --for=delete pod --selector=app=stateful-app -n my-app --timeout=60s 2>/dev/null || true
|
||||
kubectl wait --for=delete pod --selector=app=postgres -n my-app --timeout=60s 2>/dev/null || true
|
||||
|
||||
# Delete PersistentVolume and PersistentVolumeClaim
|
||||
kubectl delete -f persistent-storage.yaml 2>/dev/null || echo "PersistentVolume and PersistentVolumeClaim could not be deleted or do not exist."
|
||||
|
||||
# Delete Namespace (this will delete all resources in the namespace)
|
||||
kubectl delete -f namespace.yaml 2>/dev/null || echo "Namespace could not be deleted or does not exist."
|
||||
|
||||
echo "Application stopped in region $REGION: All Kubernetes objects have been deleted."
|
Loading…
Reference in New Issue
Block a user