Note de traduction.: Avec l'augmentation du nombre de configurations YAML pour les environnements K8s, la nécessité de leur vérification automatisée devient de plus en plus pertinente. L'auteur de cette revue n'a pas seulement sélectionné les solutions existantes pour ce défi, mais a également examiné, à travers le déploiement, comment elles fonctionnent. Cela s'est avéré trÚs informatif pour ceux que ce sujet intéresse.

TL;DR: Cet article compare six outils d'analyse statique pour vérifier et évaluer les fichiers YAML de Kubernetes en fonction des meilleures pratiques et exigences.
Les charges de travail Kubernetes sont généralement définies sous forme de documents YAML. L'un des problÚmes avec YAML est la complexité de la définition des contraintes ou des relations entre les fichiers de manifestes.
Que faire si nous devons nous assurer que toutes les images déployées dans le cluster proviennent d'un registre de confiance ?
Comment empĂȘcher l'envoi dans le cluster des dĂ©ploiements pour lesquels aucun PodDisruptionBudget n'est dĂ©fini ?
L'intégration des tests statiques permet de détecter les erreurs et les violations de politiques dÚs la phase de développement. Cela augmente ainsi les garanties de validité et de sécurité des définitions des ressources, et accroßt la probabilité que les charges de production suivent les meilleures pratiques.
L'Ă©cosystĂšme de vĂ©rification statique des fichiers YAML de Kubernetes peut ĂȘtre divisĂ© en plusieurs catĂ©gories :
- Validateurs API. Les outils de cette catégorie vérifient si le manifeste YAML répond aux exigences du serveur API Kubernetes.
- Testeurs prĂȘts Ă l'emploi. Les outils de cette catĂ©gorie viennent avec des tests prĂȘts Ă l'emploi sur la sĂ©curitĂ©, la conformitĂ© aux meilleures pratiques, etc.
- Validateurs personnalisés. Les représentants de cette catégorie permettent de créer des tests personnalisés dans divers langages, tels que Rego et Javascript.
Dans cet article, nous allons décrire et comparer six outils différents :
- kubeval;
- kube-score;
- config-lint;
- copper;
- conftest;
- Polaris.
Alors, commençons !
Vérification des déploiements
Avant d'entamer la comparaison des outils, créons une base sur laquelle nous allons les tester.
Le manifeste ci-dessous contient plusieurs erreurs et non-conformités aux meilleures pratiques : combien d'entre elles pourrez-vous trouver ?
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo(base-valid.yaml)
Nous allons utiliser ce YAML pour comparer différents outils.
Le manifeste ci-dessus
base-valid.yamlet d'autres manifestes de cet article peuvent ĂȘtre trouvĂ©s dans .
Le manifeste dĂ©crit une application web dont la principale tĂąche est de rĂ©pondre avec le message «Hello World» sur le port 5678. Il peut ĂȘtre dĂ©ployĂ© avec la commande suivante :
kubectl apply -f hello-world.yamlEt voici comment vérifier si ça fonctionne :
kubectl port-forward svc/http-echo 8080:5678Maintenant, allez sur et confirmez que l'application fonctionne. Mais respecte-t-elle les meilleures pratiques ? Vérifions.
1. Kubeval
Au cĆur de se trouve l'idĂ©e que toute interaction avec Kubernetes passe par son API REST. En d'autres termes, il est possible d'utiliser le schĂ©ma API pour vĂ©rifier si le YAML donnĂ© y correspond. Regardons un exemple.
de kubeval sont disponibles sur le site du projet.
Au moment de la rédaction de l'article original, la version 0.15.0 était disponible.
AprĂšs l'installation, fournissons-lui le manifeste ci-dessus :
$ kubeval base-valid.yaml
PASS - base-valid.yaml contient un Deployment valide (http-echo)
PASS - base-valid.yaml contient un Service valide (http-echo)En cas de succÚs, kubeval terminera avec un code de sortie 0. On peut vérifier cela de la maniÚre suivante :
$ echo $?
0Essayons maintenant kubeval avec un autre manifeste :
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo(kubeval-invalid.yaml)
Pouvez-vous identifier le problĂšme Ă l'Ćil nu ? ExĂ©cutons :
$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml contient un Deployment invalide (http-echo) - selector: le sélecteur est requis
PASS - kubeval-invalid.yaml contient un Service valide (http-echo)
# vérifions le code de retour
$ echo $?
1La ressource ne passe pas la validation.
Les Deployments utilisant une version de l'API apps/v1, doivent inclure un sélecteur correspondant à l'étiquette du pod. Le manifeste ci-dessus n'inclut pas de sélecteur, c'est pourquoi kubeval a signalé une erreur et s'est terminé avec un code non nul.
Je me demande ce qui se passerait si nous exécutons kubectl apply -f avec ce manifeste ?
Eh bien, essayons :
$ kubectl apply -f kubeval-invalid.yaml
error: error validating "kubeval-invalid.yaml": erreur de validation des données: ValidationError(Deployment.spec):
champ obligatoire "selector" manquant dans io.k8s.api.apps.v1.DeploymentSpec ; si vous choisissez d'ignorer ces erreurs,
désactivez la validation avec --validate=falseC'est exactement l'erreur dont kubeval avertissait. Vous pouvez la corriger en ajoutant un sélecteur :
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector: # !!!
matchLabels: # !!!
app: http-echo # !!!
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo(base-valid.yaml)
L'avantage des outils comme kubeval est que de telles erreurs peuvent ĂȘtre dĂ©tectĂ©es Ă un stade prĂ©coce du cycle de dĂ©ploiement.
De plus, aucune connexion au cluster n'est requise pour ces vĂ©rifications : elles peuvent ĂȘtre effectuĂ©es hors ligne.
Par dĂ©faut, kubeval vĂ©rifie que les ressources correspondent au dernier schĂ©ma de l'API Kubernetes. Cependant, dans la plupart des cas, vous souhaitez vĂ©rifier la conformitĂ© Ă une version spĂ©cifique de Kubernetes. Cela peut ĂȘtre fait Ă l'aide de l'option --kubernetes-version:
$ kubeval --kubernetes-version 1.16.1 base-valid.yamlNotez que la version doit ĂȘtre indiquĂ©e au format Major.Minor.Patch.
Pour voir la liste des versions prises en charge pour la validation, consultez la , que kubeval utilise pour la validation. Si vous devez exécuter kubeval hors ligne, téléchargez les schémas et spécifiez leur emplacement local à l'aide de l'option --schema-location.
En plus des fichiers YAML individuels, kubeval peut également travailler avec des répertoires et stdin.
De plus, Kubeval s'intÚgre facilement aux pipelines CI. Ceux qui souhaitent exécuter des tests avant d'envoyer des manifestes au cluster seront heureux de savoir que kubeval prend en charge trois formats de sortie :
- Texte brut ;
- JSON ;
- Test Anything Protocol (TAP).
Et chacun des formats peut ĂȘtre utilisĂ© pour un parsing ultĂ©rieur de la sortie, afin de gĂ©nĂ©rer un rĂ©sumĂ© des rĂ©sultats au format souhaitĂ©.
Un des inconvĂ©nients de kubeval est qu'actuellement, il ne peut pas vĂ©rifier la conformitĂ© des Custom Resource Definitions (CRDs). Cependant, kubeval peut ĂȘtre configurĂ© pour .
Kubeval est un excellent outil pour vérifier et évaluer les ressources ; cependant, il convient de souligner qu'un test réussi ne garantit pas que la ressource respecte les meilleures pratiques.
Par exemple, l'utilisation de l'étiquette latest Le conteneur ne respecte pas les meilleures pratiques. Cependant, kubeval ne considÚre pas cela comme une erreur et ne le signale pas. Cela signifie qu'un tel YAML se terminera sans avertissements.
Mais que faire si vous devez Ă©valuer le YAML et identifier des violations comme le tag latest? ĐаĐș ĐżŃĐŸĐČĐ”ŃĐžŃŃ YAML-ŃаĐčĐ» ĐœĐ° ŃĐŸĐŸŃĐČĐ”ŃŃŃĐČОД Đ»ŃŃŃĐžĐŒ ĐżŃаĐșŃĐžĐșĐ°ĐŒ?
2. Kube-score
analyse les manifestes YAML et les évalue selon des tests intégrés. Ces tests sont choisis sur la base de recommandations de sécurité et des meilleures pratiques, par exemple :
- Exécuter le conteneur sans root.
- Présence de contrÎles de santé des pods.
- Définir des demandes et des limites de ressources.
à l'issue du test, trois résultats sont générés : OK, AVERTISSEMENT et CRITIQUE.
Vous pouvez essayer Kube-score en ligne ou l'installer localement.
Au moment de la rédaction de l'article original, la version la plus récente de kube-score était 1.7.0.
Testons-le sur notre manifeste base-valid.yaml:
$ kube-score score base-valid.yaml
apps/v1/Deployment http-echo
[CRITIQUE] Tag de l'image du conteneur
· http-echo -> Image avec le tag latest
Il est recommandé d'utiliser un tag fixe pour éviter les mises à jour accidentelles
[CRITIQUE] Pod NetworkPolicy
· Le pod n'a pas de politique réseau correspondante
Créez une NetworkPolicy qui cible ce pod
[CRITIQUE] Pod Probes
· Le conteneur n'a pas de readinessProbe
Une readinessProbe doit ĂȘtre utilisĂ©e pour indiquer quand le service est prĂȘt Ă recevoir du trafic.
Sans cela, le Pod risque de recevoir du trafic avant d'avoir démarré. Cela est également utilisé lors des
dĂ©ploiements et peut Ă©viter des temps d'arrĂȘt si une nouvelle version de l'application Ă©choue.
Plus d'informations : https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITIQUE] Contexte de sécurité du conteneur
· http-echo -> Le conteneur n'a pas de contexte de sécurité configuré
Définissez securityContext pour exécuter le conteneur dans un contexte plus sécurisé.
[CRITIQUE] Ressources du conteneur
· http-echo -> La limite de CPU n'est pas définie
Des limites de ressources sont recommandées pour éviter un DDOS de ressources. Définissez resources.limits.cpu
· http-echo -> La limite de mémoire n'est pas définie
Des limites de ressources sont recommandées pour éviter un DDOS de ressources. Définissez resources.limits.memory
· http-echo -> La demande de CPU n'est pas définie
Les demandes de ressources sont recommandées pour s'assurer que l'application peut démarrer et fonctionner sans
planter. Définissez resources.requests.cpu
· http-echo -> La demande de mémoire n'est pas définie
Les demandes de ressources sont recommandées pour s'assurer que l'application peut démarrer et fonctionner sans
planter. Définissez resources.requests.memory
[CRITIQUE] Le déploiement a un PodDisruptionBudget
· Aucun PodDisruptionBudget correspondant n'a été trouvé
Il est recommandĂ© de dĂ©finir un PodDisruptionBudget pour Ă©viter des temps d'arrĂȘt inattendus lors des opĂ©rations de
maintenance de Kubernetes, telles que le drainage d'un nĆud.
[AVERTISSEMENT] Le déploiement a un PodAntiAffinity hÎte
· Le déploiement n'a pas de podAntiAffinity hÎte défini
Il est recommandĂ© de dĂ©finir un podAntiAffinity qui empĂȘche plusieurs pods d'un dĂ©ploiement d'ĂȘtre
programmĂ©s sur le mĂȘme nĆud. Cela augmente la disponibilitĂ© en cas de dĂ©faillance du nĆud.Le YAML passe les vĂ©rifications de kubeval, tandis que kube-score pointe les lacunes suivantes :
- Les vérifications de disponibilité ne sont pas configurées.
- Les demandes et limites pour les ressources CPU et mémoire sont absentes.
- Les budgets de perturbation des Pod ne sont pas définis.
- Les rÚgles de coexistence séparée sont absentes. (anti-affinity) pour maximiser la disponibilité.
- Le conteneur s'exécute avec les privilÚges root.
Tout cela constitue des remarques valables sur les lacunes à corriger pour rendre le déploiement plus efficace et fiable.
Commande kube-score affiche les informations dans un format lisible en incluant toutes les violations de type AVERTISSEMENT et CRITIQUE, ce qui est trÚs utile durant le développement.
Ceux qui souhaitent utiliser cet outil dans le cadre d'un pipeline CI peuvent activer une sortie plus concise en utilisant le drapeau --output-format ci (dans ce cas, les tests avec des résultats sont également affichés OK):
$ kube-score score base-valid.yaml --output-format ci
[OK] http-echo apps/v1/Deployment
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) La limite CPU n'est pas définie
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) La limite mémoire n'est pas définie
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) La demande CPU n'est pas définie
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) La demande mémoire n'est pas définie
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Image avec le tag latest
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: Le pod n'a pas de politique réseau correspondante
[CRITICAL] http-echo apps/v1/Deployment: Le conteneur n'a pas de readinessProbe configurée
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Le conteneur n'a pas de contexte de sécurité configuré
[CRITICAL] http-echo apps/v1/Deployment: Aucun PodDisruptionBudget correspondant trouvé
[WARNING] http-echo apps/v1/Deployment: Le déploiement n'a pas de podAntiAffinity configuré
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/ServiceTout comme kubeval, kube-score retourne un code de sortie non nul en cas d'échec d'un test. CRITIQUE. Il est également possible d'activer ce type de traitement pour AVERTISSEMENT.
De plus, il est possible de vérifier les ressources pour qu'elles soient conformes à différentes versions de l'API (comme avec kubeval). Cependant, cette information est 'hardcodée' dans kube-score : il n'est pas possible de choisir une autre version de Kubernetes. Cette limitation peut devenir un gros problÚme si vous prévoyez de mettre à jour le cluster ou si vous avez plusieurs clusters avec différentes versions de K8s.
Veuillez noter que avec la suggestion de mettre en Ćuvre cette possibilitĂ©.
Pour en savoir plus sur kube-score, consultez .
Les tests kube-score sont un excellent outil pour mettre en Ćuvre des meilleures pratiques, mais que faire si des modifications doivent ĂȘtre apportĂ©es au test ou si vous souhaitez ajouter vos propres rĂšgles ? Malheureusement, cela n'est pas possible.
Kube-score n'est pas extensible : il n'est pas possible d'ajouter ou d'ajuster des politiques.
Si vous devez écrire des tests personnalisés pour vérifier la conformité aux politiques adoptées par l'entreprise, vous pouvez utiliser l'un des quatre outils suivants : config-lint, copper, conftest ou polaris.
3. Config-lint
Config-lint est un outil de validation des fichiers de configuration au format YAML, JSON, Terraform, CSV et des manifestes Kubernetes.
Vous pouvez l'installer en suivant sur le site du projet.
La version actuelle au moment de la rédaction de l'article original est 1.5.0.
Config-lint ne contient pas de tests intégrés pour vérifier les manifestes Kubernetes.
Pour effectuer des tests, il est nécessaire de créer des rÚgles correspondantes. Celles-ci sont enregistrées dans des fichiers YAML, appelés 'ensembles de rÚgles' (rulesets), et ont la structure suivante :
version: 1
description: RÚgles pour les fichiers de spécification Kubernetes
type: Kubernetes
files:
- "*.yaml"
rules:
# liste des rĂšgles(rule.yaml)
Examinons-le de plus prĂšs :
- Champ
typeindique quel type de configuration utilisera config-lint. Pour les manifestes K8s, cela ont toujoursKubernetes. - Dans le champ
filesen plus des fichiers eux-mĂȘmes, vous pouvez spĂ©cifier un rĂ©pertoire. - Champ
rulesest destiné à définir des tests personnalisés.
Supposons que vous souhaitiez vous assurer que les images dans le Deployment sont toujours téléchargées à partir d'un dépÎt de confiance tel que my-company.com/myapp:1.0. La rÚgle pour config-lint effectuant cette vérification ressemblera à ceci :
- id: MY_DEPLOYMENT_IMAGE_TAG
severity: FAILURE
message: Le déploiement doit utiliser une balise d'image valide
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(rule-trusted-repo.yaml)
Pour chaque rĂšgle, les attributs suivants doivent ĂȘtre spĂ©cifiĂ©s :
idâ un identifiant unique pour la rĂšgle ;severityâ peut ĂȘtre FAILURE, AVERTISSEMENT et NON_COMPLIANT;messageâ lorsque la rĂšgle est violĂ©e, le contenu de cette ligne sera affichĂ© ;resourceâ le type de ressource auquel cette rĂšgle s'applique ;assertionsâ liste des conditions qui seront Ă©valuĂ©es pour cette ressource.
Dans la rÚgle ci-dessus, l'assertion appelé vérifie que tous les conteneurs dans le Deployment (key: spec.templates.spec.containers) utilisent des images de confiance (c'est-à -dire commençant par my-company.com/).
L'ensemble de rĂšgles complet ressemble Ă ceci :
version: 1
description: RÚgles pour les fichiers de spécification Kubernetes
type: Kubernetes
files:
- "*.yaml"
rules:
- id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
severity: FAILURE
message: Le déploiement doit utiliser un dépÎt d'image valide
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(ruleset.yaml)
Pour tester la rÚgle, enregistrons-la sous check_image_repo.yaml. Exécutons la vérification sur le fichier. base-valid.yaml:
$ config-lint -rules check_image_repo.yaml base-valid.yaml
[
{
"AssertionMessage": "Chaque expression échoue : L'expression 'Et' échoue : l'image ne commence pas par my-company.com/",
"Category": "",
"CreatedAt": "2020-06-04T01:29:25Z",
"Filename": "test-data/base-valid.yaml",
"LineNumber": 0,
"ResourceID": "http-echo",
"ResourceType": "Deployment",
"RuleID": "DEPLOYMENT_IMAGE_REPOSITORY",
"RuleMessage": "Le déploiement doit utiliser un référentiel d'images valide",
"Status": "ĂCHEC"
}
]La vérification a échoué. Vérifions maintenant le prochain manifeste avec un référentiel d'images valide :
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: my-company.com/http-echo:1.0 # !!!
args: ["-text", "hello-world"]
ports:
- containerPort: 5678(image-valid-mycompany.yaml)
Nous exĂ©cutons le mĂȘme test avec le manifeste ci-dessus. Aucun problĂšme dĂ©tectĂ© :
$ config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]Config-lint est un cadre prometteur permettant de créer des tests personnalisés pour vérifier les manifestes YAML Kubernetes à l'aide de YAML DSL.
Mais que faire si une logique et des tests plus complexes sont nécessaires ? Les possibilités de YAML ne sont-elles pas trop limitées pour cela ? Que diriez-vous de pouvoir créer des tests dans un véritable langage de programmation ?
4. Copper
est un cadre de validation des manifestes via des tests personnalisés (similaire à config-lint).
Cependant, il se distingue de ce dernier en ce qu'il n'utilise pas YAML pour dĂ©crire les tests. Au lieu de cela, les tests peuvent ĂȘtre créés en JavaScript. Copper fournit une bibliothĂšque avec plusieurs outils de base, aidant Ă lire les informations sur les objets Kubernetes et Ă signaler les erreurs.
La sĂ©quence des Ă©tapes pour installer Copper peut ĂȘtre trouvĂ©e dans .
2.0.1 â la version la plus rĂ©cente de cet outil au moment de la rĂ©daction de l'article original.
Tout comme config-lint, Copper n'a pas de tests intĂ©grĂ©s. Ăcrivons-en un. Qu'il vĂ©rifie que les dĂ©ploiements utilisent exclusivement des images de conteneurs provenant de rĂ©fĂ©rentiels de confiance comme my-company.com.
Créez un fichier check_image_repo.js avec le contenu suivant :
$$.forEach(function($){
if ($.kind === 'Deployment') {
$.spec.template.spec.containers.forEach(function(container) {
var image = new DockerImage(container.image);
if (image.registry.lastIndexOf('my-company.com/') != 0) {
errors.add_error('no_company_repo',"Image " + $.metadata.name + " ne provient pas du référentiel my-company.com", 1)
}
});
}
});Maintenant, pour vérifier notre manifeste base-valid.yaml, utilisez la commande copper validate:
$ copper validate --in=base-valid.yaml --validator=check_image_tag.js
Le contrÎle no_company_repo a échoué avec une gravité de 1 parce que l'image http-echo ne provient pas du référentiel my-company.com
La validation a Ă©chouĂ©Il est Ă©vident qu'avec Copper, il est possible de rĂ©aliser des tests plus complexes â par exemple, vĂ©rifier les noms de domaine dans les manifests Ingress ou rejeter des pods fonctionnant en mode privilĂ©giĂ©.
Copper intĂšgre diverses fonctions utilitaires :
DockerImagelit le fichier d'entrĂ©e spĂ©cifiĂ© et crĂ©e un objet avec les attributs suivants :nomâ le nom de l'image,tagâ le tag de l'image,registryâ le registre des images,registry_urlâ le protocole (https://) et le registre des images,fqinâ l'emplacement complet de l'image.
- Fonction
findByNameaide à trouver une ressource par un type donné (kind) et un nom (nom) dans le fichier d'entrée. - Fonction
findByLabelsaide à trouver une ressource par un type spécifié (kind) et des étiquettes (labels).
Vous pouvez explorer toutes les fonctions utilitaires disponibles .
Par défaut, il charge tout le fichier YAML d'entrée dans une variable $$ et le rend accessible aux scripts (méthode familiÚre pour ceux qui ont de l'expérience avec jQuery).
Le principal avantage de Copper est évident : vous n'avez pas besoin d'apprendre un langage spécialisé et vous pouvez utiliser diverses fonctionnalités de JavaScript pour créer vos propres tests, telles que l'interpolation de chaßnes, des fonctions, etc.
Il convient également de noter que la version actuelle de Copper fonctionne avec la version ES5 du moteur JavaScript, et non avec ES6.
Les détails sont disponibles sur .
Cependant, si vous n'aimez pas beaucoup JavaScript et prĂ©fĂ©rez un langage spĂ©cifiquement conçu pour crĂ©er des requĂȘtes et dĂ©crire des politiques, vous devriez jeter un Ćil Ă conftest.
5. Conftest
Conftest est un framework pour la vĂ©rification des donnĂ©es de configuration. Il convient Ă©galement pour le test/la vĂ©rification des manifests Kubernetes. Les tests sont dĂ©crits Ă l'aide d'un langage de requĂȘte spĂ©cialisĂ© .
Vous pouvez installer conftest en suivant les instructions disponibles sur le site du projet.
Au moment de la rédaction de l'article original, la version la plus récente disponible était 0.18.2.
à l'instar de config-lint et de copper, conftest ne comprend pas de tests intégrés. Essayons-le et écrivons notre propre politique. Comme dans les exemples précédents, nous allons vérifier si les images des conteneurs proviennent d'une source fiable.
Créez un répertoire conftest-checks, puis dans celui-ci, un fichier nommé check_image_registry.rego avec le contenu suivant :
package main
deny[msg] {
input.kind == "Deployment"
image := input.spec.template.spec.containers[_].image
not startswith(image, "my-company.com/")
msg := sprintf("l'image '%v' ne provient pas du dépÎt my-company.com", [image])
}Maintenant, testons base-valid.yaml via conftest:
$ conftest test --policy ./conftest-checks base-valid.yaml
ĂCHOUĂ - base-valid.yaml - l'image 'hashicorp/http-echo' ne provient pas du dĂ©pĂŽt my-company.com
1 tests, 1 réussi, 0 avertissements, 1 échecLe test a échoué comme prévu, car les images proviennent d'une source non fiable.
Dans le fichier Rego, nous définissons le bloc deny. Sa validité est considérée comme une violation. Si plusieurs blocs deny sont présents, conftest les vérifie indépendamment les uns des autres, et la validité de n'importe quel bloc est interprétée comme une violation.
En plus de la sortie par dĂ©faut, conftest prend en charge JSON, TAP et le format tabulaire â une fonctionnalitĂ© extrĂȘmement utile si vous devez intĂ©grer des rapports dans un pipeline CI existant. Le format requis peut ĂȘtre dĂ©fini Ă l'aide du drapeau --output.
Pour faciliter le débogage des politiques, conftest dispose d'un drapeau --trace. Il affiche une trace de la façon dont conftest analyse les fichiers de politiques spécifiés.
Les politiques de conftest peuvent ĂȘtre publiĂ©es et partagĂ©es dans des registres OCI (Open Container Initiative) sous forme d'artefacts.
Commandes push et pull permettent de publier un artefact ou d'extraire un artefact existant d'un registre distant. Essayons de publier la politique que nous avons créée dans un registre Docker local à l'aide de conftest push.
Démarrez un registre Docker local :
$ docker run -it --rm -p 5000:5000 registryDans un autre terminal, accédez au répertoire que vous avez créé précédemment conftest-checks et exécutez la commande suivante :
$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latestSi la commande réussit, vous verrez un message de type suivant :
2020/06/10 14:25:43 pushed bundle with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609cMaintenant, créez un répertoire temporaire et exécutez-y la commande conftest pull. Elle téléchargera le paquet créé par la commande précédente :
$ cd $(mktemp -d)
$ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latestDans le répertoire temporaire, un sous-répertoire apparaßtra policy, contenant notre fichier de politique :
$ tree
.
âââ policy
âââ check_image_registry.regoLes tests peuvent ĂȘtre effectuĂ©s directement depuis le rĂ©fĂ©rentiel :
$ conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml
..
FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
2 tests, 1 passed, 0 warnings, 1 failureMalheureusement, DockerHub n'est pas encore pris en charge. Donc, considérez-vous chanceux si vous utilisez (ACR) ou votre propre registre.
Le format des artefacts est identique à celui des (OPA), ce qui permet d'utiliser conftest pour exécuter des tests à partir de paquets OPA existants.
Pour en savoir plus sur le partage des politiques et d'autres fonctionnalités de conftest, consultez .
6. Polaris
Le dernier outil dont nous allons parler dans cet article est . (Nous avons dĂ©jĂ traduit son annonce de l'annĂ©e derniĂšre â Note de traduction.)
Polaris peut ĂȘtre installĂ© dans un cluster ou utilisĂ© en mode ligne de commande. Comme vous l'avez probablement devinĂ©, il permet une analyse statique des manifestes Kubernetes.
En mode ligne de commande, des tests intégrés sont disponibles, couvrant des domaines tels que la sécurité et les meilleures pratiques (similaire à kube-score). De plus, vous pouvez créer vos propres tests (comme dans config-lint, copper et conftest).
En d'autres termes, Polaris combine les avantages des deux catégories d'outils : avec des tests intégrés et personnalisés.
Pour installer Polaris en mode ligne de commande, utilisez .
Au moment de la rédaction de cet article, la version 1.0.3 est disponible.
AprÚs l'installation, vous pouvez exécuter polaris sur le manifeste base-valid.yaml avec la commande suivante :
$ polaris audit --audit-path base-valid.yamlCela affichera une ligne au format JSON avec des détails sur les tests effectués et leurs résultats. La sortie aura la structure suivante :
{
"PolarisOutputVersion": "1.0",
"AuditTime": "0001-01-01T00:00:00Z",
"SourceType": "Path",
"SourceName": "test-data/base-valid.yaml",
"DisplayName": "test-data/base-valid.yaml",
"ClusterInfo": {
"Version": "unknown",
"Nodes": 0,
"Pods": 2,
"Namespaces": 0,
"Controllers": 2
},
"Results": [
/* longue liste */
]
}La sortie complĂšte est disponible. .
Comme kube-score, Polaris identifie les problĂšmes dans les domaines oĂč le manifeste ne respecte pas les meilleures pratiques :
- Les vérifications de santé des pods sont manquantes.
- Les balises pour les images de conteneurs ne sont pas spécifiées.
- Le conteneur s'exécute avec les privilÚges root.
- Les demandes et limites pour la mémoire et le CPU ne sont pas spécifiées.
Chaque test se voit attribuer un niveau de criticité en fonction de ses résultats : warning ou danger. Pour en savoir plus sur les tests intégrés disponibles, veuillez consulter .
Si les dĂ©tails ne sont pas nĂ©cessaires, vous pouvez spĂ©cifier le drapeau --format score. Dans ce cas, Polaris affichera un nombre dans la plage de 1 Ă 100 â score (c'est-Ă -dire une Ă©valuation) :
$ polaris audit --audit-path test-data/base-valid.yaml --format score
68Plus l'évaluation est proche de 100, plus le degré de conformité est élevé. Si vous vérifiez le code de sortie de la commande polaris audit, il s'avérera égal à 0.
Forcer polaris audit Ă quitter avec un code non nul peut ĂȘtre rĂ©alisĂ© avec deux drapeaux :
- Drapeau
--set-exit-code-below-scoreprend comme argument un seuil entre 1 et 100. Dans ce cas, la commande terminera avec un code de sortie 4 si l'évaluation est inférieure au seuil. C'est trÚs pratique lorsque vous avez un certain seuil (disons 75), et que vous devez recevoir une alerte si l'évaluation tombe en dessous. - Drapeau
--set-exit-code-on-dangerCela entraßnera l'échec de l'équipe avec le code 3 si l'un des tests de danger échoue.
Essayons maintenant de crĂ©er un test personnalisĂ© qui vĂ©rifie si l'image provient d'un rĂ©fĂ©rentiel de confiance. Les tests personnalisĂ©s sont dĂ©finis au format YAML, et le test lui-mĂȘme est dĂ©crit Ă l'aide de JSON Schema.
Le fragment YAML suivant décrit un nouveau test appelé checkImageRepo:
checkImageRepo:
successMessage: Le registre d'images est valide
failureMessage: Le registre d'images n'est pas valide
category: Images
target: Conteneur
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$Examinons-le de plus prĂšs :
successMessageâ cette ligne sera affichĂ©e si le test rĂ©ussit ;failureMessageâ ce message sera affichĂ© en cas d'Ă©chec ;categoryâ indique l'une des catĂ©gories :Images,ContrĂŽles de santĂ©,SĂ©curitĂ©,RĂ©seauetRessources;cibleâ dĂ©termine Ă quel type d'objet (spec) le test s'applique. Valeurs possibles :Conteneur,PodouContrĂŽleur;- Le test lui-mĂȘme est dĂ©fini dans un objet
schémaà l'aide de JSON schema. Dans ce test, le mot-clépatternest utilisé pour comparer la source de l'image avec celle requise.
Pour exécuter le test ci-dessus, il est nécessaire de créer la configuration Polaris suivante :
checks:
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Le registre d'images est valide
failureMessage: Le registre d'images n'est pas valide
category: Images
target: Conteneur
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$(polaris-conf.yaml)
Analysons le fichier :
- Dans le champ
checksdĂ©crit les tests et leur niveau de criticitĂ©. Ătant donnĂ© qu'il est souhaitable de recevoir une alerte lorsque l'image provient d'une source non fiable, nous dĂ©finissons ici le niveaudanger. - Le test lui-mĂȘme
checkImageRepoest ensuite défini dans l'objetcustomChecks.
Enregistrez le fichier sous custom_check.yaml. Vous pouvez maintenant exécuter polaris audit avec le manifeste YAML nécessitant une vérification.
Testons notre manifeste base-valid.yaml:
$ polaris audit --config custom_check.yaml --audit-path base-valid.yamlCommande polaris audit a effectué uniquement le test personnalisé décrit ci-dessus, et il a échoué.
Si vous modifiez l'image en my-company.com/http-echo:1.0, Polaris réussira. Le manifeste avec les changements est déjà présent dans , donc vous pouvez vérifier la commande précédente sur le manifeste. image-valid-mycompany.yaml.
Maintenant, la question se pose : comment exécuter les tests intégrés avec les tests personnalisés ? C'est simple ! Il suffit d'ajouter les identifiants des tests intégrés dans le fichier de configuration. Il finira par ressembler à ceci :
vérifications:
cpuRequestsMissing: avertissement
cpuLimitsMissing: avertissement
# Autres vérifications intégrées..
# ..
# vérifications personnalisées
checkImageRepo: danger # !!!
vérificationsPersonnalisées:
checkImageRepo: # !!!
successMessage: Le registre d'images est valide
failureMessage: Le registre d'images n'est pas valide
category: Images
target: Conteneur
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$(config_with_custom_check.yaml)
Un exemple complet de fichier de configuration est disponible .
Vérifier le manifeste base-valid.yaml, en utilisant des tests intégrés et personnalisés, peut se faire avec la commande :
$ polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yamlPolaris complÚte les tests intégrés par des tests personnalisés, combinant ainsi le meilleur des deux mondes.
D'un autre cĂŽtĂ©, l'incapacitĂ© Ă utiliser des langages plus puissants comme Rego ou JavaScript peut ĂȘtre un facteur limitant qui empĂȘche la crĂ©ation de tests plus sophistiquĂ©s.
Des informations supplémentaires sur Polaris sont disponibles sur .
Résumé
Bien qu'il existe de nombreux outils pour vérifier et évaluer les fichiers YAML de Kubernetes, il est important d'avoir une idée claire de la façon dont les tests seront conçus et exécutés.
Par exemple, si l'on prend des manifestes Kubernetes passant par le pipeline, kubeval pourrait ĂȘtre le premier pas dans un tel pipeline. Il vĂ©rifierait si les dĂ©finitions d'objets correspondent au schĂ©ma API de Kubernetes.
AprÚs avoir terminé une telle vérification, il serait possible de passer à des tests plus sophistiqués, tels que la conformité aux meilleures pratiques standards et aux politiques spécifiques. Et c'est ici que kube-score et Polaris seraient utiles.
Pour ceux qui ont des exigences complexes et ont besoin de personnaliser les tests en détail, copper, config-lint et conftest seraient appropriés..
Conftest et config-lint utilisent YAML pour spécifier des tests personnalisés, tandis que copper donne accÚs à un langage de programmation complet, ce qui en fait un choix assez attrayant.
D'un autre cÎté, vaut-il mieux utiliser l'un de ces outils et donc créer tous les tests manuellement, ou préférer Polaris et simplement compléter ce dont on a besoin ? Il n'y a pas de réponse unique à cette question.
Le tableau ci-dessous contient une brĂšve description de chaque outil :
Outil
L'objectif
Inconvénients
Tests personnalisés
kubeval
Vérifie les manifestes YAML pour la conformité à une version spécifique du schéma API
Ne peut pas travailler avec des CRD
Non
kube-score
Analyse les manifestes YAML pour la conformité aux meilleures pratiques
On ne peut pas choisir sa version de l'API Kubernetes pour vérifier les ressources
Non
copper
Cadre général pour la création de tests JavaScript personnalisés pour des manisfestes YAML
Pas de tests intégrés. Documentation limitée
Oui
config-lint
Cadre général pour la création de tests dans un langage orienté objet intégré dans YAML. Prend en charge divers formats de configuration (par exemple, Terraform)
Pas de tests prĂ©conçus. Les assertions et fonctions intĂ©grĂ©es peuvent ĂȘtre insuffisantes
Oui
conftest
Cadre pour crĂ©er des tests personnalisĂ©s en Rego (langage de requĂȘte spĂ©cialisĂ©). Permet de partager des politiques via des bundles OCI
Pas de tests intégrés. Nécessite d'apprendre Rego. Docker Hub n'est pas pris en charge lors de la publication des politiques
Oui
Polaris
Analyse les manifestes YAML pour se conformer aux meilleures pratiques standards. Permet de créer des tests personnalisés à l'aide de JSON Schema
Les capacitĂ©s de test basĂ©es sur JSON Schema peuvent ĂȘtre insuffisantes
Oui
Ătant donnĂ© que ces outils ne dĂ©pendent pas de l'accĂšs Ă un cluster Kubernetes, ils sont faciles Ă installer. Ils permettent de filtrer les fichiers sources et offrent des retours rapides aux auteurs de pull requests dans les projets.
P.S. de l'auteur
Lisez aussi dans notre blog :
- «»;
- «»;
- «».
Source : habr.com
