Hinweis.: Mit der steigenden Anzahl von YAML-Konfigurationen für K8s-Umgebungen wird die Notwendigkeit ihrer automatisierten Überprüfung immer relevanter. Der Autor dieser Übersicht hat nicht nur bestehende Lösungen für diese Aufgabe ausgewählt, sondern auch am Beispiel eines Deployments demonstriert, wie sie funktionieren. Es ist sehr informativ für diejenigen, die sich für dieses Thema interessieren.

TL;DR: Der Artikel vergleicht sechs statische Überprüfungs- und Bewertungswerkzeuge für Kubernetes-YAML-Dateien hinsichtlich der Konformität mit den Best Practices und Anforderungen.
Arbeitslasten in Kubernetes werden in der Regel in Form von YAML-Dokumenten definiert. Ein Problem mit YAML ist die Schwierigkeit, Einschränkungen oder Beziehungen zwischen Manifestdateien festzulegen.
Was, wenn wir sicherstellen müssen, dass alle Images, die im Cluster bereitgestellt werden, aus einem vertrauenswürdigen Registry stammen?
Wie verhindern wir die Bereitstellung von Deployments im Cluster, für die keine PodDisruptionBudgets definiert sind?
Die Integration statischer Tests ermöglicht es, Fehler und Richtlinienverletzungen bereits in der Entwicklungsphase zu identifizieren. Dadurch wird die Genauigkeit und Sicherheit der Ressourcendefinitionen erhöht und die Wahrscheinlichkeit gesteigert, dass Produktionslasten den besten Praktiken folgen.
Das Ökosystem der statischen Überprüfung von YAML-Dateien in Kubernetes lässt sich in folgende Kategorien unterteilen:
- API-Validatoren. Werkzeuge in dieser Kategorie prüfen das YAML-Manifest auf die Anforderungen des Kubernetes-API-Servers.
- Fertige Tester. Werkzeuge aus dieser Kategorie kommen mit vorgefertigten Tests zur Sicherheit, zur Einhaltung der besten Praktiken usw.
- Benutzerdefinierte Validatoren. Vertreter dieser Kategorie erlauben die Erstellung benutzerdefinierter Tests in verschiedenen Sprachen, wie z. B. Rego und Javascript.
In diesem Artikel werden wir sechs verschiedene Tools beschreiben und vergleichen:
- kubeval;
- kube-score;
- config-lint;
- copper;
- conftest;
- Polaris.
Also, lassen Sie uns loslegen!
Überprüfung von Deployments
Bevor wir mit dem Vergleich der Werkzeuge beginnen, lassen Sie uns eine Basis schaffen, auf der wir sie testen werden.
Das folgende Manifest enthält eine Reihe von Fehlern und Abweichungen von den Best Practices: Wie viele davon können Sie finden?
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)
Wir werden dieses YAML zur Vergleichung verschiedener Werkzeuge verwenden.
Das obige Manifest
base-valid.yamlund andere Manifeste aus diesem Artikel finden Sie in .
Das Manifest beschreibt eine Webanwendung, deren Hauptaufgabe es ist, mit der Nachricht „Hello World“ auf Port 5678 zu antworten. Sie kann mit folgendem Befehl bereitgestellt werden:
kubectl apply -f hello-world.yamlUnd so überprüfen Sie die Funktionalität:
kubectl port-forward svc/http-echo 8080:5678Jetzt gehen Sie zu und bestätigen Sie, dass die Anwendung funktioniert. Hält sie jedoch den Best Practices stand? Lassen Sie uns das überprüfen.
1. Kubeval
Im Kern Es gibt die Vorstellung, dass jede Interaktion mit Kubernetes über seine REST API erfolgt. Mit anderen Worten, man kann das API-Schema verwenden, um zu überprüfen, ob ein bestimmter YAML-Datensatz dem Schema entspricht. Lassen Sie uns ein Beispiel betrachten.
kubeval ist auf der Projektwebsite verfügbar.
Zum Zeitpunkt der Erstellung des ursprünglichen Artikels war die Version 0.15.0 verfügbar.
Nach der Installation lassen Sie uns das oben genannte Manifest "füttern":
$ kubeval base-valid.yaml
PASS - base-valid.yaml enthält ein gültiges Deployment (http-echo)
PASS - base-valid.yaml enthält einen gültigen Service (http-echo)Bei Erfolg wird kubeval mit dem Exit-Code 0 beendet. Dies können Sie wie folgt überprüfen:
$ echo $?
0Lassen Sie uns nun kubeval mit einem anderen Manifest ausprobieren:
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)
Können Sie das Problem auf den ersten Blick erkennen? Wir starten:
$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml enthält ein ungültiges Deployment (http-echo) - selector: selector ist erforderlich
PASS - kubeval-invalid.yaml enthält einen gültigen Service (http-echo)
# Überprüfen wir den Rückgabewert
$ echo $?
1Die Ressource besteht die Prüfung nicht.
Deployments, die eine API-Version verwenden apps/v1, müssen einen Selector enthalten, der dem Pod-Label entspricht. Das obige Manifest enthält keinen Selector, weshalb kubeval einen Fehler gemeldet und mit einem Nicht-Null-Code beendet wurde.
Interessant, was passiert, wenn man kubectl apply -f dieses Manifest ausführt?
Nun, versuchen wir es:
$ kubectl apply -f kubeval-invalid.yaml
error: error validating "kubeval-invalid.yaml": error validating data: ValidationError(Deployment.spec):
missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors,
turn validation off with --validate=falseGenau der Fehler, vor dem kubeval gewarnt hat. Man kann ihn beheben, indem man einen Selector hinzufügt:
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)
Der Vorteil von Werkzeugen wie kubeval ist, dass solche Fehler früh im Bereitstellungsprozess erkannt werden können.
Darüber hinaus ist für diese Prüfungen kein Zugang zum Cluster erforderlich: Sie können offline durchgeführt werden.
Standardmäßig überprüft kubeval Ressourcen auf Übereinstimmung mit dem neuesten Kubernetes API-Schema. In vielen Fällen müssen Sie jedoch die Überprüfung auf eine spezifische Kubernetes-Version durchführen. Dies kann mit dem Flag erreichen, --kubernetes-version:
$ kubeval --kubernetes-version 1.16.1 base-valid.yamlBitte beachten Sie, dass die Version im Format angegeben werden muss Major.Minor.Patch.
Um die Liste der unterstützten Versionen zu sehen, besuchen Sie die , die kubeval zur Validierung verwendet. Wenn Sie kubeval offline ausführen möchten, laden Sie die Schemas herunter und geben Sie ihren lokalen Speicherort mit dem Flag an, --schema-location.
Neben einzelnen YAML-Dateien kann kubeval auch mit Verzeichnissen und stdin arbeiten.
Darüber hinaus lässt sich Kubeval problemlos in CI-Pipelines integrieren. Wer Tests durchführen möchte, bevor Manifeste in das Cluster geschickt werden, wird erfreut sein zu erfahren, dass kubeval drei Ausgabeformate unterstützt:
- Plaintext;
- JSON;
- Test Anything Protocol (TAP).
Und jedes der Formate kann zur weiteren Verarbeitung der Ausgabe verwendet werden, um eine Zusammenfassung der Ergebnisse in der gewünschten Form zu erstellen.
Ein Nachteil von kubeval ist, dass es derzeit keine Überprüfung auf die Übereinstimmung mit Custom Resource Definitions (CRDs) unterstützt. Allerdings kann kubeval so konfiguriert werden, .
Kubeval ist ein hervorragendes Tool zur Überprüfung und Bewertung von Ressourcen; es sollte jedoch betont werden, dass das Bestehen des Tests keine Garantie dafür bietet, dass die Ressource den besten Praktiken entspricht.
Zum Beispiel entspricht die Verwendung des Tags latest in einem Container nicht den besten Praktiken. Kubeval betrachtet dies jedoch nicht als Fehler und meldet es nicht. Das heißt, die Überprüfung eines solchen YAML wird ohne Warnungen abgeschlossen.
Aber was ist, wenn Sie YAML bewerten und Verstöße wie das Tag latest? Как проверить YAML-файл на соответствие лучшим практикам?
2. Kube-score
analysiert YAML-Manifestdateien und bewertet sie anhand eingebauter Tests. Diese Tests basieren auf Sicherheitsrichtlinien und besten Praktiken, wie zum Beispiel:
- Ausführung des Containers nicht als root.
- Vorhandensein von Health Checks für Pods.
- Festlegen von Ressourcenanforderungen und -limits.
Nach dem Test werden drei Ergebnisse ausgegeben: OK, WARNUNG und KRITISCH.
Kube-score kann online getestet oder lokal installiert werden.
Zum Zeitpunkt des Schreibens des ursprünglichen Artikels war die neueste Version von kube-score 1.7.0.
Lassen Sie uns es an unserem Manifest ausprobieren. base-valid.yaml:
$ kube-score score base-valid.yaml
apps/v1/Deployment http-echo
[CRITICAL] Container-Image-Tag
· http-echo -> Bild mit dem neuesten Tag
Es wird empfohlen, ein festes Tag zu verwenden, um versehentliche Updates zu vermeiden.
[CRITICAL] Pod-NetworkPolicy
· Der Pod hat keine übereinstimmende Netzwerk-Policy
Erstellen Sie eine NetworkPolicy, die diesen Pod anvisiert.
[CRITICAL] Pod-Probes
· Container fehlt ein readinessProbe
Ein readinessProbe sollte verwendet werden, um anzuzeigen, wenn der Dienst bereit ist, Traffic zu empfangen.
Ohne ihn riskiert der Pod, Traffic zu erhalten, bevor er hochgefahren ist. Er wird auch während
Rollouts verwendet und kann Ausfallzeiten verhindern, wenn eine neue Version der Anwendung fehlschlägt.
Weitere Informationen: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITICAL] Container-Sicherheitskontext
· http-echo -> Container hat keinen konfigurierten Sicherheitskontext
Setzen Sie securityContext, um den Container in einem sichereren Kontext auszuführen.
[CRITICAL] Container-Ressourcen
· http-echo -> CPU-Grenze ist nicht festgelegt
Ressourcengrenzen werden empfohlen, um DDOS auf Ressourcen zu vermeiden. Setzen Sie resources.limits.cpu
· http-echo -> Speichergrenze ist nicht festgelegt
Ressourcengrenzen werden empfohlen, um DDOS auf Ressourcen zu vermeiden. Setzen Sie resources.limits.memory
· http-echo -> CPU-Anforderung ist nicht festgelegt
Ressourcennachfragen werden empfohlen, um sicherzustellen, dass die Anwendung starten und ohne
Abstürze laufen kann. Setzen Sie resources.requests.cpu
· http-echo -> Speicheranforderung ist nicht festgelegt
Ressourcennachfragen werden empfohlen, um sicherzustellen, dass die Anwendung starten und ohne Abstürze laufen kann.
Setzen Sie resources.requests.memory
[CRITICAL] Deployment hat PodDisruptionBudget
· Es wurde kein übereinstimmendes PodDisruptionBudget gefunden
Es wird empfohlen, ein PodDisruptionBudget zu definieren, um unerwartete Ausfallzeiten während der Kubernetes-
Wartungsarbeiten, wie z. B. beim Entleeren eines Knotens, zu vermeiden.
[WARNING] Deployment hat Host-PodAntiAffinity
· Deployment hat keine Host-podAntiAffinity festgelegt
Es wird empfohlen, ein podAntiAffinity festzulegen, das verhindert, dass mehrere Pods eines Deployments
auf demselben Knoten geplant werden. Dies erhöht die Verfügbarkeit für den Fall, dass der Knoten nicht mehr verfügbar ist.YAML wird von kubeval überprüft, während kube-score die folgenden Mängel aufzeigt:
- Es sind keine Bereitschaftsprüfungen konfiguriert.
- Es fehlen Anforderungs- und Begrenzungswerte für CPU- und Speichernutzung.
- Es sind keine Pod-Störungsbudgets festgelegt.
- Es fehlen Regeln für die getrennte Existenz (anti-affinity) um die Verfügbarkeit zu maximieren.
- Der Container wird mit Root-Rechten ausgeführt.
All dies sind berechtigte Hinweise auf Mängel, die behoben werden sollten, um die Bereitstellung effizienter und zuverlässiger zu gestalten.
Der Befehl kube-score stellt die Informationen in einem lesbaren Format dar, einschließlich aller Verstöße vom Typ WARNUNG und KRITISCH, was während der Entwicklung sehr hilfreich ist.
Nutzer, die dieses Tool im Rahmen einer CI-Pipeline verwenden möchten, können eine kompaktere Ausgabe mit dem Flagge --output-format ci aktivieren (in diesem Fall werden auch Tests mit Ergebnis ausgegeben 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) CPU-Limit ist nicht gesetzt
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Speicherlimit ist nicht gesetzt
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU-Anforderung ist nicht gesetzt
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Speicheranforderung ist nicht gesetzt
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Bild mit neuestem Tag
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: Der Pod hat keine übereinstimmende Netzwerkrichtlinie
[CRITICAL] http-echo apps/v1/Deployment: Container fehlt ein readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Container hat keinen konfigurierten Sicherheitskontext
[CRITICAL] http-echo apps/v1/Deployment: Kein passendes PodDisruptionBudget gefunden
[WARNING] http-echo apps/v1/Deployment: Deployment hat kein host podAntiAffinity gesetzt
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/ServiceÄhnlich wie kubeval gibt kube-score einen ungleich nullen Rückgabewert zurück, wenn ein Test mit einem Fehler endet. KRITISCH. Außerdem kann eine ähnliche Behandlung auch für WARNUNG.
Darüber hinaus gibt es die Möglichkeit, Ressourcen auf die Konformität mit verschiedenen API-Versionen zu überprüfen (wie auch in kubeval). Diese Informationen sind jedoch 'hardcoded' in kube-score: Eine andere Kubernetes-Version kann nicht gewählt werden. Diese Einschränkung kann ein großes Problem darstellen, wenn Sie planen, den Cluster zu aktualisieren oder wenn Sie mehrere Cluster mit unterschiedlichen K8s-Versionen haben.
nicht mit einem Bindestrich beginnt. In YAML bedeutet dies, dass mit dem Angebot, diese Möglichkeit zu realisieren.
Mehr über kube-score erfahren Sie auf .
Die kube-score-Tests sind ein hervorragendes Werkzeug zur Implementierung bewährter Praktiken. Doch was ist, wenn Änderungen an einem Test erforderlich sind oder eigene Regeln hinzugefügt werden sollen? Leider ist das nicht möglich.
Kube-score ist nicht erweiterbar: Es können keine Richtlinien hinzugefügt oder angepasst werden.
Wenn benutzerdefinierte Tests zur Überprüfung der Unternehmensrichtlinien erforderlich sind, können Sie eines der folgenden vier Werkzeuge verwenden: config-lint, copper, conftest oder polaris.
3. Config-lint
Config-lint ist ein Tool zur Validierung von Konfigurationsdateien im YAML-, JSON-, Terraform-, CSV-Format und Kubernetes-Manifesten.
Es kann mit auf der Projekt-Website installiert werden.
Die aktuelle Version zum Zeitpunkt des Schreibens des ursprünglichen Artikels ist 1.5.0.
Config-lint enthält keine integrierten Tests zur Überprüfung von Kubernetes-Manifesten.
Für jeden Test müssen die entsprechenden Regeln erstellt werden. Diese werden in YAML-Dateien gespeichert, die als „Regelsätze“ (rulesets)bezeichnet werden und die folgende Struktur haben:
version: 1
description: Regeln für Kubernetes-Spezifikationsdateien
type: Kubernetes
files:
- "*.yaml"
rules:
# Regelauflistung(rule.yaml)
Lass uns einen genaueren Blick darauf werfen:
- Feld
typezeigt, welcher Konfigurationstyp von config-lint verwendet wird. Für K8s-Manifeste ist das immerKubernetes. - Im Feld
filesneben den Dateien kann auch ein Verzeichnis angegeben werden. - Feld
rulesdient zur Festlegung benutzerdefinierter Tests.
Angenommen, Sie möchten sicherstellen, dass die Images im Deployment immer aus einem vertrauenswürdigen Repository wie my-company.com/myapp:1.0. Die Regel für config-lint, die diese Überprüfung durchführt, sieht folgendermaßen aus:
- id: MY_DEPLOYMENT_IMAGE_TAG
severity: FAILURE
message: Deployment muss ein gültiges Image-Tag verwenden
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(rule-trusted-repo.yaml)
Für jede Regel müssen die folgenden Attribute angegeben werden:
id— eindeutige Identifikation der Regel;severity— kann sein FAILURE, WARNUNG und NON_COMPLIANT;message— bei Regelverstoß wird der Inhalt dieser Zeile angezeigt;resource— der Typ der Ressource, auf die diese Regel angewendet wird;assertions— eine Liste von Bedingungen, die bezüglich dieser Ressource bewertet werden.
In der obigen Regel assertion mit dem Namen überprüft, dass alle Container im Deployment (key: spec.templates.spec.containers) vertrauenswürdige Images verwenden (d.h. solche, die mit my-company.com/).
Das vollständige Regelset sieht wie folgt aus:
version: 1
description: Regeln für Kubernetes-Spezifikationsdateien
type: Kubernetes
files:
- "*.yaml"
rules:
- id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
severity: FAILURE
message: Das Deployment muss ein gültiges Image-Repository verwenden
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(ruleset.yaml)
Um den Test durchzuführen, speichern wir ihn als check_image_repo.yaml. Lassen Sie uns die Überprüfung der Datei durchführen base-valid.yaml:
$ config-lint -rules check_image_repo.yaml base-valid.yaml
[
{
"AssertionMessage": "Jede Aussage schlägt fehl: Und-Aussage schlägt fehl: Bild beginnt nicht mit 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": "Das Deployment muss ein gültiges Image-Repository verwenden",
"Status": "FAILURE"
}
]Die Überprüfung ist fehlgeschlagen. Lassen Sie uns nun das nächste Manifest mit einem gültigen Image-Repository überprüfen:
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)
Wir führen denselben Test mit dem vorstehenden Manifest durch. Keine Probleme gefunden:
$ config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]Config-lint — ein vielversprechendes Framework, das es ermöglicht, eigene Tests zur Überprüfung von YAML-Manifests für Kubernetes mithilfe von YAML DSL zu erstellen.
Aber was tun, wenn komplexere Logik und Tests erforderlich sind? Ist YAML dafür nicht zu begrenzt? Was, wenn wir Tests in einer vollwertigen Programmiersprache schreiben könnten?
4. Copper
— ist ein Framework zur Validierung von Manifests mittels benutzerdefinierter Tests (vergleichbar mit config-lint).
Allerdings unterscheidet es sich von letzterem dadurch, dass es keine YAML zur Beschreibung der Tests verwendet. Stattdessen können die Tests in JavaScript erstellt werden. Copper bietet eine Bibliothek mit mehreren grundlegenden Werkzeugen, die helfen, Informationen über Kubernetes-Objekte auszulesen und Fehler zu melden.
Die Schritt-für-Schritt-Anleitung zur Installation von Copper findet sich in .
2.0.1 — die neueste Version dieses Tools zum Zeitpunkt der Erstellung des Originalartikels.
Wie bei config-lint hat Copper keine eingebauten Tests. Lassen Sie uns einen schreiben. Dieser soll sicherstellen, dass Deployments ausschließlich Container-Images aus vertrauenswürdigen Repositories wie my-company.com.
aufrufen können. check_image_repo.js mit folgendem Inhalt:
$$.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',"Das Image " + $.metadata.name + " stammt nicht aus dem Repository von my-company.com", 1)
}
});
}
});Um nun unser Manifest zu überprüfen, base-valid.yaml, verwenden Sie den Befehl copper validate:
$ copper validate --in=base-valid.yaml --validator=check_image_tag.js
Die Überprüfung no_company_repo ist mit Schweregrad 1 fehlgeschlagen, da das Image http-echo nicht aus dem Repository von my-company.com stammt
Die Validierung ist fehlgeschlagenEs ist klar, dass man mit Copper komplexere Tests durchführen kann – zum Beispiel das Überprüfen von Domainnamen in Ingress-Manifests oder das Ablehnen von Pods, die im privilegierten Modus laufen.
Copper bietet verschiedene Dienstprogrammfunktionen:
DockerImageliest die angegebene Eingabedatei und erstellt ein Objekt mit folgenden Attributen:name— Name des Images,tag— Tag des Images,registry— Image-Registry,registry_url— Protokoll (https://) und Image-Registry,fqin— vollständiger Speicherort des Images.
- Die Funktion
findByNamehilft, eine Ressource nach dem angegebenen Typ (kind) und Namen (name) aus der Eingabedatei zu finden. - Die Funktion
findByLabelshilft, eine Ressource nach dem angegebenen Typ (kind) und den Labels (labels).
Alle verfügbaren Dienstprogrammfunktionen sind verfügbar .
Standardmäßig lädt es die gesamte Eingang YAML-Datei in eine Variable $$ und macht es für Skripte zugänglich (eine vertraute Methode für diejenigen, die Erfahrung mit jQuery haben).
Der Hauptvorteil von Copper ist offensichtlich: Sie müssen keine spezielle Sprache erlernen und können verschiedene JavaScript-Funktionen zur Erstellung eigener Tests nutzen, wie z. B. String-Interpolation, Funktionen usw.
Es ist auch wichtig zu beachten, dass die aktuelle Version von Copper mit der ES5-Version der JavaScript-Engine und nicht mit ES6 arbeitet.
Weitere Informationen finden Sie unter .
Wenn Sie JavaScript jedoch nicht besonders mögen und eine Sprache bevorzugen, die speziell für das Erstellen von Anfragen und das Beschreiben von Richtlinien entwickelt wurde, sollten Sie sich Conftest ansehen.
5. Conftest
Conftest ist ein Framework zur Überprüfung von Konfigurationsdaten. Es eignet sich auch zum Testen/Verifizieren von Kubernetes-Manifeste. Die Tests werden in einer speziellen Abfragesprache beschrieben. .
Conftest kann mit den installiert werden, die auf der Projektwebsite angegeben sind.
Zum Zeitpunkt des Schreibens des Originalartikels war die zuletzt verfügbare Version 0.18.2.
Ähnlich wie bei config-lint und copper, kommt conftest ohne integrierte Tests aus. Lassen Sie uns damit experimentieren und unsere eigene Richtlinie erstellen. Wie in den vorherigen Beispielen werden wir überprüfen, ob die Container-Images aus einer vertrauenswürdigen Quelle stammen.
Erstellen Sie ein Verzeichnis conftest-checks, und darin eine Datei mit dem Namen check_image_registry.rego mit folgendem Inhalt:
package main
deny[msg] {
input.kind == "Deployment"
image := input.spec.template.spec.containers[_].image
not startswith(image, "my-company.com/")
msg := sprintf("image '%v' stammt nicht aus dem Repository my-company.com", [image])
}Jetzt lassen Sie uns testen base-valid.yaml über conftest:
$ conftest test --policy ./conftest-checks base-valid.yaml
FAIL - base-valid.yaml - image 'hashicorp/http-echo' stammt nicht aus dem Repository my-company.com
1 Tests, 1 bestanden, 0 Warnungen, 1 FehlerDer Test ist erwartungsgemäß fehlgeschlagen, da die Images aus einer nicht vertrauenswürdigen Quelle stammen.
In der Rego-Datei definieren wir den Block deny. Seine Wahrhaftigkeit wird als Verstoß angesehen. Wenn es mehrere Blöcke gibt, überprüft conftest diese unabhängig voneinander, und die Wahrhaftigkeit eines der Blöcke wird als Verstoß gewertet. deny Neben der Standardausgabe unterstützt conftest JSON, TAP und Tabellenformat – eine äußerst nützliche Funktion, wenn Berichte in einen bestehenden CI-Pipeline integriert werden müssen. Den gewünschten Format können Sie mit dem Flag
--output --Ausgabe.
Um die Fehlersuche in den Richtlinien zu erleichtern, bietet conftest eine Option --trace. Diese gibt eine Nachverfolgung aus, wie conftest die angegebenen Richtlinien-Dateien analysiert.
Die Richtlinien von conftest können in OCI-Registries (Open Container Initiative) als Artefakte veröffentlicht und geteilt werden.
Befehle push und pull ermöglicht es, ein Artefakt zu veröffentlichen oder ein bestehendes Artefakt aus einem entfernten Registry abzurufen. Lassen Sie uns versuchen, die von uns erstellte Richtlinie in ein lokales Docker-Registry zu veröffentlichen mit conftest push.
Starten Sie ein lokales Docker-Registry:
$ docker run -it --rm -p 5000:5000 registryGehen Sie in einem anderen Terminal in das zuvor erstellte Verzeichnis conftest-checks und führen Sie den folgenden Befehl aus:
$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latestWenn der Befehl erfolgreich war, sehen Sie eine Meldung wie diese:
2020/06/10 14:25:43 Bundle mit Digest gepusht: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609cJetzt erstellen Sie ein temporäres Verzeichnis und führen darin den Befehl aus conftest pull. Dieser wird das Paket herunterladen, das mit dem vorherigen Befehl erstellt wurde:
$ cd $(mktemp -d)
$ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latestIm temporären Verzeichnis wird ein Unterverzeichnis erscheinen Richtlinie, das unsere Richtliniendatei enthält:
$ tree
.
└── policy
└── check_image_registry.regoTests können direkt aus dem Repository durchgeführt werden:
$ conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml
..
FEHLER - base-valid.yaml - das Image 'hashicorp/http-echo' stammt nicht aus dem Repository my-company.com
2 Tests, 1 bestanden, 0 Warnungen, 1 FehlerLeider wird DockerHub derzeit nicht unterstützt. Daher können Sie sich glücklich schätzen, wenn Sie (ACR) oder Ihr eigenes Registry verwenden.
Das Format der Artefakte entspricht dem von (OPA), was es ermöglicht, conftest zum Ausführen von Tests aus bestehenden OPA-Paketen zu verwenden.
Mehr über das Teilen von Richtlinien und andere Funktionen von conftest erfahren Sie unter .
6. Polaris
Das letzte Werkzeug, das in diesem Artikel behandelt wird, ist . (Wir haben die Ankündigung von letztem Jahr — Anmerk. d. Ü.)
Polaris kann im Cluster installiert oder im Befehlszeilenmodus verwendet werden. Wie Sie sich denken können, ermöglicht es die statische Analyse von Kubernetes-Manifests.
Im Befehlszeilenmodus sind integrierte Tests verfügbar, die Bereiche wie Sicherheit und bewährte Verfahren abdecken (ähnlich wie kube-score). Außerdem können eigene Tests erstellt werden (wie in config-lint, copper und conftest).
Anders ausgedrückt kombiniert Polaris die Vorteile beider Werkzeugkategorien: integrierte und benutzerdefinierte Tests.
Um Polaris im Befehlszeilenmodus zu installieren, nutzen Sie .
Zum Zeitpunkt der Erstellung des Originalartikels ist Version 1.0.3 verfügbar.
Nach Abschluss der Installation können Sie Polaris mit dem Manifest starten base-valid.yaml unter Verwendung des folgenden Befehls:
$ polaris audit --audit-path base-valid.yamlEs gibt eine JSON-Zeichenfolge mit einer detaillierten Beschreibung der durchgeführten Tests und deren Ergebnissen aus. Der Output hat die folgende Struktur:
{
"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": [
/* lange Liste */
]
}Die vollständige Ausgabe ist verfügbar .
Wie kube-score identifiziert Polaris Probleme in Bereichen, in denen das Manifest nicht den besten Praktiken entspricht:
- Es fehlen Gesundheitsprüfungen für Pods.
- Es sind keine Tags für Container-Images angegeben.
- Der Container wird mit Root-Rechten ausgeführt.
- Es sind keine Requests und Limits für Speicher und CPU angegeben.
Jeder Test wird je nach seinen Ergebnissen mit einem Schweregrad gekennzeichnet: warning oder danger. Um mehr über die verfügbaren integrierten Tests zu erfahren, wenden Sie sich an .
Wenn keine detaillierten Informationen benötigt werden, kann das Flag --format scoreangegeben werden. In diesem Fall gibt Polaris eine Zahl im Bereich von 1 bis 100 aus — score (d.h. Bewertung):
$ polaris audit --audit-path test-data/base-valid.yaml --format score
68Je näher die Bewertung bei 100 liegt, desto höher ist die Übereinstimmung. Wenn Sie den Exit-Code des Befehls polaris auditüberprüfen, wird festgestellt, dass er gleich 0 ist.
Um polaris audit einen nicht-null Exit-Code zu erzwingen, können zwei Flags verwendet werden:
- Flagge
--set-exit-code-below-scorenimmt ein Schwellenwertargument im Bereich von 1-100 entgegen. In diesem Fall wird der Befehl mit dem Exit-Code 4 beendet, wenn die Bewertung unter dem Schwellenwert liegt. Das ist sehr praktisch, wenn Sie einen spezifischen Schwellenwert (sagen wir 75) haben und eine Benachrichtigung erhalten möchten, wenn die Bewertung darunter fällt. - Flagge
--set-exit-code-on-dangerführt dazu, dass der Befehl mit dem Code 3 beendet wird, wenn einer der Danger-Tests fehlschlägt.
Lassen Sie uns nun versuchen, einen benutzerdefinierten Test zu erstellen, der überprüft, ob das Image aus einem vertrauenswürdigen Repository stammt. Benutzerdefinierte Tests werden im YAML-Format definiert, und der Test selbst wird mit JSON Schema beschrieben.
Der folgende YAML-Code beschreibt einen neuen Test mit dem Namen checkImageRepo:
checkImageRepo:
successMessage: Das Image-Repository ist gültig
failureMessage: Das Image-Repository ist ungültig
category: Bilder
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$Werfen wir einen genaueren Blick darauf:
successMessage— dieser Text wird ausgegeben, wenn der Test erfolgreich ist;failureMessage— diese Nachricht wird im Falle eines Fehlers angezeigt;category— gibt eine der Kategorien an:Bilder,Gesundheitsprüfungen,Sicherheit,NetworkingundRessourcen;target—- definiert, auf welchen Objekttyp (spec) der Test angewendet wird. Mögliche Werte:Container,PododerController;- Der Test selbst wird in einem Objekt
Schemamithilfe des JSON-Schemas definiert. In diesem Test wird das Schlüsselwortpatternverwendet, um die Bildquelle mit dem erforderlichen Wert zu vergleichen.
Um den oben genannten Test auszuführen, ist die folgende Polaris-Konfiguration erforderlich:
checks:
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Das Image-Repository ist gültig
failureMessage: Das Image-Repository ist ungültig
category: Bilder
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$(polaris-conf.yaml)
Lass uns die Datei analysieren:
- Im Feld
checksEs werden Tests und deren Kritikalitätsstufen definiert. Da es wünschenswert ist, eine Warnung zu erhalten, wenn das Image aus einer unsicheren Quelle stammt, setzen wir hier die Stufedanger. - Der Test selbst
checkImageRepowird dann im Objekt festgelegtcustomChecks.
Speichern Sie die Datei als custom_check.yaml. Jetzt können Sie starten polaris audit mit dem YAML-Manifest, das eine Überprüfung erfordert.
Testen wir unser Manifest base-valid.yaml:
$ polaris audit --config custom_check.yaml --audit-path base-valid.yamlDer Befehl polaris audit hat nur den oben definierten benutzerdefinierten Test durchgeführt, und dieser war nicht erfolgreich.
Wenn das Image geändert wird in my-company.com/http-echo:1.0, wird die Polaris-Überprüfung erfolgreich abgeschlossen. Das Manifest mit den Änderungen existiert bereits in , sodass Sie den vorherigen Befehl am Manifest überprüfen können. image-valid-mycompany.yaml.
Jetzt stellt sich die Frage: Wie führt man die integrierten Tests zusammen mit den benutzerdefinierten aus? Ganz einfach! Sie müssen lediglich die Identifikatoren der integrierten Tests in die Konfigurationsdatei einfügen. Infolgedessen sieht sie wie folgt aus:
Überprüfungen:
cpuRequestsMissing: Warnung
cpuLimitsMissing: Warnung
# Weitere integrierte Überprüfungen..
# ..
# benutzerdefinierte Überprüfungen
checkImageRepo: Gefahr # !!!
benuzterdefinierteÜberprüfungen:
checkImageRepo: # !!!
successMessage: Image-Registry ist gültig
failureMessage: Image-Registry ist nicht gültig
category: Bilder
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: objekt
properties:
image:
type: string
pattern: ^my-company.com/.+$(config_with_custom_check.yaml)
Ein Beispiel für eine vollständige Konfigurationsdatei ist verfügbar .
Manifest überprüfen base-valid.yaml, indem Sie integrierte und benutzerdefinierte Tests mit dem folgenden Befehl verwenden:
$ polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yamlPolaris ergänzt integrierte Tests durch benutzerdefinierte, wodurch das Beste aus beiden Welten kombiniert wird.
Auf der anderen Seite könnte die Unfähigkeit, leistungsfähigere Sprachen wie Rego oder JavaScript zu verwenden, ein begrenzender Faktor sein, der die Erstellung ausgefeilterer Tests behindert.
Weitere Informationen über Polaris sind verfügbar unter .
Zusammenfassung
Obwohl es viele Tools zur Prüfung und Bewertung von YAML-Dateien für Kubernetes gibt, ist es wichtig, ein klares Verständnis dafür zu haben, wie die Tests entworfen und durchgeführt werden.
Zum Beispiel wenn Kubernetes-Manifeste durch die Pipeline gehen, könnte kubeval der erste Schritt in einer solchen Pipeline sein.. Er würde darauf achten, ob die Objektdefinitionen mit dem Kubernetes-API-Schema übereinstimmen.
Nach Abschluss einer solchen Überprüfung könnte man zu anspruchsvolleren Tests übergehen, wie etwa der Übereinstimmung mit bewährten Standards und speziellen Richtlinien. Hier wären kube-score und Polaris hilfreich.
Für diejenigen mit komplexen Anforderungen, die eine detaillierte Anpassung der Tests benötigen, wären copper, config-lint und conftest empfehlenswert..
Conftest und config-lint verwenden YAML zur Definition benutzerdefinierter Tests, während copper Zugang zu einer vollwertigen Programmiersprache bietet, was es zu einer attraktiven Wahl macht.
Auf der anderen Seite, sollte man eines dieser Tools verwenden und somit alle Tests manuell erstellen, oder lieber Polaris bevorzugen und nur das hinzufügen, was benötigt wird? Es gibt keine eindeutige Antwort auf diese Frage..
Die folgende Tabelle enthält eine kurze Beschreibung jedes Tools:
Ein Tool
Zweck
Nachteile
Benutzerdefinierte Tests
kubeval
Überprüft YAML-Manifestdateien auf Übereinstimmung mit einer bestimmten Version des API-Schemas
Kann nicht mit CRD arbeiten
Nein
kube-score
Analysiert YAML-Manifestdateien auf Übereinstimmung mit bewährten Praktiken
Es kann keine eigene Kubernetes-API-Version zur Überprüfung von Ressourcen ausgewählt werden.
Nein
copper
Ein plattformübergreifendes Framework zur Erstellung eigener JavaScript-Tests für YAML-Manifeste.
Keine eingebauten Tests. Mangelnde Dokumentation.
Ja
config-lint
Ein allgemeines Framework zur Erstellung von Tests in einer domänenspezifischen Sprache, die in YAML integriert ist. Unterstützt verschiedene Konfigurationsformate (z. B. Terraform).
Keine fertigen Tests. Eingebettete Assertions und Funktionen reichen möglicherweise nicht aus.
Ja
conftest
Framework zur Erstellung eigener Tests in Rego (einer spezialisierten Abfragesprache). Ermöglicht das Teilen von Richtlinien über OCI Bundles.
Keine eingebauten Tests. Man muss Rego erlernen. Docker Hub wird nicht unterstützt, wenn Richtlinien veröffentlicht werden.
Ja
Polaris
Analysiert YAML-Manifeste auf Übereinstimmung mit branchenüblichen Best Practices. Ermöglicht die Erstellung eigener Tests mit JSON Schema.
Die Testmöglichkeiten, die auf JSON Schema basieren, könnten unzureichend sein.
Ja
Da diese Werkzeuge keinen Zugang zum Kubernetes-Cluster benötigen, sind sie leicht zu installieren. Sie ermöglichen das Filtern von Quellcode und bieten den Autoren von Pull-Requests in Projekten schnelles Feedback.
P.S. vom Übersetzer
Lesen Sie auch in unserem Blog:
- «»;
- «»;
- «».
Quelle: habr.com
