Kyverno : les politiques Kubernetes en YAML
Kyverno est un moteur de politiques cloud-native conçu spécifiquement pour Kubernetes. Contrairement à OPA/Gatekeeper qui requiert Rego (un langage de requête dédié), Kyverno exprime ses politiques directement en YAML — le même langage que les manifests Kubernetes.
Kyverno agit comme un admission controller Kubernetes et opère en trois modes :
- Validate — refuse les ressources qui ne respectent pas les règles
- Mutate — modifie automatiquement les ressources à la création/mise à jour
- Generate — crée automatiquement des ressources liées (ex. NetworkPolicy par namespace)
Sur OpenShift, Kyverno complète les Security Context Constraints (SCC) en apportant une gouvernance métier fine que les SCC ne couvrent pas.
Installation via Helm
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
oc create namespace kyverno
# Installation en mode HA (3 replicas)
helm install kyverno kyverno/kyverno \
--namespace kyverno \
--set replicaCount=3 \
--set admissionController.replicas=3 \
--set backgroundController.replicas=2 \
--set cleanupController.replicas=2 \
--set reportsController.replicas=2 \
--version 3.3.0
Vérifier l’installation :
oc get pods -n kyverno
oc get clusterpolicy
ClusterPolicy vs Policy
- ClusterPolicy — s’applique à tous les namespaces
- Policy — s’applique uniquement dans le namespace où elle est définie
# Anatomie d'une ClusterPolicy
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: ma-politique
annotations:
policies.kyverno.io/title: Titre lisible
policies.kyverno.io/description: Description de la politique
policies.kyverno.io/severity: medium # low | medium | high | critical
spec:
validationFailureAction: Enforce # Enforce | Audit
background: true # Vérifier aussi les ressources existantes
rules:
- name: nom-de-la-regle
match:
any:
- resources:
kinds: [Pod]
validate:
message: "Message d'erreur affiché à l'utilisateur"
pattern:
spec:
# Pattern à respecter
Politiques de validation essentielles
Interdire les conteneurs privileged
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
annotations:
policies.kyverno.io/title: Disallow Privileged Containers
policies.kyverno.io/severity: high
spec:
validationFailureAction: Enforce
background: true
rules:
- name: privileged-containers
match:
any:
- resources:
kinds: [Pod]
exclude:
any:
- resources:
namespaces: [kyverno, openshift-*, kube-*]
validate:
message: "Privileged containers are not allowed."
pattern:
spec:
=(initContainers):
- =(securityContext):
=(privileged): "false"
containers:
- =(securityContext):
=(privileged): "false"
Forcer les limites de ressources
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
annotations:
policies.kyverno.io/severity: medium
spec:
validationFailureAction: Enforce
background: true
rules:
- name: check-resource-limits
match:
any:
- resources:
kinds: [Pod]
exclude:
any:
- resources:
namespaces: [kube-system, openshift-*, kyverno]
validate:
message: "Resource limits (CPU and memory) are required for all containers."
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
requests:
memory: "?*"
cpu: "?*"
Interdire les images :latest
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
annotations:
policies.kyverno.io/severity: medium
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-image-tag
match:
any:
- resources:
kinds: [Pod]
exclude:
any:
- resources:
namespaces: [kube-system, openshift-*]
validate:
message: "Using ':latest' tag or no tag is not allowed. Specify an explicit image tag."
foreach:
- list: "request.object.spec.containers"
pattern:
image: "!*:latest & ?*:*"
Politiques de mutation
Ajouter automatiquement des labels
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-default-labels
spec:
rules:
- name: add-labels-to-pods
match:
any:
- resources:
kinds: [Pod]
mutate:
patchStrategicMerge:
metadata:
labels:
+(managed-by): kyverno
+(app.kubernetes.io/managed-by): kyverno
Injecter des tolérances pour les nœuds dédiés
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-gpu-toleration
spec:
rules:
- name: add-toleration
match:
any:
- resources:
kinds: [Pod]
namespaces: [gpu-workloads]
mutate:
patchStrategicMerge:
spec:
tolerations:
- (key): nvidia.com/gpu
+(effect): NoSchedule
+(operator): Exists
Définir une registry de confiance
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: replace-image-registry
spec:
rules:
- name: replace-docker-hub
match:
any:
- resources:
kinds: [Pod]
mutate:
foreach:
- list: "request.object.spec.containers"
patchStrategicMerge:
spec:
containers:
- (name): "{{ element.name }}"
image: "{{ regex_replace_all('^docker.io/', '{{element.image}}', 'registry.entreprise.com/proxy-dockerhub/') }}"
Generate : créer des ressources automatiquement
Kyverno peut générer automatiquement des ressources dans chaque nouveau namespace.
Générer une NetworkPolicy par défaut
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-default-networkpolicy
spec:
rules:
- name: default-deny-ingress
match:
any:
- resources:
kinds: [Namespace]
exclude:
any:
- resources:
namespaces: [kube-system, openshift-*, kyverno]
generate:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
name: default-deny-ingress
namespace: "{{request.object.metadata.name}}"
synchronize: true # Resynchronise si la policy est supprimée
data:
spec:
podSelector: {}
policyTypes:
- Ingress
Générer un ResourceQuota par namespace
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-namespace-quota
spec:
rules:
- name: create-quota
match:
any:
- resources:
kinds: [Namespace]
selector:
matchLabels:
team: "?*"
generate:
apiVersion: v1
kind: ResourceQuota
name: default-quota
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
persistentvolumeclaims: "10"
pods: "50"
Vérification de conformité (PolicyReport)
Kyverno génère des PolicyReports qui permettent d’auditer la conformité des ressources existantes sans bloquer les déploiements.
# Voir les rapports par namespace
oc get policyreport -n mon-app
# Voir les rapports cluster-wide
oc get clusterpolicyreport
# Détail d'un rapport
oc get policyreport -n mon-app -o yaml | \
yq '.results[] | select(.result == "fail")'
Mode Audit vs Enforce
En production, commencer par Audit pour mesurer l’impact avant de passer à Enforce :
# Passer toutes les policies en Audit d'abord
for policy in $(oc get clusterpolicy -o name); do
oc patch $policy \
--type=json \
-p '[{"op":"replace","path":"/spec/validationFailureAction","value":"Audit"}]'
done
# Vérifier les violations sans bloquer
oc get clusterpolicyreport -o json | \
jq '[.items[].results[] | select(.result=="fail")] | length'
Conclusion
Kyverno apporte une couche de gouvernance essentielle sur OpenShift, complémentaire aux SCC. Son approche YAML-native le rend accessible aux équipes qui maîtrisent Kubernetes sans nécessiter d’apprentissage d’un nouveau langage. La combinaison Validate + Mutate + Generate couvre l’ensemble du cycle de vie des ressources, tandis que les PolicyReports offrent une visibilité continue sur la conformité du cluster.