Apprenez à mettre à niveau et migrer en toute sécurité les ReplicaSets Kubernetes avec des commandes étape par étape, des vérifications de validation, des stratégies de retour en arrière et une liste de contrôle opérationnelle pour minimiser les risques.
Introduction
Les ReplicaSets sont un pilier fondamental de Kubernetes. Ils garantissent qu'un nombre spécifié de réplicas de pods est en cours d'exécution à tout moment, offrant ainsi une disponibilité de base et une auto-réparation pour les applications sans état. Cependant, les ReplicaSets ne prennent pas en charge nativement les mises à jour progressives. Pour modifier le modèle de pod (par exemple, pour mettre à jour l'image du conteneur), vous devez créer un nouveau ReplicaSet et migrer le trafic manuellement. Ce processus nécessite une planification minutieuse pour éviter les temps d'arrêt, les pertes de données ou les interruptions de service.
Ce guide propose une approche pratique et concrète pour la mise à niveau et la migration des ReplicaSets. Il couvre l'inventaire de l'environnement, la configuration, la vérification, la récupération après échec et comprend une liste de contrôle opérationnelle complète. Que vous soyez développeur, consultant DevOps ou membre d'une startup technique, vous apprendrez à exécuter les modifications de ReplicaSet avec confiance et un risque minimal.
Bien que les Deployments soient la méthode recommandée pour gérer les ReplicaSets en production car ils ajoutent des capacités de mise à jour progressive et de retour en arrière, de nombreuses équipes utilisent encore des ReplicaSets nus pour des charges de travail héritées ou spécialisées. Les techniques de ce guide s'appliquent à la fois aux ReplicaSets nus et à ceux gérés par des Deployments, mais nous nous concentrons sur le processus manuel requis lorsque vous opérez un ReplicaSet directement.
Inventaire des versions et de l'environnement
Avant toute mise à niveau, vous devez établir une image claire de votre environnement actuel. Cet inventaire permet d'identifier les dépendances, les problèmes de compatibilité et les risques potentiels. Sauter cette étape est une cause fréquente d'échec des migrations.
Vérification de la version de Kubernetes
Vérifiez les versions du plan de contrôle et des nœuds. La version de l'API ReplicaSet cible doit être compatible avec votre cluster. L'API apps/v1 est stable depuis Kubernetes 1.9, mais il est de bonne pratique de le confirmer.
Exécutez :
kubectl version --short
Exemple de sortie :
Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.27.3
Assurez-vous que la version du serveur est compatible avec les fonctionnalités que vous prévoyez d'utiliser. Par exemple, si vous prévoyez d'utiliser des conteneurs éphémères pour le débogage, vous avez besoin de Kubernetes 1.23 ou plus récent.
Détails du ReplicaSet
Listez tous les ReplicaSets dans tous les espaces de noms pour avoir une vue d'ensemble :
kubectl get replicasets --all-namespaces
Pour un ReplicaSet spécifique, inspectez sa définition YAML complète :
kubectl get replicaset my-replicaset -n my-namespace -o yaml
Champs clés à noter :
spec.replicas: le nombre de pods souhaité.spec.selector: le sélecteur d'étiquettes utilisé pour identifier les pods appartenant à ce ReplicaSet.spec.template: le modèle de pod, y compris les images des conteneurs, les ressources et d'autres paramètres.
Enregistrez la sortie dans un fichier comme sauvegarde. Vous en aurez besoin pour le retour en arrière ou comme référence.
kubectl get replicaset my-replicaset -n my-namespace -o yaml > replicaset-backup.yaml
Santé des pods
Vérifiez la santé des pods existants gérés par le ReplicaSet :
kubectl get pods -l app=my-app -n my-namespace
Tous les pods doivent être dans l'état Running et prêts. Si certains pods sont en CrashLoopBackOff, Pending ou Error, résolvez ces problèmes avant de tenter une mise à niveau. Utilisez describe et logs pour diagnostiquer :
kubectl describe pod <pod-name> -n my-namespace
kubectl logs <pod-name> -n my-namespace
Topologie et dépendances
Identifiez les Services qui acheminent le trafic vers ces pods et si des Horizontal Pod Autoscalers (HPA) référencent le ReplicaSet. Les Services sélectionnent les pods à l'aide d'étiquettes, vous devez donc connaître le sélecteur actuel. Exécutez :
kubectl get svc, hpa -n my-namespace -o wide
Inspectez le YAML du Service pour voir le sélecteur :
kubectl get svc my-service -n my-namespace -o yaml
Exemple de sélecteur de Service :
spec:
selector:
app: my-app
version: v1
Ce sélecteur signifie que le Service achemine le trafic uniquement vers les pods ayant les étiquettes app=my-app et version=v1. Lorsque vous créez un nouveau ReplicaSet, vous devez vous assurer que ses pods ont une étiquette qui correspond au sélecteur souhaité, sinon vous devrez mettre à jour le Service.
Vérifiez également les ressources Ingress, les NetworkPolicies ou d'autres contrôleurs qui pourraient dépendre des étiquettes des pods.
Liste de contrôle préalable
Avant de commencer, assurez-vous d'avoir :
kubectlconfiguré avec les autorisations appropriées pour créer, mettre à jour et supprimer des ReplicaSets et des Services dans l'espace de noms cible.- Accès aux manifestes (par exemple, dans un dépôt Git) ou la capacité de les générer.
- Une sauvegarde de la définition actuelle du ReplicaSet (comme indiqué ci-dessus).
- Un environnement de test ou de staging qui reflète la production aussi fidèlement que possible. Si vous n'avez pas d'environnement de staging, envisagez de tester dans un espace de noms isolé.
- Un plan de retour en arrière documenté et communiqué à l'équipe.
Chemin de configuration sûr
Adoptez une approche progressive : modifiez le ReplicaSet de manière contrôlée et validez avant le déploiement complet. Le principe clé est de ne jamais modifier le ReplicaSet existant sur place pour un changement majeur. Au lieu de cela, créez un nouveau ReplicaSet avec les modifications souhaitées, validez-le, puis déplacez le trafic.
Étape 1 : Extraire le manifeste actuel
Exportez la définition actuelle du ReplicaSet comme référence. Vous l'avez déjà fait à l'étape d'inventaire, mais assurez-vous d'avoir la dernière version :
kubectl get replicaset my-replicaset -n my-namespace -o yaml > replicaset-current.yaml
Étape 2 : Créer un nouveau ReplicaSet avec les modifications souhaitées
Créez un nouveau fichier YAML de ReplicaSet basé sur l'actuel, mais avec un nouveau nom et un modèle de pod mis à jour. Par exemple, si vous mettez à niveau l'image du conteneur de myapp:1.0 à myapp:2.0, et que vous souhaitez ajouter une nouvelle étiquette version: v2 pour distinguer les pods, le nouveau manifeste pourrait ressembler à ceci :
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-replicaset-v2
namespace: my-namespace
labels:
app: my-app
version: v2
spec:
replicas: 3
selector:
matchLabels:
app: my-app
version: v2
template:
metadata:
labels:
app: my-app
version: v2
spec:
containers:
- name: app-container
image: myapp:2.0
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
Détails importants :
- Le nom du ReplicaSet est unique :
my-replicaset-v2. - Le sélecteur
matchLabelsdoit correspondre aux étiquettes du modèle de pod. Dans cet exemple, c'estapp: my-appetversion: v2. C'est différent du sélecteur de l'ancien ReplicaSet, qui pourrait avoir seulementapp: my-appou inclureversion: v1. - L'image du conteneur est mise à jour vers
myapp:2.0. - Les demandes et limites de ressources sont définies explicitement. C'est une bonne pratique pour garantir un ordonnancement prévisible.
Appliquez le nouveau ReplicaSet :
kubectl apply -f replicaset-v2.yaml
Vérifiez qu'il est créé :
kubectl get replicaset my-replicaset-v2 -n my-namespace
Étape 3 : Valider le nouveau ReplicaSet en isolation
Les pods du nouveau ReplicaSet ont l'étiquette version=v2, tandis que les anciens pods ont version=v1 (si vous aviez cette étiquette auparavant). Comme le sélecteur du Service existant pointe probablement encore vers version=v1, le trafic continue d'être acheminé vers les anciens pods. C'est intentionnel : les nouveaux pods sont en cours d'exécution mais ne reçoivent pas de trafic de production.
Attendez que les pods du nouveau ReplicaSet deviennent prêts :
kubectl get pods -l version=v2 -n my-namespace
Tous les pods doivent afficher READY 1/1 et STATUS Running.
Pour tester les nouveaux pods sans affecter le trafic de production, vous pouvez utiliser le transfert de port directement vers le ReplicaSet ou vers un pod spécifique :
kubectl port-forward rs/my-replicaset-v2 8080:80
Ouvrez ensuite http://localhost:8080 dans votre navigateur ou utilisez curl depuis un autre terminal :
curl http://localhost:8080
De plus, vous pouvez créer un Service temporaire avec un sélecteur qui ne correspond qu'à version=v2 pour tester la connectivité en interne. Par exemple, enregistrez ce qui suit sous test-service-v2.yaml :
apiVersion: v1
kind: Service
metadata:
name: my-service-v2-test
namespace: my-namespace
spec:
selector:
app: my-app
version: v2
ports:
- port: 80
targetPort: 80
Appliquez-le :
kubectl apply -f test-service-v2.yaml
Lancez ensuite un pod temporaire pour tester le service :
kubectl run test-pod --rm -it --image=busybox --restart=Never -- /bin/sh
Dans le pod, utilisez wget ou curl (si disponible) pour accéder au service :
wget -qO- http://my-service-v2-test
Vous devriez voir la réponse de la nouvelle version. Après le test, supprimez le service et le pod temporaires :
kubectl delete svc my-service-v2-test -n my-namespace
Étape 4 : Déplacer le trafic progressivement
Une fois que vous êtes sûr que la nouvelle version fonctionne correctement, vous devez mettre à jour le Service de production pour acheminer le trafic vers les nouveaux pods. Il y a deux approches courantes :
- Bascule directe : Mettez à jour le sélecteur du Service pour qu'il ne corresponde qu'à
version=v2. Cela déplace immédiatement tout le trafic vers les nouveaux pods. - Déploiement canari : Utilisez un mécanisme plus sophistiqué comme un contrôleur Ingress avec répartition du trafic (par exemple, NGINX Ingress avec annotations canari) ou un maillage de services comme Istio ou Linkerd. Cela vous permet d'envoyer un petit pourcentage de trafic vers la nouvelle version et de l'augmenter progressivement.
Pour rester simple et comme ce guide se concentre sur les ReplicaSets, nous allons démontrer une bascule directe. Cependant, si vous disposez de l'outillage, une approche canari réduit encore plus les risques.
Pour effectuer une bascule directe, modifiez le Service :
kubectl edit svc my-service -n my-namespace
Changez le sélecteur dans l'éditeur de :
selector:
app: my-app
version: v1
à :
selector:
app: my-app
version: v2
Enregistrez et quittez. Le Service achemine maintenant le trafic vers les pods avec version=v2. Vous pouvez également utiliser kubectl patch pour une mise à jour non interactive :
kubectl patch svc my-service -n my-namespace -p '{"spec":{"selector":{"version":"v2"}}}'
Vérifiez les points de terminaison du Service :
kubectl get endpoints my-service -n my-namespace
Vous devriez voir les adresses IP des nouveaux pods.
Étape 5 : Réduire l'ancien ReplicaSet
Après avoir vérifié que la nouvelle version gère correctement le trafic, réduisez l'ancien ReplicaSet à zéro :
kubectl scale replicaset my-replicaset --replicas=0 -n my-namespace
Ne supprimez pas l'ancien ReplicaSet immédiatement. Gardez-le pendant une fenêtre de retour en arrière (par exemple, 24 heures). Si quelque chose ne va pas avec la nouvelle version, vous pouvez rapidement remettre l'ancien ReplicaSet à l'échelle et rebasculer le sélecteur du Service vers version=v1.
Après la fenêtre de retour en arrière et une fois que vous êtes confiant, supprimez l'ancien ReplicaSet :
kubectl delete replicaset my-replicaset -n my-namespace
Étape 6 : Mettre à jour les références
Si vous utilisez un HPA qui cible le ReplicaSet, mettez-le à jour pour référencer le nouveau ReplicaSet. Notez que les HPA ciblent généralement les Deployments, mais ils peuvent être configurés pour cibler les ReplicaSets en utilisant scaleTargetRef avec kind: ReplicaSet. Par exemple :
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
namespace: my-namespace
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: ReplicaSet
name: my-replicaset-v2
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
Appliquez le HPA mis à jour :
kubectl apply -f hpa-v2.yaml
Choix d'implémentation ciblés
- Utilisez des espaces de noms pour isoler les changements, surtout si vous testez.
- Envisagez d'utiliser des Deployments au lieu de ReplicaSets nus pour les charges de travail futures. Les Deployments gèrent les ReplicaSets et fournissent automatiquement des mises à jour progressives et des retours en arrière.
- Gardez toujours la définition de l'ancien ReplicaSet et sa sauvegarde YAML pour le retour en arrière.
- Utilisez une étiquette de version (comme
version: v1etversion: v2) pour distinguer les pods. C'est essentiel pour un déplacement de trafic en toute sécurité.
Vérification et diagnostics
Après avoir appliqué les changements, vous devez vérifier que la mise à niveau ou la migration est réussie et que l'application se comporte correctement. Effectuez ces vérifications systématiquement.
Vérifier l'état du ReplicaSet
kubectl get rs my-replicaset-v2 -n my-namespace
Sortie attendue :
NAME DESIRED CURRENT READY AGE
my-replicaset-v2 3 3 3 5m
Les colonnes DESIRED, CURRENT et READY doivent toutes correspondre au nombre de réplicas que vous avez spécifié. Si ce n'est pas le cas, examinez les pods.
Vérifier l'état de préparation des pods
kubectl get pods -l version=v2 -n my-namespace
Tous les pods doivent afficher READY 1/1 et STATUS Running. Si un pod n'est pas prêt, vérifiez ses événements et ses journaux.
Inspecter les journaux
Affichez les journaux de tous les nouveaux pods :
kubectl logs -l version=v2 -n my-namespace --tail=50
Recherchez les messages d'erreur, les traces de pile ou les problèmes de connexion. Si votre application journalise des informations de démarrage, vérifiez qu'elle a démarré avec la bonne version.
Tester la connectivité du Service
Utilisez un pod temporaire pour tester le Service depuis l'intérieur du cluster :
kubectl run test-pod --rm -it --image=busybox --restart=Never -- /bin/sh
Dans le pod, utilisez wget ou curl (si installé) pour accéder au Service :
wget -qO- http://my-service
Ou, si curl est disponible :
curl http://my-service
Attendez-vous à la réponse de l'application. Si vous obtenez une connexion refusée ou un délai d'attente, le Service n'achemine peut-être pas correctement. Vérifiez les points de terminaison du Service et l'état de préparation des pods.
Vérifier les événements pour les erreurs
kubectl describe rs my-replicaset-v2 -n my-namespace
Recherchez des événements tels que Created pod, Scaled up replica set ou tout avertissement. Des avertissements comme FailedScheduling ou Failed to pull image indiquent des problèmes.
Surveiller l'utilisation des ressources
Si le serveur de métriques est installé, vous pouvez afficher l'utilisation du CPU et de la mémoire des nouveaux pods :
kubectl top pods -l version=v2 -n my-namespace
Comparez l'utilisation des ressources avec les demandes et les limites. Une utilisation élevée du CPU ou de la mémoire peut indiquer un problème de performances avec la nouvelle version.
Considération sur les vérifications automatisées
Pour les environnements de production, envisagez de scripter ces vérifications pour qu'elles s'exécutent automatiquement après le déploiement. Un simple script shell ou une étape de pipeline CI/CD peut exécuter les commandes kubectl et faire échouer le pipeline si une vérification échoue. Cela réduit les erreurs humaines et accélère le processus.
Modes de défaillance et récupération
Malgré une planification minutieuse, des échecs peuvent survenir. Voici les modes de défaillance courants, leurs causes, les diagnostics et les étapes de récupération.
Échec : Nouveaux pods en CrashLoopBackOff
Cause : Mauvaise configuration, image incompatible, variables d'environnement manquantes ou bug applicatif.
Diagnostics :
kubectl get pods -l version=v2 -n my-namespace
kubectl logs <pod-name> -n my-namespace
kubectl describe pod <pod-name> -n my-namespace
Exemple : Vous voyez des pods dans l'état CrashLoopBackOff. Les journaux montrent Error: Cannot find module 'express' indiquant une dépendance manquante dans l'image.
Récupération :
- Rebasculez le trafic vers l'ancien ReplicaSet en mettant à jour le sélecteur du Service vers
version=v1(si l'ancien ReplicaSet existe toujours et que ses réplicas ne sont pas à zéro). Si vous avez réduit l'ancien ReplicaSet à zéro, remettez-le d'abord à l'échelle :
kubectl scale replicaset my-replicaset --replicas=3 -n my-namespace
kubectl patch svc my-service -n my-namespace -p '{"spec":{"selector":{"version":"v1"}}}'
- Supprimez ou réduisez le nouveau ReplicaSet pour éviter l'utilisation des ressources :
kubectl scale replicaset my-replicaset-v2 --replicas=0 -n my-namespace
- Corrigez la configuration ou l'image et planifiez la prochaine tentative.
Échec : Nouveaux pods non planifiés
Cause : Ressources du cluster insuffisantes, contraintes de sélecteur de nœud, teintures/tolérances ou volumes persistants non disponibles.
Diagnostics :
kubectl describe rs my-replicaset-v2 -n my-namespace
Recherchez des événements comme FailedScheduling avec des messages tels que 0/3 nodes are available: 3 Insufficient cpu.
Récupération :
- Ajustez les demandes et limites de ressources pour tenir dans la capacité disponible.
- Modifiez les sélecteurs de nœud ou ajoutez des tolérances si nécessaire.
- Réduisez l'ancien ReplicaSet pour libérer des ressources (après le déplacement du trafic ou si vous testez encore) :
kubectl scale replicaset my-replicaset --replicas=1 -n my-namespace
Ensuite, recréez ou mettez à l'échelle le nouveau ReplicaSet.
Échec : Trafic du Service interrompu
Cause : Changement de sélecteur de Service trop brusque, sélecteur mal configuré ou bug dans la nouvelle version causant de mauvaises performances ou des plantages.
Récupération :
Rétablissez immédiatement le sélecteur du Service à sa valeur précédente :
kubectl patch svc my-service -n my-namespace -p '{"spec":{"selector":{"version":"v1"}}}'
Si l'ancien ReplicaSet a été réduit à zéro, remettez-le d'abord à l'échelle.
Ensuite, examinez le problème avec la nouvelle version.
Échec : Perte de données ou incohérence
Cause : Application non conçue pour une migration sans temps d'arrêt, changements de schéma de base de données non rétrocompatibles ou incompatibilité de version.
Récupération :
- Restaurez à partir des sauvegardes si des données ont été perdues.
- Envisagez d'exécuter les anciennes et nouvelles versions en parallèle avec une approche canari pour détecter les incohérences tôt.
- Si possible, utilisez une stratégie de déploiement bleu-vert avec un outil de migration de base de données prenant en charge les changements rétrocompatibles.
Étapes générales de retour en arrière
- Identifiez le problème (à partir des journaux, des métriques, des rapports utilisateurs).
- Restaurez le sélecteur du Service vers l'ancienne version.
- Remettez l'ancien ReplicaSet à l'échelle souhaitée s'il a été réduit.
- Supprimez ou réduisez le nouveau ReplicaSet.
- Corrigez la configuration et planifiez la prochaine tentative.
Mesures préventives
- Gardez toujours l'ancien ReplicaSet jusqu'à ce que le nouveau soit prouvé stable.
- Utilisez une étiquette de version pour distinguer les pods.
- Testez d'abord en staging, idéalement avec un trafic similaire à la production.
- Automatisez le déploiement et le retour en arrière pour réduire les erreurs humaines.
- Surveillez en continu les métriques et journaux de l'application pendant la migration.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour chaque mise à niveau ou migration de ReplicaSet. Remplissez les noms et commandes spécifiques à votre environnement.
| Étape | Action | Commande / Preuve |
|---|---|---|
| 1 | Vérifier l'accès au cluster et la version | kubectl cluster-info |
| 2 | Inventorier les ReplicaSets existants | kubectl get rs --all-namespaces |
| 3 | Sauvegarder le manifeste actuel du ReplicaSet | kubectl get rs <name> -n <ns> -o yaml > backup.yaml |
| 4 | Identifier les sélecteurs de Service et dépendances | kubectl get svc -n <ns> -o yaml |
| 5 | Créer un nouveau ReplicaSet avec un modèle mis à jour | kubectl apply -f new-rs.yaml |
| 6 | Valider que les nouveaux pods sont en cours d'exécution et prêts | kubectl get pods -l version=v2 -n <ns> |
| 7 | Tester les nouveaux pods via le transfert de port ou un service temporaire | kubectl port-forward rs/new-rs 8080:80 |
| 8 | Basculer le trafic du Service vers la nouvelle version | kubectl edit svc <svc> -n <ns> |
| 9 | Surveiller les journaux et métriques de l'application | kubectl logs -l version=v2 -n <ns> |
| 10 | Réduire l'ancien ReplicaSet | kubectl scale rs <old-rs> --replicas=0 -n <ns> |
| 11 | Garder l'ancien ReplicaSet pour la fenêtre de retour en arrière (par exemple, 24 h) | - |
| 12 | Supprimer l'ancien ReplicaSet après une période stable | kubectl delete rs <old-rs> -n <ns> |
| 13 | Mettre à jour la documentation et les procédures | - |
Points de revue
- Confirmez le plan de retour en arrière avant de commencer.
- Communiquez avec les membres de l'équipe sur la fenêtre de changement.
- Effectuez la mise à niveau pendant une fenêtre de maintenance si possible, surtout pour les services à fort trafic.
- Ayez un ingénieur d'astreinte disponible pendant et immédiatement après la migration.
Conclusion
La mise à niveau et la migration des ReplicaSets Kubernetes peuvent être effectuées en toute sécurité avec une planification minutieuse et des étapes incrémentales. En inventoriant votre environnement, en créant de nouveaux ReplicaSets à côté des anciens, en validant en isolation et en ayant un plan de retour en arrière solide, vous minimisez les risques. Utilisez la liste de contrôle opérationnelle fournie pour standardiser le processus. N'oubliez pas de garder les anciens ReplicaSets jusqu'à ce que vous soyez certain que la nouvelle version est stable, et envisagez d'utiliser des Deployments pour les charges de travail futures afin de profiter des mises à jour progressives intégrées. Avec ces pratiques, vous pouvez gérer en toute confiance les changements de cycle de vie des ReplicaSets en production.