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.