Valider Kubernetes YAML i forhold til bedste praksis og politikker

Bemærk. overs.: Med det voksende antal YAML-konfigurationer til K8s-miljøer bliver behovet for deres automatiserede verifikation mere og mere presserende. Forfatteren til denne anmeldelse valgte ikke kun eksisterende løsninger til denne opgave, men brugte også Deployment som et eksempel for at se, hvordan de fungerer. Det viste sig at være meget informativt for dem, der er interesserede i dette emne.

Valider Kubernetes YAML i forhold til bedste praksis og politikker

TL; DR: Denne artikel sammenligner seks statiske værktøjer til at validere og evaluere Kubernetes YAML-filer i forhold til bedste praksis og krav.

Kubernetes-arbejdsbelastninger er typisk defineret i form af YAML-dokumenter. Et af problemerne med YAML er vanskeligheden ved at specificere begrænsninger eller relationer mellem manifestfiler.

Hvad hvis vi skal sikre os, at alle billeder, der er implementeret til klyngen, kommer fra et pålideligt register?

Hvordan kan jeg forhindre implementeringer, der ikke har PodDisruptionBudgets, i at blive sendt til klyngen?

Integration af statisk test giver dig mulighed for at identificere fejl og politikovertrædelser på udviklingsstadiet. Dette øger garantien for, at ressourcedefinitionerne er korrekte og sikre, og gør det mere sandsynligt, at produktionsbelastningen følger bedste praksis.

Kubernetes statiske YAML-filinspektionsøkosystem kan opdeles i følgende kategorier:

  • API validatorer. Værktøjer i denne kategori kontrollerer YAML-manifestet i forhold til kravene fra Kubernetes API-serveren.
  • Klare testere. Værktøjer fra denne kategori kommer med færdige test for sikkerhed, overholdelse af bedste praksis osv.
  • Brugerdefinerede validatorer. Repræsentanter for denne kategori giver dig mulighed for at oprette brugerdefinerede tests på forskellige sprog, for eksempel Rego og Javascript.

I denne artikel vil vi beskrive og sammenligne seks forskellige værktøjer:

  1. kubeval;
  2. kube-score;
  3. config-lint;
  4. kobber;
  5. konkurrence;
  6. polaris.

Nå, lad os komme i gang!

Kontrol af implementeringer

Før vi begynder at sammenligne værktøjer, lad os skabe noget baggrund, som vi kan teste dem på.

Manifestet nedenfor indeholder en række fejl og manglende overholdelse af bedste praksis: hvor mange af dem kan du finde?

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)

Vi vil bruge denne YAML til at sammenligne forskellige værktøjer.

Ovenstående manifest base-valid.yaml og andre manifester fra denne artikel kan findes i Git repositories.

Manifestet beskriver en webapplikation, hvis hovedopgave er at svare med en "Hello World"-meddelelse til port 5678. Den kan implementeres med følgende kommando:

kubectl apply -f hello-world.yaml

Og så - tjek arbejdet:

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

Gå nu til http://localhost:8080 og bekræft, at applikationen virker. Men følger den bedste praksis? Lad os tjekke.

1. Kubeval

Kernen kubeval Ideen er, at enhver interaktion med Kubernetes sker gennem dens REST API. Med andre ord kan du bruge et API-skema til at kontrollere, om en given YAML er i overensstemmelse med det. Lad os se på et eksempel.

Installations instruktioner kubeval er tilgængelige på projektets hjemmeside.

På tidspunktet for skrivning af den originale artikel var version 0.15.0 tilgængelig.

Når det er installeret, lad os give det manifestet ovenfor:

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

Hvis det lykkes, afsluttes kubeval med udgangskode 0. Du kan kontrollere det på følgende måde:

$ echo $?
0

Lad os nu prøve kubeval med et andet 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)

Kan du se problemet med øjet? Lad os starte:

$ 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

Ressourcen bliver ikke verificeret.

Implementeringer ved hjælp af API-versionen apps/v1, skal indeholde en vælger, der matcher podens etiket. Manifestet ovenfor inkluderer ikke vælgeren, så kubeval rapporterede en fejl og afsluttede med en kode, der ikke er nul.

Jeg spekulerer på, hvad der vil ske, hvis jeg gør det kubectl apply -f med dette manifest?

