De Docker Swarm à Kubernetes
Pourquoi migrer de Swarm vers Kubernetes ?
Docker Swarm reste un excellent outil d'orchestration. Il est simple à mettre en place, intuitive, et suffit pour beaucoup de cas d'usage. Mais en production, certaines limites apparaissent :
- Scaling limité : Swarm gère le scaling, mais sans mécanisme avancé d'autoscaling (pas de HPA natif)
- Networking rigide : le routing mesh est pratique mais offre peu de contrôle sur le trafic entrant/sortant
- Absence de self-healing intelligent : Swarm redémarre les containers, mais ne comprend pas les états d'application
- Écosystème restreint : pas d'operators, pas de CRDs, peu d'intégrations enterprise
- Stagnation du projet : Docker Inc. a réduit l'investissement dans Swarm au profit de Docker Desktop
Comparaison : Swarm vs Kubernetes
| Aspect | Docker Swarm | Kubernetes |
|---|---|---|
| Complexité | Faible — config Docker native | Élevée — courbe d'apprentissage importante |
| Fichier de config | docker-compose.yml |
Manifests YAML multiples (Deployment, Service, Ingress...) |
| Scaling | Manuel ou basique | HPA, VPA, Cluster Autoscaler |
| Self-healing | Redémarrage du container | Liveness/readiness/startup probes |
| Networking | Overlay, routing mesh | CNI plugin (Calico, Cilium, Flannel) |
| Ingress / Load Balancing | Built-in routing mesh | Ingress controllers, LoadBalancer, MetalLB |
| Stockage | Volumes Docker | PersistentVolumes, PVC, StorageClasses |
| Secrets | docker secret |
Secrets natifs + Sealed Secrets, Vault |
| Rolling updates | Oui (basique) | Oui (blue-green, canary, rolling) |
| Stateful apps | Limité | StatefulSets, Operators |
| Écosystème | Étroit | Massif (Helm, Operators, CRDs) |
| Cloud natif | Non | Oui (EKS, GKE, AKS) |
Les changements architecturaux fondamentaux
Un modèle déclaratif poussé à l'extrême
Docker Swarm est déclaratif (vous déclarez l'état souhaité), mais Kubernetes porte ce concept beaucoup plus loin. Chaque ressource est un objet dans un store distribué (etcd), et le control plane travaille en permanence pour rapprocher l'état réel de l'état déclaré.
# Swarm : un seul fichier
docker stack deploy -c docker-compose.yml monapp
# Kubernetes : plusieurs manifests
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
kubectl apply -f configmap.yaml
docker-compose.yml, Kubernetes sépare les responsabilités : Deployment (qui tourne), Service (comment joindre), Ingress (comment exposer), ConfigMap (configuration), Secret (secrets). C'est plus verbeux, mais plus modulaire.Une API unifiée
Swarm est couplé à Docker. Kubernetes a sa propre API REST. C'est une force : tout est programmeable, scriptable, extensible via des opérateurs et des CRDs (Custom Resource Definitions).
Adapter le réseau
C'est l'un des changements les plus impactants. Le modèle de réseau est radicalement différent.
Swarm : le routing mesh
En Swarm, le routing mesh est magique : chaque nœud du cluster accepte le trafic sur le port publie, et le route vers le bon service. C'est simple et transparent.
Kubernetes : CNI + Ingress
Kubernetes ne impose pas de solution réseau. Il utilise des plugins CNI (Container Network Interface) pour le réseau pod-to-pod, et des Ingress controllers pour le trafic externe.
| Besoins | Swarm | Kubernetes |
|---|---|---|
| Pod-to-pod | Overlay network (built-in) | CNI plugin : Calico, Cilium, Flannel |
| Service discovery | DNS intégré (name → service) | CoreDNS + Service objects |
| Trafic externe | Routing mesh (port publish) | Ingress controller (nginx, traefik, HAProxy) |
| Load balancing interne | Built-in round-robin | Service kube-proxy (iptables/IPVS) |
| Réseau par défaut | Overlay chiffré | Non chiffré par défaut (à configurer) |
# Swarm : créer un réseau overlay
docker network create --driver overlay --encrypted mon-reseau
# Kubernetes : créer un namespace avec policies réseau
kubectl create namespace production
cat <
Adapter le load balancing
Swarm : transparent par défaut
En Swarm, le load balancing est intégré. Vous exposez un port, le routing mesh s'occupe du reste. C'est merveilleusement simple.
Kubernetes : un choix à faire
Kubernetes vous laisse le choix, ce qui implique de comprendre les options :
- ClusterIP : accès interne uniquement (par défaut)
- NodePort : expose sur un port de chaque nœud (limité)
- LoadBalancer : balance vers un LB externe (cloud)
- Ingress : proxy HTTP/HTTPS avec routing par host/path
LoadBalancer en address pool local. C'est l'équivalent du routing mesh de Swarm pour Kubernetes.# Equivalent Swarm : docker service publish --published-port 80:80
# Kubernetes avec Ingress :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mon-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mon-app
port:
number: 80
Adapter le stockage
Swarm : volumes simples
Swarm utilise les volumes Docker classiques. Pour le stockage persistant entre nœuds, il faut des drivers de volumes externes (NFS, Portworx, etc.).
Kubernetes : PersistentVolumes + StorageClasses
Kubernetes introduit un système de stockage abstrait et puissant :
- PersistentVolume (PV) : le stockage physique (NFS, disque cloud, etc.)
- PersistentVolumeClaim (PVC) : la demande de stockage par le pod
- StorageClass : automatise la création de PV selon le besoin
| Concept | Swarm | Kubernetes |
|---|---|---|
| Volume | docker volume create |
PersistentVolume |
| Demande | Directe (dans le service) | PersistentVolumeClaim |
| Classe | Driver (NFS, local...) | StorageClass (dynamic provisioning) |
| Stateful | Limité | StatefulSets + volumeClaimTemplates |
# Swarm
docker service create --name bdd --mount type=volume,source=data-pg,target=/var/lib/postgresql/data postgres:15
# Kubernetes : 3 fichiers nécessaires
# 1. StorageClass (si dynamic provisioning)
# 2. PVC (la demande)
# 3. StatefulSet (qui référence le PVC)
Adapter les secrets
Swarm : docker secret
Swarm a un système de secrets simple et efficace : les secrets sont stockés dans le raft et montés en tmpfs dans les containers.
Kubernetes : Secrets natifs et au-delà
Kubernetes a des secrets natifs, mais ils sont base64 encodés, pas chiffrés par défaut. En production, il faut aller plus loin :
- Sealed Secrets : secrets chiffrés dans Git, déchiffrés par le cluster
- External Secrets Operator : synchronise depuis Vault, AWS Secrets Manager, etc.
- HashiCorp Vault : solution enterprise de gestion de secrets
# Swarm
echo "ma_secret" | docker secret create mon_secret -
# Kubernetes natif
kubectl create secret generic mon-secret --from-literal=password=ma_secret
# Kubernetes chiffré (Sealed Secrets)
echo -n ma_secret | kubeseal --format yaml > sealed-secret.yaml
Adapter les health checks
Swarm : Docker healthcheck
Swarm utilise le healthcheck de Docker. C'est un seul mécanisme qui vérifie si le container est vivant.
Kubernetes : trois probes distinctes
Kubernetes distingue trois types de vérifications, chacun avec un rôle précis :
| Probe | Objectif | Quand |
|---|---|---|
| Liveness | Le container est-il vivant ? | En continu — redémarre si échec |
| Readiness | Le container est-il prêt à servir ? | Avant de recevoir du trafic |
| Startup | L'application a-t-elle démarré ? | Une seule fois au démarrage |
# Swarm
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
# Kubernetes
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
httpGet:
path: /health
port: 80
failureThreshold: 30
periodSeconds: 10
Adapter les deployments
Swarm : rolling update basique
Swarm propose un rolling update avec contrôle de la parallélisme. C'est suffisant pour beaucoup de cas.
Kubernetes : stratégies avancées
Kubernetes offre un contrôle plus granulaire :
- Rolling Update (par défaut) : remplacement progressif des pods
- Recreate : arrêt de tous les anciens avant le démarrage des nouveaux
- Blue-Green : deux versions côte à côte, switch instantané
- Canary : déploiement progressif sur un sous-ensemble
# Swarm
docker service update --update-parallelism 2 --update-delay 30s mon-service
# Kubernetes : Rolling Update (par défaut)
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-app
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 1 pod de plus pendant le update
maxUnavailable: 0 # zéro downtime
Resource limits
En Swarm, les limites de ressources sont optionnelles et rarement utilisées. En K8s, c'est essentiel pour la stabilité du cluster.
# Swarm (optionnel)
docker service create --limit-cpu 1 --limit-memory 512M mon-service
# Kubernetes (obligatoire en production)
resources:
requests:
cpu: "250m" # minimum garanti
memory: "256Mi"
limits:
cpu: "500m" # maximum autorisé
memory: "512Mi"
Stratégie de migration
Étape 1 : Inventaire et audit
Avant toute chose, cartographiez votre infrastructure Swarm :
- Lister tous les services et leurs dépendances
- Identifier les services stateful (bases de données, files d'attente)
- Documenter les réseaux et les secrets utilisés
- Noter les custom configurations (health checks, update configs, placement constraints)
Étape 2 : Parallélisation
Ne migrez pas tout d'un coup. La stratégie recommandée :
- Monter un cluster K8s à côté du cluster Swarm existant
- Migrer les services stateless d'abord (APIs, workers, frontends)
- Migrer les bases de données en dernier (avec une période de double écriture si possible)
- Tester en staging avant la production
Étape 3 : Cutover
- Mettre à jour le DNS pour pointer vers le nouveau cluster
- Surveiller les logs et métriques pendant 24-48h
- Conserver le cluster Swarm en standby pendant 1-2 semaines
- Décommissionner Swarm une fois la stabilité confirmée
Outils d'aide à la migration
Kompose
Kompose convertit vos docker-compose.yml en manifests Kubernetes. Ce n'est pas parfait, mais c'est un excellent point de départ.
# Installer Kompose
curl -L https://github.com/kubernetes/kompose/releases/latest/download/kompose-linux-amd64 -o kompose
chmod +x kompose && sudo mv kompose /usr/local/bin/
# Convertir
kompose convert -f docker-compose.yml
# Résultat : plusieurs fichiers YAML (deployment, service, etc.)
# À adapter manuellement ensuite
Checklist de conversion
| Swarm | Kubernetes | Notes |
|---|---|---|
| services | Deployment + Service | Séparer déploiement et exposition |
| networks | NetworkPolicy | Ou juste le namespace par défaut |
| volumes | PVC + PV | Ajouter StorageClass si dynamic |
| secrets | Secrets / Sealed Secrets | Ne jamais stocker en clair |
| configs | ConfigMap | Séparer config et secrets |
| deploy.resources | resources.requests/limits | Obligatoire en production |
| healthcheck | liveness/readiness/startup | Configurer les trois probes |
| deploy.update_config | strategy.rollingUpdate | maxSurge + maxUnavailable |
| deploy.placement | nodeSelector / affinity | Contraintes de placement |
| ports | Ingress / LoadBalancer | Exposition externe |
Monitoring et observabilité
Swarm : outils limités
Swarm ne propose pas de stack de monitoring intégrée. La plupart des équipes ajoutent cAdvisor, Prometheus et Grafana manuellement.
Kubernetes : un écosystème riche
- Prometheus : métriques natives (métriques du cluster et des apps)
- Grafana : dashboards (kube-prometheus-stack inclut tout)
- Loki : logs (agrégation légère, intégré à Grafana)
- Jaeger / Tempo : tracing distribué
# Installer kube-prometheus-stack (Prometheus + Grafana + Alerting)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install monitoring prometheus-community/kube-prometheus-stack -n monitoring --create-namespace
Conclusion
Migrer de Docker Swarm vers Kubernetes est un projet significatif, mais pas insurmontable. Les points clés à retenir :
- Le réseau change en profondeur — prévoyez du temps pour configurer CNI et Ingress
- Le stockage est plus complexe mais plus puissant — PV/PVC/StorageClass valent l'investissement
- Les secrets nécessitent une attention particulière — ne restez pas sur les secrets base64
- Les health checks sont plus granulaires — exploitez les trois probes
- Les resource limits sont obligatoires — c'est la base de la stabilité
- Migration incrémentale — ne faites pas un Big Bang
Checklist de migration
- ☐ Cluster Kubernetes opérationnel (kubeadm, k3s, ou cloud managed)
- ☐ CNI plugin configuré (Calico, Cilium, ou Flannel)
- ☐ Ingress controller installé (nginx, traefik)
- ☐ StorageClasses configurées pour votre environnement
- ☐ Secrets chiffrés (Sealed Secrets ou Vault)
- ☐ Resource requests/limits définis pour tous les services
- ☐ Health checks (liveness + readiness) configurés
- ☐ Network policies en place
- ☐ Monitoring déployé (Prometheus + Grafana)
- ☐ Stack de logging (Loki ou EFK)
- ☐ Backup des PV configuré
- ☐ Plan de rollback documenté
- ☐ DNS mis à jour pour le cutover