From ac8addb65abcd0b3a49a86d8c277d7d97e8b7ab2 Mon Sep 17 00:00:00 2001 From: Waloshi6 Date: Thu, 5 Feb 2026 18:45:19 +0100 Subject: [PATCH] =?UTF-8?q?Cr=C3=A9ation=20d'un=20.md=20=C3=A0=20la=20raci?= =?UTF-8?q?ne=20du=20dossier=20projet=20avec=20le=20contenu=20du=20tp=20de?= =?UTF-8?q?=20deepseek=20+=20commentaires=20de=20son=20=C3=A9tat=20actuel,?= =?UTF-8?q?=20d=C3=A9but=20de=20restructuration=20=C3=A0=20corriger=20et?= =?UTF-8?q?=20am=C3=A9liorer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TpDevOpsProject.md | 1496 +++++++++++++++++ .../indexers/issues.bleve/store/root.bolt | Bin 65536 -> 65536 bytes .../queues/common/{000093.log => 000095.log} | 0 gitea/gitea-data/gitea/queues/common/CURRENT | 2 +- .../gitea/queues/common/CURRENT.bak | 2 +- gitea/gitea-data/gitea/queues/common/LOG | 9 + .../{MANIFEST-000094 => MANIFEST-000096} | 0 7 files changed, 1507 insertions(+), 2 deletions(-) create mode 100644 TpDevOpsProject.md rename gitea/gitea-data/gitea/queues/common/{000093.log => 000095.log} (100%) rename gitea/gitea-data/gitea/queues/common/{MANIFEST-000094 => MANIFEST-000096} (100%) diff --git a/TpDevOpsProject.md b/TpDevOpsProject.md new file mode 100644 index 0000000..1a6b608 --- /dev/null +++ b/TpDevOpsProject.md @@ -0,0 +1,1496 @@ +#TP DevOps Corrigé par DeepSeek + +# ...et en cours de restructuration par Oualim (commentaires pour le futur pour tester une autre création à l'IA d'un tp, en tenant compte des manquements et des erreurs pour ne pas laisser l'IA les reproduire) + +Original pourrit: https://cloud.bonisco.fr/s/Cb2bFdLXeFEFcLm + +# Commentaire de Oualim (Celui de Deepseek est juste un peu moins pourri mais c'était aussi de la merde) +# Ce TP contient encore beaucoup de fautes sur les manips et fichiers et aucun sens sur la structure car l'IA a juste pris les mots clefs de "devops" sur internet, copié des fichiers et mélangé des concepts sans aucune présentation ni introduction ou explications (ex : correctif de l'ancien tp tout en bas :-/ ; terraform sur des docker ??? ; kub en faisant un doublon d'appli potentiellement conflictuel, aucune explication ni structure d'étape pour comprendre les logiques de docker et k8') + +#📚 RÉCAPITULATIF DES CORRECTIONS APPORTÉES +#✅ Corrections majeures : +Python : Ajout de Response dans les imports FastAPI + +Docker Compose : Chemins corrigés, versions spécifiées + +Kubernetes : Changé LoadBalancer → NodePort pour Windows + +Image Docker : Tag :local au lieu de :latest pour K8s + +Terraform : Suppression du provider Docker problématique + +Scripts : Ajout de gestion d'erreurs robuste + +Tests : Ajout de tests unitaires Python + +Health checks : Ajout dans Docker Compose et K8s + + +#🎯 Améliorations : +Structure de projet logique et organisée + +Scripts PowerShell avec paramètres et gestion d'erreurs + +Configuration monitoring fonctionnelle + +Documentation claire étape par étape + +Solutions de dépannage incluses + +Versionning spécifique des images Docker + + +# Commentaire de Oualim +# Ce TP permet pour l'instant, de réaliser le paysage de docker pour un débutant, de comprendre une organisation de dossiers et fichiers, de créer qq containeurs docker : +# - http://localhost:8000 (App) +# - http://localhost:8000/docs (Documentation API) +# - http://localhost:9090 (Prometheus) +# - http://localhost:3000 (Grafana - admin/admin123) +# - http://localhost:9000 (Portainer) + + + + + + +#🚀 TP DevOps Windows - Stack Complète Locale (Corrigé & Optimisé) +#📋 PRÉ-REQUIS WINDOWS - Installation Pas à Pas +#🔧 1. Préparation du système (PowerShell Administrateur) + +# Ouvrir PowerShell en tant qu'ADMINISTRATEUR (clic droit → Exécuter en tant qu'administrateur) + +# 1. Activer les fonctionnalités Windows nécessaires +Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux +Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform + +# 2. Installer WSL2 et Ubuntu +wsl --install -d Ubuntu-22.04 + +# 3. Définir WSL2 comme version par défaut +wsl --set-default-version 2 + +# 4. Redémarrer l'ordinateur (OBLIGATOIRE) +Restart-Computer +#📥 2. Installation des outils (après redémarrage) + +# 1. Installer Chocolatey (package manager Windows) +Set-ExecutionPolicy Bypass -Scope Process -Force +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 +iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + +# 2. Installer tous les outils +choco install -y git docker-desktop vscode kubernetes-cli minikube terraform helm postman +#🐧 3. Configuration WSL2 et Ubuntu + +# Vérifier l'installation WSL +wsl --list --verbose +# Doit afficher : Ubuntu-22.04 Running 2 + +# Entrer dans WSL pour configurer +wsl + +# Dans le terminal Ubuntu WSL : +sudo apt update +sudo apt upgrade -y +sudo apt install -y python3 python3-pip python3-venv nodejs npm curl wget + +# Créer un alias pratique +echo "alias k=kubectl" >> ~/.bashrc +source ~/.bashrc +exit # Retour à PowerShell +#🐋 ÉTAPE 1 : CONFIGURATION DOCKER DESKTOP +#⚙️ Configuration manuelle obligatoire : +Ouvrir Docker Desktop après installation + +Settings → General : + +✅ Use WSL 2 based engine + +✅ Expose daemon on tcp://localhost:2375 without TLS + +Settings → Resources → WSL Integration : + +✅ Enable integration with my default WSL distro + +✅ Ubuntu-22.04 + +Settings → Kubernetes : + +✅ Enable Kubernetes + +✅ Deploy Docker Stacks to Kubernetes by default + +Settings → Advanced : + +CPUs : 4 (ou 50% de vos CPUs) + +Memory : 4.0 GB (ou 50% de votre RAM) + +Swap : 1.0 GB + +Appliquer et redémarrer Docker Desktop + +#✅ Vérification Docker/WSL2 : + +# Dans PowerShell +docker --version +# Doit afficher : Docker version 24.0.x + +docker run hello-world +# Doit afficher "Hello from Docker!" + +# Vérifier l'intégration WSL2 +wsl -d Ubuntu-22.04 -e docker version +# Doit fonctionner sans erreur +#📁 ÉTAPE 2 : STRUCTURE DU PROJET OPTIMISÉE +#🗂️ Création de la structure : + +# Créer le dossier principal +mkdir C:\DevOpsProject +cd C:\DevOpsProject + +# Structure ORGANISÉE et LOGIQUE +New-Item -ItemType Directory -Path @( + "src\app", + "src\app\tests", + "docker", + "kubernetes\manifests", + "kubernetes\helm", + "terraform", + ".github\workflows", + "monitoring", + "scripts", + "docs", + "config" +) + +# Structure finale : +C:\DevOpsProject\ +├── src\ # Code source +│ ├── app\ # Application Python +│ └── app\tests\ # Tests unitaires +├── docker\ # Dockerfiles & Compose +├── kubernetes\ # K8s manifests +├── terraform\ # Infrastructure as Code +├── monitoring\ # Prometheus, Grafana +├── scripts\ # Scripts PowerShell +├── .github\workflows\ # CI/CD +├── config\ # Fichiers de config +└── docs\ # Documentation +#🐍 ÉTAPE 3 : APPLICATION PYTHON CORRIGÉE +#3.1 Fichier : src\app\requirements.txt + +fastapi==0.104.1 +uvicorn[standard]==0.24.0 +pydantic==2.5.0 +prometheus-client==0.19.0 +python-dotenv==1.0.0 +pytest==7.4.3 +httpx==0.25.1 +#3.2 Fichier : src\app\main.py (CORRIGÉ) + +from fastapi import FastAPI, Request, Response, HTTPException +from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST +import time +import os +import logging +from typing import Dict + +# Configuration du logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +app = FastAPI( + title="DevOps Windows API", + description="Application de démonstration DevOps sous Windows", + version="1.0.0" +) + +# Métriques Prometheus - CORRIGÉ +REQUEST_COUNT = Counter( + 'http_requests_total', + 'Total HTTP Requests', + ['method', 'endpoint', 'status'] +) +REQUEST_LATENCY = Histogram( + 'http_request_duration_seconds', + 'HTTP Request latency', + ['method', 'endpoint'] +) + +@app.middleware("http") +async def monitor_requests(request: Request, call_next): + """Middleware pour monitorer les requêtes""" + start_time = time.time() + + try: + response = await call_next(request) + status_code = str(response.status_code) + except Exception as e: + status_code = "500" + response = Response( + content=f"Internal Server Error: {str(e)}", + status_code=500 + ) + + process_time = time.time() - start_time + + # Enregistrement des métriques - CORRIGÉ + REQUEST_COUNT.labels( + method=request.method, + endpoint=request.url.path, + status=status_code + ).inc() + + REQUEST_LATENCY.labels( + method=request.method, + endpoint=request.url.path + ).observe(process_time) + + # Ajouter le temps de traitement dans les headers + response.headers["X-Process-Time"] = f"{process_time:.3f}s" + + return response + +@app.get("/") +async def home(): + """Endpoint principal""" + return { + "message": "🚀 DevOps Stack Windows - Fonctionnel !", + "environment": os.getenv("ENV", "development"), + "status": "running", + "hostname": os.getenv("HOSTNAME", "windows-devops"), + "version": "1.0.0" + } + +@app.get("/health") +async def health(): + """Health check pour Kubernetes et load balancers""" + return { + "status": "healthy", + "timestamp": time.time(), + "service": "devops-app" + } + +@app.get("/metrics") +async def metrics(): + """Endpoint Prometheus - CORRIGÉ""" + try: + data = generate_latest() + return Response( + content=data, + media_type=CONTENT_TYPE_LATEST, + headers={"Cache-Control": "no-cache"} + ) + except Exception as e: + logger.error(f"Error generating metrics: {e}") + raise HTTPException(status_code=500, detail="Metrics generation failed") + +@app.get("/info") +async def info(): + """Informations système""" + return { + "python_version": "3.11", + "platform": "windows", + "service": "FastAPI DevOps", + "features": ["docker", "kubernetes", "monitoring", "ci-cd"] + } + +@app.get("/env") +async def show_env(): + """Afficher les variables d'environnement (sécurisé)""" + safe_env = { + "ENV": os.getenv("ENV", "not-set"), + "HOSTNAME": os.getenv("HOSTNAME", "not-set"), + "PYTHON_VERSION": os.getenv("PYTHON_VERSION", "not-set") + } + return safe_env + +# Pour le développement local +if __name__ == "__main__": + import uvicorn + logger.info("Starting FastAPI server...") + uvicorn.run( + app, + host="0.0.0.0", + port=8000, + log_level="info", + reload=True # Auto-reload en développement + ) +#3.3 Fichier : src\app\tests\test_main.py (NOUVEAU) + +import pytest +from fastapi.testclient import TestClient +from main import app + +client = TestClient(app) + +def test_home_endpoint(): + """Test de l'endpoint principal""" + response = client.get("/") + assert response.status_code == 200 + data = response.json() + assert "message" in data + assert "status" in data + assert data["status"] == "running" + +def test_health_endpoint(): + """Test du health check""" + response = client.get("/health") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "healthy" + assert "service" in data + +def test_metrics_endpoint(): + """Test des métriques Prometheus""" + response = client.get("/metrics") + assert response.status_code == 200 + assert "text/plain" in response.headers["content-type"] + assert "http_requests_total" in response.text + +def test_info_endpoint(): + """Test des informations""" + response = client.get("/info") + assert response.status_code == 200 + data = response.json() + assert "python_version" in data + assert "platform" in data + +def test_env_endpoint(): + """Test des variables d'environnement""" + response = client.get("/env") + assert response.status_code == 200 + data = response.json() + assert "ENV" in data +#3.4 Fichier : src\app\Dockerfile (OPTIMISÉ) + +# Étape 1 : Build +FROM python:3.11-slim AS builder + +WORKDIR /app + +# Copier les requirements d'abord (cache Docker) +COPY requirements.txt . +RUN pip install --user --no-cache-dir -r requirements.txt + +# Étape 2 : Runtime +FROM python:3.11-slim + +WORKDIR /app + +# Copier les packages depuis le builder +COPY --from=builder /root/.local /root/.local +COPY . . + +# Ajouter au PATH +ENV PATH=/root/.local/bin:$PATH +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV ENV=production +ENV HOSTNAME=devops-container + +# Exposer le port +EXPOSE 8000 + +# Utiliser un user non-root pour la sécurité +RUN useradd -m -u 1000 devopsuser && chown -R devopsuser:devopsuser /app +USER devopsuser + +# Commande de démarrage +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--no-access-log"] +#🐳 ÉTAPE 4 : DOCKER COMPOSE CORRIGÉ +#4.1 Fichier : docker\docker-compose.yml (RECOMMENCÉ) + +version: '3.8' + +services: + # Application principale + app: + build: + context: ../src/app + dockerfile: Dockerfile + container_name: devops-app + ports: + - "8000:8000" + environment: + - ENV=development + - HOSTNAME=devops-local + volumes: + - ../src/app:/app + - app-logs:/app/logs + networks: + - devops-network + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + labels: + - "com.devops.description=Application FastAPI" + - "prometheus.scrape=true" + - "prometheus.port=8000" + - "prometheus.path=/metrics" + + # Prometheus pour le monitoring + prometheus: + image: prom/prometheus:v2.47.2 + container_name: devops-prometheus + ports: + - "9090:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro + - prometheus-data:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--web.console.libraries=/etc/prometheus/console_libraries' + - '--web.console.templates=/etc/prometheus/consoles' + - '--storage.tsdb.retention.time=200h' + - '--web.enable-lifecycle' + networks: + - devops-network + restart: unless-stopped + depends_on: + - app + + # Grafana pour les dashboards + grafana: + image: grafana/grafana:10.2.0 + container_name: devops-grafana + ports: + - "3000:3000" + environment: + - GF_SECURITY_ADMIN_PASSWORD=admin123 + - GF_SECURITY_ADMIN_USER=admin + - GF_INSTALL_PLUGINS=grafana-piechart-panel,grafana-clock-panel + - GF_USERS_ALLOW_SIGN_UP=false + - GF_SERVER_DOMAIN=localhost + volumes: + - grafana-data:/var/lib/grafana + - ./grafana-dashboards:/etc/grafana/provisioning/dashboards + - ./grafana-datasources:/etc/grafana/provisioning/datasources + networks: + - devops-network + restart: unless-stopped + depends_on: + - prometheus + + # Portainer pour gérer Docker + portainer: + image: portainer/portainer-ce:2.19.3 + container_name: devops-portainer + ports: + - "9000:9000" + - "9443:9443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - portainer-data:/data + networks: + - devops-network + restart: unless-stopped + command: -H unix:///var/run/docker.sock + + # Nginx comme reverse proxy (optionnel) + nginx: + image: nginx:alpine + container_name: devops-nginx + ports: + - "8080:80" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + networks: + - devops-network + restart: unless-stopped + depends_on: + - app + +networks: + devops-network: + driver: bridge + name: devops-network + +volumes: + prometheus-data: + name: prometheus-data + grafana-data: + name: grafana-data + portainer-data: + name: portainer-data + app-logs: + name: app-logs +#4.2 Fichier : docker\prometheus.yml (À CRÉER) + +global: + scrape_interval: 15s + evaluation_interval: 15s + external_labels: + cluster: 'windows-devops' + environment: 'development' + +# Règles d'alerte +rule_files: + # - "alerts.yml" + +# Configuration de scraping +scrape_configs: + # Scraper l'application FastAPI + - job_name: 'fastapi-app' + static_configs: + - targets: ['app:8000'] + labels: + app: 'devops-app' + component: 'backend' + tier: 'application' + + # Scraper Prometheus lui-même + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:9090'] + labels: + component: 'monitoring' + + # Découverte de service Docker + - job_name: 'docker' + static_configs: + - targets: ['host.docker.internal:9323'] + metrics_path: /metrics + scheme: http + +# Alerting (exemple) +# alerting: +# alertmanagers: +# - static_configs: +# - targets: [] +#4.3 Exécution Docker Compose : + +# Se placer dans le dossier docker +cd C:\DevOpsProject\docker + +# Lancer en arrière-plan +docker-compose up -d + +# Vérifier que tout fonctionne +docker-compose ps + +# Voir les logs de l'application +docker-compose logs app + +# Tester l'application +curl http://localhost:8000 +# ou dans PowerShell +Invoke-WebRequest -Uri "http://localhost:8000" -UseBasicParsing +#☸️ ÉTAPE 5 : KUBERNETES SIMPLIFIÉ POUR WINDOWS +#5.1 Activer Kubernetes dans Docker Desktop : + +1. Docker Desktop → Settings (roue crantée) +2. Onglet Kubernetes +3. ✅ Enable Kubernetes +4. ✅ Show system containers (optional) +5. Apply & Restart (patienter 2-3 minutes) +#5.2 Vérification : + +# Vérifier que Kubernetes fonctionne +kubectl cluster-info +# Doit afficher : Kubernetes control plane is running at https://... + +kubectl get nodes +# Doit afficher : docker-desktop Ready + +kubectl get pods --all-namespaces +# Doit montrer les pods système +#5.3 Fichier : kubernetes\manifests\namespace.yaml + +apiVersion: v1 +kind: Namespace +metadata: + name: devops-demo + labels: + name: devops-demo + environment: development +#5.4 Fichier : kubernetes\manifests\configmap.yaml (NOUVEAU) + +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-config + namespace: devops-demo +data: + ENV: "production" + APP_NAME: "devops-windows-app" + LOG_LEVEL: "INFO" + PYTHONUNBUFFERED: "1" +#5.5 Fichier : kubernetes\manifests\deployment.yaml (SIMPLIFIÉ) + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: devops-app + namespace: devops-demo + labels: + app: devops-app + version: v1 +spec: + replicas: 2 + selector: + matchLabels: + app: devops-app + template: + metadata: + labels: + app: devops-app + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8000" + prometheus.io/path: "/metrics" + spec: + containers: + - name: app + image: devops-app:local # IMPORTANT : Utiliser l'image locale + imagePullPolicy: IfNotPresent # Ne pas pull depuis Docker Hub + ports: + - containerPort: 8000 + name: http + envFrom: + - configMapRef: + name: app-config + env: + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "200m" + readinessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 15 + livenessProbe: + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 30 + periodSeconds: 30 +--- +apiVersion: v1 +kind: Service +metadata: + name: devops-app-service + namespace: devops-demo +spec: + selector: + app: devops-app + ports: + - port: 80 + targetPort: 8000 + protocol: TCP + name: http + type: NodePort # CORRIGÉ : NodePort au lieu de LoadBalancer pour Windows +#5.6 Déploiement Kubernetes : + +# 1. Build l'image Docker avec un tag spécifique +cd C:\DevOpsProject\src\app +docker build -t devops-app:local . + +# 2. Appliquer les manifests Kubernetes +cd C:\DevOpsProject\kubernetes\manifests + +# Dans l'ordre : +kubectl apply -f namespace.yaml +kubectl apply -f configmap.yaml +kubectl apply -f deployment.yaml + +# 3. Vérifier le déploiement +kubectl get all -n devops-demo + +# 4. Obtenir l'URL d'accès +kubectl get svc -n devops-demo devops-app-service -o jsonpath='{.spec.ports[0].nodePort}' +# Notez le numéro de port (ex: 30456) + +# 5. Accéder à l'application +# http://localhost:[PORT] (ex: http://localhost:30456) +#🏗️ ÉTAPE 6 : TERRAFORM SIMPLIFIÉ (OPTIONNEL) +#⚠️ IMPORTANT : Terraform + Docker sur Windows/WSL2 est complexe. +#Je recommande de SAUTER cette étape pour les débutants. +Si vous voulez quand même essayer : + +#6.1 Fichier : terraform\main.tf (VERSION SIMPLIFIÉE) + +# Terraform minimal pour Windows - KUBERNETES UNIQUEMENT +terraform { + required_version = ">= 1.5.0" + + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.23" + } + } +} + +# Provider Kubernetes avec Docker Desktop +provider "kubernetes" { + config_path = "~/.kube/config" + config_context = "docker-desktop" +} + +# Namespace +resource "kubernetes_namespace" "devops" { + metadata { + name = "terraform-ns" + + labels = { + created-by = "terraform" + environment = "development" + } + } +} + +# Déploiement simple +resource "kubernetes_deployment" "app" { + metadata { + name = "terraform-app" + namespace = kubernetes_namespace.devops.metadata[0].name + + labels = { + app = "terraform-app" + } + } + + spec { + replicas = 1 + + selector { + match_labels = { + app = "terraform-app" + } + } + + template { + metadata { + labels = { + app = "terraform-app" + } + } + + spec { + container { + name = "app" + image = "nginx:alpine" # Image simple pour test + + port { + container_port = 80 + } + + resources { + limits = { + cpu = "100m" + memory = "128Mi" + } + requests = { + cpu = "50m" + memory = "64Mi" + } + } + } + } + } + } + + depends_on = [kubernetes_namespace.devops] +} + +# Service +resource "kubernetes_service" "app" { + metadata { + name = "terraform-service" + namespace = kubernetes_namespace.devops.metadata[0].name + } + + spec { + selector = { + app = kubernetes_deployment.app.spec[0].template[0].metadata[0].labels.app + } + + port { + port = 8080 + target_port = 80 + } + + type = "NodePort" + } +} + +# Output utile +output "application_url" { + value = "http://localhost:${kubernetes_service.app.spec[0].port[0].node_port}" +} + +output "namespace" { + value = kubernetes_namespace.devops.metadata[0].name +} +#6.2 Utilisation Terraform : + +cd C:\DevOpsProject\terraform + +# Initialiser +terraform init + +# Voir ce qui va être créé +terraform plan + +# Appliquer (tapez 'yes' quand demandé) +terraform apply + +# Pour détruire +terraform destroy +#📦 ÉTAPE 7 : HELM SIMPLE POUR WINDOWS +#7.1 Création d'un chart Helm simple : + +cd C:\DevOpsProject\kubernetes\helm + +# Créer un chart Helm +helm create devops-chart + +# Supprimer les fichiers inutiles créés par défaut +Remove-Item devops-chart\templates\* -Recurse -Force + +# Créer une structure propre +New-Item -ItemType Directory -Path @( + "devops-chart\templates", + "devops-chart\charts" +) +#7.2 Fichier : kubernetes\helm\devops-chart\Chart.yaml + +apiVersion: v2 +name: devops-chart +description: Chart Helm pour DevOps Windows +type: application +version: 0.1.0 +appVersion: "1.0.0" +#7.3 Fichier : kubernetes\helm\devops-chart\values.yaml + +# Configuration de l'application +app: + name: "devops-helm-app" + image: + repository: "devops-app" + tag: "local" + pullPolicy: "IfNotPresent" + + replicaCount: 2 + + service: + type: NodePort + port: 80 + targetPort: 8000 + + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "200m" + + env: + ENV: "production" + LOG_LEVEL: "INFO" + +# Monitoring +monitoring: + enabled: true + prometheusScrape: true +#7.4 Fichier : kubernetes\helm\devops-chart\templates\deployment.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.app.name }} + labels: + app: {{ .Values.app.name }} + chart: {{ .Chart.Name }} + version: {{ .Chart.Version }} +spec: + replicas: {{ .Values.app.replicaCount }} + selector: + matchLabels: + app: {{ .Values.app.name }} + template: + metadata: + labels: + app: {{ .Values.app.name }} + {{- if .Values.monitoring.enabled }} + annotations: + prometheus.io/scrape: "{{ .Values.monitoring.prometheusScrape }}" + prometheus.io/port: "{{ .Values.app.service.targetPort }}" + prometheus.io/path: "/metrics" + {{- end }} + spec: + containers: + - name: {{ .Values.app.name }} + image: "{{ .Values.app.image.repository }}:{{ .Values.app.image.tag }}" + imagePullPolicy: {{ .Values.app.image.pullPolicy }} + ports: + - containerPort: {{ .Values.app.service.targetPort }} + name: http + env: + {{- range $key, $value := .Values.app.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + resources: + {{- toYaml .Values.app.resources | nindent 10 }} + readinessProbe: + httpGet: + path: /health + port: {{ .Values.app.service.targetPort }} + initialDelaySeconds: 10 + periodSeconds: 15 +#7.5 Installation avec Helm : + +cd C:\DevOpsProject\kubernetes\helm + +# Installer le chart +helm install devops-release ./devops-chart -n devops-demo --create-namespace + +# Vérifier l'installation +helm list -n devops-demo + +# Mettre à jour +helm upgrade devops-release ./devops-chart -n devops-demo + +# Désinstaller +helm uninstall devops-release -n devops-demo +#🔄 ÉTAPE 8 : GITHUB ACTIONS CORRIGÉ +#8.1 Fichier : .github\workflows\ci-cd.yml (PRATIQUE) + +name: CI/CD DevOps Windows + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + workflow_dispatch: # Permet de déclencher manuellement + +jobs: + # Job 1 : Tests de l'application + test: + runs-on: windows-latest + + steps: + - name: Checkout du code + uses: actions/checkout@v3 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r src/app/requirements.txt + + - name: Run tests + run: | + cd src/app + python -m pytest tests/ -v --cov=. --cov-report=xml + + - name: Upload coverage + uses: codecov/codecov-action@v3 + with: + file: ./src/app/coverage.xml + flags: unittests + + # Job 2 : Build Docker + build: + needs: test + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to DockerHub (seulement sur main) + if: github.ref == 'refs/heads/main' + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build Docker image + uses: docker/build-push-action@v4 + with: + context: ./src/app + push: ${{ github.ref == 'refs/heads/main' }} + tags: | + ${{ secrets.DOCKER_USERNAME }}/devops-app:latest + ${{ secrets.DOCKER_USERNAME }}/devops-app:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # Job 3 : Déploiement (optionnel pour Windows) + deploy: + needs: build + runs-on: windows-latest + if: github.ref == 'refs/heads/main' + + steps: + - uses: actions/checkout@v3 + + - name: Setup kubectl + uses: azure/setup-kubectl@v3 + with: + version: 'latest' + + - name: Configure kubeconfig + run: | + # Pour une vraie installation, configurez votre kubeconfig ici + # Pour la démo, on affiche juste un message + echo "Dans un environnement réel, vous configureriez kubeconfig ici" + echo "Utilisez des secrets GitHub pour stocker votre configuration" + + - name: Deploy to Kubernetes + run: | + echo "Déploiement simulé" + echo "En production, vous utiliseriez :" + echo "kubectl apply -f kubernetes/manifests/" + echo "ou" + echo "helm upgrade --install ..." +#📊 ÉTAPE 9 : MONITORING FONCTIONNEL +#9.1 Dashboard Grafana prêt à l'emploi : + +# Créer un dossier pour les dashboards Grafana +mkdir C:\DevOpsProject\docker\grafana-dashboards + +# Créer un fichier de dashboard simple +@' +{ + "dashboard": { + "title": "DevOps Windows Dashboard", + "panels": [ + { + "title": "Requêtes HTTP", + "type": "graph", + "targets": [{ + "expr": "rate(http_requests_total[5m])", + "legendFormat": "{{method}} {{endpoint}}" + }] + }, + { + "title": "Latence", + "type": "graph", + "targets": [{ + "expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))", + "legendFormat": "p95" + }] + } + ] + } +} +'@ | Out-File -FilePath "C:\DevOpsProject\docker\grafana-dashboards\dashboard.json" -Encoding UTF8 +#9.2 Accès aux interfaces : + +✅ Après docker-compose up -d : + +1. Application FastAPI : http://localhost:8000 +2. Documentation API : http://localhost:8000/docs (Swagger UI) +3. Métriques Prometheus : http://localhost:9090 +4. Grafana Dashboard : http://localhost:3000 + → Login : admin / admin123 +5. Portainer : http://localhost:9000 + +✅ Après déploiement Kubernetes : + +1. Application K8s : http://localhost:[NODE_PORT] + (trouvez le port avec : kubectl get svc -n devops-demo) +#🛠️ ÉTAPE 10 : SCRIPTS PRATIQUES +#10.1 Script : scripts\setup.ps1 (AMÉLIORÉ) + +# DevOps Windows Setup Script +# PowerShell 5.1+ requis + +param( + [switch]$SkipDocker = $false, + [switch]$SkipK8s = $false, + [switch]$Help = $false +) + +if ($Help) { + Write-Host "Usage: .\setup.ps1 [-SkipDocker] [-SkipK8s] [-Help]" -ForegroundColor Cyan + Write-Host " -SkipDocker : Ne pas démarrer Docker Compose" -ForegroundColor Gray + Write-Host " -SkipK8s : Ne pas déployer sur Kubernetes" -ForegroundColor Gray + Write-Host " -Help : Afficher cette aide" -ForegroundColor Gray + exit 0 +} + +Write-Host "========================================" -ForegroundColor Green +Write-Host " DEVOPS WINDOWS SETUP" -ForegroundColor Green +Write-Host "========================================" -ForegroundColor Green +Write-Host "" + +# 1. Vérification des outils +Write-Host "[1/5] Vérification des outils..." -ForegroundColor Yellow + +$tools = @( + @{Name="Docker"; Cmd="docker --version"}, + @{Name="kubectl"; Cmd="kubectl version --client"}, + @{Name="helm"; Cmd="helm version"}, + @{Name="python"; Cmd="python --version"} +) + +foreach ($tool in $tools) { + try { + $output = Invoke-Expression $tool.Cmd 2>&1 + Write-Host " ✅ $($tool.Name) : OK" -ForegroundColor Green + } catch { + Write-Host " ❌ $($tool.Name) : MANQUANT" -ForegroundColor Red + Write-Host " Installez avec: choco install $($tool.Name.ToLower())" -ForegroundColor Gray + } +} + +Write-Host "" + +# 2. Build de l'application +Write-Host "[2/5] Build de l'application Docker..." -ForegroundColor Yellow +try { + Set-Location "$PSScriptRoot\..\src\app" + docker build -t devops-app:local . + Write-Host " ✅ Image Docker construite" -ForegroundColor Green + Set-Location $PSScriptRoot +} catch { + Write-Host " ❌ Erreur lors du build Docker" -ForegroundColor Red + Write-Host $_.Exception.Message + exit 1 +} + +# 3. Docker Compose +if (-not $SkipDocker) { + Write-Host "[3/5] Démarrage Docker Compose..." -ForegroundColor Yellow + try { + Set-Location "$PSScriptRoot\..\docker" + + # Arrêter si déjà en cours + docker-compose down 2>$null + + # Démarrer + docker-compose up -d + + # Attendre que les services soient prêts + Start-Sleep -Seconds 10 + + Write-Host " ✅ Docker Compose démarré" -ForegroundColor Green + Write-Host " Attente supplémentaire pour les services..." -ForegroundColor Gray + + # Vérifier l'application + $attempts = 0 + $maxAttempts = 6 + while ($attempts -lt $maxAttempts) { + try { + $response = Invoke-WebRequest -Uri "http://localhost:8000/health" -UseBasicParsing -TimeoutSec 5 + if ($response.StatusCode -eq 200) { + Write-Host " ✅ Application accessible" -ForegroundColor Green + break + } + } catch { + $attempts++ + Write-Host " ⏳ Tentative $attempts/$maxAttempts..." -ForegroundColor Yellow + Start-Sleep -Seconds 10 + + if ($attempts -eq $maxAttempts) { + Write-Host " ⚠️ Application lente à démarrer" -ForegroundColor Yellow + } + } + } + + Set-Location $PSScriptRoot + } catch { + Write-Host " ⚠️ Erreur Docker Compose : $($_.Exception.Message)" -ForegroundColor Yellow + Set-Location $PSScriptRoot + } +} + +# 4. Kubernetes +if (-not $SkipK8s) { + Write-Host "[4/5] Déploiement Kubernetes..." -ForegroundColor Yellow + try { + Set-Location "$PSScriptRoot\..\kubernetes\manifests" + + # Vérifier que Kubernetes est activé + $k8sContext = kubectl config current-context 2>$null + if ($LASTEXITCODE -ne 0) { + Write-Host " ℹ️ Kubernetes non configuré, passage au mode Docker uniquement" -ForegroundColor Yellow + } else { + # Appliquer les manifests + kubectl apply -f namespace.yaml + kubectl apply -f configmap.yaml + kubectl apply -f deployment.yaml + + Write-Host " ✅ Déploiement Kubernetes terminé" -ForegroundColor Green + + # Obtenir les infos + $service = kubectl get svc -n devops-demo devops-app-service -o json | ConvertFrom-Json + $nodePort = $service.spec.ports[0].nodePort + Write-Host " Accès K8s : http://localhost:$nodePort" -ForegroundColor Cyan + } + + Set-Location $PSScriptRoot + } catch { + Write-Host " ⚠️ Erreur Kubernetes : $($_.Exception.Message)" -ForegroundColor Yellow + Set-Location $PSScriptRoot + } +} + +Write-Host "[5/5] Récapitulatif..." -ForegroundColor Yellow +Write-Host "" +Write-Host "========================================" -ForegroundColor Green +Write-Host " SETUP TERMINÉ !" -ForegroundColor Green +Write-Host "========================================" -ForegroundColor Green +Write-Host "" +Write-Host "🌐 ACCèS AUX SERVICES :" -ForegroundColor White +Write-Host "" +Write-Host " 📊 Application FastAPI :" -ForegroundColor Cyan +Write-Host " • Interface : http://localhost:8000" -ForegroundColor Gray +Write-Host " • Health : http://localhost:8000/health" -ForegroundColor Gray +Write-Host " • Docs : http://localhost:8000/docs" -ForegroundColor Gray +Write-Host " • Métriques : http://localhost:8000/metrics" -ForegroundColor Gray +Write-Host "" +Write-Host " 📈 Monitoring :" -ForegroundColor Cyan +Write-Host " • Prometheus : http://localhost:9090" -ForegroundColor Gray +Write-Host " • Grafana : http://localhost:3000" -ForegroundColor Gray +Write-Host " Login : admin / admin123" -ForegroundColor DarkGray +Write-Host "" +Write-Host " 🐳 Gestion Docker :" -ForegroundColor Cyan +Write-Host " • Portainer : http://localhost:9000" -ForegroundColor Gray +Write-Host "" +if (-not $SkipK8s) { + Write-Host " ☸️ Kubernetes :" -ForegroundColor Cyan + Write-Host " • Vérifier : kubectl get pods -n devops-demo" -ForegroundColor Gray + Write-Host " • Logs : kubectl logs -f -n devops-demo -l app=devops-app" -ForegroundColor Gray +} +Write-Host "" +Write-Host "🔧 COMMANDES UTILES :" -ForegroundColor White +Write-Host " * Voir les logs : docker-compose logs -f [app|prometheus|grafana]" -ForegroundColor DarkGray +Write-Host " * Arrêter tout : docker-compose down" -ForegroundColor DarkGray +Write-Host " * Nettoyer : docker system prune -a -f --volumes" -ForegroundColor DarkGray +Write-Host "" +Write-Host "💡 CONSEIL :" -ForegroundColor Yellow +Write-Host " Testez avec : curl http://localhost:8000 ou dans PowerShell :" -ForegroundColor Gray +Write-Host " Invoke-WebRequest -Uri 'http://localhost:8000' -UseBasicParsing" -ForegroundColor DarkGray +Write-Host "" + +# Test automatique +try { + $test = Invoke-WebRequest -Uri "http://localhost:8000/health" -UseBasicParsing -TimeoutSec 5 + if ($test.StatusCode -eq 200) { + Write-Host "✅ Test de santé réussi !" -ForegroundColor Green + } +} catch { + Write-Host "⚠️ L'application n'est pas encore accessible, patientez..." -ForegroundColor Yellow +} +#10.2 Script : scripts\cleanup.ps1 (COMPLET) + +# Nettoyage complet DevOps Stack +Write-Host "🧹 NETTOYAGE DEVOPS STACK" -ForegroundColor Yellow +Write-Host "==========================" -ForegroundColor Yellow +Write-Host "" + +# 1. Arrêter Docker Compose +Write-Host "[1/4] Arrêt Docker Compose..." -ForegroundColor Yellow +try { + if (Test-Path "..\docker\docker-compose.yml") { + Set-Location "..\docker" + docker-compose down -v # -v pour supprimer les volumes + Write-Host " ✅ Docker Compose arrêté" -ForegroundColor Green + Set-Location $PSScriptRoot + } +} catch { + Write-Host " ⚠️ Aucun service Docker Compose en cours" -ForegroundColor Gray +} + +# 2. Nettoyer Kubernetes +Write-Host "[2/4] Nettoyage Kubernetes..." -ForegroundColor Yellow +try { + # Supprimer le namespace (supprime tout à l'intérieur) + kubectl delete namespace devops-demo --ignore-not-found=true + kubectl delete namespace terraform-ns --ignore-not-found=true + + # Désinstaller Helm + helm uninstall devops-release --namespace devops-demo --ignore-not-found=true + + Write-Host " ✅ Kubernetes nettoyé" -ForegroundColor Green +} catch { + Write-Host " ⚠️ Kubernetes non configuré ou déjà nettoyé" -ForegroundColor Gray +} + +# 3. Nettoyer Docker +Write-Host "[3/4] Nettoyage Docker..." -ForegroundColor Yellow +try { + # Arrêter tous les conteneurs + docker stop $(docker ps -aq) 2>$null + + # Supprimer tous les conteneurs + docker rm $(docker ps -aq) 2>$null + + # Supprimer toutes les images + docker rmi $(docker images -q) -f 2>$null + + # Nettoyer le système + docker system prune -a -f --volumes + + Write-Host " ✅ Docker nettoyé" -ForegroundColor Green +} catch { + Write-Host " ℹ️ Aucune ressource Docker à nettoyer" -ForegroundColor Gray +} + +# 4. Nettoyer Terraform +Write-Host "[4/4] Nettoyage Terraform..." -ForegroundColor Yellow +try { + if (Test-Path "..\terraform") { + Set-Location "..\terraform" + + # Détruire l'infrastructure si terraform.tfstate existe + if (Test-Path "terraform.tfstate") { + terraform destroy -auto-approve 2>$null + } + + # Supprimer les fichiers temporaires + Remove-Item -Path "*.tfstate*", ".terraform*", "terraform.tfstate.backup" -Force -ErrorAction SilentlyContinue + + Write-Host " ✅ Terraform nettoyé" -ForegroundColor Green + Set-Location $PSScriptRoot + } +} catch { + Write-Host " ℹ️ Terraform non configuré" -ForegroundColor Gray +} + +Write-Host "" +Write-Host "========================================" -ForegroundColor Green +Write-Host " NETTOYAGE TERMINÉ !" -ForegroundColor Green +Write-Host "========================================" -ForegroundColor Green +Write-Host "" +Write-Host "✅ Toutes les ressources ont été nettoyées" -ForegroundColor Green +Write-Host "" +Write-Host "Pour recommencer :" -ForegroundColor Cyan +Write-Host " .\setup.ps1" -ForegroundColor Gray +#🎯 VALIDATION FINALE +#Testez votre installation : + +# 1. Lancer le setup +cd C:\DevOpsProject\scripts +.\setup.ps1 + +# 2. Tester chaque service +# Application +curl http://localhost:8000 +# ou +Invoke-WebRequest -Uri "http://localhost:8000" -UseBasicParsing | Select-Object -ExpandProperty Content + +# Health check +curl http://localhost:8000/health + +# Métriques Prometheus +curl http://localhost:8000/metrics + +# 3. Vérifier Docker +docker ps +docker-compose ps + +# 4. Vérifier Kubernetes +kubectl get pods --all-namespaces +kubectl get svc -n devops-demo + +# 5. Accéder aux interfaces web +# Ouvrez votre navigateur et allez sur : +# - http://localhost:8000 (App) +# - http://localhost:8000/docs (Documentation API) +# - http://localhost:9090 (Prometheus) +# - http://localhost:3000 (Grafana - admin/admin123) +# - http://localhost:9000 (Portainer) + +#Problèmes courants et solutions : +Problème +Solution +WSL2 ne démarre pas +wsl --shutdown puis redémarrer Docker Desktop +Docker Desktop ne démarre pas +Vérifier Hyper-V dans "Fonctionnalités Windows" +Port déjà utilisé +`netstat -ano +kubectl non reconnu +Réinstaller : choco install kubernetes-cli -y +Prometheus ne scrape pas +Vérifier docker\prometheus.yml et les labels +Application inaccessible +Vérifier les logs : docker-compose logs app + +Votre stack DevOps Windows est maintenant fonctionnelle et prête à l'emploi ! 🎉 + + + + + +# Commentaire de Oualim +# Avant d'aller plus loin, les partie 6,7 et 8 n'étant pas encore abordée à cette étape, en lançant uniquement les commandes de la partie 4.3 on se retrouvera avec des containeurs orphelins : + +PS C:\DevOpsProject\docker> docker-compose ps +"....Found orphan containers ([gitea logstash kibana filebeat elasticsearch devops-db])...." + + + + +# 6. Pour aller plus loin : + +- Ajouter une base de données (PostgreSQL) + + +- Implémenter un vrai pipeline CI/CD avec déploiement automatique + + +- Ajouter du logging centralisé (ELK Stack) + + +- Configurer des alertes Prometheus + + + +# Commentaire de Oualim +# 7. Basculer sur kubernets (découverte nodes & pods) + +- Mettre en place du GitOps avec ArgoCD + +- Configurer HTTPS avec un reverse proxy + + + +# Commentaire de Oualim +# 8. Simuler une prod qu'on pourrait relancer en 5mn from scratch après un reset du cluster k8' ou une réinstall de docker desktop +- Créer des scripts regroupant tous les démarrages pour : +- les dockers (Deploy.ctnrs.ps1) +- les pods (deploy.Pods.ps1) +- créer le dashbord et générer le kubeconfig (dashboard.kubeconfig) pour s'y connecter (GnrkbCfOpnDash.ps1) +- créer argo et lancer la page web de connexion avec id et mdp (start-argocd.ps1) + + + + + + + + + + + diff --git a/gitea/gitea-data/gitea/indexers/issues.bleve/store/root.bolt b/gitea/gitea-data/gitea/indexers/issues.bleve/store/root.bolt index 05761814b110b7662b68b296ac20ed61ef4819fb..5133646e85e8f1c1b53787fa80588c4b1de30169 100644 GIT binary patch delta 61 zcmZo@U}9#8W;y4f&c1OFz4B?2O*A%><_riNCAW_m{E24-fa N2IiKVcNln_2LK@>5+(ou delta 60 zcmZo@U}Bd027=M+W-In diff --git a/gitea/gitea-data/gitea/queues/common/000093.log b/gitea/gitea-data/gitea/queues/common/000095.log similarity index 100% rename from gitea/gitea-data/gitea/queues/common/000093.log rename to gitea/gitea-data/gitea/queues/common/000095.log diff --git a/gitea/gitea-data/gitea/queues/common/CURRENT b/gitea/gitea-data/gitea/queues/common/CURRENT index 0ab25fa..6274e55 100644 --- a/gitea/gitea-data/gitea/queues/common/CURRENT +++ b/gitea/gitea-data/gitea/queues/common/CURRENT @@ -1 +1 @@ -MANIFEST-000094 +MANIFEST-000096 diff --git a/gitea/gitea-data/gitea/queues/common/CURRENT.bak b/gitea/gitea-data/gitea/queues/common/CURRENT.bak index 5b83d76..0ab25fa 100644 --- a/gitea/gitea-data/gitea/queues/common/CURRENT.bak +++ b/gitea/gitea-data/gitea/queues/common/CURRENT.bak @@ -1 +1 @@ -MANIFEST-000092 +MANIFEST-000094 diff --git a/gitea/gitea-data/gitea/queues/common/LOG b/gitea/gitea-data/gitea/queues/common/LOG index 2184600..e54c641 100644 --- a/gitea/gitea-data/gitea/queues/common/LOG +++ b/gitea/gitea-data/gitea/queues/common/LOG @@ -406,3 +406,12 @@ 12:59:33.512231 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00] 12:59:33.572905 db@janitor F·3 G·0 12:59:33.573247 db@open done T·67.527982ms +=============== Feb 4, 2026 (UTC) =============== +13:52:44.406047 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +13:52:44.415847 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00] +13:52:44.417579 db@open opening +13:52:44.424530 journal@recovery F·1 +13:52:44.424776 journal@recovery recovering @91 +13:52:44.428084 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00] +13:52:44.486849 db@janitor F·3 G·0 +13:52:44.487042 db@open done T·69.246442ms diff --git a/gitea/gitea-data/gitea/queues/common/MANIFEST-000094 b/gitea/gitea-data/gitea/queues/common/MANIFEST-000096 similarity index 100% rename from gitea/gitea-data/gitea/queues/common/MANIFEST-000094 rename to gitea/gitea-data/gitea/queues/common/MANIFEST-000096