zkt26/sk1/README.md
2026-05-12 19:27:18 +02:00

9.6 KiB
Raw Blame History

Vigimétéo Azure Kubernetes Deployment

1. Application Description

Vigimétéo is a weather monitoring web app. Users can log in, browse meteorological stations and sensors, consult measurements (temperature, humidity, pressure, wind) and manage objects depending on their role (regular user, complex user, admin).

Stack: React + Vite (frontend) · Java 17 / Vert.x (backend REST API) · PostgreSQL 17 (database)


2. Cloud & Kubernetes Infrastructure

Public cloud: Microsoft Azure (region: Poland Central)

Azure Service Purpose
Azure Kubernetes Service (AKS) Standard_B2als_v2 × 2 nodes Runs all application workloads
Azure Container Registry (ACR) Basic SKU Stores Docker images for backend and frontend
Azure Disk (managed-csi, 1 Gi PVC) Persistent storage for the PostgreSQL database
Azure Load Balancer + Public IP Exposes the NGINX ingress with a public FQDN

Kubernetes objects:

Kind Name Description
Namespace vigimeteo Isolates all app resources
PersistentVolumeClaim vigimeteo-db-pvc 1 Gi Azure Disk for PostgreSQL data
ConfigMap vigimeteo-db-init Holds init_db.sql, auto-run on first DB start
Secret db-credentials DB credentials injected at deploy time, never in Git
StatefulSet vigimeteo-db Single PostgreSQL replica with stable storage
Deployment (×2) vigimeteo-backend / vigimeteo-frontend 2-replica backend and frontend pods
Services NodePort 30888 / 30500 + Headless Internal and external service exposure
Ingress vigimeteo-ingress Routes HTTPS traffic to the frontend via ingress-nginx
ClusterIssuer letsencrypt-prod cert-manager ACME issuer for automatic TLS certificates

Database schema: 6 tables weather_objects, weather_data, range_data, users, categories, deletion_requests.


3. Annual Cost Analysis (1 000 users/day 50 GB)

Resource SKU Monthly (USD)
AKS 2 × Standard_B2als_v2 VMs 2 vCPU, 4 GB RAM each ~$60
Azure Container Registry Basic SKU ~$5
Azure Disk (Premium SSD 64 Gi) managed-csi ~$10
Azure Load Balancer Standard ~$18
Public IP (Static) Standard SKU ~$4
Outbound bandwidth (~1 000 users × 5 MB/day) Per GB after free tier ~$10
Let's Encrypt TLS Free $0
Total ~$107/month → ~$1 284/year

Assumptions: 50 GB stored on 64 Gi disk, moderate REST API traffic, no high-frequency streaming, first 100 GB/month egress free.

💡 Use pause-app.sh to scale nodes to 0 during off-hours → cost drops to ~$25/month.


4. Repository Files

File Description
prepare-app.sh Recommended deploy script creates Azure infra (RG, ACR, AKS), builds & pushes Docker images, deploys all Kubernetes objects, sets up HTTPS. Includes structured logging, fixed DNS label and post-deploy health checks
remove-app.sh Deletes the entire ExamApp-RG resource group (irreversible)
pause-app.sh Scales AKS node pool to 0 stops VM billing while keeping the disk
resume-app.sh Scales node pool back to 1 and redeploys all Kubernetes objects
backup-db.sh Dumps the live PostgreSQL database to ./sql/backup_<timestamp>.sql via pg_dump
lib/logger.sh Shared logging library sourced by all scripts structured INFO/WARN/ERROR/DEBUG output with timestamps, color-coded terminal output, and log file written to ./logs/
logs/ Auto-created directory that stores timestamped log files from each script run (excluded from Git)
namespace.yaml Kubernetes Namespace vigimeteo
statefulset.yaml PVC (managed-csi) + PostgreSQL StatefulSet + headless Service
deployment.yaml 2-replica Deployments for backend and frontend; DB credentials from Secret
service.yaml NodePort Services for backend (30888) and frontend (30500)
ingress.yaml NGINX Ingress routing HTTPS to the frontend; TLS via cert-manager
cluster-issuer.yaml Let's Encrypt ACME ClusterIssuer (HTTP-01 challenge)
docker-compose.yaml Local development alternative runs all three services without any cloud
sql/init_db.sql Full PostgreSQL dump: schema + seed data (users, stations, measurements)
Back-end/ Java 17 / Vert.x source code + Maven build + Dockerfile
Front-end/ React + Vite source code + Nginx config + Dockerfile

