1495 lines
41 KiB
Markdown
1495 lines
41 KiB
Markdown
# TP DevOps
|
||
|
||
...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)
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|