Introduction
Les contrôleurs d'admission Kubernetes sont un point de contrôle puissant mais souvent mal compris dans un cluster. Lorsqu'ils sont mal configurés, ils peuvent silencieusement rejeter des charges de travail valides, autoriser des ressources non sécurisées, voire bloquer les administrateurs. Ce guide de mise en œuvre pratique se concentre sur la transformation des problèmes de configuration observés en correctifs vérifiés et sûrs.
Cet article s'adresse aux développeurs, consultants DevOps et équipes techniques de startups qui gèrent des clusters Kubernetes. Il relie les erreurs courantes de configuration des contrôleurs d'admission, les techniques de validation, les procédures de restauration et les étapes de dépannage à 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'action, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter comment récupérer si l'état attendu n'est pas atteint.
Inventaire de la version et de l'environnement
Avant de toucher à un contrôleur d'admission, faites l'inventaire de votre environnement. Connaître la version exacte de Kubernetes, les contrôleurs d'admission activés par défaut et la topologie de votre cluster évite les erreurs de diagnostic et les modifications inutiles.
Version de Kubernetes
Utilisez kubectl version pour voir les versions client et serveur. Le comportement et les valeurs par défaut des contrôleurs d'admission varient selon les versions. Par exemple, le contrôleur d'admission PodSecurity a remplacé PodSecurityPolicy dans Kubernetes 1.25. Si vous supposez qu'un contrôleur est actif sans vérifier, vous risquez de tenter de configurer quelque chose qui n'existe plus.
kubectl version --short
Sortie attendue pour un client et un serveur :
Client Version: v1.29.1
Server Version: v1.28.3
Lister les contrôleurs d'admission activés
Le processus kube-apiserver spécifie les contrôleurs d'admission activés avec le drapeau --enable-admission-plugins. Sur un cluster managé (EKS, GKE, AKS), vous n'avez peut-être pas un accès direct à ce drapeau. Inspectez plutôt les pods du serveur API ou la configuration.
Pour les clusters où vous pouvez lister les pods du serveur API :
kubectl get pods -n kube-system | grep kube-apiserver
Si le pod est visible (par exemple, les clusters kubeadm), décrivez-le pour voir les drapeaux de ligne de commande :
kubectl describe pod kube-apiserver-control-plane -n kube-system
Cherchez la ligne --enable-admission-plugins dans la section Containers. Exemple :
--enable-admission-plugins=NodeRestriction,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeClaimResize,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
Cela montre exactement quels contrôleurs intégrés sont activés. Si un contrôleur que vous souhaitez configurer est absent, vous devez l'ajouter (si possible) ou utiliser un autre mécanisme.
Vérifier les contrôleurs d'admission dynamiques
Les contrôleurs d'admission dynamiques (webhooks) sont implémentés sous forme de ressources MutatingWebhookConfiguration et ValidatingWebhookConfiguration. Listez-les pour voir quelle logique personnalisée est active :
kubectl get mutatingwebhookconfigurations
kubectl get validatingwebhookconfigurations
Exemple de sortie :
NAME WEBHOOKS AGE
pod-policy.example.com 1 3d
Pour chaque webhook, décrivez-le pour voir les règles et la politique d'échec :
kubectl describe validatingwebhookconfiguration pod-policy.example.com
Faites attention à failurePolicy. Si elle est définie sur Fail, un service webhook indisponible bloquera toutes les requêtes correspondantes. C'est une erreur courante qui met un cluster hors service. Nous y reviendrons plus tard.
Prérequis pour une configuration sûre
- Un cluster ou un espace de noms de test où vous pouvez simuler des échecs sans affecter la production.
kubectlconfiguré avec les permissions appropriées.- Accès aux journaux d'événements du cluster (
kubectl get events). - Sauvegarde de toutes les configurations de contrôleurs d'admission existantes avant les modifications.
Vérification pratique : Commencez par kubectl get pods -o wide, puis utilisez kubectl describe pod <nom> pour les détails de planification et d'événements, kubectl logs <nom> --previous pour les boucles de crash, et kubectl rollout status deployment/<nom> avant de supposer qu'une version a réussi.
Pour les tests locaux, gardez une portée limitée. Appliquez un manifeste à la fois, inspectez les ressources générées et vérifiez le trafic avec kubectl port-forward ou un type de service local avant de passer à un équilibreur de charge cloud ou à un contrôleur d'entrée.
Chemin de configuration sûr
Lors de la modification des contrôleurs d'admission, suivez un chemin discipliné pour minimiser les risques. Les étapes de haut niveau sont :
- Observer le comportement actuel et enregistrer la référence.
- Concevoir le changement de configuration prévu.
- Appliquer le changement dans un environnement de test.
- Valider avec des tests positifs et négatifs.
- Déployer en production avec un plan de restauration.
Erreur courante : Modifier plusieurs contrôleurs à la fois
Une erreur fréquente est d'activer plusieurs contrôleurs d'admission simultanément ou de modifier plusieurs règles de webhook sans test isolé. Cela rend difficile l'identification du changement qui a provoqué une défaillance.
Approche correcte : Modifiez un contrôleur ou une règle à la fois. Pour les contrôleurs intégrés, si vous devez en activer plusieurs, faites-le progressivement dans un cluster de test.
Exemple : Supposons que vous souhaitiez activer PodSecurity avec le niveau baseline et également activer ResourceQuota. Ne modifiez pas les deux dans le même redémarrage de kube-apiserver. Activez d'abord PodSecurity, vérifiez, puis activez ResourceQuota.
Pour les webhooks dynamiques, mettez à jour une configuration de webhook à la fois. Après l'application, vérifiez le statut du webhook et testez les requêtes autorisées et refusées.
Exemple concret : Configurer un ValidatingWebhook pour la sécurité des pods
Parcourons un exemple pratique de configuration d'un webhook d'admission de validation qui applique une politique simple : tous les pods doivent avoir une étiquette owner.
Étape 1 : Créer le serveur webhook
Créez un serveur HTTPS simple qui valide les demandes de création de pods. Par souci de concision, nous décrirons la logique ; le code complet dépasse le cadre de cet article. Le serveur doit répondre aux requêtes AdmissionReview par autorisé ou refusé.
Étape 2 : Déployer le serveur webhook
Déployez le serveur en tant que service dans votre cluster. Assurez-vous qu'il possède un certificat signé par une autorité de certification approuvée par le serveur API.
apiVersion: v1
kind: Service
metadata:
name: webhook-service
namespace: webhook
spec:
selector:
app: webhook-server
ports:
- port: 443
targetPort: 8443
Étape 3 : Créer la ValidatingWebhookConfiguration
Créez une configuration qui appelle le webhook pour la création de pods :
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-label-validator
webhooks:
- name: validate-pod-label.example.com
clientConfig:
service:
name: webhook-service
namespace: webhook
path: "/validate"
caBundle: <certificat-CA-encodé-en-base64>
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
admissionReviewVersions: ["v1"]
sideEffects: None
failurePolicy: Fail # Ceci est dangereux ; nous en discuterons plus tard
Étape 4 : Appliquer et tester
Appliquez la configuration :
kubectl apply -f validatingwebhook.yaml
Vérifiez qu'elle existe :
kubectl get validatingwebhookconfiguration pod-label-validator
Testez avec un pod sans étiquette :
kubectl run test-pod --image=nginx
Résultat attendu : la création du pod est refusée avec une erreur similaire à :
Error from server: admission webhook "validate-pod-label.example.com" denied the request: pod missing required label 'owner'
Testez maintenant avec un pod conforme :
kubectl run test-pod --image=nginx --labels=owner=team-a
Cela devrait réussir.
Important : Utilisez failurePolicy: Ignore en développement
La configuration ci-dessus utilise failurePolicy: Fail. Cela signifie que si le service webhook est indisponible ou injoignable, toutes les créations de pods sont bloquées. Cela peut mettre votre cluster hors service. Une valeur par défaut plus sûre pour les nouveaux webhooks est failurePolicy: Ignore, qui autorise les requêtes si le webhook échoue. Une fois que vous avez confiance, vous pouvez passer à Fail pour une application critique.
Pour modifier, patchez la configuration :
kubectl patch validatingwebhookconfiguration pod-label-validator --type='json' -p='[{"op": "replace", "path": "/webhooks/0/failurePolicy", "value": "Ignore"}]'
Vérifiez :
kubectl get validatingwebhookconfiguration pod-label-validator -o yaml | grep failurePolicy
Sortie attendue :
failurePolicy: Ignore
Vérification et diagnostic
Après avoir configuré les contrôleurs d'admission, une vérification approfondie est essentielle. Cette section couvre les commandes et les signaux pour confirmer le bon fonctionnement et diagnostiquer les problèmes.
Vérifier l'activité des contrôleurs d'admission
Kubernetes ne fournit pas par défaut un journal direct de chaque décision d'admission. Cependant, vous pouvez activer la journalisation d'audit ou utiliser les journaux du serveur API pour voir le comportement des contrôleurs d'admission.
Pour les contrôleurs intégrés, les journaux du serveur API incluent des lignes indiquant les échecs d'admission. Par exemple, l'activation de NamespaceLifecycle enregistrera des erreurs lorsqu'une requête cible un espace de noms en cours de terminaison.
Accédez aux journaux du serveur API (si autorisé) :
kubectl logs -n kube-system kube-apiserver-control-plane | grep -i admission
Pour les webhooks dynamiques, vous pouvez vérifier les journaux du serveur webhook pour chaque requête.
Utiliser Dry-Run pour tester sans persistance
kubectl prend en charge le dry-run, qui simule la requête sans persistance. C'est inestimable pour tester les webhooks d'admission.
Exemple :
kubectl run test-pod --image=nginx --dry-run=server
Si le contrôleur d'admission rejette la requête, vous verrez l'erreur sans réellement créer le pod. La sortie sera similaire au refus sans dry-run.
Inspecter les événements en cas d'échec
Les refus des contrôleurs d'admission génèrent souvent des événements. Utilisez kubectl get events pour voir les avertissements récents.
kubectl get events --field-selector type=Warning
Cherchez les messages mentionnant les webhooks d'admission ou les violations de politique.
Déboguer la connectivité des webhooks
Si un webhook n'est pas appelé, vérifiez les points suivants :
- La configuration du webhook référence le bon service et l'espace de noms.
- Le sélecteur de service correspond aux pods du serveur webhook.
- Le serveur webhook fonctionne et écoute sur le bon port.
- Le bundle CA dans
clientConfig.caBundleest correct et approuvé. - Les politiques réseau ou les règles de pare-feu permettent au serveur API d'atteindre le service webhook.
Testez le point de terminaison du service depuis l'intérieur du cluster à l'aide d'un pod temporaire :
kubectl run curl-pod --image=curlimages/curl --rm -it -- sh
# À l'intérieur du pod :
curl -k https://webhook-service.webhook.svc:443/health
Si le serveur webhook a un point de terminaison de santé, il devrait renvoyer une réponse de succès.
Vérifier le déploiement des modifications des contrôleurs d'admission
Pour les modifications des contrôleurs intégrés via les drapeaux de kube-apiserver, vous devez redémarrer le serveur API. C'est perturbateur. Sur les clusters managés, le fournisseur cloud gère cela. Pour les clusters kubeadm auto-gérés, vous modifiez généralement le manifeste du serveur API :
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
Ajoutez ou modifiez le drapeau --enable-admission-plugins, enregistrez. Le kubelet redémarrera automatiquement le pod du serveur API. Surveillez le pod du serveur API :
kubectl get pods -n kube-system -w
Attendez que le pod du serveur API soit RUNNING et READY. Vérifiez que le cluster est fonctionnel :
kubectl get nodes
Si le serveur API ne démarre pas, revenez immédiatement sur la modification du manifeste. C'est pourquoi avoir une sauvegarde du manifeste original est critique.
Modes de défaillance et récupération
Les erreurs de configuration des contrôleurs d'admission peuvent provoquer des pannes à l'échelle du cluster ou des contournements subtils de politique. Comprendre les modes de défaillance courants vous prépare à une récupération rapide.
Mode de défaillance 1 : Webhook indisponible avec failurePolicy: Fail
Symptôme : Toutes les requêtes du type correspondant (par exemple, création de pod) sont rejetées avec l'erreur « failed calling webhook ».
Diagnostic : Vérifiez la disponibilité du service webhook :
kubectl get pods -n webhook
kubectl get svc -n webhook
Si les pods sont en crash ou non prêts, le webhook est indisponible.
Options de récupération :
- Patchez la configuration du webhook pour définir
failurePolicy: Ignorecomme atténuation immédiate :
kubectl patch validatingwebhookconfiguration pod-label-validator --type='json' -p='[{"op": "replace", "path": "/webhooks/0/failurePolicy", "value": "Ignore"}]'
- Supprimez ou modifiez la configuration du webhook pour retirer entièrement le webhook défaillant s'il n'est pas encore critique :
kubectl delete validatingwebhookconfiguration pod-label-validator
- Réparez le serveur webhook (redémarrez les pods, ajustez la configuration) puis restaurez
failurePolicy: Fail.
Mode de défaillance 2 : NamespaceSelector trop large
Un webhook sans namespaceSelector ou avec un sélecteur large peut bloquer par inadvertance des ressources dans des espaces de noms critiques comme kube-system ou kube-public. Cela peut empêcher le cluster de se réparer ou de s'étendre.
Symptôme : Les composants système ne peuvent pas être créés ou mis à jour ; les opérations du cluster échouent.
Diagnostic : Regardez le namespaceSelector de la configuration du webhook :
kubectl get validatingwebhookconfiguration pod-label-validator -o yaml | grep -A5 namespaceSelector
S'il est absent ou défini pour correspondre à tout, le webhook s'applique à tous les espaces de noms.
Récupération : Patchez la configuration pour restreindre les espaces de noms. Par exemple, pour n'appliquer qu'aux espaces de noms avec l'étiquette policy=enforced :
kubectl patch validatingwebhookconfiguration pod-label-validator --type='json' -p='[{"op": "add", "path": "/webhooks/0/namespaceSelector", "value": {"matchLabels": {"policy": "enforced"}}}]'
Ensuite, étiquetez les espaces de noms souhaités :
kubectl label namespace myapp policy=enforced
Les espaces de noms système restent non affectés.
Mode de défaillance 3 : RBAC manquant pour le service webhook
Le serveur API doit pouvoir s'authentifier et s'autoriser auprès du service webhook. Si le RBAC est mal configuré, les appels échouent.
Symptôme : Les requêtes webhook sont refusées avec des erreurs d'autorisation dans les journaux du serveur API ou du serveur webhook.
Diagnostic : Vérifiez les journaux du serveur webhook pour les 403 Forbidden.
Récupération : Assurez-vous que le compte de service utilisé par le serveur webhook dispose des permissions RBAC appropriées pour traiter la revue d'admission. En général, le serveur webhook n'a pas besoin de permissions de cluster, mais il doit être joignable. Du côté du serveur API, assurez-vous que clientConfig inclut les bonnes informations d'identification si nécessaire (bien que la référence de service soit généralement suffisante).
Mode de défaillance 4 : MutatingWebhook mal configuré provoque des mutations invalides
Un webhook de mutation peut injecter des side-cars ou modifier des ressources d'une manière qui les rend invalides ou viole d'autres politiques.
Symptôme : Les pods ne démarrent pas avec des erreurs cryptiques, ou les webhooks de validation ultérieurs rejettent la ressource mutée.
Diagnostic : Inspectez l'objet muté. Vous pouvez utiliser kubectl get pod <nom> -o yaml pour voir l'état final, ou si le pod n'est pas créé, utilisez un dry-run avec un webhook de mutation factice qui enregistre l'objet.
Récupération : Désactiver temporairement le webhook de mutation en définissant failurePolicy: Ignore n'aidera pas car la mutation est le problème. Au lieu de cela, vous pouvez définir la matchPolicy ou les règles du webhook pour exclure les ressources problématiques, ou patcher la logique du webhook.
Liste de vérification générale pour la récupération
- Gardez des sauvegardes de toutes les configurations de webhook et des manifestes du serveur API.
- Ayez un moyen rapide de désactiver un webhook : une commande comme
kubectl delete validatingwebhookconfiguration <nom>peut sauver la mise. - Utilisez
failurePolicy: Ignorepour les webhooks non critiques. - Testez toutes les modifications des contrôleurs d'admission dans un cluster de préproduction d'abord.
- Surveillez la santé du cluster après les modifications : vérifiez
kubectl get nodes,kubectl get pods --all-namespaceset les journaux du serveur API.
Liste de vérification des opérations
Utilisez cette liste pour assurer une gestion sûre et efficace des contrôleurs d'admission.
Liste de vérification avant modification
- [ ] Enregistrer la version actuelle de Kubernetes et les contrôleurs d'admission activés.
- [ ] Lister les configurations de webhooks de mutation et de validation existantes.
- [ ] Identifier les types de ressources et les espaces de noms exacts affectés par la modification.
- [ ] Prendre des sauvegardes de chaque configuration YAML qui sera modifiée.
- [ ] Préparer un scénario de test dans un environnement non productif.
- [ ] Définir les résultats de test positifs et négatifs attendus.
Liste de vérification pendant la modification
- [ ] Appliquer les modifications une par une.
- [ ] Utiliser
kubectl apply --dry-run=serverlorsque possible pour tester avant de persister. - [ ] Surveiller en direct avec
kubectl get events --watch. - [ ] Vérifier la santé du service webhook immédiatement après l'application de la configuration.
- [ ] Avoir une commande de restauration prête (par exemple,
kubectl delete -f <fichier>ou patch versfailurePolicy: Ignore).
Liste de vérification après modification
- [ ] Exécuter des tests positifs : les applications qui devraient être autorisées le sont.
- [ ] Exécuter des tests négatifs : les applications qui devraient être refusées le sont avec le message d'erreur attendu.
- [ ] Confirmer qu'aucune ressource non intentionnelle n'est bloquée : créer un pod ou une autre ressource dans un espace de noms qui ne devrait pas être affecté.
- [ ] Vérifier la santé des espaces de noms système :
kubectl get pods -n kube-system. - [ ] Vérifier le statut de déploiement de tout déploiement impliqué dans le webhook ou le contrôleur.
- [ ] Documenter la modification et toute bizarrerie observée.
Exemple d'entrée de liste de vérification avec des valeurs concrètes
| Étape | Action | Commande | Résultat attendu | Responsable |
|---|---|---|---|---|
| 1 | Vérifier la version du serveur API | kubectl version --short | Version serveur 1.28.3 | Jordan Lee, ingénieur DevOps |
| 2 | Lister les plugins d'admission activés | kubectl describe pod kube-apiserver-control-plane -n kube-system | Contient PodSecurity dans --enable-admission-plugins | Jordan Lee |
| 3 | Sauvegarder la configuration webhook existante | kubectl get validatingwebhookconfiguration pod-label-validator -o yaml > backup.yaml | Fichier sauvegardé | Jordan Lee |
| 4 | Appliquer la configuration webhook mise à jour | kubectl apply -f new-webhook.yaml | Configuration mise à jour | Jordan Lee |
| 5 | Tester un pod sans étiquette | kubectl run test-pod --image=nginx | Création refusée avec « missing label 'owner' » | Jordan Lee |
| 6 | Tester un pod avec étiquette | kubectl run test-pod --image=nginx --labels=owner=team-a | Pod créé avec succès | Jordan Lee |
| 7 | Vérifier la santé de l'espace de noms système | kubectl get pods -n kube-system | Tous les pods en cours d'exécution | Jordan Lee |
Conclusion
Les erreurs de configuration des contrôleurs d'admission Kubernetes peuvent avoir des conséquences graves, mais avec une planification et une vérification minutieuses, elles sont gérables. Ce guide a fourni des exemples pratiques d'inventaire de votre environnement, d'application de modifications de configuration sûres, de validation du comportement, de diagnostic des échecs et de récupération des faux pas courants.
Chaque recommandation de cet article est délimitée par version, observable et réversible lorsque la technologie le permet. Copier une commande sans vérifier les prérequis et la sortie attendue n'est pas une procédure opérationnelle.
Comme prochaine étape, choisissez une vérification à faible risque pour votre configuration de contrôleur d'admission. Enregistrez l'état actuel, exécutez une vérification documentée, comparez le résultat avec le signal attendu et examinez les dépendances telles que les espaces de noms, les rôles et les configurations de webhook. Commencez par un webhook de validation non critique dans un espace de noms de test, expérimentez les politiques d'échec et observez comment elles affectent la création de pods. Introduisez-le ensuite progressivement en production avec un plan de restauration.
Un flux de travail technique fiable rend les échecs visibles, protège les valeurs sensibles, limite les modifications à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision. Avec ces pratiques, vous pouvez exploiter les contrôleurs d'admission pour appliquer la sécurité et la conformité sans sacrifier la stabilité du cluster.