Introduction
Les contrôleurs d'admission sont un garde-fou essentiel dans le pipeline de requêtes de l'API Kubernetes. Ils interceptent chaque requête de création, de mise à jour et de suppression, appliquent des politiques et peuvent muter les ressources avant leur persistance. Lorsqu'ils sont mal configurés ou surchargés, ils deviennent un goulot d'étranglement qui ralentit les déploiements, casse les pipelines CI/CD et provoque des délais d'attente mystérieux. Ce guide vous accompagne dans un processus systématique pour régler les performances des contrôleurs d'admission : de l'observation initiale et de l'inventaire des versions aux changements de configuration sûrs, en passant par la vérification, la récupération en cas d'échec et une liste de contrôle opérationnelle. Chaque section comprend des commandes concrètes, les sorties attendues et des exemples pratiques pour les développeurs, les consultants DevOps et les équipes techniques de startups.
Nous nous concentrerons sur deux types principaux de contrôleurs d'admission :
- Les contrôleurs d'admission intégrés (par exemple, ResourceQuota, LimitRanger, PodSecurity) compilés dans le serveur d'API Kubernetes.
- Les webhooks d'admission dynamiques (par exemple, ValidatingWebhookConfiguration, MutatingWebhookConfiguration) qui appellent des services HTTP externes.
Des problèmes de performance peuvent survenir avec l'un ou l'autre type, mais les webhooks dynamiques sont la source de latence la plus courante car ils ajoutent des allers-retours réseau à chaque requête API. Tout au long de cet article, nous utiliserons un scénario typique : une équipe constate que kubectl apply prend 10 secondes au lieu d'une seconde, et que les pods restent à l'état Pending plus longtemps que prévu.
Inventaire des versions et de l'environnement
Avant de modifier toute configuration, rassemblez des informations précises sur votre version de Kubernetes, les contrôleurs d'admission actuellement activés et les webhooks installés. Cette base de référence est essentielle pour comparer les performances avant et après, et pour garantir que tout changement est compatible avec votre cluster.
Vérifier la version de Kubernetes
Exécutez la commande suivante pour obtenir la version du serveur :
kubectl version --short
Sortie attendue (exemple) :
Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.3
Notez la version du serveur ; pour le réglage des contrôleurs d'admission, les versions 1.24 et ultérieures ont des délais d'attente de webhook cohérents (10 secondes) et prennent en charge failurePolicy.
Lister les contrôleurs d'admission activés
Vous pouvez voir les contrôleurs d'admission activés sur le serveur d'API en vérifiant ses indicateurs. Si vous avez accès aux nœuds du plan de contrôle ou au manifeste kube-apiserver, examinez l'indicateur --enable-admission-plugins. Par exemple :
ps aux | grep kube-apiserver | grep enable-admission-plugins
Si vous utilisez un service Kubernetes managé (EKS, GKE, AKS), vous n'aurez peut-être pas d'accès direct. À la place, vous pouvez déduire certains plugins en vérifiant des ressources ou des comportements spécifiques. Par exemple, pour voir si ResourceQuota est activé, créez un espace de noms et essayez d'appliquer un quota. Cependant, le moyen le plus fiable pour les clusters managés est de consulter la documentation du fournisseur.
Sinon, utilisez kubectl api-versions pour voir si certaines API sont disponibles, ce qui peut indiquer les contrôleurs d'admission activés. Par exemple, si policy/v1 est disponible et que vous pouvez récupérer des PodDisruptionBudgets, le contrôleur d'admission PodDisruptionBudget est probablement actif.
Lister les webhooks d'admission configurés
Les webhooks dynamiques sont définis dans les objets ValidatingWebhookConfiguration et MutatingWebhookConfiguration. Listez-les :
kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurations
Exemple de sortie pour les webhooks de validation :
NAME WEBHOOKS AGE
gatekeeper-validating-webhook 1 30d
pod-policy.example.com 1 10d
Pour chaque webhook, inspectez sa configuration pour voir quelles ressources il intercepte, son délai d'attente et sa politique d'échec :
kubectl get validatingwebhookconfiguration gatekeeper-validating-webhook -o yaml
Les champs cruciaux sont :
timeoutSeconds: temps maximal d'attente du serveur d'API pour une réponse du webhook (10 secondes par défaut).failurePolicy: soitFail(la requête est rejetée en cas d'échec du webhook) soitIgnore(la requête aboutit quand même).rules: quelles ressources et opérations de l'API déclenchent le webhook.
Exemple d'extrait :
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: gatekeeper-validating-webhook
webhooks:
- name: validation.gatekeeper.sh
timeoutSeconds: 3
failurePolicy: Fail
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["*"]
apiVersions: ["*"]
resources: ["pods", "deployments"]
Vérifier la santé des points de terminaison des webhooks
Les webhooks sont généralement exposés en tant que services dans le cluster ou sous forme d'URL externes. Vérifiez que les pods sous-jacents sont en cours d'exécution et réactifs. Pour un service dans l'espace de noms gatekeeper-system :
kubectl get pods -n gatekeeper-system -o wide
kubectl logs -n gatekeeper-system <pod-name> --tail=50
Si le service webhook dispose d'un point de terminaison de santé, testez-le avec kubectl port-forward ou curl. Par exemple :
kubectl port-forward -n gatekeeper-system svc/gatekeeper-webhook-service 8443:443 &
curl -k https://localhost:8443/healthz
Sortie attendue : ok.
Chemin de configuration sûr
L'étape suivante consiste à apporter des modifications ciblées pour améliorer les performances tout en minimisant les risques. Commencez toujours par une observation en lecture seule, puis appliquez le plus petit changement qui résout le goulot d'étranglement, et ayez toujours un plan de retour en arrière.
Identifier le goulot d'étranglement
Le premier diagnostic consiste à mesurer la latence des requêtes API et à déterminer si les webhooks d'admission en sont la cause. Activez la journalisation d'audit ou utilisez les métriques du serveur d'API Kubernetes.
1. Utiliser les métriques du serveur d'API Kubernetes (si Prometheus est disponible)
Le serveur d'API expose des métriques à /metrics. Métriques clés pour l'admission :
apiserver_admission_controller_admission_duration_secondsapiserver_admission_webhook_admission_duration_seconds
Interrogez Prometheus pour la latence au 99e percentile :
histogram_quantile(0.99, rate(apiserver_admission_webhook_admission_duration_seconds_bucket[5m]))
Si cette valeur dépasse 1 seconde, les webhooks contribuent probablement aux ralentissements.
2. Utiliser les journaux d'audit
Si la journalisation d'audit est activée, recherchez les étapes de requête et les latences. Par exemple, dans le journal d'audit, trouvez les entrées avec "stage":"ResponseComplete" et inspectez le champ "annotations" pour les latences des webhooks.
3. Effectuer un test de latence manuel
Créez un pod de test et chronométrez la requête :
time kubectl run test-pod --image=nginx --restart=Never
Ensuite, supprimez-le :
kubectl delete pod test-pod --wait=false
Comparez le temps avec et sans un webhook particulier (en le désactivant temporairement, si possible).
Réglage des contrôleurs d'admission intégrés
Les contrôleurs d'admission intégrés sont généralement efficaces, mais certains peuvent entraîner une surcharge. Par exemple, ResourceQuota et LimitRanger effectuent des recherches et des calculs supplémentaires. Cependant, ils sont rarement le principal goulot d'étranglement des performances. Si vous soupçonnez un contrôleur intégré, vous pouvez mesurer sa durée via les métriques :
apiserver_admission_controller_admission_duration_seconds{name="ResourceQuota", quantile="0.99"}
Si la valeur est élevée, envisagez de réduire le nombre de quotas ou de plages de limites, ou de restreindre la portée du contrôleur (par exemple, appliquer des quotas à moins d'espaces de noms). Mais dans la plupart des cas, le problème vient des webhooks dynamiques.
Réglage des webhooks dynamiques
Les principaux leviers pour les performances des webhooks sont :
- Réduire
timeoutSeconds: cela fixe une limite supérieure, mais ne rend pas le webhook plus rapide. Cependant, le réduire (par exemple, de 10 à 3 secondes) peut échouer plus rapidement et éviter de longues attentes lorsque le webhook est en panne. Toutefois, si le webhook est lent mais répond finalement dans les 3 secondes, réduire le délai peut entraîner davantage d'échecs.
- Ajuster
failurePolicysurIgnore: si un webhook n'est pas critique et subit des échecs intermittents, définirfailurePolicy: Ignorepermet aux requêtes de se poursuivre sans l'approbation du webhook. C'est un compromis entre disponibilité et application des politiques. À utiliser uniquement pour les webhooks consultatifs ou de type audit.
- Restreindre la portée du webhook : plus un webhook intercepte de ressources et d'opérations, plus il traite de requêtes. Limitez les
rulesaux ressources nécessaires. Par exemple, si un webhook valide uniquement les pods, n'incluez pasdeploymentsdans les règles (puisque les déploiements créent des pods, la création du pod déclenchera quand même le webhook ; intercepter les déploiements entraînerait des appels en double).
- Améliorer les performances du service webhook : assurez-vous que le backend du webhook dispose de suffisamment de répliques, qu'il est évolutif horizontalement et qu'il a une faible latence interne. Vérifiez l'utilisation du processeur et de la mémoire :
kubectl top pods -n <webhook-namespace>
Si les pods manquent de ressources, augmentez les limites ou le nombre de répliques.
- Utiliser des sélecteurs d'objets : si le webhook ne doit traiter qu'un sous-ensemble d'objets (par exemple, des espaces de noms ou des étiquettes spécifiques), utilisez
namespaceSelectorouobjectSelectorpour filtrer côté serveur d'API, réduisant ainsi les appels inutiles au webhook.
Exemple : réglage d'un webhook de validation lent
Supposons que vous ayez un webhook de validation qui vérifie les politiques de sécurité des pods et prend en moyenne 4 secondes par requête. La configuration actuelle ressemble à :
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-security-webhook
webhooks:
- name: pod-security.example.com
timeoutSeconds: 10
failurePolicy: Fail
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["*"]
apiVersions: ["*"]
resources: ["pods", "deployments", "statefulsets", "daemonsets", "jobs", "cronjobs"]
namespaceSelector:
matchLabels:
pod-security: enabled
Problèmes : le webhook intercepte de nombreux types de ressources et n'a pas de délai d'attente réduit. De plus, le backend est peut-être sous-provisionné.
Changements sûrs :
- Limitez les règles aux seuls
pods(puisque tous les autres contrôleurs de charge de travail créent des pods, l'événement de création du pod est suffisant) ou utilisezobjectSelectorsi possible. - Réduisez
timeoutSecondsà 3 secondes. - Faites évoluer le déploiement du webhook avec davantage de répliques.
Appliquez les changements :
kubectl apply -f updated-webhook.yaml
Ensuite, testez avec une création de pod :
time kubectl run test-pod --image=nginx --restart=Never
Observez la nouvelle latence et assurez-vous que le pod est créé avec succès.
Vérification et diagnostics
Après avoir apporté des modifications, vérifiez que les performances se sont améliorées et que les contrôleurs d'admission fonctionnent correctement. Utilisez une combinaison de métriques, de journaux et de tests réels.
Vérifier le temps de réponse des webhooks
Utilisez les métriques du serveur d'API pour confirmer que la latence des webhooks a diminué. Si Prometheus n'est pas disponible, vous pouvez activer temporairement la journalisation d'audit ou utiliser l'indicateur kubectl --v=6 pour voir le chronométrage détaillé des requêtes.
Par exemple, exécutez :
kubectl get pod test-pod -v=6
La sortie comprend le chronométrage de chaque phase, y compris l'admission :
I1015 10:30:00.123456 12345 round_trippers.go:553] GET https://api-server:6443/api/v1/namespaces/default/pods/test-pod 200 OK in 123 milliseconds
Le temps total n'est pas décomposé par admission, mais si le temps total est proche de votre paramètre de délai d'attente, les webhooks sont encore lents.
Vérifier les taux de succès/échec des webhooks
Si le service webhook exporte des métriques, surveillez-les. Sinon, consultez les journaux du service webhook pour détecter des erreurs ou des délais d'attente. Par exemple :
kubectl logs -n pod-security-webhook -l app=webhook --tail=100 | grep -i error
Vérifiez également les journaux du serveur d'API pour les délais d'attente des webhooks. Sur un cluster managé, vous n'y aurez peut-être pas accès, mais sur un cluster auto-géré, consultez les journaux du conteneur kube-apiserver :
journalctl -u kube-apiserver | grep -i webhook
Erreurs attendues comme :
E1015 10:35:00.234567 12345 dispatcher.go:173] failed calling webhook "pod-security.example.com": failed to call webhook: Post https://pod-security-webhook.default.svc:443/validate?timeout=3s: context deadline exceeded
Valider que les politiques sont toujours appliquées
Le réglage des performances ne doit pas compromettre l'application des politiques. Testez que le contrôleur d'admission refuse toujours les requêtes invalides. Par exemple, si le webhook impose une exigence d'étiquette, essayez de créer un pod sans l'étiquette requise et attendez-vous à un rejet :
kubectl run bad-pod --image=nginx --restart=Never
La sortie attendue comprend un message d'erreur du webhook :
Error from server (Forbidden): admission webhook "pod-security.example.com" denied the request: missing required label 'app'
Si la requête est acceptée, le webhook est peut-être mal configuré (par exemple, failurePolicy: Ignore l'amenant à ignorer les erreurs) ou les règles ne correspondent plus.
Test de performance à grande échelle
Pour simuler la charge, utilisez un outil comme kubectl apply dans une boucle ou un outil de test de charge. Par exemple, créez 100 pods par lots et mesurez le temps total :
time for i in $(seq 1 100); do kubectl run test-$i --image=nginx --restart=Never --labels=app=test-$i; done
Ensuite, nettoyez :
kubectl delete pods -l app --selector 'app in (test-1,test-2,...)'
Comparez le temps avant et après le réglage. Une réduction significative du temps total indique une amélioration.
Modes de défaillance et récupération
Même avec un réglage minutieux, les contrôleurs d'admission peuvent tomber en panne et provoquer des pannes généralisées. Comprenez les modes de défaillance courants et comment récupérer rapidement.
Échecs dus aux délais d'attente des webhooks
Si un webhook dépasse son timeoutSeconds, le serveur d'API traite cela comme un échec selon failurePolicy. Si failurePolicy: Fail, la requête est rejetée avec une erreur comme :
Error from server (InternalError): an error on the server ("") has prevented the request from succeeding
Cela peut entraîner l'échec de toutes les requêtes correspondantes. Pour récupérer rapidement :
- Désactivez temporairement le webhook en définissant
failurePolicy: Ignoreou en supprimant la configuration du webhook. Pour une correction temporaire, vous pouvez modifier le webhook :
kubectl edit validatingwebhookconfiguration pod-security-webhook
Changez failurePolicy en Ignore et enregistrez. Les requêtes se poursuivront alors sans validation.
- Faites évoluer le backend du webhook pour gérer la charge.
- Enquêtez sur la cause profonde (par exemple, problèmes réseau, épuisement des ressources) et corrigez-la.
Service webhook indisponible
Si les points de terminaison du service webhook ne sont pas prêts (par exemple, les pods sont en boucle de crash), le serveur d'API échouera également les requêtes. Vérifiez les points de terminaison du service :
kubectl get endpoints -n pod-security-webhook
S'il n'y a pas de points de terminaison, le sélecteur de service peut ne pas correspondre aux pods, ou les pods ne sont pas prêts. Vérifiez l'état et les journaux des pods.
Règles de webhook mal configurées
Un webhook avec des règles trop larges peut intercepter plus de requêtes que prévu, entraînant une dégradation des performances et des refus inattendus. Par exemple, un webhook destiné aux pods mais configuré pour intercepter toutes les ressources (resources: ["*"]) sera appelé pour chaque objet. Pour récupérer, restreignez les règles à des ressources spécifiques.
Problèmes avec les contrôleurs d'admission intégrés
Bien que moins courants, les contrôleurs d'admission intégrés peuvent également causer des problèmes. Par exemple, si le contrôleur ResourceQuota est lent, cela peut être dû à un grand nombre de quotas dans le cluster. Dans des cas extrêmes, vous devrez peut-être désactiver temporairement le contrôleur d'admission. Cela nécessite de modifier le manifeste du serveur d'API et n'est pas recommandé en production sans tests approfondis.
Stratégie de retour en arrière
Conservez toujours une sauvegarde des configurations de webhook d'origine avant d'apporter des modifications. Utilisez kubectl get <resource> -o yaml > backup.yaml pour les enregistrer. Si un changement pose problème, restaurez à partir de la sauvegarde :
kubectl apply -f backup.yaml
De plus, versionnez vos configurations à l'aide d'outils GitOps comme Argo CD ou Flux, qui permettent des retours en arrière faciles.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour vous assurer d'avoir couvert tous les aspects du réglage des performances des contrôleurs d'admission :
- [ ] Identifier la version de Kubernetes et les contrôleurs d'admission activés.
- [ ] Lister toutes les configurations de webhooks de validation et de mutation.
- [ ] Examiner les paramètres
timeoutSecondsetfailurePolicyde chaque webhook. - [ ] Mesurer la latence de base des requêtes API avec et sans les webhooks.
- [ ] Analyser les métriques du serveur d'API pour la durée d'admission, si disponibles.
- [ ] Identifier les webhooks les plus chronophages.
- [ ] Restreindre les règles des webhooks aux ressources et opérations minimales nécessaires.
- [ ] Réduire
timeoutSecondsà une valeur qui équilibre disponibilité et détection des échecs. - [ ] Envisager de définir
failurePolicy: Ignorepour les webhooks non critiques. - [ ] Utiliser
namespaceSelectorouobjectSelectorpour filtrer l'invocation des webhooks. - [ ] Adapter les déploiements du backend des webhooks de manière appropriée.
- [ ] Surveiller l'utilisation des ressources du backend des webhooks (CPU, mémoire) et ajuster les limites.
- [ ] Vérifier que les politiques sont toujours appliquées après le réglage.
- [ ] Effectuer un test de performance sous une charge réaliste.
- [ ] Documenter les modifications et s'assurer que des procédures de retour en arrière sont en place.
- [ ] Mettre en place des alertes sur la latence et les taux d'échec des webhooks si ce n'est pas déjà fait.
Conclusion
Le réglage des contrôleurs d'admission Kubernetes est un équilibre entre performance et application des politiques. En mesurant systématiquement, en apportant des modifications ciblées et en vérifiant les résultats, vous pouvez éliminer les goulots d'étranglement et prévenir les pannes. N'oubliez pas de toujours avoir un plan de retour en arrière et de surveiller les effets de vos modifications au fil du temps. Grâce aux étapes pratiques de ce guide, vous pouvez vous assurer que les contrôleurs d'admission font leur travail sans ralentir votre cluster.