425 lines
12 KiB
Markdown
425 lines
12 KiB
Markdown
# 15 — Opérations, Scaling et Troubleshooting
|
|
|
|
Référence quotidienne pour gérer le cluster en production.
|
|
|
|
---
|
|
|
|
## Commandes kubectl essentielles
|
|
|
|
### Vue d'ensemble rapide
|
|
|
|
```bash
|
|
# État du cluster
|
|
kubectl get nodes
|
|
kubectl get pods -n xpeditis-prod
|
|
kubectl get pods -n xpeditis-prod -o wide # + infos sur les nœuds
|
|
|
|
# Ressources consommées
|
|
kubectl top nodes
|
|
kubectl top pods -n xpeditis-prod --sort-by=cpu
|
|
|
|
# Événements récents (erreurs, warnings)
|
|
kubectl get events -n xpeditis-prod --sort-by='.lastTimestamp' | tail -30
|
|
kubectl get events -n xpeditis-prod -w # En temps réel
|
|
|
|
# État des déploiements
|
|
kubectl get deployments -n xpeditis-prod
|
|
kubectl get hpa -n xpeditis-prod
|
|
kubectl get pvc -n xpeditis-prod
|
|
```
|
|
|
|
### Logs
|
|
|
|
```bash
|
|
# Logs backend (tous les pods)
|
|
kubectl logs -l app=xpeditis-backend -n xpeditis-prod --since=1h
|
|
|
|
# Logs frontend
|
|
kubectl logs -l app=xpeditis-frontend -n xpeditis-prod --since=1h
|
|
|
|
# Logs en temps réel (un pod spécifique)
|
|
kubectl logs -f pod/xpeditis-backend-5b8d6c7f9-xxxxx -n xpeditis-prod
|
|
|
|
# Logs multi-pods en temps réel (avec stern)
|
|
stern xpeditis-backend -n xpeditis-prod
|
|
stern xpeditis -n xpeditis-prod # Backend + frontend
|
|
|
|
# Filtrer les erreurs
|
|
kubectl logs -l app=xpeditis-backend -n xpeditis-prod --since=1h | grep -E "ERROR|error|Error"
|
|
|
|
# Logs des dernières 100 lignes d'un pod crashé
|
|
kubectl logs --previous pod/xpeditis-backend-xxx -n xpeditis-prod | tail -100
|
|
```
|
|
|
|
### Exécution dans un pod
|
|
|
|
```bash
|
|
# Shell interactif dans un pod backend
|
|
kubectl exec -it deployment/xpeditis-backend -n xpeditis-prod -- /bin/sh
|
|
|
|
# Commande unique
|
|
kubectl exec deployment/xpeditis-backend -n xpeditis-prod -- \
|
|
node -e "console.log(process.env.NODE_ENV)"
|
|
|
|
# Vérifier la connectivité DB depuis un pod
|
|
kubectl exec deployment/xpeditis-backend -n xpeditis-prod -- \
|
|
nc -zv 10.0.1.100 5432
|
|
```
|
|
|
|
---
|
|
|
|
## Déploiements
|
|
|
|
### Déploiement d'une nouvelle version
|
|
|
|
```bash
|
|
# Via CI/CD (automatique sur push main) — voir doc 11
|
|
|
|
# Manuel : mettre à jour l'image
|
|
IMAGE_TAG="sha-$(git rev-parse --short HEAD)"
|
|
|
|
kubectl set image deployment/xpeditis-backend \
|
|
backend=ghcr.io/<ORG>/xpeditis-backend:${IMAGE_TAG} \
|
|
-n xpeditis-prod
|
|
|
|
# Suivre le déploiement
|
|
kubectl rollout status deployment/xpeditis-backend -n xpeditis-prod --timeout=300s
|
|
|
|
# Vérifier la version déployée
|
|
kubectl get deployment xpeditis-backend -n xpeditis-prod \
|
|
-o jsonpath='{.spec.template.spec.containers[0].image}'
|
|
```
|
|
|
|
### Rollback
|
|
|
|
```bash
|
|
# Rollback vers la version précédente
|
|
kubectl rollout undo deployment/xpeditis-backend -n xpeditis-prod
|
|
|
|
# Rollback vers une version spécifique
|
|
kubectl rollout history deployment/xpeditis-backend -n xpeditis-prod
|
|
# REVISION CHANGE-CAUSE
|
|
# 1 Initial deployment
|
|
# 2 sha-abc1234
|
|
# 3 sha-def5678 ← actuelle
|
|
|
|
kubectl rollout undo deployment/xpeditis-backend \
|
|
--to-revision=2 \
|
|
-n xpeditis-prod
|
|
|
|
# Vérifier
|
|
kubectl rollout status deployment/xpeditis-backend -n xpeditis-prod
|
|
```
|
|
|
|
### Redémarrage forcé (sans changer l'image)
|
|
|
|
```bash
|
|
# Utile après modification des secrets ou configmaps
|
|
kubectl rollout restart deployment/xpeditis-backend -n xpeditis-prod
|
|
kubectl rollout restart deployment/xpeditis-frontend -n xpeditis-prod
|
|
|
|
# Ou redémarrer un pod spécifique (K8s en recrée un nouveau)
|
|
kubectl delete pod xpeditis-backend-5b8d6c7f9-xxxxx -n xpeditis-prod
|
|
```
|
|
|
|
---
|
|
|
|
## Scaling manuel
|
|
|
|
```bash
|
|
# Scale horizontal (nombre de pods)
|
|
kubectl scale deployment xpeditis-backend \
|
|
--replicas=5 \
|
|
-n xpeditis-prod
|
|
|
|
# Scale horizontal frontend
|
|
kubectl scale deployment xpeditis-frontend \
|
|
--replicas=3 \
|
|
-n xpeditis-prod
|
|
|
|
# Désactiver temporairement le HPA (maintenance)
|
|
kubectl patch hpa backend-hpa -n xpeditis-prod \
|
|
-p '{"spec":{"minReplicas":0,"maxReplicas":0}}'
|
|
|
|
# Réactiver le HPA
|
|
kubectl patch hpa backend-hpa -n xpeditis-prod \
|
|
-p '{"spec":{"minReplicas":2,"maxReplicas":15}}'
|
|
```
|
|
|
|
---
|
|
|
|
## Gestion des nœuds
|
|
|
|
### Maintenance d'un nœud (drain)
|
|
|
|
```bash
|
|
# 1. Mettre le nœud en maintenance (draine les pods, bloque les nouveaux)
|
|
kubectl cordon xpeditis-prod-cx32-worker-1
|
|
kubectl drain xpeditis-prod-cx32-worker-1 \
|
|
--ignore-daemonsets \
|
|
--delete-emptydir-data \
|
|
--grace-period=30
|
|
|
|
# 2. Effectuer la maintenance (mise à jour OS, etc.)
|
|
ssh -i ~/.ssh/xpeditis_hetzner root@<NODE_IP>
|
|
apt-get update && apt-get upgrade -y
|
|
reboot
|
|
|
|
# 3. Remettre le nœud en service
|
|
kubectl uncordon xpeditis-prod-cx32-worker-1
|
|
|
|
# Vérifier que les pods reviennent
|
|
kubectl get pods -n xpeditis-prod -o wide | grep worker-1
|
|
```
|
|
|
|
### Ajouter un nœud worker
|
|
|
|
```bash
|
|
# Méthode 1 : Via hetzner-k3s (recommandé)
|
|
# Modifier cluster.yaml → instance_count: 3 (ou plus)
|
|
hetzner-k3s apply --config ~/.xpeditis/cluster.yaml
|
|
|
|
# Méthode 2 : Via Cluster Autoscaler (automatique)
|
|
# Le CA crée des nœuds quand des pods sont en état "Pending"
|
|
# Pour forcer : déployer une charge
|
|
kubectl scale deployment xpeditis-backend --replicas=20 -n xpeditis-prod
|
|
# Le CA va créer des nœuds automatiquement
|
|
# Remettre en place après test
|
|
kubectl scale deployment xpeditis-backend --replicas=2 -n xpeditis-prod
|
|
```
|
|
|
|
---
|
|
|
|
## Mise à jour de k3s
|
|
|
|
Le System Upgrade Controller gère les upgrades automatiquement. Pour une mise à jour manuelle :
|
|
|
|
```bash
|
|
# Vérifier la version actuelle
|
|
kubectl get nodes -o jsonpath='{.items[0].status.nodeInfo.kubeletVersion}'
|
|
# v1.30.4+k3s1
|
|
|
|
# Créer un Plan de mise à jour
|
|
cat > /tmp/k3s-upgrade.yaml << 'EOF'
|
|
apiVersion: upgrade.cattle.io/v1
|
|
kind: Plan
|
|
metadata:
|
|
name: k3s-server
|
|
namespace: system-upgrade
|
|
spec:
|
|
concurrency: 1 # Un nœud à la fois
|
|
cordon: true
|
|
serviceAccountName: system-upgrade
|
|
version: v1.31.0+k3s1 # Nouvelle version
|
|
upgrade:
|
|
image: rancher/k3s-upgrade
|
|
channel: https://update.k3s.io/v1-release/channels/stable
|
|
nodeSelector:
|
|
matchExpressions:
|
|
- {key: node-role.kubernetes.io/control-plane, operator: Exists}
|
|
---
|
|
apiVersion: upgrade.cattle.io/v1
|
|
kind: Plan
|
|
metadata:
|
|
name: k3s-agent
|
|
namespace: system-upgrade
|
|
spec:
|
|
concurrency: 1
|
|
cordon: true
|
|
serviceAccountName: system-upgrade
|
|
version: v1.31.0+k3s1
|
|
prepare:
|
|
image: rancher/k3s-upgrade
|
|
args: ["prepare", "k3s-server"]
|
|
upgrade:
|
|
image: rancher/k3s-upgrade
|
|
channel: https://update.k3s.io/v1-release/channels/stable
|
|
nodeSelector:
|
|
matchExpressions:
|
|
- {key: node-role.kubernetes.io/control-plane, operator: DoesNotExist}
|
|
EOF
|
|
|
|
kubectl apply -f /tmp/k3s-upgrade.yaml
|
|
|
|
# Suivre la progression
|
|
kubectl get plans -n system-upgrade
|
|
kubectl get jobs -n system-upgrade
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting — Problèmes courants
|
|
|
|
### Pod en CrashLoopBackOff
|
|
|
|
```bash
|
|
# 1. Voir les logs du crash
|
|
kubectl logs pod/xpeditis-backend-xxx -n xpeditis-prod --previous
|
|
|
|
# 2. Décrire le pod
|
|
kubectl describe pod xpeditis-backend-xxx -n xpeditis-prod
|
|
# Chercher : "Error", "OOMKilled", "Exit Code"
|
|
|
|
# Causes fréquentes :
|
|
# - OOMKilled (Exit 137) → Augmenter limits.memory
|
|
# - Exit 1 → Erreur applicative (DB unreachable, env var manquante)
|
|
# - Exit 126 → Problème de permissions sur le fichier d'entrée
|
|
|
|
# 3. Si env var manquante
|
|
kubectl exec deployment/xpeditis-backend -n xpeditis-prod -- env | sort | grep -E "DB|REDIS|JWT"
|
|
```
|
|
|
|
### Pod en Pending (pas démarré)
|
|
|
|
```bash
|
|
# Voir pourquoi le pod ne démarre pas
|
|
kubectl describe pod xpeditis-backend-xxx -n xpeditis-prod | grep -A 20 Events
|
|
|
|
# Causes fréquentes :
|
|
# "Insufficient cpu/memory" → Pas assez de ressources sur les nœuds → Scale up
|
|
# "0/2 nodes are available" → Vérifier les taints/tolerations
|
|
# "did not trigger scale-up" → Cluster Autoscaler peut-être désactivé
|
|
|
|
# Vérifier le Cluster Autoscaler
|
|
kubectl logs -n kube-system deployment/cluster-autoscaler | tail -30
|
|
```
|
|
|
|
### L'API backend retourne des 500
|
|
|
|
```bash
|
|
# 1. Vérifier les logs récents
|
|
kubectl logs -l app=xpeditis-backend -n xpeditis-prod --since=15m | grep -E "Error|error|500"
|
|
|
|
# 2. Tester le health check directement
|
|
kubectl exec deployment/xpeditis-backend -n xpeditis-prod -- \
|
|
wget -qO- http://localhost:4000/api/v1/health | jq .
|
|
|
|
# 3. Tester la connexion DB
|
|
kubectl exec deployment/xpeditis-backend -n xpeditis-prod -- \
|
|
node -e "
|
|
const { Client } = require('pg');
|
|
const c = new Client({connectionString: process.env.DATABASE_URL || 'postgres://'+process.env.DATABASE_USER+':'+process.env.DATABASE_PASSWORD+'@'+process.env.DATABASE_HOST+':'+process.env.DATABASE_PORT+'/'+process.env.DATABASE_NAME});
|
|
c.connect().then(() => { console.log('DB OK'); c.end(); }).catch(e => { console.error('DB Error:', e.message); });
|
|
"
|
|
|
|
# 4. Tester la connexion Redis
|
|
kubectl exec deployment/xpeditis-backend -n xpeditis-prod -- \
|
|
node -e "
|
|
const Redis = require('ioredis');
|
|
const r = new Redis({host:process.env.REDIS_HOST,port:process.env.REDIS_PORT,password:process.env.REDIS_PASSWORD});
|
|
r.ping().then(res => { console.log('Redis OK:', res); r.quit(); }).catch(e => { console.error('Redis Error:', e.message); });
|
|
"
|
|
```
|
|
|
|
### TLS ne fonctionne pas
|
|
|
|
```bash
|
|
# Vérifier cert-manager
|
|
kubectl get certificates -n xpeditis-prod
|
|
kubectl describe certificate xpeditis-tls-prod -n xpeditis-prod
|
|
|
|
# Voir les challenges ACME
|
|
kubectl get challenges -n xpeditis-prod
|
|
|
|
# Si challenge bloqué : vérifier que l'IP du LB est dans le DNS Cloudflare
|
|
dig +short api.xpeditis.com
|
|
# Doit retourner l'IP du Hetzner LB
|
|
|
|
# Forcer le renouvellement du certificat
|
|
kubectl delete certificate xpeditis-tls-prod -n xpeditis-prod
|
|
kubectl apply -f k8s/07-ingress.yaml # Le certificat sera recréé automatiquement
|
|
```
|
|
|
|
### WebSocket se déconnecte fréquemment
|
|
|
|
```bash
|
|
# 1. Vérifier les sticky sessions dans Traefik
|
|
kubectl logs -l app.kubernetes.io/name=traefik -n kube-system | grep -i sticky
|
|
|
|
# 2. Vérifier Cloudflare WebSocket est activé
|
|
# Cloudflare → Votre domaine → Network → WebSockets → ON
|
|
|
|
# 3. Vérifier le timeout WebSocket
|
|
# Cloudflare → Rules → Configuration Rules
|
|
# Créer une règle pour api.xpeditis.com/* → WebSocket timeout : 300s
|
|
|
|
# 4. Vérifier les logs Socket.IO
|
|
kubectl logs -l app=xpeditis-backend -n xpeditis-prod | grep -i socket
|
|
```
|
|
|
|
---
|
|
|
|
## Mise en maintenance planifiée
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# scripts/maintenance-mode.sh
|
|
|
|
echo "🔧 Activation du mode maintenance"
|
|
|
|
# 1. Mettre à jour le ConfigMap pour afficher une page de maintenance
|
|
kubectl patch configmap frontend-config -n xpeditis-prod \
|
|
--type='json' \
|
|
-p='[{"op":"add","path":"/data/MAINTENANCE_MODE","value":"true"}]'
|
|
|
|
# 2. Redémarrer le frontend
|
|
kubectl rollout restart deployment/xpeditis-frontend -n xpeditis-prod
|
|
kubectl rollout status deployment/xpeditis-frontend -n xpeditis-prod
|
|
|
|
# 3. Prévenir l'équipe
|
|
echo "✅ Mode maintenance activé. L'app affiche une page de maintenance."
|
|
echo "Pour désactiver : kubectl patch configmap frontend-config -n xpeditis-prod --type='json' -p='[{\"op\":\"remove\",\"path\":\"/data/MAINTENANCE_MODE\"}]'"
|
|
```
|
|
|
|
---
|
|
|
|
## Surveillance quotidienne (5 min/jour)
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# scripts/daily-check.sh
|
|
echo "=== Rapport Quotidien Xpeditis $(date) ==="
|
|
|
|
echo -e "\n--- CLUSTER ---"
|
|
kubectl get nodes
|
|
kubectl top nodes
|
|
|
|
echo -e "\n--- PODS ---"
|
|
kubectl get pods -n xpeditis-prod
|
|
|
|
echo -e "\n--- HPA ---"
|
|
kubectl get hpa -n xpeditis-prod
|
|
|
|
echo -e "\n--- EVENTS RÉCENTS (warnings) ---"
|
|
kubectl get events -n xpeditis-prod \
|
|
--field-selector type=Warning \
|
|
--sort-by='.lastTimestamp' | tail -10
|
|
|
|
echo -e "\n--- HEALTH CHECK ---"
|
|
curl -sf https://api.xpeditis.com/api/v1/health | jq '.status' || echo "❌ API DOWN"
|
|
curl -sf -o /dev/null -w "Frontend: %{http_code}\n" https://app.xpeditis.com/
|
|
|
|
echo -e "\n--- CERTIFICATS ---"
|
|
kubectl get certificate -n xpeditis-prod
|
|
|
|
echo -e "\n--- STOCKAGE ---"
|
|
kubectl get pvc -n xpeditis-prod
|
|
|
|
echo "=== Fin du rapport ==="
|
|
```
|
|
|
|
---
|
|
|
|
## Liens utiles
|
|
|
|
| Ressource | URL |
|
|
|---|---|
|
|
| Dashboard Grafana | https://monitoring.xpeditis.com |
|
|
| API Swagger | https://api.xpeditis.com/api/docs |
|
|
| Hetzner Console | https://console.hetzner.cloud |
|
|
| Cloudflare Dashboard | https://dash.cloudflare.com |
|
|
| Neon Dashboard | https://console.neon.tech |
|
|
| Upstash Console | https://console.upstash.com |
|
|
| GitHub Actions | https://github.com/<ORG>/xpeditis2.0/actions |
|
|
| GitHub GHCR | https://github.com/<ORG>/xpeditis2.0/pkgs/container |
|