Nå, lad os prøve:

$ 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

Det er præcis den fejl, som kubeval advarede om. Du kan rette dette ved at tilføje en vælger:

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)

Fordelen ved værktøjer som kubeval er, at fejl som disse kan fanges tidligt i implementeringscyklussen.

Derudover kræver disse kontroller ikke adgang til klyngen; de kan udføres offline.

Som standard kontrollerer kubeval ressourcer i forhold til det seneste Kubernetes API-skema. Men i de fleste tilfælde kan det være nødvendigt at tjekke mod en specifik Kubernetes-udgivelse. Dette kan gøres ved hjælp af flaget --kubernetes-version:

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

Bemærk venligst, at versionen skal angives i formatet Major.Minor.Patch.

For en liste over versioner, for hvilke verifikation er understøttet, henvises til JSON-skema på GitHub, som kubeval bruger til validering. Hvis du har brug for at køre kubeval offline, skal du downloade skemaerne og angive deres lokale placering ved hjælp af flaget --schema-location.

Udover individuelle YAML-filer kan kubeval også arbejde med mapper og stdin.

Derudover kan Kubeval nemt integreres i CI-pipelinen. De, der ønsker at køre test, før de sender manifester til klyngen, vil være glade for at vide, at kubeval understøtter tre outputformater:

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

Og et hvilket som helst af formaterne kan bruges til yderligere parsing af output for at generere en oversigt over resultaterne af den ønskede type.

En af ulemperne ved kubeval er, at den i øjeblikket ikke kan kontrollere for overensstemmelse med Custom Resource Definitions (CRD'er). Det er dog muligt at konfigurere kubeval ignorere dem.

Kubeval er et fantastisk værktøj til at kontrollere og evaluere ressourcer; Det skal dog understreges, at beståelse af testen ikke garanterer, at ressourcen er i overensstemmelse med bedste praksis.

For eksempel ved at bruge tagget latest i en container ikke følger bedste praksis. Kubeval betragter dog ikke dette som en fejl og rapporterer det ikke. Det vil sige, at verifikationen af ​​en sådan YAML fuldføres uden advarsler.

Men hvad nu hvis du vil evaluere YAML og identificere overtrædelser som tagget latest? Hvordan kontrollerer jeg en YAML-fil i forhold til bedste praksis?

2. Kube-score

Kube-score analyserer YAML-manifester og evaluerer dem i forhold til indbyggede tests. Disse tests er udvalgt ud fra sikkerhedsretningslinjer og bedste praksis, såsom:

  • Kører beholderen ikke som root.
  • Tilgængelighed af pod-sundhedstjek.
  • Indstilling af anmodninger og grænser for ressourcer.

Baseret på testresultaterne gives tre resultater: OK, ADVARSEL и KRITISK.

Du kan prøve Kube-score online eller installere det lokalt.

På tidspunktet for skrivning af den originale artikel var den seneste version af kube-score 1.7.0.

Lad os prøve det på vores manifest 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 består kubeval-tests, mens kube-score peger på følgende fejl:

  • Beredskabstjek er ikke konfigureret.
  • Der er ingen anmodninger eller begrænsninger for CPU-ressourcer og hukommelse.
  • Pod-afbrydelsesbudgetter er ikke specificeret.
  • Der er ingen regler for adskillelse (anti-affinitet) for at maksimere tilgængeligheden.
  • Beholderen kører som rod.

Disse er alle gyldige punkter om mangler, der skal løses for at gøre implementeringen mere effektiv og pålidelig.

Team kube-score viser information i menneskelig læsbar form, herunder alle typeovertrædelser ADVARSEL и KRITISK, hvilket hjælper meget under udviklingen.

De, der ønsker at bruge dette værktøj i CI-pipelinen, kan aktivere mere komprimeret output ved hjælp af flaget --output-format ci (i dette tilfælde vises også test med resultatet 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

I lighed med kubeval returnerer kube-score en udgangskode, der ikke er nul, når der er en test, der mislykkes KRITISK. Du kan også aktivere lignende behandling for ADVARSEL.

Derudover er det muligt at kontrollere ressourcer for overholdelse af forskellige API-versioner (som i kubeval). Denne information er dog hårdkodet i selve kube-score: du kan ikke vælge en anden version af Kubernetes. Denne begrænsning kan være et stort problem, hvis du har til hensigt at opgradere din klynge, eller hvis du har flere klynger med forskellige versioner af K8'er.

Bemærk, at der er allerede et problem med et forslag om at realisere denne mulighed.

Mere information om kube-score kan findes på det officielle site.

Kube-score-tests er et fantastisk værktøj til at implementere bedste praksis, men hvad nu hvis du skal lave ændringer i testen eller tilføje dine egne regler? Ak, dette kan ikke lade sig gøre.

Kube-score kan ikke udvides: du kan ikke tilføje politikker til det eller justere dem.

Hvis du har brug for at skrive brugerdefinerede tests for at bekræfte overholdelse af virksomhedens politikker, kan du bruge et af følgende fire værktøjer: config-lint, kobber, conftest eller polaris.

3.Config-lint

Config-lint er et værktøj til at validere YAML, JSON, Terraform, CSV-konfigurationsfiler og Kubernetes-manifester.

Du kan installere det vha instruktioner på projektets hjemmeside.

Den aktuelle udgivelse på tidspunktet for skrivning af den originale artikel er 1.5.0.

Config-lint har ikke indbyggede tests til validering af Kubernetes-manifester.

For at udføre nogen test skal du oprette passende regler. De er skrevet i YAML-filer kaldet "regelsæt" (regelsæt)og har følgende struktur:

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

(rule.yaml)

Lad os studere det nærmere:

  • Field type angiver, hvilken type konfiguration config-lint vil bruge. For K8s manifesterer dette altid Kubernetes.
  • I feltet files Ud over selve filerne kan du angive en mappe.
  • Field rules beregnet til indstilling af brugertest.

Lad os sige, at du vil sikre dig, at billeder i Deployment altid downloades fra et pålideligt lager som f.eks my-company.com/myapp:1.0. En config-lint-regel, der udfører en sådan kontrol, ville se sådan ud:

- 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)

Hver regel skal have følgende attributter:

  • id — entydig identifikator for reglen;
  • severity - Måske FIASKO, ADVARSEL и IKKE_KOMPLIANT;
  • message — hvis en regel overtrædes, vises indholdet af denne linje;
  • resource — den type ressource, som denne regel gælder for;
  • assertions — en liste over forhold, der vil blive evalueret i forhold til denne ressource.

I reglen ovenfor assertion berettiget every kontrollerer, at alle containere er i implementering (key: spec.templates.spec.containers) bruge pålidelige billeder (dvs. begyndende med my-company.com/).

Det komplette regelsæt ser således ud:

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)

For at prøve testen, lad os gemme den som check_image_repo.yaml. Lad os tjekke filen 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"
  }
]

Kontrollen mislykkedes. Lad os nu tjekke følgende manifest med det korrekte billedlager:

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)

Vi kører den samme test med ovenstående manifest. Ingen problemer fundet:

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

Config-lint er en lovende ramme, der giver dig mulighed for at oprette dine egne tests for at validere Kubernetes YAML-manifester ved hjælp af YAML DSL.

Men hvad hvis du har brug for mere kompleks logik og tests? Er YAML ikke for begrænset til dette? Hvad hvis du kunne lave test i et komplet programmeringssprog?

4. Kobber

Kobber V2 er en ramme til validering af manifester ved hjælp af brugerdefinerede tests (svarende til config-lint).

Den adskiller sig dog fra sidstnævnte ved, at den ikke bruger YAML til at beskrive tests. Tests kan i stedet skrives i JavaScript. Kobber giver et bibliotek med flere grundlæggende værktøjer, som hjælper dig med at læse information om Kubernetes-objekter og rapportere fejl.

Trinene til installation af kobber kan findes i officiel dokumentation.

2.0.1 er den seneste udgivelse af dette hjælpeprogram på tidspunktet for skrivning af den originale artikel.

Ligesom config-lint har Copper ikke indbyggede tests. Lad os skrive en. Lad det kontrollere, at implementeringer udelukkende bruger containerbilleder fra betroede lagre som f.eks my-company.com.

Opret en fil check_image_repo.js med følgende indhold:

$$.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)
            }
        });
    }
});

Nu for at teste vores manifest base-valid.yaml, brug kommandoen 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

Det er klart, at du ved hjælp af kobber kan udføre mere komplekse tests - for eksempel at tjekke domænenavne i Ingress-manifester eller afvise pods, der kører i privilegeret tilstand.

Kobber har forskellige hjælpefunktioner indbygget:

  • DockerImage læser den angivne inputfil og opretter et objekt med følgende attributter:
    • name - navn på billedet,
    • tag - billedmærke,
    • registry - billedregistrering,
    • registry_url - protokol (https://) og billedregistrering,
    • fqin — fuld placering af billedet.
  • Funktion findByName hjælper med at finde en ressource efter en given type (kind) og navn (name) fra inputfilen.
  • Funktion findByLabels hjælper med at finde en ressource efter en specificeret type (kind) og etiketter (labels).

Du kan se alle tilgængelige servicefunktioner her.

Som standard indlæser den hele input YAML-filen til en variabel $$ og gør det tilgængeligt for scripting (en velkendt teknik for dem med jQuery-erfaring).

Den største fordel ved Copper er indlysende: du behøver ikke at beherske et specialiseret sprog, og du kan bruge forskellige JavaScript-funktioner til at oprette dine egne tests, såsom strenginterpolation, funktioner osv.

Det skal også bemærkes, at den nuværende version af Copper fungerer med ES5-versionen af ​​JavaScript-motoren, ikke ES6.

Detaljer tilgængelige på officielle projekthjemmeside.

Men hvis du ikke rigtig kan lide JavaScript og foretrækker et sprog, der er specielt designet til at oprette forespørgsler og beskrive politikker, bør du være opmærksom på conftest.

5. Conftest

Conftest er en ramme til test af konfigurationsdata. Også velegnet til test/verificering af Kubernetes-manifester. Tests beskrives ved hjælp af et specialiseret forespørgselssprog Rego.

Du kan installere conftest vha instruktioneropført på projektets hjemmeside.

På tidspunktet for skrivning af den originale artikel var den seneste tilgængelige version 0.18.2.

I lighed med config-lint og kobber kommer conftest uden indbyggede tests. Lad os prøve det og skrive vores egen politik. Som i tidligere eksempler vil vi kontrollere, om containerbillederne er taget fra en pålidelig kilde.

Opret en mappe conftest-checks, og i den er der en fil med navnet check_image_registry.rego med følgende indhold:

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])
}

Lad os nu teste base-valid.yaml gennem 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

Testen mislykkedes forudsigeligt, fordi billederne kom fra en upålidelig kilde.

I Rego-filen definerer vi blokken deny. Dens sandhed betragtes som en krænkelse. Hvis blokerer deny flere, confetest kontrollerer dem uafhængigt af hinanden, og sandheden af ​​enhver af blokkene behandles som en overtrædelse.

Ud over standardoutputtet understøtter conftest JSON, TAP og tabelformat - en yderst nyttig funktion, hvis du har brug for at integrere rapporter i en eksisterende CI-pipeline. Du kan indstille det ønskede format ved hjælp af flaget --output.

For at gøre det nemmere at fejlsøge politikker har conftest et flag --trace. Det udsender et spor af, hvordan conftest analyserer de angivne politikfiler.

Konkurrencepolitikker kan publiceres og deles i OCI (Open Container Initiative) registre som artefakter.

Команды push и pull giver dig mulighed for at publicere en artefakt eller hente en eksisterende artefakt fra en fjernregistrering. Lad os prøve at udgive den politik, vi har oprettet, til det lokale Docker-register ved hjælp af conftest push.

Start dit lokale Docker-register:

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

I en anden terminal skal du gå til den mappe, du oprettede tidligere conftest-checks og kør følgende kommando:

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

Hvis kommandoen lykkedes, vil du se en meddelelse som denne:

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

Opret nu en midlertidig mappe og kør kommandoen i den conftest pull. Det vil downloade pakken oprettet af den forrige kommando:

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

En undermappe vises i den midlertidige mappe policyindeholdende vores politikfil:

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

Test kan køres direkte fra depotet:

$ 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

Desværre er DockerHub ikke understøttet endnu. Så anser dig selv for heldig, hvis du bruger Azure Container Registry (ACR) eller dit eget register.

Artefaktformatet er det samme som Åbn Policy Agent-pakker (OPA), som giver dig mulighed for at bruge confetest til at køre test fra eksisterende OPA-pakker.

Du kan lære mere om politikdeling og andre funktioner i conftest på officielle projekthjemmeside.

6. Polaris

Det sidste værktøj, der vil blive diskuteret i denne artikel er Polaris. (Hans sidste års meddelelse vi allerede oversatca. oversættelse)

Polaris kan installeres i en klynge eller bruges i kommandolinjetilstand. Som du måske har gættet, giver det dig mulighed for statisk at analysere Kubernetes-manifester.

Når du kører i kommandolinjetilstand, er indbyggede test tilgængelige, der dækker områder som sikkerhed og bedste praksis (svarende til kube-score). Derudover kan du oprette dine egne tests (som i config-lint, copper og confest).

Med andre ord kombinerer Polaris fordelene ved begge kategorier af værktøjer: med indbyggede og tilpassede tests.

For at installere Polaris i kommandolinjetilstand skal du bruge vejledning på projektets hjemmeside.

På tidspunktet for skrivning af den originale artikel er version 1.0.3 tilgængelig.

Når installationen er færdig, kan du køre polaris på manifestet base-valid.yaml med følgende kommando:

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

Den udsender en streng i JSON-format med en detaljeret beskrivelse af de udførte tests og deres resultater. Outputtet vil have følgende 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": [
    /* длинный список */
  ]
}

Fuld output tilgængelig her.

Ligesom kube-score identificerer Polaris problemer på områder, hvor manifestet ikke opfylder bedste praksis:

  • Der er ingen sundhedstjek for bælg.
  • Tags for containerbilleder er ikke angivet.
  • Beholderen kører som rod.
  • Anmodninger og grænser for hukommelse og CPU er ikke specificeret.

Hver test, afhængigt af dens resultater, tildeles en grad af kritikalitet: advarsel eller fare. For at lære mere om de tilgængelige indbyggede test, se venligst dokumentation.

Hvis detaljer ikke er nødvendige, kan du angive flaget --format score. I dette tilfælde vil Polaris udsende et tal fra 1 til 100 − score (dvs. vurdering):

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

Jo tættere scoren er på 100, jo højere grad af overensstemmelse. Hvis du tjekker udgangskoden for kommandoen polaris audit, viser det sig, at det er lig med 0.

Kraft polaris audit Du kan afslutte arbejdet med ikke-nul kode ved at bruge to flag:

  • flag --set-exit-code-below-score tager som argument en tærskelværdi i området 1-100. I dette tilfælde afsluttes kommandoen med udgangskode 4, hvis scoren er under tærsklen. Dette er meget nyttigt, når du har en bestemt tærskelværdi (f.eks. 75), og du skal modtage en advarsel, hvis scoren går under.
  • flag --set-exit-code-on-danger vil få kommandoen til at mislykkes med kode 3, hvis en af ​​faretestene mislykkes.

Lad os nu prøve at oprette en brugerdefineret test, der kontrollerer, om billedet er taget fra et pålideligt lager. Brugerdefinerede tests er specificeret i YAML-format, og selve testen er beskrevet ved hjælp af JSON Schema.

Følgende YAML-kodestykke beskriver en ny test kaldet 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/.+$

Lad os se nærmere på det:

  • successMessage — denne linje udskrives, hvis testen gennemføres med succes;
  • failureMessage — denne meddelelse vil blive vist i tilfælde af fejl;
  • category — angiver en af ​​kategorierne: Images, Health Checks, Security, Networking и Resources;
  • target--- bestemmer hvilken type objekt (spec) test anvendes. Mulige værdier: Container, Pod eller Controller;
  • Selve testen er angivet i objektet schema ved hjælp af JSON-skema. Nøgleordet i denne test er pattern bruges til at sammenligne billedkilden med den påkrævede.

For at køre ovenstående test skal du oprette følgende Polaris-konfiguration:

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)

Lad os analysere filen:

  • I feltet checks tests og deres kritiske niveau er foreskrevet. Da det er ønskeligt at modtage en advarsel, når et billede er taget fra en ikke-pålidelig kilde, indstiller vi niveauet her danger.
  • Selve testen checkImageRepo derefter registreret i objektet customChecks.

Gem filen som custom_check.yaml. Nu kan du løbe polaris audit med et YAML-manifest, der kræver verifikation.

Lad os teste vores manifest base-valid.yaml:

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

Team polaris audit kørte kun brugertesten angivet ovenfor, og den mislykkedes.

Hvis du retter billedet til my-company.com/http-echo:1.0, vil Polaris fuldføre med succes. Manifestet med ændringerne er allerede inde depoterså du kan tjekke den forrige kommando på manifestet image-valid-mycompany.yaml.

Nu opstår spørgsmålet: hvordan kører man indbyggede tests sammen med brugerdefinerede? Let! Du skal blot tilføje de indbyggede testidentifikatorer til konfigurationsfilen. Som et resultat vil det antage følgende form:

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)

Et eksempel på en komplet konfigurationsfil er tilgængelig her.

Tjek manifest base-valid.yamlved hjælp af indbyggede og brugerdefinerede tests kan du bruge kommandoen:

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

Polaris supplerer de indbyggede tests med brugerdefinerede tests og kombinerer derved det bedste fra begge verdener.

På den anden side kan manglende evne til at bruge mere kraftfulde sprog såsom Rego eller JavaScript være en begrænsende faktor, der forhindrer oprettelsen af ​​mere sofistikerede tests.

Mere information om Polaris er tilgængelig på projektets hjemmeside.

Resumé

Mens der er mange tilgængelige værktøjer til at inspicere og evaluere Kubernetes YAML-filer, det er vigtigt at have en klar forståelse af, hvordan testene vil blive designet og udført.

For eksempel, hvis du tager Kubernetes-manifester, der går gennem en pipeline, kan kubeval være det første skridt i en sådan pipeline. Det ville overvåge, om objektdefinitioner er i overensstemmelse med Kubernetes API-skemaet.

Når en sådan gennemgang er afsluttet, kan man gå videre til mere sofistikerede tests, såsom overholdelse af standard bedste praksis og specifikke politikker. Det er her kube-score og Polaris ville komme til nytte.

For dem, der har komplekse krav og har brug for at tilpasse test i detaljer, ville kobber, config-lint og confetest være velegnede.

Conftest og config-lint bruger YAML til at definere brugerdefinerede tests, og kobber giver dig adgang til et komplet programmeringssprog, hvilket gør det til et ret attraktivt valg.

På den anden side, er det værd at bruge et af disse værktøjer og derfor oprette alle testene manuelt, eller foretrækker Polaris og tilføjer kun det, der er nødvendigt til det? Der er ikke noget klart svar på dette spørgsmål.

Tabellen nedenfor giver en kort beskrivelse af hvert værktøj:

Tool
skæbne
Begrænsninger
Brugertests

kubeval
Validerer YAML-manifester mod en specifik version af API-skemaet
Kan ikke arbejde med CRD
Nej

kube-score
Analyserer YAML-manifester i forhold til bedste praksis
Kan ikke vælge din Kubernetes API-version for at kontrollere ressourcer
Nej

kobber
En generel ramme til oprettelse af brugerdefinerede JavaScript-test til YAML-manifester
Ingen indbyggede tests. Dårlig dokumentation
Ja

config-lint
En generel ramme for oprettelse af test i et domænespecifikt sprog indlejret i YAML. Understøtter forskellige konfigurationsformater (fx Terraform)
Der er ingen færdige test. Indbyggede påstande og funktioner er muligvis ikke nok
Ja

konkurrence
En ramme til oprettelse af dine egne tests ved hjælp af Rego (et specialiseret forespørgselssprog). Tillader deling af politikker via OCI-bundter
Ingen indbyggede tests. Jeg skal lære Rego. Docker Hub understøttes ikke ved udgivelse af politikker
Ja

Polaris
Anmeldelser YAML manifesterer sig mod standard bedste praksis. Giver dig mulighed for at oprette dine egne tests ved hjælp af JSON Schema
Testfunktioner baseret på JSON-skema er muligvis ikke tilstrækkelige
Ja

Fordi disse værktøjer ikke er afhængige af adgang til Kubernetes-klyngen, er de nemme at installere. De giver dig mulighed for at filtrere kildefiler og give hurtig feedback til forfatterne af pull-anmodninger i projekter.

PS fra oversætteren

Læs også på vores blog:

Kilde: www.habr.com

Tilføj en kommentar