Introduction
Les contrôleurs d'admission Kubernetes sont des modules qui régissent et font respecter la manière dont le cluster est utilisé. Ils agissent comme un garde-barrière qui intercepte les requêtes API authentifiées et peut modifier l'objet de la requête ou le refuser entièrement. Bien qu'ils soient un outil puissant pour appliquer la sécurité, la gestion des ressources et les politiques de configuration, ils sont aussi une source fréquente de frustration lorsqu'ils dysfonctionnent. Un contrôleur d'admission mal configuré peut bloquer le déploiement de charges de travail, empêcher les pods de démarrer ou provoquer des mutations inattendues des ressources, entraînant des interruptions de production.
Cet article se concentre sur les erreurs les plus courantes rencontrées avec les contrôleurs d'admission Kubernetes et fournit des correctifs pratiques et actionnables. Il s'adresse aux développeurs, aux ingénieurs DevOps et aux équipes techniques de startups qui doivent passer rapidement d'un problème observé à un résultat vérifié. Nous couvrirons les concepts de base, les scénarios d'erreur typiques, les techniques de débogage efficaces et les procédures de récupération étape par étape. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter la zone d'impact, utiliser des valeurs de substitution plutôt que des secrets, vérifier les résultats et documenter les procédures de récupération.
Comprendre les contrôleurs d'admission
Avant d'aborder les erreurs, il est essentiel de comprendre comment fonctionnent les contrôleurs d'admission. Les contrôleurs d'admission sont des morceaux de code qui interceptent les requêtes vers le serveur d'API Kubernetes après l'authentification et l'autorisation, mais avant que l'objet ne soit persisté dans etcd. Ils peuvent être classés en deux catégories :
- Contrôleurs d'admission intégrés : ils sont compilés dans le binaire kube-apiserver et activés via le drapeau
--enable-admission-plugins. Exemples :NamespaceLifecycle,LimitRanger,PodSecurityetResourceQuota. - Contrôleurs d'admission dynamiques : ce sont des webhooks configurables à l'exécution à l'aide des objets
ValidatingWebhookConfigurationetMutatingWebhookConfiguration. Ils appellent des services externes (rappels HTTP) pour prendre des décisions d'admission.
Les erreurs courantes des contrôleurs d'admission peuvent provenir de l'une ou l'autre catégorie. Cependant, les webhooks dynamiques sont souvent en cause car ils impliquent des dépendances externes et des appels réseau.
Inventaire de la version et de l'environnement
Avant de dépanner un problème de contrôleur d'admission, vous devez établir un inventaire clair de votre environnement. Cela inclut la version de Kubernetes, les contrôleurs d'admission activés et la configuration des webhooks. Connaître la version est essentiel car certains contrôleurs d'admission sont supprimés ou dépréciés dans différentes versions, et les versions d'API des webhooks évoluent.
1. Déterminer la version de Kubernetes
Exécutez la commande suivante pour obtenir la version du serveur :
kubectl version --short
Exemple de sortie :
Client Version: v1.28.0
Server Version: v1.28.3
Si vous utilisez un service Kubernetes managé (EKS, GKE, AKS), la version peut être indiquée dans la vue d'ensemble du cluster. Notez la version mineure car le comportement des contrôleurs d'admission peut varier.
2. Lister les contrôleurs d'admission activés
Pour voir quels contrôleurs d'admission sont activés sur votre kube-apiserver, vous pouvez inspecter la spécification du pod kube-apiserver si vous utilisez un cluster autogéré avec des pods statiques (par exemple, kubeadm). Si vous avez accès au nœud du plan de contrôle, exécutez :
ps aux | grep kube-apiserver
Recherchez le drapeau --enable-admission-plugins. Alternativement, si votre kube-apiserver s'exécute comme un pod, utilisez :
kubectl get pod -n kube-system -l component=kube-apiserver -o yaml | grep enable-admission-plugins
Exemple de sortie :
- --enable-admission-plugins=NodeRestriction,PodSecurity,ResourceQuota,DefaultStorageClass
Dans les clusters managés (EKS, GKE), vous pouvez ne pas avoir un accès direct, mais vous pouvez déduire les contrôleurs activés en tentant de créer des ressources qu'ils rejetteraient.
3. Lister les configurations de webhook
Pour les contrôleurs d'admission dynamiques, listez les configurations de webhook :
kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurations
Exemple de sortie :
NAME WEBHOOKS AGE
istio-validator 1 5d
cert-manager-webhook 1 10d
Ensuite, examinez les détails du webhook concerné :
kubectl describe validatingwebhookconfiguration istio-validator
Cela affichera les règles, le sélecteur d'espace de noms et le service ou l'URL que le webhook appelle.
4. Vérifier les services et points de terminaison des webhooks
Pour les webhooks qui utilisent une référence de service (le modèle le plus courant), assurez-vous que le service existe et a des points de terminaison prêts. Par exemple :
kubectl get svc -n istio-system istiod
kubectl get endpoints -n istio-system istiod
Si la liste des points de terminaison est vide, le webhook échouera car le serveur d'API ne peut joindre aucun pod backend.
Erreurs courantes et correctifs
Erreur 1 : Webhook indisponible (délai d'attente ou connexion refusée)
Symptôme : Lors de la création d'une ressource, vous obtenez une erreur telle que :
Error from server (InternalError): error when creating "pod.yaml": Internal error occurred: failed calling webhook "webhook.example.com": Post "https://istiod.istio-system.svc:443/validate?timeout=10s": dial tcp 10.0.0.10:443: connect: connection refused
Ou vous pouvez voir un délai d'attente :
Error from server: error when creating "pod.yaml": Internal error occurred: failed calling webhook "webhook.example.com": Post "https://istiod.istio-system.svc:443/validate?timeout=10s": context deadline exceeded
Cause : Le service webhook n'est pas en cours d'exécution, n'est pas prêt, ou le serveur d'API ne peut pas l'atteindre en raison de politiques réseau ou d'une mauvaise configuration TLS.
Correctif :
- Vérifiez si le pod backend du webhook est en cours d'exécution :
kubectl get pods -n istio-system -l app=istiod
- Vérifiez les points de terminaison du service :
kubectl get endpoints -n istio-system istiod
S'il n'y a pas de points de terminaison, le sélecteur du service ne correspond à aucun pod en cours d'exécution. Ajustez le sélecteur du service ou augmentez le nombre de réplicas du déploiement.
- Vérifiez que le serveur d'API peut atteindre le service. Si vous avez des politiques réseau, assurez-vous qu'elles autorisent le trafic depuis l'espace de noms du serveur d'API (généralement kube-system) vers le service webhook sur le port requis.
- Si TLS est mal configuré, vérifiez le bundle CA dans la configuration du webhook. Le champ
caBundledoit contenir le certificat CA qui a signé le certificat du serveur webhook. Vous pouvez le mettre à jour avec :
kubectl patch validatingwebhookconfiguration my-webhook --type='json' -p='[{"op": "replace", "path": "/webhooks/0/clientConfig/caBundle", "value": "<base64-encoded-CA>"}]'
Erreur 2 : Le webhook rejette toutes les requêtes en raison d'une mauvaise configuration de politique
Symptôme : Vous obtenez un refus clair du webhook, par exemple :
Error from server: admission webhook "namespace.dns.required" denied the request: namespace must have label 'team'
Cause : La politique du webhook est trop stricte ou l'objet que vous créez ne respecte pas la politique.
Correctif :
- Examinez les règles et la politique du webhook. Vous pouvez inspecter la configuration du webhook et éventuellement ses journaux.
- Si la politique est correcte, ajustez votre objet pour vous y conformer. Par exemple, ajoutez l'étiquette requise à l'espace de noms :
kubectl label namespace my-namespace team=myteam
- Si la politique est trop large ou si vous devez la contourner temporairement, vous pouvez :
- Modifier le
namespaceSelectordu webhook pour exclure certains espaces de noms. - Ou, en cas d'urgence, supprimer ou désactiver le webhook (non recommandé à long terme, mais peut vous débloquer) :
kubectl delete validatingwebhookconfiguration my-webhook
Remarque : Documentez toujours la suppression et recréez-le avec un correctif dès que possible.
Erreur 3 : Le webhook mutateur modifie les ressources de manière inattendue
Symptôme : Les ressources sont créées avec des annotations, des étiquettes ou des conteneurs sidecar inattendus (par exemple, sidecar Istio, proxy Linkerd). Vous pouvez observer un comportement inattendu dans vos applications.
Cause : Un webhook d'admission mutateur modifie vos ressources. Cela peut être intentionnel (par exemple, injection automatique de sidecar), mais parfois un webhook mal configuré peut appliquer des modifications de manière incorrecte.
Correctif :
- Identifiez quel webhook mutateur est actif :
kubectl get mutatingwebhookconfigurations
- Décrivez le webhook pour voir ses règles et son
namespaceSelector:
kubectl describe mutatingwebhookconfiguration istio-sidecar-injector
- Si le webhook cible des espaces de noms qu'il ne devrait pas, ajustez le
namespaceSelector. Par exemple, pour exclure un espace de noms, assurez-vous qu'il ne correspond pas au sélecteur. Si le sélecteur estmatchLabels: {istio-injection: enabled}, tout espace de noms sans cette étiquette ne sera pas ciblé.
Pour désactiver l'injection pour un espace de noms spécifique, supprimez l'étiquette :
kubectl label namespace my-namespace istio-injection-
- Pour tester l'effet, vous pouvez simuler un déploiement avec et sans l'étiquette pour voir les changements. Utilisez
kubectl apply --dry-run=server -f deployment.yaml -o yaml(nécessite Kubernetes 1.18+).
Erreur 4 : Contrôleur d'admission manquant dans les drapeaux du serveur d'API
Symptôme : Vous vous attendez à ce qu'un contrôleur d'admission intégré applique une politique, mais rien ne se passe. Par exemple, vous avez défini un ResourceQuota, mais des pods peuvent encore être créés au-delà des limites.
Cause : Le contrôleur d'admission n'est pas activé dans les drapeaux du kube-apiserver. Par exemple, ResourceQuota n'est pas dans la liste --enable-admission-plugins.
Correctif :
- Vérifiez les plugins activés comme décrit précédemment.
- Modifiez le manifeste du kube-apiserver (par exemple,
/etc/kubernetes/manifests/kube-apiserver.yaml) pour inclure le contrôleur manquant dans la liste. Pour les clusters managés, vous devrez peut-être vérifier les options de configuration du fournisseur cloud.
- Après la mise à jour, le pod kube-apiserver redémarrera automatiquement. Surveillez son état :
kubectl get pods -n kube-system -l component=kube-apiserver
- Vérifiez que le contrôleur est maintenant actif en tentant une requête qui devrait être rejetée. Pour ResourceQuota, essayez de créer un pod qui dépasse le quota et observez s'il est interdit.
Erreur 5 : Configuration du webhook d'admission avec des règles ou conditions de correspondance invalides
Symptôme : Le webhook n'est pas appelé pour certaines ressources, ou il est appelé pour des ressources qu'il ne devrait pas concerner.
Cause : Le champ rules dans la configuration du webhook peut être mal configuré. Par exemple, il manque un groupe d'API ou une ressource, ou * est utilisé incorrectement.
Correctif :
- Examinez les règles :
kubectl get validatingwebhookconfiguration my-webhook -o yaml
Recherchez la section rules :
rules:
- operations: ["CREATE"]
apiGroups: ["apps"]
apiVersions: ["v1"]
resources: ["deployments"]
scope: "Namespaced"
- Assurez-vous que
apiGroupscorrespond au groupe de la ressource. Pour les ressources cœur, utilisez""(chaîne vide). Par exemple, pour correspondre aux pods, définissezapiGroups: [""].
- Ajustez les règles selon les besoins et appliquez la configuration mise à jour.
Vérification et diagnostics
Une fois que vous avez appliqué un correctif, il est crucial de vérifier que le problème est résolu sans introduire de nouveaux problèmes.
1. Tests de simulation (dry-run)
Utilisez kubectl apply --dry-run=server ou kubectl create --dry-run=server pour simuler la requête. Cela validera l'objet auprès des contrôleurs d'admission sans le persister.
Exemple :
kubectl apply --dry-run=server -f deployment.yaml
Si la commande retourne deployment.apps/myapp created (server dry run), l'admission est réussie. S'il y a une erreur, elle sera affichée.
2. Vérifier les événements
Après avoir appliqué une ressource, vérifiez les événements dans l'espace de noms pour voir s'il y a des avertissements liés à l'admission :
kubectl get events -n my-namespace --sort-by='.lastTimestamp'
3. Inspecter les journaux du serveur d'API
Si le problème concerne le kube-apiserver ou les échecs d'appel de webhook, consultez les journaux du serveur d'API. Pour les clusters autogérés, vous pouvez souvent y accéder sur le nœud du plan de contrôle :
journalctl -u kube-apiserver -f
Ou affichez les journaux du pod :
kubectl logs -n kube-system kube-apiserver-master -f
Recherchez les lignes contenant admission ou webhook.
4. Utiliser kubectl describe pour les ressources
Lorsqu'une ressource ne peut pas être créée, parfois l'erreur n'est visible que dans les événements de la ressource si elle est partiellement créée. Utilisez kubectl describe sur le type de ressource ou vérifiez si un objet de configuration existe.
5. Surveiller les journaux du backend du webhook
Consultez les journaux des pods backend du webhook pour voir s'ils ont reçu les requêtes et quelles décisions ils ont prises.
kubectl logs -n istio-system -l app=istiod --tail=50
Recherchez des messages d'erreur ou des journaux de revue d'admission.
Modes de défaillance et récupération
Il est important de planifier les modes de défaillance lorsque les contrôleurs d'admission bloquent des opérations critiques. Voici quelques scénarios de défaillance courants et les étapes de récupération.
Service webhook complètement hors service
Si le service webhook est hors service et que vous ne pouvez pas le rétablir rapidement, vous devrez peut-être désactiver temporairement le webhook pour permettre les déploiements. Cependant, cela peut compromettre la sécurité ou la politique. Évaluez le risque.
Pour désactiver temporairement un webhook, vous pouvez soit :
- Supprimer la configuration du webhook (et la recréer plus tard).
- Définir
failurePolicysurIgnoresi elle est actuellementFail. Cela permet aux requêtes de se poursuivre même si le webhook échoue. Cependant, cela nécessite de modifier la configuration du webhook, ce que vous pouvez faire si vous avez accès à l'API.
kubectl patch validatingwebhookconfiguration my-webhook --type='merge' -p '{"webhooks":[{"name":"webhook.example.com","failurePolicy":"Ignore"}]}'
Remarque : C'est une mesure temporaire ; la politique du webhook ne sera pas appliquée tant qu'il est hors service. Documentez le changement et revenez en arrière une fois le service rétabli.
Webhook bloquant la suppression de nœuds
Certains webhooks peuvent bloquer la suppression de nœuds ou de pods, surtout s'ils ont des finaliseurs. Assurez-vous que les règles du webhook sont correctement délimitées pour éviter d'interférer avec les ressources système.
La mise à niveau du cluster casse les contrôleurs d'admission
Lors de la mise à niveau de Kubernetes, les contrôleurs d'admission intégrés peuvent changer. Par exemple, PodSecurityPolicy a été supprimé dans la v1.25 et remplacé par Pod Security Admission. Consultez les notes de version et mettez à jour vos configurations en conséquence.
Après une mise à niveau, vérifiez que tous les webhooks sont toujours joignables et que leurs certificats TLS sont valides. Les certificats peuvent expirer ou le bundle CA peut nécessiter une mise à jour.
Liste de contrôle des opérations
Utilisez cette liste de contrôle pour traiter systématiquement les problèmes de contrôleurs d'admission :
- Identifier la requête en échec : Notez la commande exacte, le type de ressource et le message d'erreur.
- Vérifier la version de Kubernetes et les plugins d'admission activés : Utilisez
kubectl versionet inspectez les drapeaux du kube-apiserver. - Lister toutes les configurations de webhook :
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations. - Déterminer quel webhook est impliqué : Le message d'erreur nomme généralement le webhook.
- Vérifier la santé du backend du webhook : Assurez-vous que les pods sont en cours d'exécution et que les points de terminaison sont peuplés.
- Examiner la configuration du webhook : Regardez les règles,
namespaceSelector,caBundleetfailurePolicy. - Tester avec un dry-run : Simulez la requête pour voir si elle passe sans effets secondaires.
- Inspecter les journaux : Consultez les journaux du serveur d'API et du backend du webhook pour des causes détaillées.
- Appliquer un correctif minimal : Changez un élément à la fois (par exemple, ajouter une étiquette, ajuster le sélecteur, mettre à jour le CA).
- Vérifier le correctif : Réessayez la requête d'origine et surveillez.
- Documenter l'incident et la résolution : Mettez à jour les runbooks et notez tout changement temporaire.
Conclusion
Les contrôleurs d'admission Kubernetes sont puissants mais peuvent être une source de difficultés opérationnelles lorsqu'ils sont mal configurés. En suivant une approche systématique — commençant par un inventaire de l'environnement, comprenant l'erreur spécifique, diagnostiquant avec les bonnes commandes et appliquant des correctifs ciblés — vous pouvez résoudre la plupart des problèmes rapidement et en toute sécurité. N'oubliez jamais d'observer avant de modifier, de limiter la zone d'impact et de vérifier les résultats. Documentez vos procédures de récupération afin que les incidents futurs soient traités encore plus rapidement.
Comme prochaine étape, mettez en place un contrôle de surveillance de base pour vos webhooks d'admission : testez régulièrement qu'ils sont joignables et que leurs certificats sont valides. De plus, établissez une politique pour gérer les défaillances temporaires des webhooks, y compris quand définir failurePolicy sur Ignore et comment suivre et annuler de tels changements.
Avec ces pratiques, vous pouvez maintenir les avantages de sécurité et de politique des contrôleurs d'admission tout en minimisant leur potentiel à perturber les opérations de votre cluster.