Introduction
La mise à niveau et la migration d'un cluster Kubernetes multi-locataire sont des opérations à haut risque. Une seule erreur peut provoquer des pannes inter-locataires, des conflits de ressources ou des brèches de sécurité. Ce guide propose une approche pratique, étape par étape, destinée aux développeurs, consultants DevOps et équipes techniques de startups qui doivent passer d'un problème observé à un résultat vérifié avec un risque minimal.
Nous nous concentrons sur cinq activités critiques : la mise à niveau de Kubernetes multi-locataire, la migration, la mise à niveau de version, la validation et la restauration. Chaque activité est reliée à des commandes concrètes, des sorties attendues, des signaux d'échec et des décisions de récupération. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, protéger les données sensibles, vérifier le résultat et documenter les chemins de récupération.
Nous commençons par un inventaire de l'environnement, puis nous parcourons les modifications de configuration sûres, la vérification, les modes d'échec avec récupération, et une liste de contrôle opérationnelle. Tout au long, nous utilisons des espaces réservés comme <namespace> ou <deployment-name> que vous remplacerez par vos valeurs réelles, mais nous fournissons des exemples de sorties pour illustrer les résultats typiques.
Inventaire des versions et de l'environnement
Avant de toucher à quoi que ce soit, vous devez savoir exactement ce que vous exécutez. La multi-location repose fortement sur les Namespaces, les Resource Quotas et le RBAC ; toute mise à niveau doit tenir compte de leurs versions et configurations.
Commencez par une observation en lecture seule de la version du cluster et des composants clés :
kubectl version --short
kubectl get nodes -o wide
kubectl get namespaces
kubectl get resourcequota --all-namespaces
kubectl get clusterrole,clusterrolebinding --all-namespaces
La sortie attendue pour kubectl version --short pourrait être :
Client Version: v1.25.3
Server Version: v1.24.6
Si les versions client et serveur diffèrent significativement, notez que certaines fonctionnalités peuvent ne pas être disponibles. Pour un cluster multi-locataire, vérifiez les contrôleurs d'admission activés du serveur API, car ils affectent l'isolation :
kubectl get --raw /metrics | grep apiserver_admission_controller_admission_duration_seconds | head
Mieux encore, vérifiez les arguments du pod kube-apiserver si vous y avez accès :
kubectl -n kube-system get pod -l component=kube-apiserver -o yaml | grep enable-admission-plugins
La sortie typique inclut NamespaceLifecycle, ResourceQuota, LimitRanger et PodSecurityPolicy ou PodSecurity. Assurez-vous qu'ils sont présents avant de faire des modifications.
Capturez l'état actuel et les horodatages dans un fichier pour la traçabilité :
date >> upgrade-audit.log
kubectl get all --all-namespaces >> upgrade-audit.log
kubectl get resourcequota --all-namespaces -o yaml >> upgrade-audit.log
kubectl get roles,rolebindings --all-namespaces -o yaml >> upgrade-audit.log
Protégez les identifiants et le matériel privé : utilisez kubectl config get-contexts pour confirmer que vous êtes dans le bon cluster, et ne journalisez jamais les secrets. Si vous devez examiner des secrets, utilisez kubectl get secret <secret-name> -o yaml mais assainissez avant de partager.
De petits tests locaux sont inestimables. Par exemple, créez un namespace temporaire avec un quota pour vous assurer que la comptabilité des ressources fonctionne après une mise à niveau mineure :
kubectl create ns test-quota
kubectl apply -f - <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: test-quota
spec:
hard:
requests.cpu: "2"
requests.memory: 2Gi
limits.cpu: "4"
limits.memory: 4Gi
EOF
kubectl get resourcequota -n test-quota
La sortie attendue montre le quota avec les limites utilisées et dures :
NAME AGE REQUEST LIMIT
compute-quota 5s requests.cpu: 0/2, requests.memory: 0/2Gi limits.cpu: 0/4, limits.memory: 0/4Gi
Si le quota n'apparaît pas ou n'est pas appliqué, enquêtez sur les contrôleurs d'admission ou les problèmes de CRD avant de continuer.
Chemin de configuration sûr
Les modifications de configuration dans les clusters multi-locataires doivent être incrémentales et réversibles. Une tâche de mise à niveau courante est la transition de PodSecurityPolicy (obsolète) vers Pod Security Admission (PSA). Ou bien, vous pourriez avoir besoin de mettre à jour les rôles RBAC pour de nouvelles versions d'API.
Parcourons un déploiement contrôlé d'une nouvelle politique réseau ou d'une augmentation de quota. Supposons que vous deviez augmenter la limite CPU par défaut pour le locataire "team-a" de 2 à 4 CPU. Ne modifiez jamais directement le quota existant en production sans test. Créez plutôt un nouvel objet quota dans un namespace de staging qui reflète celui de production.
D'abord, observez le quota actuel :
kubectl get resourcequota compute-quota -n team-a -o yaml
Sortie attendue (tronquée) :
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "4"
limits.memory: 8Gi
Maintenant, dans un namespace de test team-a-staging, créez une copie avec les nouvelles limites :
kubectl create ns team-a-staging
kubectl apply -f - <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: team-a-staging
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
EOF
Vérifiez que les pods peuvent être planifiés avec les nouvelles limites :
kubectl run test-pod --image=nginx --restart=Never -n team-a-staging --requests='cpu=500m,memory=256Mi' --limits='cpu=1,memory=512Mi'
kubectl get pod test-pod -n team-a-staging
Si le pod est en cours d'exécution (Running), le quota fonctionne. Supprimez le pod de test et le namespace :
kubectl delete pod test-pod -n team-a-staging
kubectl delete ns team-a-staging
Appliquez maintenant le changement au quota de production. D'abord, sauvegardez le quota actuel :
kubectl get resourcequota compute-quota -n team-a -o yaml > team-a-quota-backup.yaml
Ensuite, patchez ou appliquez la nouvelle spécification :
kubectl patch resourcequota compute-quota -n team-a --type='merge' -p '{"spec":{"hard":{"requests.cpu":"4","requests.memory":"8Gi","limits.cpu":"8","limits.memory":"16Gi"}}}'
Vérifiez :
kubectl get resourcequota compute-quota -n team-a -o yaml
Si quelque chose tourne mal, restaurez :
kubectl apply -f team-a-quota-backup.yaml
Ayez toujours un plan de restauration. Conservez le fichier de sauvegarde dans le contrôle de version.
Vérification et diagnostics
La vérification n'est pas optionnelle. Après chaque modification, confirmez que l'état attendu est atteint et que les locataires ne sont pas affectés.
Pour les changements de quota, vérifiez que les nouveaux pods du locataire peuvent demander les ressources augmentées :
kubectl run verify-pod --image=busybox --restart=Never -n team-a --command -- sleep 3600 --requests='cpu=500m,memory=256Mi'
Vérifiez si le pod est admis :
kubectl get pod verify-pod -n team-a
S'il est en attente (Pending), décrivez-le :
kubectl describe pod verify-pod -n team-a
Recherchez des événements comme "FailedScheduling" ou "Exceeded quota". Si vous voyez des erreurs de quota malgré le patch, le quota n'a peut-être pas été mis à jour correctement ou il existe un autre objet LimitRange qui contraint les demandes.
Vérifiez les LimitRanges existants :
kubectl get limitrange -n team-a
Si un LimitRange avec un CPU maximum de 2 existe, les pods ne peuvent pas le dépasser même si le quota le permet. Ajustez en conséquence.
Pour vérifier les changements RBAC, utilisez kubectl auth can-i en tant qu'utilisateur locataire. Supposons que vous ayez accordé un nouveau rôle à un compte de service. Testez l'accès :
kubectl auth can-i create deployments --as=system:serviceaccount:team-a:deployer -n team-a
Sortie attendue : yes ou no. Si no, inspectez le RoleBinding et le Role :
kubectl get rolebinding -n team-a
kubectl get role deployer-role -n team-a -o yaml
Pour valider les politiques réseau, créez deux pods dans des namespaces différents et testez la connectivité :
kubectl run web --image=nginx -n tenant-a
kubectl run curl --image=radial/busyboxplus:curl -n tenant-b --command -- sleep 3600
kubectl exec -n tenant-b curl -- curl --max-time 5 http://web.tenant-a.svc.cluster.local
Si la politique réseau isole correctement les locataires, le curl devrait échouer avec un délai d'attente. S'il réussit, votre politique n'est pas appliquée correctement.
Utilisez kubectl rollout status pour tous les déploiements affectés par le changement :
kubectl rollout status deployment/myapp -n team-a
Sortie attendue : deployment "myapp" successfully rolled out. Si elle se bloque, vérifiez l'état des pods et les journaux :
kubectl get pods -n team-a
kubectl logs deployment/myapp -n team-a --tail=20
Modes d'échec et récupération
Même avec une planification minutieuse, des échecs surviennent. Voici les modes d'échec courants lors des mises à niveau multi-locataires et comment récupérer.
Échec : l'augmentation de quota n'est pas effective
Symptôme : Après le patch du quota, les nouveaux pods échouent toujours avec "exceeded quota".
Diagnostic : Vérifiez l'objet quota, le LimitRange et les webhooks d'admission qui pourraient modifier les spécifications des pods.
kubectl get resourcequota -n team-a -o yaml
kubectl get limitrange -n team-a -o yaml
kubectl get validatingwebhookconfiguration -o yaml | grep -B5 -A5 "team-a"
Récupération : Si un LimitRange est le coupable, mettez-le à jour en conséquence. Si un webhook interfère, désactivez-le temporairement (si sûr) ou ajustez sa configuration. Dans le pire des cas, annulez le changement de quota et enquêtez.
Échec : la politique réseau bloque tout le trafic
Symptôme : Après l'application d'une politique réseau, tous les pods d'un namespace perdent la connectivité, y compris vers le serveur API ou le DNS.
Diagnostic : Vérifiez si la politique refuse accidentellement la sortie vers le DNS ou le serveur API. Décrivez la politique :
kubectl describe networkpolicy deny-all -n team-a
Récupération : Supprimez la politique fautive pour restaurer la connectivité :
kubectl delete networkpolicy deny-all -n team-a
Ensuite, affinez la politique pour autoriser les sorties requises (par exemple, vers kube-dns sur le port 53).
Échec : le changement RBAC verrouille les utilisateurs
Symptôme : Les utilisateurs ou comptes de service ne peuvent soudainement plus accéder aux ressources après un changement de liaison de rôle.
Diagnostic : Vérifiez les liaisons de rôle de cluster et les rôles pour le sujet affecté :
kubectl get clusterrolebinding -o yaml | grep -A10 "team-a"
Récupération : Restaurez la liaison de rôle précédente à partir de la sauvegarde ou recréez-la. Par exemple, si une liaison a été supprimée accidentellement, recréez :
kubectl create rolebinding team-a-admin --clusterrole=admin --serviceaccount=team-a:default -n team-a
Échec : obsolescence de la version d'API
Symptôme : L'application d'un manifeste échoue avec "no matches for kind" ou "resource is deprecated".
Diagnostic : Vérifiez les ressources API disponibles :
kubectl api-resources --namespaced=true | grep deployments
Si la version est obsolète, vous verrez seulement apps/v1, et les anciennes extensions/v1beta1 manqueront.
Récupération : Mettez à jour vos manifestes vers la nouvelle version d'API. Utilisez kubectl convert si disponible (peut nécessiter un plugin) ou éditez manuellement. Testez d'abord dans un namespace de staging.
Échec : déploiement bloqué après la mise à niveau
Symptôme : Après la mise à niveau du cluster, les pods d'un déploiement sont en CrashLoopBackOff ou ImagePullBackOff.
Diagnostic : Vérifiez les journaux des pods et les événements :
kubectl describe pod <pod-name> -n team-a
kubectl logs <pod-name> -n team-a --previous
Récupération : Selon la cause :
- Pour ImagePullBackOff, vérifiez l'accessibilité du registre d'images et les identifiants.
- Pour CrashLoopBackOff, examinez les journaux de l'application ; l'application peut nécessiter une mise à jour de configuration pour la nouvelle version du cluster.
- Si tout échoue, annulez le déploiement à la version précédente en utilisant
kubectl rollout undo deployment/<deployment-name> -n team-a.
Documentez toujours l'échec, sa cause et les étapes de récupération dans un post-mortem pour améliorer les futures mises à niveau.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour chaque mise à niveau ou migration multi-locataire. Chaque élément comprend une commande ou action concrète et le résultat attendu.
Liste de contrôle pré-changement
- [ ] Confirmer les versions du cluster et du client : Exécutez
kubectl version --short. Attendu : version du serveur dans la plage prise en charge, version du client compatible. - [ ] Sauvegarder toutes les ressources critiques des locataires :
kubectl get all,resourcequota,limitrange,networkpolicy,role,rolebinding --all-namespaces -o yaml > full-backup-$(date +%Y%m%d).yaml - [ ] Vérifier les autorisations RBAC pour votre utilisateur :
kubectl auth can-i '' '' --all-namespaces(devrait retourner yes pour les autorisations nécessaires). - [ ] Identifier les locataires et applications affectés : listez les namespaces et déploiements :
kubectl get ns,kubectl get deploy --all-namespaces. - [ ] Vérifier les changements en attente ou les ressources en échec :
kubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -20. - [ ] Créer un environnement de staging qui reflète la production : copiez les quotas, limit ranges, politiques réseau et exemples de déploiements pertinents.
Liste de contrôle pendant le changement
- [ ] Appliquer les changements de manière incrémentale : utilisez
kubectl applyavec des manifestes, pas des commandes ad hoc. - [ ] Surveiller l'état du déploiement : pour chaque déploiement modifié, exécutez
kubectl rollout status deployment/<name> -n <namespace>. - [ ] Surveiller les erreurs dans les événements :
kubectl get events -n <namespace> --watchpendant le déploiement. - [ ] Valider l'isolation des locataires : effectuez des tests de connectivité entre namespaces comme décrit précédemment.
- [ ] Vérifier l'utilisation des ressources :
kubectl top pods --all-namespacespour s'assurer qu'il n'y a pas de pics inattendus.
Liste de contrôle post-changement
- [ ] Vérifier que tous les changements sont reflétés : par exemple,
kubectl get resourcequota -n team-a -o yamlmontre de nouvelles limites. - [ ] Exécuter des tests fonctionnels pour chaque locataire : par exemple, créer un pod de test, accéder à un service, vérifier les journaux.
- [ ] Mettre à jour la documentation et les runbooks avec les nouvelles versions et configurations.
- [ ] Stocker les sauvegardes et journaux d'audit dans un emplacement sécurisé.
- [ ] Planifier une revue pour identifier les leçons apprises.
Exemple d'élément de liste de contrôle avec des valeurs concrètes
Supposons que vous mettiez à niveau le quota de ressources d'un locataire de 2 à 4 CPU. Voici comment remplir la liste de contrôle :
- Changement : Augmenter les demandes et limites CPU dans ResourceQuota pour le namespace
team-a. - Responsable : Priya Shah, responsable de l'ingénierie.
- Métrique cible : Les nouveaux pods peuvent demander jusqu'à 4 CPU sans erreurs de quota d'ici le T3.
- Commande de vérification :
kubectl run test-pod --image=nginx -n team-a --requests='cpu=500m' --limits='cpu=1'et vérifiez l'état du pod. - Restauration :
kubectl apply -f team-a-quota-backup.yaml.
Conclusion
La mise à niveau et la migration multi-locataire Kubernetes exigent de la rigueur. Chaque étape doit être délimitée par version, observable et réversible lorsque c'est possible. Copier des commandes sans comprendre les prérequis et la sortie attendue n'est pas une procédure ; c'est un pari.
Nous avons couvert le flux de travail essentiel : inventorier votre environnement, apporter des modifications de configuration sûres, vérifier soigneusement, se préparer aux échecs avec des étapes de récupération et suivre une liste de contrôle opérationnelle. En appliquant ces pratiques, vous pouvez mettre à niveau et migrer des clusters multi-locataires avec confiance, en minimisant les risques pour vos locataires et votre équipe.
Prochaines étapes : choisissez un changement à faible risque, comme l'augmentation d'un quota de ressources, et exécutez le cycle complet : observer, sauvegarder, modifier, vérifier et documenter. Ensuite, examinez les dépendances comme Namespace, Resource Quota et RBAC pour vous assurer qu'ils sont correctement configurés pour votre stratégie multi-locataire.
Un flux de travail technique fiable rend l'échec visible, protège les valeurs sensibles, limite les modifications aux ressources prévues et définit la vérification de récupération avant qu'un incident ne force la décision.