
Kyverno est un policy engine Kubernetes qui permet de valider, muter, générer des ressources et vérifier les signatures d'images. Projet CNCF Incubating, Kyverno utilise des policies YAML et supporte CEL. Ce guide est utile en complément d'une préparation CKS pour traduire les exigences sécurité en policies concrètes.
Un mot sur le positionnement par rapport à la CKS : le curriculum de la certification ne cite pas Kyverno comme compétence requise. Il mentionne Pod Security Standards, registries autorisées, signature et validation d'artefacts et analyse statique. Kyverno est un outil pratique pour implémenter ces exigences sur un cluster réel, mais ce n'est pas un sujet d'examen en soi.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Quand utiliser Kyverno (et quand ne pas l'utiliser)
- Installer Kyverno et comprendre sa complexité opérationnelle
- Créer des policies de validation orientées sécurité
- Vérifier les signatures d'images (Supply Chain Security)
- Diagnostiquer les violations avec les PolicyReports
Compatibilité et versions
Section intitulée « Compatibilité et versions »Kyverno suit un cycle de versions aligné avec Kubernetes. Chaque version majeure de Kyverno supporte plusieurs versions de Kubernetes, mais les fonctionnalités varient. Voici les versions actuelles.
| Kyverno | Kubernetes officiellement supporté | Notes |
|---|---|---|
| 1.18.x | 1.33 – 1.35 | Branche courante, publiée le 29 avril 2026 |
| 1.17.x | En fin de support depuis la sortie de 1.18 | CRD legacy kyverno.io/v1 marquées deprecated |
Le support communautaire dure environ trois mois par branche mineure : la sortie de la version n+1 met fin aux correctifs de la version n. Les versions de Kubernetes hors de la plage annoncée peuvent fonctionner, mais elles ne sont pas testées par le projet et aucune garantie n'est donnée.
Quand utiliser Kyverno
Section intitulée « Quand utiliser Kyverno »Chaque outil a son domaine d'excellence. Ce tableau vous aide à choisir en fonction de votre besoin réel, pas de la popularité de l'outil.
| Besoin | Outil recommandé | Pourquoi |
|---|---|---|
| Validation simple, pas de dépendance | VAP | Natif, GA depuis K8s 1.30 |
| Profils sécurité standard (runAsNonRoot...) | Pod Security Admission | 3 profils prêts à l'emploi |
| Mutation avancée (sidecars, defaults) | Kyverno | Mutation mature et flexible |
| Génération automatique (NetworkPolicies) | Kyverno | Fonctionnalité unique |
| Vérification signatures images | Kyverno | Intégration Cosign/Sigstore |
| Culture OPA/Rego existante | Gatekeeper | Écosystème Rego |
Règle de décision simple : Si vous avez besoin de mutation ou de génération, Kyverno est très probablement le bon choix. Sinon, commencez par les solutions natives (PSA, VAP).
Ce que Kyverno fait mieux
Section intitulée « Ce que Kyverno fait mieux »Trois de ces quatre capacités n'ont aucun équivalent natif dans Kubernetes : l'API server sait refuser une ressource avec une ValidatingAdmissionPolicy, mais il ne sait ni la modifier, ni en créer une autre en réaction, ni interroger un registry pour vérifier une signature. C'est ce qui justifie d'ajouter une dépendance au control plane.
- Mutation : injecter sidecars, ajouter labels/annotations, defaults
- Génération : créer automatiquement NetworkPolicies, Secrets, ResourceQuotas
- Vérification d'images : Cosign, Sigstore, attestations SLSA
- PolicyReports : audit de conformité natif
Quand ne PAS utiliser Kyverno
Section intitulée « Quand ne PAS utiliser Kyverno »Le point commun de ces quatre situations est le rapport bénéfice / dette d'exploitation. Chaque webhook ajouté au cluster est un composant à maintenir, à mettre à jour au rythme de Kubernetes et à surveiller. Si le besoin se couvre avec un mécanisme déjà présent dans l'API server, l'ajout de Kyverno coûte plus qu'il ne rapporte.
- Validation simple sans mutation → préférez VAP (natif, pas de dépendance)
- Profils sécurité standards → préférez Pod Security Admission (plus simple)
- Cluster sans HA → Kyverno est un webhook d'admission, composant sensible
- Équipe déjà formée à Rego → préférez Gatekeeper
Complexité opérationnelle
Section intitulée « Complexité opérationnelle »Installer Kyverno revient à insérer un composant entre l'API server et toutes les écritures de ressources du cluster. Cette position explique l'essentiel de ses contraintes d'exploitation : sa disponibilité conditionne celle des déploiements, ses certificats TLS ont une durée de vie limitée, et ses droits RBAC couvrent une large partie du cluster. Avant d'écrire une seule policy, il faut donc décider comment le cluster se comporte quand Kyverno est indisponible.
En production, déployez avec HA :
helm install kyverno kyverno/kyverno \ --set admissionController.replicas=3 \ --set backgroundController.replicas=2 \ -n kyverno --create-namespaceSi Kyverno bloque le cluster :
# Supprimer les webhooks en urgencekubectl delete validatingwebhookconfiguration kyverno-resource-validating-webhook-cfgkubectl delete mutatingwebhookconfiguration kyverno-resource-mutating-webhook-cfgInstallation
Section intitulée « Installation »Deux méthodes coexistent, et le choix n'est pas cosmétique. Le chart Helm expose les réglages
de production (nombre de réplicas par contrôleur, ressources, exclusions de namespaces) et permet
une mise à jour maîtrisée. Le manifeste install.yaml déploie une configuration figée, pratique
pour un cluster jetable mais difficile à personnaliser ensuite. Dans les deux cas, Kyverno doit
vivre dans un namespace dédié : le projet interdit explicitement de le cohabiter avec d'autres
applications, y compris kube-system.
# Ajouter le repo Helmhelm repo add kyverno https://kyverno.github.io/kyverno/helm repo update
# Installer Kyverno avec HAhelm install kyverno kyverno/kyverno \ -n kyverno --create-namespace \ --set admissionController.replicas=2 \ --wait --timeout 5mkubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.18.2/install.yamlVérifier l'installation :
kubectl get pods -n kyvernoNAME READY STATUS RESTARTS AGEkyverno-admission-controller-b469db77f-57xcn 1/1 Running 0 39skyverno-admission-controller-b469db77f-8k2lp 1/1 Running 0 39skyverno-background-controller-6674dc69f5-spbvp 1/1 Running 0 39skyverno-cleanup-controller-5bb56f66f4-psp8f 1/1 Running 0 39skyverno-reports-controller-647dd56678-56kmg 1/1 Running 0 39sExemple 1 : Exiger runAsNonRoot (CKS-ready)
Section intitulée « Exemple 1 : Exiger runAsNonRoot (CKS-ready) »Cet exemple est directement aligné avec l'objectif CKS « Use appropriate pod security standards ».
Les deux onglets produisent le même refus, mais par des chemins très différents : la version
CEL évalue une expression booléenne sur l'objet soumis, alors que la version historique compare la
ressource à un motif YAML que Kyverno applique récursivement. La version CEL gagne sur la
lisibilité des conditions complexes, notamment l'exclusion des namespaces système, qui tient ici en
une seule ligne matchConditions.
apiVersion: policies.kyverno.io/v1kind: ValidatingPolicymetadata: name: require-run-as-non-rootspec: validationActions: [Deny] matchConstraints: resourceRules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"] matchConditions: - name: exclude-system-ns expression: >- !(['kube-system','kyverno'].exists(ns, object.metadata.namespace == ns)) validations: - expression: >- object.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.runAsNonRoot) && c.securityContext.runAsNonRoot == true ) message: "Tous les conteneurs doivent avoir runAsNonRoot: true."apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: require-run-as-non-rootspec: # DEPRECATED: utilisez spec.rules[*].validate.failureAction validationFailureAction: Enforce background: true rules: - name: run-as-non-root match: any: - resources: kinds: - Pod validate: message: "Tous les conteneurs doivent avoir runAsNonRoot: true" pattern: spec: containers: - securityContext: runAsNonRoot: trueExemple 2 : Refuser hostPath et hostNetwork
Section intitulée « Exemple 2 : Refuser hostPath et hostNetwork »Ces trois règles ferment les portes qui donnent au conteneur un accès direct au nœud : un
volume hostPath monte un répertoire de l'hôte dans le pod, hostNetwork place le pod dans
l'espace réseau du nœud, hostPID et hostIPC lui donnent la visibilité sur les processus et la
mémoire partagée de l'hôte. Chaque règle est indépendante et échoue séparément, ce qui rend le
diagnostic lisible : Kyverno indique le chemin exact qui a déclenché le refus, par exemple
rule deny-hostpath failed at path /spec/volumes/0/hostPath/.
Notez l'ancre =(volumes) : elle rend le contrôle conditionnel. Un pod sans aucun volume
passe la règle au lieu d'échouer sur un champ absent.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: deny-host-accessspec: background: true rules: - name: deny-hostpath match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "Les volumes hostPath sont interdits" pattern: spec: =(volumes): - X(hostPath): "null" - name: deny-host-network match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "hostNetwork n'est pas autorisé" pattern: spec: =(hostNetwork): false - name: deny-host-pid-ipc match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "hostPID et hostIPC sont interdits" pattern: spec: =(hostPID): false =(hostIPC): falseExemple 3 : Limiter les registries autorisées
Section intitulée « Exemple 3 : Limiter les registries autorisées »Ce contrôle relie Kyverno au domaine Supply Chain Security de la CKS. La boucle foreach
parcourt chaque conteneur du pod, ce qui évite l'angle mort classique d'une règle qui ne
vérifierait que le premier. Attention au piège de l'image sans registry explicite : un
manifeste qui demande nginx:1.29.2 ne correspond à aucun des motifs autorisés et sera refusé,
alors que l'image proviendrait bien de Docker Hub. Le développeur doit écrire
docker.io/library/nginx:1.29.2 pour passer la règle, ce qui est précisément l'effet recherché,
mais il faut l'expliquer dans le message d'erreur.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: restrict-image-registriesspec: background: true rules: - name: validate-registries match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "Images autorisées uniquement depuis gcr.io ou docker.io/library" foreach: - list: "request.object.spec.containers" deny: conditions: all: - key: "{{ element.image }}" operator: AnyNotIn value: - "gcr.io/*" - "docker.io/library/*"Vérification des signatures d'images (Supply Chain)
Section intitulée « Vérification des signatures d'images (Supply Chain) »Vérifier une signature à l'admission déplace le contrôle au dernier moment utile : peu importe ce qui s'est passé dans la chaîne de build, une image non signée par la clé attendue n'entre pas dans le cluster. Kyverno résout la référence d'image auprès du registry, récupère la signature Cosign associée et la valide contre la clé publique déclarée dans la policy. Conséquence directe à anticiper : le contrôleur d'admission a besoin d'un accès réseau sortant vers le registry, et un registry privé impose de lui fournir des identifiants de lecture.
Avec les nouveaux policy types CEL (1.17+)
Section intitulée « Avec les nouveaux policy types CEL (1.17+) »ImageValidatingPolicy sépare deux préoccupations que la syntaxe historique mélangeait. Le bloc
attestors déclare qui a le droit de signer, ici via une clé publique stockée dans un Secret
Kubernetes ; le bloc validations décrit ce qu'on exige de l'image une fois la signature
vérifiée. L'expression "true" de l'exemple signifie donc « la signature suffit » : c'est là
qu'on ajouterait une condition sur une attestation SLSA ou sur le contenu d'un SBOM.
apiVersion: policies.kyverno.io/v1kind: ImageValidatingPolicymetadata: name: verify-image-signaturespec: validationActions: [Deny] matchConstraints: resourceRules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"] matchImageReferences: - glob: "gcr.io/my-project/*" attestors: - name: my-cosign-key cosign: key: secretRef: name: cosign-public-key namespace: kyverno validations: - expression: "true" message: "Image must be signed with our Cosign key."Avec ClusterPolicy legacy
Section intitulée « Avec ClusterPolicy legacy »La règle verifyImages inscrit la clé publique en clair dans la policy, ce qui reste
acceptable puisqu'une clé publique n'est pas un secret, mais complique la rotation : changer de
clé oblige à modifier chaque policy concernée. Le background: false n'est pas un détail :
vérifier des signatures suppose des appels réseau vers le registry, opération trop coûteuse pour
être rejouée en tâche de fond sur toutes les ressources existantes.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: verify-image-cosignspec: background: false rules: - name: verify-signature match: any: - resources: kinds: - Pod verifyImages: - imageReferences: - "gcr.io/my-project/*" attestors: - entries: - keys: publicKeys: | -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE... -----END PUBLIC KEY-----Mutation : ajouter des defaults
Section intitulée « Mutation : ajouter des defaults »La mutation permet de modifier automatiquement les ressources. C'est une fonctionnalité mature de Kyverno :
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: add-security-defaultsspec: background: false # Mutation = pas de background rules: - name: add-security-context match: any: - resources: kinds: - Pod mutate: patchStrategicMerge: spec: containers: - (name): "*" securityContext: +(runAsNonRoot): true +(allowPrivilegeEscalation): false +(readOnlyRootFilesystem): trueOpérateurs de mutation
Section intitulée « Opérateurs de mutation »La syntaxe de mutation Kyverno utilise des opérateurs spéciaux pour contrôler le comportement. Comprendre ces opérateurs est essentiel pour écrire des mutations efficaces.
| Opérateur | Effet | Usage |
|---|---|---|
(key) | Ancre conditionnelle | Cibler des conteneurs spécifiques |
+(key) | Ajouter si absent | Defaults non intrusifs |
-(key) | Supprimer | Retirer des champs |
=(key) | Remplacer si existe | Forcer une valeur |
Exemple concret : Si vous voulez ajouter runAsNonRoot: true uniquement aux pods qui n'ont pas déjà cette valeur, utilisez +(runAsNonRoot): true. Cela évite de surcharger une configuration explicite du développeur.
Génération : NetworkPolicies automatiques
Section intitulée « Génération : NetworkPolicies automatiques »La génération répond à un problème récurrent : une ressource de sécurité doit exister dans chaque
namespace, mais personne ne pense à la créer. Ici, la création d'un namespace déclenche la
création d'une NetworkPolicy qui bloque tout le trafic entrant et sortant par défaut. Le champ
synchronize: true change le contrat : Kyverno ne se contente pas de créer la ressource, il la
remet en état si quelqu'un la modifie ou la supprime. C'est ce qui distingue la génération
d'un simple script d'initialisation.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: generate-default-denyspec: rules: - name: create-network-policy match: any: - resources: kinds: - Namespace exclude: any: - resources: namespaces: - kube-system - kyverno generate: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy name: default-deny namespace: "{{request.object.metadata.name}}" synchronize: true data: spec: podSelector: {} policyTypes: - Ingress - EgressEffet : Chaque nouveau namespace reçoit automatiquement une NetworkPolicy default-deny.
failureAction et déploiement progressif
Section intitulée « failureAction et déploiement progressif »Déployer une policy directement en mode bloquant (Enforce) est risqué. Kyverno permet un déploiement progressif avec deux modes et des overrides par namespace.
| Valeur | Effet | Phase |
|---|---|---|
Enforce | Bloque la requête | Production |
Audit | Log dans PolicyReports | Découverte |
Stratégie recommandée :
- Démarrez avec
Audit: Les violations sont enregistrées dans les PolicyReports. Regardez-les pour comprendre l'impact. - Ajoutez des overrides : Passez à
Enforcesur les namespaces critiques (production) tout en restant enAuditailleurs. - Généralisez
Enforce: Une fois tous les workloads conformes, passez globalement en mode bloquant.
Stratégie progressive avec overrides :
spec: rules: - name: require-labels match: any: - resources: kinds: - Pod validate: failureAction: Audit # Permissif par défaut failureActionOverrides: - action: Enforce namespaces: - production # Strict en production message: "Le label 'app' est obligatoire" pattern: metadata: labels: app: "?*"Kyverno CLI (shift-left)
Section intitulée « Kyverno CLI (shift-left) »La CLI permet de tester les policies localement avant déploiement, sans cluster, ce qui la
rend utilisable dans un job de pipeline. Deux commandes couvrent l'essentiel : kyverno apply
évalue une policy contre un ou plusieurs manifestes et affiche le compte
pass / fail / warn / error / skip, tandis que kyverno test exécute une suite de cas décrite
dans un fichier kyverno-test.yaml. La commande apply sert aussi de contrôle syntaxique :
une policy mal formée remonte en error avant même d'atteindre le cluster.
# Installer via Krewkubectl krew install kyverno
# Tester une policy sur un manifestekyverno apply ./policy.yaml --resource ./deployment.yaml
# Générer un fichier de test à partir d'une policy et d'une ressourcekyverno create test -p policy.yaml -r deployment.yaml \ --pass require-run-as-non-root,run-as-non-root,api-paiement,production,Pod
# Exécuter une suite de testskyverno test ./policy-tests/La sortie de kyverno apply sur un pod qui viole la policy de l'exemple 1 ressemble à ceci :
Applying 1 policy rule(s) to 1 resource(s)...policy require-run-as-non-root -> resource equipe-web/Pod/nginx-sans-securite failed:1 - Tous les conteneurs doivent avoir runAsNonRoot: true.
pass: 0, fail: 1, warn: 0, error: 0, skip: 0Un réflexe fréquent consiste à chercher une commande kyverno validate pour contrôler la syntaxe :
elle n'existe pas. La CLI 1.18 expose exactement apply, create, docs, jp, json,
migrate, test et version. Pour détecter une policy invalide, passez par kyverno apply.
Diagnostiquer les policies
Section intitulée « Diagnostiquer les policies »Commandes essentielles
Section intitulée « Commandes essentielles »Le diagnostic suit deux pistes distinctes qu'il ne faut pas confondre. La première concerne la
policy elle-même : est-elle acceptée par Kyverno ? La réponse est dans kubectl describe, au
niveau du champ status.conditions. La seconde concerne les ressources évaluées : quelles
violations ont été relevées ? Elles vivent dans les PolicyReports, une ressource par namespace,
alimentée seulement si la policy est en mode Audit ou si background: true est actif.
# Lister les policieskubectl get clusterpolicies,policies -A
# Détails d'une policy (erreurs, conditions)kubectl describe clusterpolicy <name>
# PolicyReports (violations par namespace)kubectl get policyreport -A
# Détail des violationskubectl describe policyreport -n <namespace>
# Résumé rapidekubectl get policyreport -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.summary}{"\n"}{end}'Erreurs courantes
Section intitulée « Erreurs courantes »Voici les problèmes les plus fréquents et comment les résoudre rapidement.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Policy "Ready: False" | Erreur de syntaxe | kubectl describe clusterpolicy |
| Pas de violation en Audit | background: false | Ajouter background: true |
| Mutation non appliquée | Pod déjà existant | Recréer le pod |
| Webhook timeout | Kyverno surchargé | Augmenter replicas |
Astuce : Le champ status.conditions d'une ClusterPolicy contient les messages d'erreur détaillés. Regardez-le en premier.
À retenir
Section intitulée « À retenir »- Les CRD
ClusterPolicyetCleanupPolicysont deprecated depuis la 1.17, leur suppression est planifiée pour la v1.20 (estimée octobre 2026) validationFailureActionest deprecated → utilisezvalidate.failureActionau niveau règle- Composant sensible, déployez avec HA, surveillez les webhooks
- Meilleur pont CKS : vérification d'images (Supply Chain Security)
- Si validation simple → préférez VAP (natif, pas de dépendance)
- Fonctionnalités uniques : génération et mutation mature
kyverno validaten'existe pas : la CLI se contrôle aveckyverno applyetkyverno test
Testez vos connaissances
Section intitulée « Testez vos connaissances »Ces questions portent uniquement sur ce guide : le positionnement de Kyverno face aux solutions natives, la syntaxe des policies de validation et de mutation, et la lecture des PolicyReports.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications