Validieren Sie Kubernetes YAML anhand von Best Practices und Richtlinien

Notiz. übersetzen: Mit der wachsenden Zahl von YAML-Konfigurationen für K8s-Umgebungen wird der Bedarf an deren automatisierter Überprüfung immer dringlicher. Der Autor dieser Rezension hat nicht nur bestehende Lösungen für diese Aufgabe ausgewählt, sondern auch Deployment als Beispiel verwendet, um zu sehen, wie sie funktionieren. Es erwies sich als sehr informativ für diejenigen, die sich für dieses Thema interessieren.

Validieren Sie Kubernetes YAML anhand von Best Practices und Richtlinien

TL; DR: In diesem Artikel werden sechs statische Tools zur Validierung und Bewertung von Kubernetes-YAML-Dateien anhand von Best Practices und Anforderungen verglichen.

Kubernetes-Workloads werden typischerweise in Form von YAML-Dokumenten definiert. Eines der Probleme mit YAML ist die Schwierigkeit, Einschränkungen oder Beziehungen zwischen Manifestdateien anzugeben.

Was ist, wenn wir sicherstellen müssen, dass alle im Cluster bereitgestellten Images aus einer vertrauenswürdigen Registrierung stammen?

Wie kann ich verhindern, dass Bereitstellungen ohne PodDisruptionBudgets an den Cluster gesendet werden?

Durch die Integration statischer Tests können Sie Fehler und Richtlinienverstöße bereits in der Entwicklungsphase erkennen. Dies erhöht die Garantie dafür, dass Ressourcendefinitionen korrekt und sicher sind, und erhöht die Wahrscheinlichkeit, dass Produktions-Workloads den Best Practices folgen.

Das statische YAML-Dateiinspektionsökosystem von Kubernetes kann in die folgenden Kategorien unterteilt werden:

  • API-Validatoren. Tools in dieser Kategorie prüfen das YAML-Manifest anhand der Anforderungen des Kubernetes-API-Servers.
  • Bereite Tester. Tools aus dieser Kategorie werden mit vorgefertigten Tests für Sicherheit, Einhaltung von Best Practices usw. geliefert.
  • Benutzerdefinierte Validatoren. Vertreter dieser Kategorie ermöglichen Ihnen die Erstellung benutzerdefinierter Tests in verschiedenen Sprachen, beispielsweise Rego und Javascript.

In diesem Artikel beschreiben und vergleichen wir sechs verschiedene Tools:

  1. kubeval;
  2. kube-score;
  3. config-lint;
  4. Kupfer;
  5. conftest;
  6. Polaris.

Nun, fangen wir an!

Bereitstellungen prüfen

Bevor wir mit dem Vergleichen von Tools beginnen, erstellen wir zunächst einen Hintergrund, auf dem wir sie testen können.

Das folgende Manifest enthält eine Reihe von Fehlern und Verstößen gegen 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 verwenden, um verschiedene Tools zu vergleichen.

Das obige Manifest base-valid.yaml und weitere Manifeste aus diesem Artikel finden Sie in Git-Repositorys.

Das Manifest beschreibt eine Webanwendung, deren Hauptaufgabe darin besteht, mit einer „Hello World“-Nachricht auf Port 5678 zu antworten. Sie kann mit dem folgenden Befehl bereitgestellt werden:

kubectl apply -f hello-world.yaml

Und so - überprüfen Sie die Arbeit:

kubectl port-forward svc/http-echo 8080:5678

Gehe jetzt zu http://localhost:8080 und bestätigen Sie, dass die Anwendung funktioniert. Aber folgt es den Best Practices? Lass uns das Prüfen.

1. Kubeval

Das Herzstück kubeval Die Idee ist, dass jede Interaktion mit Kubernetes über seine REST-API erfolgt. Mit anderen Worten: Sie können ein API-Schema verwenden, um zu prüfen, ob eine bestimmte YAML damit konform ist. Schauen wir uns ein Beispiel an.

Installationsanleitung kubeval sind auf der Projektwebsite verfügbar.

Zum Zeitpunkt der Erstellung des Originalartikels war Version 0.15.0 verfügbar.

Sobald es installiert ist, füttern wir es mit dem Manifest oben:

$ kubeval base-valid.yaml
PASS - base-valid.yaml contains a valid Deployment (http-echo)
PASS - base-valid.yaml contains a valid Service (http-echo)

Bei Erfolg wird kubeval mit dem Exit-Code 0 beendet. Sie können dies wie folgt überprüfen:

$ echo $?
0

Versuchen wir es nun mit Kubeval mit einem anderen Manifest:

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 mit bloßem Auge erkennen? Lasst uns starten:

$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml contains an invalid Deployment (http-echo) - selector: selector is required
PASS - kubeval-invalid.yaml contains a valid Service (http-echo)

# проверим код возврата
$ echo $?
1

Die Ressource wird nicht überprüft.

Bereitstellungen mit der API-Version apps/v1, muss einen Selektor enthalten, der mit der Bezeichnung des Pods übereinstimmt. Das obige Manifest enthält den Selektor nicht, daher hat kubeval einen Fehler gemeldet und mit einem Code ungleich Null beendet.

Ich frage mich, was passieren wird, wenn ich es tue kubectl apply -f mit diesem Manifest?

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=false

Dies ist genau der Fehler, vor dem Kubeval gewarnt hat. Sie können dies beheben, indem Sie einen Selektor hinzufügen:

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 Tools wie kubeval besteht darin, dass Fehler wie diese frühzeitig im Bereitstellungszyklus erkannt werden können.

Darüber hinaus ist für diese Prüfungen kein Zugriff auf den Cluster erforderlich, sie können offline durchgeführt werden.

Standardmäßig prüft kubeval Ressourcen anhand des neuesten Kubernetes-API-Schemas. In den meisten Fällen müssen Sie jedoch möglicherweise eine Prüfung anhand einer bestimmten Kubernetes-Version durchführen. Dies kann mithilfe der Flagge erfolgen --kubernetes-version:

$ kubeval --kubernetes-version 1.16.1 base-valid.yaml

Bitte beachten Sie, dass im Format die Version angegeben werden muss Major.Minor.Patch.

Eine Liste der Versionen, für die die Verifizierung unterstützt wird, finden Sie unter JSON-Schema auf GitHub, das kubeval zur Validierung verwendet. Wenn Sie kubeval offline ausführen müssen, laden Sie die Schemata herunter und geben Sie ihren lokalen Speicherort mithilfe des Flags an --schema-location.

Neben einzelnen YAML-Dateien kann kubeval auch mit Verzeichnissen und stdin arbeiten.

Darüber hinaus lässt sich Kubeval problemlos in die CI-Pipeline integrieren. Diejenigen, die Tests durchführen möchten, bevor sie Manifeste an den Cluster senden, werden erfreut sein zu erfahren, dass kubeval drei Ausgabeformate unterstützt:

  1. Klartext;
  2. JSON;
  3. Test Anything Protocol (TAP).

Und jedes der Formate kann zur weiteren Analyse der Ausgabe verwendet werden, um eine Zusammenfassung der Ergebnisse des gewünschten Typs zu erstellen.

Einer der Nachteile von Kubeval besteht darin, dass es derzeit nicht die Einhaltung von Custom Resource Definitions (CRDs) prüfen kann. Es ist jedoch möglich, Kubeval zu konfigurieren ignoriere sie.

Kubeval ist ein großartiges Tool zum Überprüfen und Bewerten von Ressourcen. Es sollte jedoch betont werden, dass das Bestehen des Tests keine Garantie dafür ist, dass die Ressource den Best Practices entspricht.

Zum Beispiel mit dem Tag latest in einem Container entspricht nicht den Best Practices. Kubeval betrachtet dies jedoch nicht als Fehler und meldet ihn nicht. Das heißt, die Überprüfung einer solchen YAML wird ohne Warnungen abgeschlossen.

Was aber, wenn Sie YAML auswerten und Verstöße wie das Tag identifizieren möchten? latest? Wie überprüfe ich eine YAML-Datei anhand von Best Practices?

2. Kube-Score

Kube-Score analysiert YAML-Manifeste und bewertet sie anhand integrierter Tests. Diese Tests werden auf der Grundlage von Sicherheitsrichtlinien und Best Practices ausgewählt, wie zum Beispiel:

  • Den Container nicht als Root ausführen.
  • Verfügbarkeit von Pod-Gesundheitsprüfungen.
  • Anforderungen und Limits für Ressourcen festlegen.

Basierend auf den Testergebnissen werden drei Ergebnisse angegeben: OK, WARNUNG и KRITISCH.

Sie können Kube-Score online ausprobieren oder lokal installieren.

Zum Zeitpunkt der Erstellung des Originalartikels war die neueste Version von kube-score 1.7.0.

Probieren wir es auf unserem Manifest aus base-valid.yaml:

$ kube-score score base-valid.yaml

apps/v1/Deployment http-echo
[CRITICAL] Container Image Tag
  · http-echo -> Image with latest tag
      Using a fixed tag is recommended to avoid accidental upgrades
[CRITICAL] Pod NetworkPolicy
  · The pod does not have a matching network policy
      Create a NetworkPolicy that targets this pod
[CRITICAL] Pod Probes
  · Container is missing a readinessProbe
      A readinessProbe should be used to indicate when the service is ready to receive traffic.
      Without it, the Pod is risking to receive traffic before it has booted. It is also used during
      rollouts, and can prevent downtime if a new version of the application is failing.
      More information: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITICAL] Container Security Context
  · http-echo -> Container has no configured security context
      Set securityContext to run the container in a more secure context.
[CRITICAL] Container Resources
  · http-echo -> CPU limit is not set
      Resource limits are recommended to avoid resource DDOS. Set resources.limits.cpu
  · http-echo -> Memory limit is not set
      Resource limits are recommended to avoid resource DDOS. Set resources.limits.memory
  · http-echo -> CPU request is not set
      Resource requests are recommended to make sure that the application can start and run without
      crashing. Set resources.requests.cpu
  · http-echo -> Memory request is not set
      Resource requests are recommended to make sure that the application can start and run without crashing.
      Set resources.requests.memory
[CRITICAL] Deployment has PodDisruptionBudget
  · No matching PodDisruptionBudget was found
      It is recommended to define a PodDisruptionBudget to avoid unexpected downtime during Kubernetes
      maintenance operations, such as when draining a node.
[WARNING] Deployment has host PodAntiAffinity
  · Deployment does not have a host podAntiAffinity set
      It is recommended to set a podAntiAffinity that stops multiple pods from a deployment from
      being scheduled on the same node. This increases availability in case the node becomes unavailable.

YAML besteht Kubeval-Tests, während Kube-Score auf die folgenden Mängel hinweist:

  • Bereitschaftsprüfungen sind nicht konfiguriert.
  • Es gibt keine Anforderungen oder Beschränkungen für CPU-Ressourcen und Speicher.
  • Budgets für Pod-Unterbrechungen sind nicht angegeben.
  • Es gibt keine Trennungsregeln (Anti-Affinität) um die Verfügbarkeit zu maximieren.
  • Der Container wird als Root ausgeführt.

Dies sind alles gültige Punkte zu Mängeln, die behoben werden müssen, um die Bereitstellung effizienter und zuverlässiger zu gestalten.

Team kube-score Zeigt Informationen in für Menschen lesbarer Form an, einschließlich aller Typverstöße WARNUNG и KRITISCH, was bei der Entwicklung sehr hilfreich ist.

Wer dieses Tool innerhalb der CI-Pipeline verwenden möchte, kann mithilfe des Flags eine stärker komprimierte Ausgabe aktivieren --output-format ci (In diesem Fall werden auch Tests mit dem Ergebnis angezeigt 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 is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory limit is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Image with latest tag
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: The pod does not have a matching network policy
[CRITICAL] http-echo apps/v1/Deployment: Container is missing a readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Container has no configured security context
[CRITICAL] http-echo apps/v1/Deployment: No matching PodDisruptionBudget was found
[WARNING] http-echo apps/v1/Deployment: Deployment does not have a host podAntiAffinity set
[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 Exit-Code ungleich Null zurück, wenn ein Test fehlschlägt KRITISCH. Sie können eine ähnliche Verarbeitung auch für aktivieren WARNUNG.

Darüber hinaus ist es möglich, Ressourcen auf Konformität mit verschiedenen API-Versionen zu überprüfen (wie in kubeval). Diese Informationen sind jedoch im Kube-Score selbst fest codiert: Sie können keine andere Version von Kubernetes auswählen. Diese Einschränkung kann ein großes Problem darstellen, wenn Sie beabsichtigen, Ihren Cluster zu aktualisieren, oder wenn Sie über mehrere Cluster mit unterschiedlichen K8-Versionen verfügen.

Bitte beachten Sie, dass Es gibt bereits ein Problem mit einem Vorschlag, diese Chance zu nutzen.

Weitere Informationen zum Kube-Score finden Sie unter die offizielle Seite.

Kube-Score-Tests sind ein großartiges Tool zur Implementierung von Best Practices. Was aber, wenn Sie Änderungen am Test vornehmen oder Ihre eigenen Regeln hinzufügen müssen? Leider ist dies nicht möglich.

Kube-Score ist nicht erweiterbar: Sie können keine Richtlinien hinzufügen oder anpassen.

Wenn Sie benutzerdefinierte Tests schreiben müssen, um die Einhaltung von Unternehmensrichtlinien zu überprüfen, können Sie eines der folgenden vier Tools verwenden: config-lint, copper, conftest oder polaris.

3.Config-lint

Config-lint ist ein Tool zur Validierung von YAML-, JSON-, Terraform-, CSV-Konfigurationsdateien und Kubernetes-Manifesten.

Sie können es mit installieren Anweisungen auf der Projektwebsite.

Die aktuelle Version zum Zeitpunkt der Erstellung des Originalartikels ist 1.5.0.

Config-lint verfügt nicht über integrierte Tests zur Validierung von Kubernetes-Manifesten.

Um Tests durchführen zu können, müssen Sie entsprechende Regeln erstellen. Sie sind in YAML-Dateien namens „Regelsätze“ geschrieben. (Regelsätze)und haben die folgende Struktur:

version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
  - "*.yaml"
rules:
   # список правил

(rule.yaml)

Schauen wir uns das genauer an:

  • Feld type Gibt an, welche Art von Konfiguration config-lint verwenden wird. Für K8s-Manifeste ist dies der Fall immer Kubernetes.
  • Im files Zusätzlich zu den Dateien selbst können Sie ein Verzeichnis angeben.
  • Feld rules zum Festlegen von Benutzertests vorgesehen.

Angenommen, Sie möchten sicherstellen, dass Bilder in der Bereitstellung immer von einem vertrauenswürdigen Repository wie heruntergeladen werden my-company.com/myapp:1.0. Eine config-lint-Regel, die eine solche Prüfung durchführt, würde wie folgt aussehen:

- id: MY_DEPLOYMENT_IMAGE_TAG
  severity: FAILURE
  message: Deployment must use a valid image tag
  resource: Deployment
  assertions:
    - every:
        key: spec.template.spec.containers
        expressions:
          - key: image
            op: starts-with
            value: "my-company.com/"

(rule-trusted-repo.yaml)

Jede Regel muss die folgenden Attribute haben:

  • id — eindeutige Kennung der Regel;
  • severity - kann sein FEHLER, WARNUNG и NICHT_KONFORM;
  • message — Bei einem Regelverstoß wird der Inhalt dieser Zeile angezeigt;
  • resource — die Art der Ressource, für die diese Regel gilt;
  • assertions – eine Liste von Bedingungen, die in Bezug auf diese Ressource ausgewertet werden.

In der Regel oben assertion berechtigt every prüft, ob sich alle Container im Deployment befinden (key: spec.templates.spec.containers) vertrauenswürdige Bilder verwenden (d. h. beginnend mit my-company.com/).

Der komplette Regelsatz sieht so aus:

version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
  - "*.yaml"
rules:

 - id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
    severity: FAILURE
    message: Deployment must use a valid image repository
    resource: Deployment
    assertions:
      - every:
          key: spec.template.spec.containers
          expressions:
            - key: image
              op: starts-with
              value: "my-company.com/"

(ruleset.yaml)

Um den Test auszuprobieren, speichern wir ihn unter check_image_repo.yaml. Lassen Sie uns die Datei überprüfen base-valid.yaml:

$ config-lint -rules check_image_repo.yaml base-valid.yaml

[
  {
  "AssertionMessage": "Every expression fails: And expression fails: image does not start with 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": "Deployment must use a valid image repository",
  "Status": "FAILURE"
  }
]

Die Prüfung ist fehlgeschlagen. Schauen wir uns nun das folgende Manifest mit dem richtigen Image-Repository an:

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 den gleichen Test mit dem obigen Manifest durch. Keine Probleme gefunden:

$ config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]

Config-lint ist ein vielversprechendes Framework, mit dem Sie eigene Tests zur Validierung von Kubernetes-YAML-Manifesten mithilfe der YAML-DSL erstellen können.

Was aber, wenn Sie komplexere Logik und Tests benötigen? Ist YAML dafür nicht zu begrenzt? Was wäre, wenn Sie Tests in einer vollständigen Programmiersprache erstellen könnten?

4. Kupfer

Kupfer V2 ist ein Framework zur Validierung von Manifesten mithilfe benutzerdefinierter Tests (ähnlich wie config-lint).

Der Unterschied zu Letzterem besteht jedoch darin, dass zur Beschreibung von Tests kein YAML verwendet wird. Tests können stattdessen in JavaScript geschrieben werden. Copper stellt eine Bibliothek mit mehreren grundlegenden Werkzeugen bereit, die Ihnen helfen, Informationen über Kubernetes-Objekte zu lesen und Fehler zu melden.

Die Schritte zur Installation von Copper finden Sie in amtliche Dokumentation.

2.0.1 ist die neueste Version dieses Dienstprogramms zum Zeitpunkt der Erstellung des Originalartikels.

Wie config-lint verfügt auch Copper über keine integrierten Tests. Lass uns eins schreiben. Lassen Sie es überprüfen, ob Bereitstellungen Container-Images ausschließlich aus vertrauenswürdigen Repositorys wie verwenden my-company.com.

Erstellen Sie eine Datei 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',"Image " + $.metadata.name + " is not from my-company.com repo", 1)
            }
        });
    }
});

Nun testen wir unser Manifest base-valid.yaml, verwenden Sie den Befehl copper validate:

$ copper validate --in=base-valid.yaml --validator=check_image_tag.js

Check no_company_repo failed with severity 1 due to Image http-echo is not from my-company.com repo
Validation failed

Es ist klar, dass Sie mit Hilfe von Kupfer komplexere Tests durchführen können – zum Beispiel die Überprüfung von Domänennamen in Ingress-Manifesten oder die Ablehnung von Pods, die im privilegierten Modus ausgeführt werden.

In Kupfer sind verschiedene nützliche Funktionen integriert:

  • DockerImage liest die angegebene Eingabedatei und erstellt ein Objekt mit den folgenden Attributen:
    • name - Name des Bildes,
    • tag - Bild-Tag,
    • registry - Bildregister,
    • registry_url - Protokoll (https://) und Bildregister,
    • fqin — vollständige Position des Bildes.
  • Funktion findByName hilft, eine Ressource nach einem bestimmten Typ zu finden (kind) und Name (name) aus der Eingabedatei.
  • Funktion findByLabels hilft, eine Ressource nach einem bestimmten Typ zu finden (kind) und Etiketten (labels).

Sie können alle verfügbaren Servicefunktionen einsehen hier.

Standardmäßig wird die gesamte eingegebene YAML-Datei in eine Variable geladen $$ und stellt es für die Skripterstellung zur Verfügung (eine vertraute Technik für diejenigen mit jQuery-Erfahrung).

Der Hauptvorteil von Copper liegt auf der Hand: Sie müssen keine spezielle Sprache beherrschen und können verschiedene JavaScript-Funktionen verwenden, um Ihre eigenen Tests zu erstellen, wie z. B. String-Interpolation, Funktionen usw.

Es sollte auch beachtet werden, dass die aktuelle Version von Copper mit der ES5-Version der JavaScript-Engine funktioniert, nicht mit ES6.

Einzelheiten finden Sie unter die offizielle Website des Projekts.

Wenn Sie jedoch JavaScript nicht wirklich mögen und eine Sprache bevorzugen, die speziell für die Erstellung von Abfragen und die Beschreibung von Richtlinien entwickelt wurde, sollten Sie auf conftest achten.

5.Wettbewerb

Conftest ist ein Framework zum Testen von Konfigurationsdaten. Auch zum Testen/Verifizieren von Kubernetes-Manifesten geeignet. Tests werden mithilfe einer speziellen Abfragesprache beschrieben Rego.

Sie können conftest mit installieren Anweisungenauf der Projektwebsite aufgeführt.

Zum Zeitpunkt der Erstellung des Originalartikels war die neueste verfügbare Version 0.18.2.

Ähnlich wie config-lint und copper kommt conftest ohne integrierte Tests aus. Probieren wir es aus und schreiben wir unsere eigene Richtlinie. Wie in den vorherigen Beispielen prüfen wir, ob die Containerbilder aus einer zuverlässigen Quelle stammen.

Erstellen Sie ein Verzeichnis conftest-checks, und darin befindet sich 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' doesn't come from my-company.com repository", [image])
}

Jetzt lasst uns testen base-valid.yaml durch conftest:

$ conftest test --policy ./conftest-checks base-valid.yaml

FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
1 tests, 1 passed, 0 warnings, 1 failure

Der Test schlug vorhersehbar fehl, da die Bilder von einer nicht vertrauenswürdigen Quelle stammten.

In der Rego-Datei definieren wir den Block deny. Sein Wahrheitsgehalt gilt als Verstoß. Wenn blockiert deny Bei mehreren Blöcken prüft conftest sie unabhängig voneinander, und die Wahrheit eines der Blöcke wird als Verstoß behandelt.

Zusätzlich zur Standardausgabe unterstützt conftest JSON, TAP und das Tabellenformat – eine äußerst nützliche Funktion, wenn Sie Berichte in eine vorhandene CI-Pipeline einbetten müssen. Über das Flag können Sie das gewünschte Format einstellen --output.

Um das Debuggen von Richtlinien zu erleichtern, verfügt conftest über ein Flag --trace. Es gibt eine Spur davon aus, wie conftest die angegebenen Richtliniendateien analysiert.

Wettbewerbsrichtlinien können als Artefakte in OCI-Registern (Open Container Initiative) veröffentlicht und geteilt werden.

Befehle push и pull ermöglichen es Ihnen, ein Artefakt zu veröffentlichen oder ein vorhandenes Artefakt aus einer Remote-Registrierung abzurufen. Versuchen wir, die von uns erstellte Richtlinie mithilfe von in der lokalen Docker-Registrierung zu veröffentlichen conftest push.

Starten Sie Ihre lokale Docker-Registrierung:

$ docker run -it --rm -p 5000:5000 registry

Gehen Sie in einem anderen Terminal zu dem Verzeichnis, das Sie zuvor erstellt haben conftest-checks und führen Sie den folgenden Befehl aus:

$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latest

Wenn der Befehl erfolgreich war, wird eine Meldung wie diese angezeigt:

2020/06/10 14:25:43 pushed bundle with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609c

Erstellen Sie nun ein temporäres Verzeichnis und führen Sie darin den Befehl aus conftest pull. Das mit dem vorherigen Befehl erstellte Paket wird heruntergeladen:

$ cd $(mktemp -d)
$ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latest

Im temporären Verzeichnis wird ein Unterverzeichnis angezeigt policyenthält unsere Richtliniendatei:

$ tree
.
└── policy
  └── check_image_registry.rego

Tests können direkt aus dem Repository ausgeführt werden:

$ 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 failure

Leider wird DockerHub noch nicht unterstützt. Seien Sie also froh, wenn Sie es verwenden Azure Container Registry (ACR) oder Ihre eigene Registry.

Das Artefaktformat ist das gleiche wie Öffnen Sie Policy Agent-Pakete (OPA), mit dem Sie mit conftest Tests aus vorhandenen OPA-Paketen ausführen können.

Weitere Informationen zum Teilen von Richtlinien und anderen Funktionen von conftest finden Sie unter die offizielle Website des Projekts.

6. Polaris

Das letzte Tool, das in diesem Artikel besprochen wird, ist Polaris. (Seine Ankündigung vom letzten Jahr haben wir bereits übersetzt - ca. Übersetzung)

Polaris kann in einem Cluster installiert oder im Befehlszeilenmodus verwendet werden. Wie Sie vielleicht schon vermutet haben, können Sie damit Kubernetes-Manifeste statisch analysieren.

Bei der Ausführung im Befehlszeilenmodus stehen integrierte Tests zur Verfügung, die Bereiche wie Sicherheit und Best Practices abdecken (ähnlich wie bei kube-score). Darüber hinaus können Sie eigene Tests erstellen (wie in config-lint, copper und conftest).

Mit anderen Worten: Polaris vereint die Vorteile beider Werkzeugkategorien: mit integrierten und benutzerdefinierten Tests.

Um Polaris im Befehlszeilenmodus zu installieren, verwenden Sie Anweisungen auf der Projektwebsite.

Zum Zeitpunkt der Erstellung des Originalartikels ist Version 1.0.3 verfügbar.

Sobald die Installation abgeschlossen ist, können Sie Polaris im Manifest ausführen base-valid.yaml mit folgendem Befehl:

$ polaris audit --audit-path base-valid.yaml

Es wird eine Zeichenfolge im JSON-Format mit einer detaillierten Beschreibung der durchgeführten Tests und ihrer Ergebnisse ausgegeben. Die Ausgabe 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": [
    /* длинный список */
  ]
}

Volle Leistung verfügbar hier.

Wie Kube-Score identifiziert Polaris Probleme in Bereichen, in denen das Manifest nicht den Best Practices entspricht:

  • Es gibt keine Gesundheitsprüfungen für Pods.
  • Tags für Containerbilder sind nicht angegeben.
  • Der Container wird als Root ausgeführt.
  • Anforderungen und Grenzen für Speicher und CPU werden nicht angegeben.

Jedem Test wird abhängig von seinen Ergebnissen ein Grad an Kritikalität zugeordnet: Warnung oder Gefahr. Weitere Informationen zu den verfügbaren integrierten Tests finden Sie unter Dokumentation.

Wenn keine Details benötigt werden, können Sie das Flag angeben --format score. In diesem Fall gibt Polaris eine Zahl zwischen 1 und 100 aus Ergebnis (d. h. Beurteilung):

$ polaris audit --audit-path test-data/base-valid.yaml --format score
68

Je näher der Wert bei 100 liegt, desto höher ist der Grad der Übereinstimmung. Wenn Sie den Exit-Code des Befehls überprüfen polaris audit, es stellt sich heraus, dass es gleich 0 ist.

Machen polaris audit Sie können die Arbeit mit Code ungleich Null mithilfe von zwei Flags beenden:

  • Flagge --set-exit-code-below-score nimmt als Argument einen Schwellenwert im Bereich 1-100. In diesem Fall wird der Befehl mit Exit-Code 4 beendet, wenn die Punktzahl unter dem Schwellenwert liegt. Dies ist sehr nützlich, wenn Sie einen bestimmten Schwellenwert haben (z. B. 75) und eine Benachrichtigung erhalten möchten, wenn der Wert unterschritten wird.
  • Flagge --set-exit-code-on-danger führt dazu, dass der Befehl mit Code 3 fehlschlägt, wenn einer der Gefahrentests fehlschlägt.

Versuchen wir nun, einen benutzerdefinierten Test zu erstellen, der prüft, ob das Image aus einem vertrauenswürdigen Repository stammt. Benutzerdefinierte Tests werden im YAML-Format angegeben und der Test selbst wird mithilfe des JSON-Schemas beschrieben.

Das folgende YAML-Code-Snippet beschreibt einen neuen Test namens checkImageRepo:

checkImageRepo:
  successMessage: Image registry is valid
  failureMessage: Image registry is not valid
  category: Images
  target: Container
  schema:
    '$schema': http://json-schema.org/draft-07/schema
    type: object
    properties:
      image:
        type: string
        pattern: ^my-company.com/.+$

Schauen wir es uns genauer an:

  • successMessage — Diese Zeile wird gedruckt, wenn der Test erfolgreich abgeschlossen wurde.
  • failureMessage — Diese Meldung wird im Fehlerfall angezeigt.
  • category – gibt eine der Kategorien an: Images, Health Checks, Security, Networking и Resources;
  • target--- bestimmt, welche Art von Objekt (spec)-Test angewendet wird. Mögliche Werte: Container, Pod oder Controller;
  • Der Test selbst wird im Objekt angegeben schema unter Verwendung des JSON-Schemas. Das Schlüsselwort in diesem Test ist pattern Wird verwendet, um die Bildquelle mit der erforderlichen zu vergleichen.

Um den obigen Test auszuführen, müssen Sie die folgende Polaris-Konfiguration erstellen:

checks:
  checkImageRepo: danger
customChecks:
  checkImageRepo:
    successMessage: Image registry is valid
    failureMessage: Image registry is not valid
    category: Images
    target: Container
    schema:
      '$schema': http://json-schema.org/draft-07/schema
      type: object
      properties:
        image:
          type: string
          pattern: ^my-company.com/.+$

(polaris-conf.yaml)

Lassen Sie uns die Datei analysieren:

  • Im checks Tests und deren Kritikalitätsgrad werden vorgegeben. Da es wünschenswert ist, eine Warnung zu erhalten, wenn ein Bild von einer nicht vertrauenswürdigen Quelle stammt, legen wir hier die Stufe fest danger.
  • Der Test selbst checkImageRepo dann im Objekt registriert customChecks.

Speichern Sie die Datei unter custom_check.yaml. Jetzt können Sie laufen polaris audit mit einem YAML-Manifest, das überprüft werden muss.

Testen wir unser Manifest base-valid.yaml:

$ polaris audit --config custom_check.yaml --audit-path base-valid.yaml

Team polaris audit Es wurde nur der oben angegebene Benutzertest ausgeführt, der jedoch fehlschlug.

Wenn Sie das Bild reparieren my-company.com/http-echo:1.0, Polaris wird erfolgreich abgeschlossen. Das Manifest mit den Änderungen ist bereits da LagerstättenSo können Sie den vorherigen Befehl im Manifest überprüfen image-valid-mycompany.yaml.

Nun stellt sich die Frage: Wie führt man integrierte Tests zusammen mit benutzerdefinierten Tests aus? Leicht! Sie müssen lediglich die integrierten Testkennungen zur Konfigurationsdatei hinzufügen. Als Ergebnis wird es die folgende Form annehmen:

checks:
  cpuRequestsMissing: warning
  cpuLimitsMissing: warning
  # Other inbuilt checks..
  # ..
  # custom checks
  checkImageRepo: danger # !!!
customChecks:
  checkImageRepo:        # !!!
    successMessage: Image registry is valid
    failureMessage: Image registry is not valid
    category: Images
    target: Container
    schema:
      '$schema': http://json-schema.org/draft-07/schema
      type: object
      properties:
        image:
          type: string
          pattern: ^my-company.com/.+$

(config_with_custom_check.yaml)

Ein Beispiel einer vollständigen Konfigurationsdatei ist verfügbar hier.

Überprüfen Sie das Manifest base-valid.yamlWenn Sie integrierte und benutzerdefinierte Tests verwenden, können Sie den folgenden Befehl verwenden:

$ polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yaml

Polaris ergänzt die integrierten Tests durch benutzerdefinierte Tests und vereint so das Beste aus beiden Welten.

Andererseits kann die Unfähigkeit, leistungsfähigere Sprachen wie Rego oder JavaScript zu verwenden, ein limitierender Faktor sein, der die Erstellung anspruchsvollerer Tests verhindert.

Weitere Informationen zu Polaris finden Sie unter Projektseite.

Zusammenfassung

Zwar stehen zahlreiche Tools zum Überprüfen und Auswerten von Kubernetes-YAML-Dateien zur Verfügung, Es ist wichtig, ein klares Verständnis darüber zu haben, wie die Tests konzipiert und durchgeführt werden.

Zum Beispiel kann die Wenn Sie Kubernetes-Manifeste durch eine Pipeline laufen lassen, könnte Kubeval der erste Schritt in einer solchen Pipeline sein. Es würde überwachen, ob Objektdefinitionen dem Kubernetes-API-Schema entsprechen.

Sobald eine solche Überprüfung abgeschlossen ist, könnte man mit anspruchsvolleren Tests fortfahren, beispielsweise der Einhaltung standardmäßiger Best Practices und spezifischer Richtlinien. Hier würden sich Kube-Score und Polaris als nützlich erweisen.

Für diejenigen, die komplexe Anforderungen haben und Tests im Detail anpassen müssen, wären Copper, config-lint und conftest geeignet.

Conftest und config-lint verwenden YAML, um benutzerdefinierte Tests zu definieren, und Copper bietet Ihnen Zugriff auf eine vollständige Programmiersprache, was es zu einer ziemlich attraktiven Wahl macht.

Lohnt es sich andererseits, eines dieser Tools zu verwenden und daher alle Tests manuell zu erstellen, oder lieber Polaris und nur das hinzufügen, was benötigt wird? Auf diese Frage gibt es keine eindeutige Antwort.

Die folgende Tabelle enthält eine kurze Beschreibung jedes Tools:

Werkzeug
Zweck
Begrenztheit
Benutzertests

kubeval
Validiert YAML-Manifeste anhand einer bestimmten Version des API-Schemas
Funktioniert nicht mit CRD
Nein

kube-score
Analysiert YAML-Manifeste anhand von Best Practices
Sie können Ihre Kubernetes-API-Version nicht auswählen, um Ressourcen zu überprüfen
Nein

Kupfer
Ein allgemeines Framework zum Erstellen benutzerdefinierter JavaScript-Tests für YAML-Manifeste
Keine integrierten Tests. Schlechte Dokumentation
Ja

config-lint
Ein allgemeines Framework zum Erstellen von Tests in einer domänenspezifischen Sprache, eingebettet in YAML. Unterstützt verschiedene Konfigurationsformate (z. B. Terraform)
Es gibt keine vorgefertigten Tests. Integrierte Behauptungen und Funktionen reichen möglicherweise nicht aus
Ja

conftest
Ein Framework zum Erstellen eigener Tests mit Rego (einer speziellen Abfragesprache). Ermöglicht die gemeinsame Nutzung von Richtlinien über OCI-Bundles
Keine integrierten Tests. Ich muss Rego lernen. Docker Hub wird beim Veröffentlichen von Richtlinien nicht unterstützt
Ja

Polaris
Überprüft YAML-Manifeste anhand standardmäßiger Best Practices. Ermöglicht Ihnen die Erstellung eigener Tests mithilfe des JSON-Schemas
Auf dem JSON-Schema basierende Testfunktionen sind möglicherweise nicht ausreichend
Ja

Da diese Tools nicht auf den Zugriff auf den Kubernetes-Cluster angewiesen sind, sind sie einfach zu installieren. Sie ermöglichen das Filtern von Quelldateien und geben den Autoren von Pull Requests in Projekten schnelles Feedback.

PS vom Übersetzer

Lesen Sie auch auf unserem Blog:

Source: habr.com

Kommentar hinzufügen