
Les Admission Controllers sont des plugins qui interceptent les requêtes vers l’API Kubernetes après authentification et autorisation, mais avant la persistance dans etcd. Ils peuvent valider (accepter ou refuser) ou muter (modifier) les ressources. Ce mécanisme est la base du policy-as-code sur Kubernetes.
Comment fonctionnent les Admission Controllers ?
Section intitulée « Comment fonctionnent les Admission Controllers ? »Quand vous créez une ressource avec kubectl apply, la requête traverse plusieurs étapes :
Les 2 types d’admission controllers
Section intitulée « Les 2 types d’admission controllers »Les admission controllers se divisent en deux catégories qui interviennent à des moments différents du cycle de vie de la requête. Comprendre cette distinction est essentiel pour savoir quel type utiliser selon votre besoin.
| Type | Rôle | Exemple |
|---|---|---|
| Mutating | Modifie la ressource avant persistance | Injecter un sidecar, ajouter des labels |
| Validating | Accepte ou refuse la ressource | Bloquer les pods privileged, exiger des labels |
Exemple concret : Imaginez le déploiement d’un pod. Un Mutating Admission Controller peut automatiquement ajouter un label team: backend à tous les pods créés dans un namespace donné. Ensuite, un Validating Admission Controller vérifie que ce label existe bien — si vous aviez oublié de le configurer, la mutation l’a ajouté pour vous.
Les Admission Controllers intégrés
Section intitulée « Les Admission Controllers intégrés »Kubernetes inclut de nombreux admission controllers activés par défaut. Vous n’avez pas besoin de les installer : ils font partie de l’API Server. Leur activation se contrôle via le flag --enable-admission-plugins au démarrage de l’API Server.
Pour la certification CKS et la sécurité en production, certains contrôleurs sont particulièrement importants. Voyons lesquels et pourquoi.
Contrôleurs de sécurité
Section intitulée « Contrôleurs de sécurité »Ces contrôleurs protègent votre cluster contre les configurations dangereuses et les escalades de privilèges.
| Contrôleur | Type | Rôle | Activé par défaut |
|---|---|---|---|
| PodSecurity | Validating | Applique les Pod Security Standards | ✅ |
| NodeRestriction | Validating | Limite ce que les kubelets peuvent modifier | ✅ |
| ServiceAccount | Mutating | Injecte le token ServiceAccount | ✅ |
| AlwaysPullImages | Mutating | Force imagePullPolicy: Always | ❌ |
Pourquoi PodSecurity est-il si important ? C’est le gardien qui empêche les pods de s’exécuter avec des privilèges excessifs. Sans lui, n’importe quel développeur pourrait déployer un pod en mode privileged, avec un accès complet au nœud hôte.
Pourquoi NodeRestriction ? Ce contrôleur empêche un nœud compromis de modifier des ressources qui ne lui appartiennent pas. Par exemple, un kubelet malveillant ne peut pas modifier les pods d’un autre nœud.
Contrôleurs de ressources
Section intitulée « Contrôleurs de ressources »Ces contrôleurs gèrent les quotas et les limites pour éviter qu’un namespace ne consomme toutes les ressources du cluster.
| Contrôleur | Type | Rôle | Activé par défaut |
|---|---|---|---|
| LimitRanger | Mutating + Validating | Applique les limites par défaut | ✅ |
| ResourceQuota | Validating | Vérifie les quotas namespace | ✅ |
| DefaultStorageClass | Mutating | Ajoute la StorageClass par défaut | ✅ |
LimitRanger en action : Si vous créez un pod sans spécifier de resources.limits, LimitRanger peut automatiquement ajouter des limites par défaut définies dans un objet LimitRange. C’est une mutation qui évite les pods sans limites qui pourraient consommer toutes les ressources d’un nœud.
ResourceQuota : Ce contrôleur valide que la création d’une ressource ne dépasse pas les quotas du namespace. Si votre namespace a une limite de 10 pods et que vous essayez d’en créer un 11ème, ResourceQuota le refuse.
Voir les contrôleurs actifs
Section intitulée « Voir les contrôleurs actifs »# Contrôleurs activés sur l'API Serverkubectl get pods -n kube-system kube-apiserver-* -o yaml | \ grep -A1 "enable-admission-plugins"
# Ou via le manifest (kubeadm)cat /etc/kubernetes/manifests/kube-apiserver.yaml | \ grep enable-admission-pluginsPod Security Admission (PSA)
Section intitulée « Pod Security Admission (PSA) »Le Pod Security Admission est l’admission controller qui applique les Pod Security Standards. Il est activé par défaut depuis Kubernetes 1.25.
Configuration
Section intitulée « Configuration »PSA se configure via des labels sur les namespaces :
apiVersion: v1kind: Namespacemetadata: name: production labels: # Niveau à appliquer pod-security.kubernetes.io/enforce: restricted # Version du standard (latest ou v1.xx) pod-security.kubernetes.io/enforce-version: latest # Mode audit (logs uniquement) pod-security.kubernetes.io/audit: restricted # Mode warn (affiche un warning) pod-security.kubernetes.io/warn: restrictedExemptions
Section intitulée « Exemptions »Certains workloads système nécessitent des privilèges (CNI, monitoring). Exemptez-les dans la configuration :
# /etc/kubernetes/psa.yaml (fichier de config API Server)apiVersion: apiserver.config.k8s.io/v1kind: AdmissionConfigurationplugins:- name: PodSecurity configuration: apiVersion: pod-security.admission.config.k8s.io/v1 kind: PodSecurityConfiguration defaults: enforce: "baseline" enforce-version: "latest" exemptions: usernames: [] runtimeClasses: [] namespaces: - kube-system - kube-node-leaseWebhooks personnalisés
Section intitulée « Webhooks personnalisés »Au-delà des contrôleurs intégrés, vous pouvez créer vos propres admission controllers via des webhooks.
ValidatingWebhookConfiguration
Section intitulée « ValidatingWebhookConfiguration »Refuse les ressources non conformes :
apiVersion: admissionregistration.k8s.io/v1kind: ValidatingWebhookConfigurationmetadata: name: require-labelswebhooks:- name: require-labels.example.com clientConfig: service: name: label-validator namespace: admission path: /validate caBundle: ${CA_BUNDLE} rules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"] admissionReviewVersions: ["v1"] sideEffects: None failurePolicy: Fail # Refuse si le webhook est indisponibleMutatingWebhookConfiguration
Section intitulée « MutatingWebhookConfiguration »Modifie automatiquement les ressources :
apiVersion: admissionregistration.k8s.io/v1kind: MutatingWebhookConfigurationmetadata: name: inject-sidecarwebhooks:- name: inject-sidecar.example.com clientConfig: service: name: sidecar-injector namespace: admission path: /mutate caBundle: ${CA_BUNDLE} rules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE"] resources: ["pods"] admissionReviewVersions: ["v1"] sideEffects: None failurePolicy: Ignore # Accepte si le webhook est indisponibleValidatingAdmissionPolicy (VAP)
Section intitulée « ValidatingAdmissionPolicy (VAP) »Depuis Kubernetes 1.30, ValidatingAdmissionPolicy permet de créer des politiques de validation sans webhook externe, directement avec des expressions CEL.
Avantages vs Webhooks
Section intitulée « Avantages vs Webhooks »Pourquoi utiliser VAP plutôt que des webhooks classiques ? La réponse tient en deux mots : simplicité et fiabilité.
Avec un webhook, vous devez déployer un service, gérer ses certificats TLS, assurer sa haute disponibilité, et maintenir le code. Si le webhook est down, vos déploiements peuvent être bloqués (avec failurePolicy: Fail) ou passer sans validation (avec Ignore).
VAP élimine ces problèmes : la validation s’exécute directement dans l’API Server, sans appel réseau externe.
| Critère | Webhooks | ValidatingAdmissionPolicy |
|---|---|---|
| Dépendance externe | Oui (service à maintenir) | Non (natif) |
| Latence | Variable (appel réseau) | Minimale |
| Langage | Go, Python, etc. | CEL |
| Complexité | Élevée | Faible à moyenne |
| Depuis K8s | 1.9+ | 1.30+ (stable) |
La contrepartie ? CEL est moins flexible que du code Go ou Python. Pour des validations simples (“ce champ doit exister”, “cette valeur est interdite”), VAP est parfait. Pour de la logique métier complexe ou des appels à des services externes, les webhooks restent nécessaires.
Exemple : interdire les pods privileged
Section intitulée « Exemple : interdire les pods privileged »apiVersion: admissionregistration.k8s.io/v1kind: ValidatingAdmissionPolicymetadata: name: deny-privilegedspec: failurePolicy: Fail matchConstraints: resourceRules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"] validations: - expression: "!object.spec.containers.exists(c, c.securityContext.privileged == true)" message: "Les conteneurs privileged sont interdits"---apiVersion: admissionregistration.k8s.io/v1kind: ValidatingAdmissionPolicyBindingmetadata: name: deny-privileged-bindingspec: policyName: deny-privileged validationActions: - Deny matchResources: namespaceSelector: matchExpressions: - key: environment operator: In values: ["production"]Comparatif des solutions Policy-as-Code
Section intitulée « Comparatif des solutions Policy-as-Code »Plusieurs outils permettent d’implémenter du policy-as-code sur Kubernetes. Comment choisir ? Cela dépend de votre contexte : préparation CKS, expertise de l’équipe, besoins fonctionnels.
| Solution | Type | Langage | Courbe d’apprentissage | CKS |
|---|---|---|---|---|
| Pod Security Admission | Intégré | Labels | Facile | ✅ |
| ValidatingAdmissionPolicy | Intégré | CEL | Moyenne | ✅ |
| Kyverno | Add-on | YAML | Facile | ⚠️ |
| OPA Gatekeeper | Add-on | Rego | Difficile | ⚠️ |
Comment lire ce tableau ?
- PSA est le point de départ : activez-le sur tous vos namespaces avec au minimum le niveau
baseline. C’est rapide et efficace. - VAP complète PSA pour des règles personnalisées que PSA ne couvre pas (ex: interdire certaines images, exiger des annotations spécifiques).
- Kyverno et Gatekeeper apportent des fonctionnalités avancées (mutation, génération de ressources, audit) mais ajoutent de la complexité opérationnelle.
Diagnostic et dépannage
Section intitulée « Diagnostic et dépannage »Voir les webhooks configurés
Section intitulée « Voir les webhooks configurés »# Webhooks de validationkubectl get validatingwebhookconfigurations
# Webhooks de mutationkubectl get mutatingwebhookconfigurations
# Détail d'un webhookkubectl describe validatingwebhookconfiguration <name>Erreurs courantes
Section intitulée « Erreurs courantes »“connection refused” ou timeout
Le webhook n’est pas accessible. Vérifiez :
- Le service existe et a des endpoints
- Le certificat CA est correct
- Le NetworkPolicy autorise le trafic depuis l’API Server
kubectl get endpoints -n <namespace> <service-name>kubectl describe service -n <namespace> <service-name>“failed to call webhook”
Le webhook retourne une erreur. Vérifiez les logs :
kubectl logs -n <namespace> -l app=<webhook-app>À retenir
Section intitulée « À retenir »- Admission Controllers : plugins qui interceptent les requêtes API avant persistance
- Mutating (modifie) → Validating (accepte/refuse) → etcd
- Pod Security Admission : contrôleur intégré pour les Pod Security Standards
- ValidatingAdmissionPolicy (K8s 1.30+) : validation native en CEL, sans webhook
- Webhooks : pour des cas complexes nécessitant de la logique métier
- CKS : focus sur PSA et VAP (natives), pas sur Kyverno/Gatekeeper