Aller au contenu
Conteneurs & Orchestration high
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Kyverno — Policy Engine Kubernetes en YAML et CEL

16 min de lecture

Logo Kubernetes

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.

  • 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

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.

KyvernoKubernetes supportéNotes
1.17.x1.32 – 1.35CRDs legacy deprecated, CEL-first
1.16.x1.31 – 1.34Dernière version avec CRDs stables

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.

BesoinOutil recommandéPourquoi
Validation simple, pas de dépendanceVAPNatif, GA depuis K8s 1.30
Profils sécurité standard (runAsNonRoot…)Pod Security Admission3 profils prêts à l’emploi
Mutation avancée (sidecars, defaults)KyvernoMutation mature et flexible
Génération automatique (NetworkPolicies)KyvernoFonctionnalité unique
Vérification signatures imagesKyvernoIntégration Cosign/Sigstore
Culture OPA/Rego existanteGatekeeperÉ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).

  • 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
  • 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

En production, déployez avec HA :

Fenêtre de terminal
helm install kyverno kyverno/kyverno \
--set admissionController.replicas=3 \
--set backgroundController.replicas=2 \
-n kyverno --create-namespace

Si Kyverno bloque le cluster :

Fenêtre de terminal
# Supprimer les webhooks en urgence
kubectl delete validatingwebhookconfiguration kyverno-resource-validating-webhook-cfg
kubectl delete mutatingwebhookconfiguration kyverno-resource-mutating-webhook-cfg
Fenêtre de terminal
# Ajouter le repo Helm
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
# Installer Kyverno avec HA
helm install kyverno kyverno/kyverno \
-n kyverno --create-namespace \
--set admissionController.replicas=2 \
--wait --timeout 5m

Vérifier l’installation :

Fenêtre de terminal
kubectl get pods -n kyverno
NAME READY STATUS RESTARTS AGE
kyverno-admission-controller-b469db77f-57xcn 1/1 Running 0 39s
kyverno-admission-controller-b469db77f-8k2lp 1/1 Running 0 39s
kyverno-background-controller-6674dc69f5-spbvp 1/1 Running 0 39s
kyverno-cleanup-controller-5bb56f66f4-psp8f 1/1 Running 0 39s
kyverno-reports-controller-647dd56678-56kmg 1/1 Running 0 39s

Cet exemple est directement aligné avec l’objectif CKS “Use appropriate pod security standards” :

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-run-as-non-root
spec:
background: true
rules:
- name: run-as-non-root
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- kyverno
validate:
failureAction: Enforce # Niveau règle (nouvelle syntaxe)
message: "Tous les conteneurs doivent avoir runAsNonRoot: true"
pattern:
spec:
containers:
- securityContext:
runAsNonRoot: true

Deux contrôles essentiels pour la sécurité des workloads :

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deny-host-access
spec:
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): false

Ce contrôle relie Kyverno au domaine Supply Chain Security de la CKS :

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
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) »
apiVersion: policies.kyverno.io/v1alpha1
kind: ImageValidatingPolicy
metadata:
name: verify-image-signature
spec:
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
attestors:
- name: my-cosign-key
cosign:
key:
secretRef:
name: cosign-public-key
namespace: kyverno
imageRules:
- glob: "gcr.io/my-project/*"
attestors:
- name: my-cosign-key
message: "Image must be signed with our Cosign key"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-cosign
spec:
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-----

La mutation permet de modifier automatiquement les ressources. C’est une fonctionnalité mature de Kyverno :

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-security-defaults
spec:
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): true

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érateurEffetUsage
(key)Ancre conditionnelleCibler des conteneurs spécifiques
+(key)Ajouter si absentDefaults non intrusifs
-(key)SupprimerRetirer des champs
=(key)Remplacer si existeForcer 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.

Fonctionnalité unique à Kyverno — créer des ressources automatiquement :

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-default-deny
spec:
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
- Egress

Effet : Chaque nouveau namespace reçoit automatiquement une NetworkPolicy default-deny.

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.

ValeurEffetPhase
EnforceBloque la requêteProduction
AuditLog dans PolicyReportsDécouverte

Stratégie recommandée :

  1. Démarrez avec Audit : Les violations sont enregistrées dans les PolicyReports. Regardez-les pour comprendre l’impact.
  2. Ajoutez des overrides : Passez à Enforce sur les namespaces critiques (production) tout en restant en Audit ailleurs.
  3. 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: "?*"

La CLI permet de tester les policies localement avant déploiement — essentiel pour un workflow shift-left :

Fenêtre de terminal
# Installer via Krew
kubectl krew install kyverno
# Tester une policy sur un manifeste
kyverno apply ./policy.yaml --resource ./deployment.yaml
# Exécuter une suite de tests
kyverno test ./policy-tests/
# Valider le parsing d'une policy
kyverno validate ./policy.yaml
Fenêtre de terminal
# Lister les policies
kubectl 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 violations
kubectl describe policyreport -n <namespace>
# Résumé rapide
kubectl get policyreport -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.summary}{"\n"}{end}'

Voici les problèmes les plus fréquents et comment les résoudre rapidement.

SymptômeCause probableSolution
Policy “Ready: False”Erreur de syntaxekubectl describe clusterpolicy
Pas de violation en Auditbackground: falseAjouter background: true
Mutation non appliquéePod déjà existantRecréer le pod
Webhook timeoutKyverno surchargéAugmenter replicas

Astuce : Le champ status.conditions d’une ClusterPolicy contient les messages d’erreur détaillés. Regardez-le en premier.

  1. Kyverno 1.17 migre vers CEL — CRDs ClusterPolicy/Policy deprecated
  2. validationFailureAction est deprecated → utilisez validate.failureAction au niveau règle
  3. Composant sensible — déployez avec HA, surveillez les webhooks
  4. Meilleur pont CKS : vérification d’images (Supply Chain Security)
  5. Si validation simple → préférez VAP (natif, pas de dépendance)
  6. Fonctionnalités uniques : génération et mutation mature

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn