Dans Kubernetes “Validating Admission Policy” est un mécanisme qui contrôle la conformité des manifestes lors de la création, la mise à jour ou la suppression de ressources. Ceci permet de valider la conformité à certaines règles avant que les ressources ne soient acceptées dans le cluster.

Les administrateurs peuvent donc définir et appliquer des politiques personnalisées pour s’assurer que les configurations et les déploiements respectent les standards et les exigences spécifiques de l’organisation.

Par exemple on peut vouloir vérifier lors de la phase d’admission d’un manifeste Kubernetes que certains Labels sont bien positionnés sur les ressources ou contrôler le nombre de réplicas demandé pour un déploiement.

Avant la version v1.30 de Kubernetes il fallait soit développer son propre webhook d’admission, soit déployer sur le cluster une solution comme Kyverno ou Kubewarden. Mais désormais Kubernetes embarque en version stable la fonctionnalité Validating Admission Policy qui permet d’effectuer nativement et de manière déclarative ce type de contrôles.

Cet article décrit 2 exemples d’utilisation.

Vérifier la présence de Labels

Dans cet exemple on déclare une politique permettant de s’assurer que certains Labels sont bien présents sur les Deployments et les Pods qui seront déployés sur le cluster.

Fichier check-mandatory-labels.validatingadmissionpolicy.yaml

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: check-mandatory-labels
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments","replicasets", "pod"]
  validations:
    - expression: "'owner' in object.metadata.labels && object.metadata.labels.owner.matches('.*')"
      message: "Label 'owner' must be set with non-empty value."
    - expression: "'environment' in object.metadata.labels && object.metadata.labels.environment.matches('^dev$|^preprod$|^prod$')"
      message: "Label 'environment' must be set with one of the following values: 'dev', 'preprod', 'prod'."

Cette polique définit qu’on veut la présence :

  • du Label owner avec une valeur non vide,
  • du Label environment avec une des valeurs suivantes : dev, preprod ou prod.

Notons que les expressions permettant la validation sont définies à l’aide du Common Expression Language (CEL). Le site CEL Playground fournit un environnement permettant de tester facilement en ligne des expressions CEL. La documentation de Kubernetes propose également une page décrivant l’utilisation du langage CEL dans Kubernetes.

La seconde étape consiste à ajouter un binding pour indiquer à quel niveau on souhaite appliquer la politique. Par exemple le fichier suivant permet de dire qu’on appliquera la politique sur toutes les ressources soumises dans les Namespaces qui portent le Label policies: enforce :

Fichier check-mandatory-labels.validatingadmissionpolicybinding.yaml

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: check-mandatory-labels
spec:
  policyName: check-mandatory-labels
  validationActions: [Deny]
  matchResources:
    namespaceSelector:
      matchLabels:
        policies: enforce # Applies on all namespaces that have this label

Pour tester il nous faut donc créer un namespace qui portera le Label policies: enforce :

Fichier my-namespace.ns.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace
  labels:
    policies: enforce

Appliquons nos trois ressources :

kubectl apply -f check-mandatory-labels.validatingadmissionpolicy.yaml
kubectl apply -f check-mandatory-labels.validatingadmissionpolicybinding.yaml
kubectl apply -f my-namespace.ns.yaml

Et essayons maitenant de déployer une application dans le namespace my-namespace à l’aide du fichier my-app.deployment.yaml suivant :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: my-namespace
  labels:
    app: my-app
    # owner: bob
    # environment: dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        # owner: bob
        # environment: dev
    spec:
      containers:
      - image: xian310/who-is-there:25
        name: who-is-there
kubectl apply -f manifests/my-app.deployment.yaml 
The deployments "my-app" is invalid: : 
ValidatingAdmissionPolicy 'check-mandatory-labels' 
with binding 'check-mandatory-labels' denied request: 
Label 'owner' must be set with non-empty value.

La ressource est refusée et un message indiquant la raison du refus est affiché.

Si on décommente les 4 lignes commentées et qu’on ré-applique le fichier, la ressource sera acceptée sur le cluster.

Contrôler le nombre de réplicas

Dans cet autre exemple nous ajoutons une politique pour contrôler le nombre de réplicas d’un Deployment :

Fichier check-min-replicas-count.validatingadmissionpolicy.yaml

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: check-min-replicas-count
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments","replicasets"]
  validations:
    - expression: "object.spec.replicas >= 3"
      messageExpression: "'Replicas count must be at least 3 ; ' + string(object.spec.replicas) +' provided.'"

Notons, qu’ici on fait usage de messageExpression au lieu de de message pour pouvoir indiquer dans le message à retourner le nombre de réplicas soumis.

Puis comme précédemment nous créons l’objet de binding pour indiquer les Namespaces concernés par cette politique :

Fichier check-min-replicas-count.validatingadmissionpolicybinding.yaml

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: check-min-replicas-count
spec:
  policyName: check-min-replicas-count
  validationActions: [Deny]
  matchResources:
    namespaceSelector:
      matchLabels:
        policies: enforce # Applies on all namespaces that have this label

Après avoir appliqué ces deux nouveaux fichiers, essayons de soumettre notre Deployment :

kubectl apply -f manifests/my-app.deployment.yaml 
The deployments "my-app" is invalid: : 
ValidatingAdmissionPolicy 'check-min-replicas-count' 
with binding 'check-min-replicas-count' denied request: 
Replicas count must be at least 3 ; 1 provided.

A nouveau la ressource est refusée avec un message explicite.