5. Configuration Summary

  • DB credentials are injected as a Kubernetes Secret (db-credentials) by prepare-app.sh. The backend reads them via secretKeyRef environment variables (DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD). Credentials are never committed to Git.
  • PostgreSQL init init_db.sql is loaded into a ConfigMap and mounted at /docker-entrypoint-initdb.d/. It runs automatically on first startup. PGDATA is set to a subdirectory (/var/lib/postgresql/data/pgdata) to avoid the Azure Disk lost+found initdb error.
  • Security context fsGroup: 999 lets Kubernetes chown the Azure Disk to the postgres GID before starting the container.
  • Nginx reverse proxy nginx.conf proxies /api/ requests to the backend service, avoiding CORS issues.
  • TLS cluster-issuer.yaml requests a Let's Encrypt certificate via ACME HTTP-01. The ingress stores it in Secret vigimeteo-tls-secret.
  • Images built locally and pushed to ACR by prepare-app.sh. The MON_REGISTRE placeholder in deployment.yaml is replaced on-the-fly with sed.
  • Logging all scripts source lib/logger.sh which writes colour-coded, timestamped output to the terminal and appends plain-text logs to ./logs/<script>-<timestamp>.log. Set export LOG_LEVEL=DEBUG before running any script to enable verbose output.
  • Fixed DNS label the public IP DNS label is always vigimeteo-prod (not random), ensuring the FQDN and TLS certificate remain valid across re-deployments.

6. How to View and Use the Application

Cloud (AKS)

After prepare-app.sh completes, the FQDN is printed:

👉 https://vigimeteo-prod.polandcentral.cloudapp.azure.com

Open the URL in a browser. The TLS certificate is ready within ~2 minutes.
The DNS label vigimeteo-prod is fixed — the URL never changes between re-deployments.

Local (Docker Compose)

docker compose up --build
# Open: http://localhost:5000

Test credentials

Role Email Password
Admin admin@a.com azertyuiop
Complex user complexe@gmail.com azertyuiop
Regular user user@gmail.com azertyuiop

Verify pods

kubectl get all -n vigimeteo

7. How to Perform a Database Backup

bash backup-db.sh
# Output: ./sql/backup_YYYYMMDD_HHMMSS.sql

Or directly from the Kubernetes pod:

POD=$(kubectl get pod -n vigimeteo -l app=vigimeteo-db -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n vigimeteo "$POD" -- pg_dump -U postgres -d postgres --clean > ./sql/backup.sql

Restore:

kubectl exec -i -n vigimeteo "$POD" -- psql -U postgres -d postgres < ./sql/backup.sql

8. How to View Access Records from the Internet

Ingress (NGINX) logs all inbound HTTP/HTTPS requests:

INGRESS_POD=$(kubectl get pod -n ingress-nginx -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].metadata.name}')
kubectl logs -n ingress-nginx "$INGRESS_POD" -f

Backend logs:

kubectl logs -n vigimeteo deployment/vigimeteo-backend -f

Frontend logs:

kubectl logs -n vigimeteo deployment/vigimeteo-frontend -f

9. Conditions for Running prepare-app.sh and remove-app.sh

prepare-app.sh

All of the following must be true before running:

  • Azure CLI installed and logged in (az login)
  • Docker daemon running
  • kubectl installed
  • DB_USER and DB_PASSWORD environment variables exported:
    export DB_USER="postgres"
    export DB_PASSWORD="your_password"
    bash prepare-app.sh
    
  • Sufficient Azure subscription quota for Standard_B2als_v2 VMs (2 nodes)

The script is idempotent safe to re-run if the cluster or ACR already exist.
Deploy logs are written to ./logs/deploy-<timestamp>.log automatically.

Optional enable verbose debug output:

export LOG_LEVEL=DEBUG
bash prepare-app.sh

remove-app.sh

  • Azure CLI installed and logged in
  • A backup has been taken if data must be preserved (bash backup-db.sh)
  • Run: bash remove-app.sh

⚠️ Deletes all Azure resources permanently. Data is not recoverable.


10. External Resources & Generative AI

Resource Type Usage
Azure AKS docs Official docs Cluster setup, managed-csi storage
Kubernetes docs Official docs StatefulSet, Ingress, Secrets, PVC
Eclipse Vert.x docs Official docs Async HTTP server, JDBC client
cert-manager docs Official docs ClusterIssuer, ACME HTTP-01
ingress-nginx Official docs Controller deployment, annotations
PostgreSQL docs Official docs pg_dump, pg_isready, PGDATA
Stack Overflow Q&A forum Debugging Azure Disk initdb errors, Vert.x JDBC issues
Google Gemini (LLM) Generative AI Architecture advice, manifest debugging, script generation, README writing. All suggestions were reviewed and tested before applying.
GitHub Copilot (LLM) Generative AI Inline code completion for Java handlers and React components