12 KiB
12 KiB
15 — Opérations, Scaling et Troubleshooting
Référence quotidienne pour gérer le cluster en production.
Commandes kubectl essentielles
Vue d'ensemble rapide
# É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
# 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
# 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
# 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
# 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)
# 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
# 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)
# 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
# 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 :
# 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
# 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é)
# 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
# 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
# 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
# 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
#!/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)
#!/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//xpeditis2.0/actions |
| GitHub GHCR | https://github.com//xpeditis2.0/pkgs/container |