Compare commits
3 Commits
54d6fced76
...
8171d3b197
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8171d3b197 | ||
|
|
3444a94c5f | ||
|
|
823b9df176 |
182
z2/README.md
Normal file
182
z2/README.md
Normal file
@ -0,0 +1,182 @@
|
||||
# Vigimétéo – Kubernetes Deployment (z2)
|
||||
|
||||
---
|
||||
|
||||
## 1. Application description
|
||||
|
||||
**Vigimétéo** is a weather monitoring web application.
|
||||
Users can log in, browse weather stations, consult meteorological data (wind, temperature, pressure…) and manage objects depending on their role.
|
||||
|
||||
The stack is made of three services:
|
||||
- A **React** frontend served by Nginx
|
||||
- A **Java / Vert.x** REST backend that exposes the API
|
||||
- A **PostgreSQL** database that stores all data
|
||||
|
||||
---
|
||||
|
||||
## 2. Containers used
|
||||
|
||||
| Container | Image | Role |
|
||||
|---|---|---|
|
||||
| `vigimeteo-frontend` | `vigimeteo-frontend:latest` (built from `Front-end/Dockerfile`) | React SPA built with Vite, served by Nginx on port 80 |
|
||||
| `vigimeteo-backend` | `vigimeteo-backend:latest` (built from `Back-end/Dockerfile`) | Java 17 / Vert.x REST API on port 8888. Connects to PostgreSQL using environment variables |
|
||||
| `postgres` | `postgres:17-alpine` | PostgreSQL database. Automatically runs `init.sql` on first start to create tables and insert seed data |
|
||||
| `busybox` (init) | `busybox:1.36` | Temporary init container inside the backend pod. Waits until PostgreSQL port 5432 is open before letting the backend start |
|
||||
|
||||
---
|
||||
|
||||
## 3. Kubernetes objects
|
||||
|
||||
| Kind | Name | Description |
|
||||
|---|---|---|
|
||||
| `Namespace` | `vigimeteo` | Isolates all objects of this application from the rest of the cluster |
|
||||
| `PersistentVolume` | `vigimeteo-db-pv` | 1 Gi storage volume mapped to `~/vigimeteo-db-data` on the host node |
|
||||
| `PersistentVolumeClaim` | `vigimeteo-db-pvc` | Request for storage, bound to the PV above. Used by the StatefulSet |
|
||||
| `ConfigMap` | `vigimeteo-db-init` | Holds the SQL init script (`init.sql`). Mounted into the PostgreSQL container |
|
||||
| `StatefulSet` | `vigimeteo-db` | Manages the PostgreSQL pod. Provides a stable name and stable storage |
|
||||
| `Deployment` | `vigimeteo-backend` | Manages 2 replicas of the Vert.x backend |
|
||||
| `Deployment` | `vigimeteo-frontend` | Manages 2 replicas of the Nginx/React frontend |
|
||||
| `Service` (Headless) | `vigimeteo-db` | Gives the PostgreSQL pod a stable DNS name: `vigimeteo-db.vigimeteo.svc.cluster.local` |
|
||||
| `Service` (NodePort) | `vigimeteo-backend-service` | Exposes the backend API on port **30888** (accessible from the host) |
|
||||
| `Service` (NodePort) | `vigimeteo-frontend-service` | Exposes the frontend on port **30500** (accessible from the host) |
|
||||
|
||||
---
|
||||
|
||||
## 4. Networks and volumes
|
||||
|
||||
### Network
|
||||
Kubernetes creates a virtual internal network for the `vigimeteo` namespace automatically.
|
||||
- Pods communicate internally using **DNS service names** (e.g. `vigimeteo-db.vigimeteo.svc.cluster.local`).
|
||||
- The frontend and backend are exposed externally via **NodePort** services.
|
||||
|
||||
| Access | Address |
|
||||
|---|---|
|
||||
| Frontend (browser) | `http://localhost:30500` |
|
||||
| Backend API | `http://localhost:30888` |
|
||||
| Database (internal only) | `vigimeteo-db.vigimeteo.svc.cluster.local:5432` |
|
||||
|
||||
### Volume
|
||||
| Name | Type | Host path | Used by |
|
||||
|---|---|---|---|
|
||||
| `vigimeteo-db-pv` | PersistentVolume (hostPath) | `~/vigimeteo-db-data` | PostgreSQL StatefulSet |
|
||||
|
||||
The volume is created by `prepare-app.sh` with `mkdir -p ~/vigimeteo-db-data`.
|
||||
It persists data even after the application is stopped.
|
||||
|
||||
---
|
||||
|
||||
## 5. Container configuration
|
||||
|
||||
### Backend – environment variables
|
||||
|
||||
The backend connects to the database using these environment variables set in `deployment.yaml`:
|
||||
|
||||
| Variable | Value |
|
||||
|---|---|
|
||||
| `DB_HOST` | `vigimeteo-db.vigimeteo.svc.cluster.local` |
|
||||
| `DB_PORT` | `5432` |
|
||||
| `DB_NAME` | `postgres` |
|
||||
| `DB_USER` | `postgres` |
|
||||
| `DB_PASSWORD` | `admin` |
|
||||
|
||||
### Backend – init container
|
||||
|
||||
To avoid connection errors on startup, a `busybox` init container runs first and waits until PostgreSQL accepts connections on port 5432:
|
||||
|
||||
```bash
|
||||
until nc -z vigimeteo-db.vigimeteo.svc.cluster.local 5432; do sleep 3; done
|
||||
```
|
||||
|
||||
### Database – init script
|
||||
|
||||
The ConfigMap `vigimeteo-db-init` contains `init.sql` and is mounted into `/docker-entrypoint-initdb.d/` inside the PostgreSQL container. PostgreSQL automatically runs all `.sql` files in that folder on first startup.
|
||||
|
||||
### Images
|
||||
|
||||
Both images are built locally with `imagePullPolicy: IfNotPresent` so Kubernetes never tries to pull them from a registry.
|
||||
|
||||
---
|
||||
|
||||
## 6. How to run the application
|
||||
|
||||
### Prerequisites
|
||||
- `docker` installed and running
|
||||
- `kubectl` configured and connected to a cluster
|
||||
- For **Minikube**: run `eval $(minikube docker-env)` first so images are built inside Minikube's daemon
|
||||
|
||||
### Step 1 – Prepare (first time only)
|
||||
|
||||
```bash
|
||||
bash prepare-app.sh
|
||||
```
|
||||
|
||||
This creates the PV host directory and builds the two Docker images.
|
||||
|
||||
### Step 2 – Start
|
||||
|
||||
```bash
|
||||
bash start-app.sh
|
||||
```
|
||||
|
||||
Applies all Kubernetes objects in the correct order and waits for PostgreSQL to be ready before deploying the backend.
|
||||
|
||||
### Step 3 – Pause / restart
|
||||
|
||||
There is no "pause" in Kubernetes. To stop traffic you can scale down replicas:
|
||||
|
||||
```bash
|
||||
kubectl scale deployment vigimeteo-backend vigimeteo-frontend --replicas=0 -n vigimeteo
|
||||
```
|
||||
|
||||
To restart:
|
||||
|
||||
```bash
|
||||
kubectl scale deployment vigimeteo-backend vigimeteo-frontend --replicas=2 -n vigimeteo
|
||||
```
|
||||
|
||||
### Step 4 – Delete
|
||||
|
||||
```bash
|
||||
bash stop-app.sh
|
||||
```
|
||||
|
||||
This deletes the namespace (which removes all objects inside it) and the PersistentVolume.
|
||||
The data folder `~/vigimeteo-db-data` is **not** deleted. To fully clean up:
|
||||
|
||||
```bash
|
||||
rm -rf ~/vigimeteo-db-data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. How to access the application
|
||||
|
||||
Once the app is started, open your browser at:
|
||||
|
||||
**http://localhost:30500**
|
||||
|
||||
### Test credentials
|
||||
|
||||
| Role | Email | Password |
|
||||
|---|---|---|
|
||||
| Admin | `admin@a.com` | `azertyuiop` |
|
||||
| Complexe user | `complexe@gmail.com` | `azertyuiop` |
|
||||
| Regular user | `user@gmail.com` | `azertyuiop` |
|
||||
|
||||
### Verify everything is running
|
||||
|
||||
```bash
|
||||
kubectl get all -n vigimeteo
|
||||
```
|
||||
|
||||
All pods should show `1/1 Running`.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Pod stays `Pending`** → The PVC is not bound. Run `kubectl describe pod -n vigimeteo <pod-name>` and check the events. Make sure `~/vigimeteo-db-data` exists.
|
||||
|
||||
**Backend `CrashLoopBackOff`** → Check logs with `kubectl logs -n vigimeteo deployment/vigimeteo-backend`. Usually a DB connection issue.
|
||||
|
||||
**Images not found** → For Minikube, run `eval $(minikube docker-env)` before `prepare-app.sh`.
|
||||
@ -0,0 +1,52 @@
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Deployment – Vert.x Backend (2 replicas)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: vigimeteo-backend
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-backend
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: vigimeteo-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: vigimeteo-backend
|
||||
spec:
|
||||
initContainers:
|
||||
# Wait until PostgreSQL is ready before starting the backend
|
||||
- name: wait-for-db
|
||||
image: busybox:1.36
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
until nc -z vigimeteo-db.vigimeteo.svc.cluster.local 5432; do
|
||||
echo "Waiting for PostgreSQL...";
|
||||
sleep 3;
|
||||
done;
|
||||
echo "PostgreSQL is ready."
|
||||
containers:
|
||||
- name: vigimeteo-backend
|
||||
image: vigimeteo-backend:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8888
|
||||
name: http
|
||||
env:
|
||||
- name: DB_HOST
|
||||
value: "vigimeteo-db.vigimeteo.svc.cluster.local"
|
||||
- name: DB_PORT
|
||||
value: "5432"
|
||||
- name: DB_NAME
|
||||
value: "postgres"
|
||||
- name: DB_USER
|
||||
value: "postgres"
|
||||
- name: DB_PASSWORD
|
||||
value: "admin"
|
||||
|
||||
7
z2/namespace.yaml
Normal file
7
z2/namespace.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo
|
||||
environment: production
|
||||
@ -1,4 +1,20 @@
|
||||
#!/bin/bash
|
||||
# Prepare the app: create the storage directory and build the Docker images
|
||||
set -e
|
||||
|
||||
echo "╔══════════════════════════════════════════╗"
|
||||
echo "║ Vigimétéo – Prepare App ║"
|
||||
echo "╚══════════════════════════════════════════╝"
|
||||
echo "Preparing app..."
|
||||
docker compose build
|
||||
echo "App is prepared."
|
||||
|
||||
# 1 - Create the directory used by the PersistentVolume
|
||||
mkdir -p ~/vigimeteo-db-data
|
||||
|
||||
# 2 - Build Docker images
|
||||
docker build -t vigimeteo-backend:latest ./Back-end
|
||||
docker build -t vigimeteo-frontend:latest ./Front-end
|
||||
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════"
|
||||
echo " Preparation complete! Run ./start-app.sh"
|
||||
echo "════════════════════════════════════════════"
|
||||
@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
echo "Removed app."
|
||||
docker compose down -v --rmi local
|
||||
91
z2/service.yaml
Normal file
91
z2/service.yaml
Normal file
@ -0,0 +1,91 @@
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Deployment – React/Nginx Frontend (2 replicas)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: vigimeteo-frontend
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-frontend
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: vigimeteo-frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: vigimeteo-frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: vigimeteo-frontend
|
||||
image: vigimeteo-frontend:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
### part bellow recommanded by ia for health check
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 15
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "200m"
|
||||
memory: "128Mi"
|
||||
|
||||
---
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Service – Backend ClusterIP (internal access only)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: vigimeteo-backend-service
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-backend
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: vigimeteo-backend
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 8888
|
||||
targetPort: 8888
|
||||
nodePort: 30888
|
||||
|
||||
---
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Service – Frontend NodePort (external access via <nodeIP>:30500)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: vigimeteo-frontend-service
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-frontend
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: vigimeteo-frontend
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
nodePort: 30500
|
||||
@ -1,4 +1,39 @@
|
||||
#!/bin/bash
|
||||
echo "Running app ..."
|
||||
docker compose up -d
|
||||
echo "The app is available at http://localhost:5000"
|
||||
# Deploy all Kubernetes objects for Vigimeteo
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
NS="vigimeteo"
|
||||
|
||||
echo "╔══════════════════════════════════════════╗"
|
||||
echo "║ Vigimétéo – Start App ║"
|
||||
echo "╚══════════════════════════════════════════╝"
|
||||
echo "Starting app..."
|
||||
|
||||
# 1. Create the namespace
|
||||
kubectl apply -f namespace.yaml
|
||||
|
||||
# 2. Create the ConfigMap from the SQL init script, then apply storage and database
|
||||
kubectl create configmap vigimeteo-db-init \
|
||||
--from-file=init.sql=sql/init_db.sql \
|
||||
-n vigimeteo \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
kubectl apply -f statefulset.yaml
|
||||
|
||||
# 3. Wait for the database to be ready before starting the backend
|
||||
echo "Waiting for PostgreSQL to be ready..."
|
||||
kubectl rollout status statefulset/vigimeteo-db -n vigimeteo --timeout=120s
|
||||
|
||||
# 4. Deploy the backend and frontend
|
||||
kubectl apply -f deployment.yaml
|
||||
kubectl apply -f service.yaml
|
||||
|
||||
# ── Summary ───────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════"
|
||||
echo " All objects deployed in namespace: $NS"
|
||||
echo ""
|
||||
kubectl get all -n "$NS"
|
||||
echo ""
|
||||
|
||||
echo "App deployed! Available at http://localhost:30500"
|
||||
|
||||
116
z2/statefulset.yaml
Normal file
116
z2/statefulset.yaml
Normal file
@ -0,0 +1,116 @@
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# PersistentVolume – host-path volume for PostgreSQL data
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: vigimeteo-db-pv
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-db
|
||||
spec:
|
||||
capacity:
|
||||
storage: 1Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: manual
|
||||
hostPath:
|
||||
path: /home/cytech/vigimeteo-db-data
|
||||
|
||||
---
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# PersistentVolumeClaim – claimed by the StatefulSet below
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: vigimeteo-db-pvc
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-db
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: manual
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
|
||||
---
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# StatefulSet – single PostgreSQL replica
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: vigimeteo-db
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-db
|
||||
spec:
|
||||
serviceName: vigimeteo-db
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: vigimeteo-db
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: vigimeteo-db
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:17-alpine
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
name: postgres
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: "postgres"
|
||||
- name: POSTGRES_PASSWORD
|
||||
value: "admin"
|
||||
- name: POSTGRES_DB
|
||||
value: "postgres"
|
||||
volumeMounts:
|
||||
- name: vigimeteo-db-storage
|
||||
mountPath: /var/lib/postgresql/data
|
||||
- name: vigimeteo-db-init
|
||||
mountPath: /docker-entrypoint-initdb.d
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", "postgres"]
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", "postgres"]
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
volumes:
|
||||
- name: vigimeteo-db-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: vigimeteo-db-pvc
|
||||
- name: vigimeteo-db-init
|
||||
configMap:
|
||||
name: vigimeteo-db-init
|
||||
|
||||
---
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Headless Service – required by the StatefulSet
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: vigimeteo-db
|
||||
namespace: vigimeteo
|
||||
labels:
|
||||
app: vigimeteo-db
|
||||
spec:
|
||||
clusterIP: None # headless – stable DNS name for StatefulSet pods
|
||||
selector:
|
||||
app: vigimeteo-db
|
||||
ports:
|
||||
- name: postgres
|
||||
port: 5432
|
||||
targetPort: 5432
|
||||
@ -1,3 +1,22 @@
|
||||
#!/bin/bash
|
||||
# Remove all Kubernetes objects for Vigimeteo
|
||||
set -e
|
||||
|
||||
echo "╔══════════════════════════════════════════╗"
|
||||
echo "║ Vigimétéo – Stop App ║"
|
||||
echo "╚══════════════════════════════════════════╝"
|
||||
|
||||
echo "Stopping app..."
|
||||
docker compose stop
|
||||
|
||||
# 1- Deleting the namespace removes everything inside it automatically
|
||||
kubectl delete namespace vigimeteo --ignore-not-found
|
||||
|
||||
# 2 - The PersistentVolume is cluster-scoped so it must be deleted separately
|
||||
kubectl delete pv vigimeteo-db-pv --ignore-not-found
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════"
|
||||
echo " All Vigimeteo Kubernetes objects removed."
|
||||
echo " Note: ~/vigimeteo-db-data was NOT deleted."
|
||||
echo " Run: rm -rf ~/vigimeteo-db-data to clean up."
|
||||
echo "════════════════════════════════════════════"
|
||||
echo "App stopped."
|
||||
|
||||
Loading…
Reference in New Issue
Block a user