Validering af Kubernetes YAML mod bedste praksis og politikker

Bem. overs.: Med det stigende antal YAML-konfigurationer til K8s-miljøer bliver behovet for deres automatiserede kontrol stadig mere aktuelt. Forfatteren af denne gennemgang har ikke blot udvalgt eksisterende løsninger til denne opgave, men har også set på, hvordan de fungerer ved hjælp af et eksempel med Deployment. Det er blevet meget informativt for dem, der er interesseret i emnet.

Validering af Kubernetes YAML mod bedste praksis og politikker

TL;DR: Artiklen sammenligner seks statiske værktøjer til kontrol og evaluering af Kubernetes YAML-filer i forhold til bedste praksis og krav.

Kubernetes arbejdsbyrder defineres normalt i form af YAML-dokumenter. Et af problemerne med YAML er kompleksiteten i at angive begrænsninger eller relationer mellem manifestfiler.

Hvad hvis vi skal sikre os, at alle billeder, der implementeres i klusteret, kommer fra et betroet register?

Hvordan forhindrer man at sende Deployments til klusteret, for hvilke der ikke er angivet PodDisruptionBudgets?

Integration af statisk testning gør det muligt at opdage fejl og overtrædelser af politikker allerede i udviklingsfasen. Dette øger garantierne for korrekthed og sikkerhed i ressourcehenvisningerne og øger sandsynligheden for, at produktionsarbejdsbyrderne følger bedste praksis.

Økosystemet for statisk kontrol af Kubernetes YAML-filer kan opdeles i følgende kategorier:

  • API-valideringsværktøjer. Værktøjer i denne kategori tjekker YAML-manifestet for overholdelse af kravene fra Kubernetes API-server.
  • Færdige testværktøjer. Værktøjer fra denne kategori leveres med færdige tests for sikkerhed, overholdelse af bedste praksis osv.
  • Tilpassede valideringsværktøjer. Repræsentanter i denne kategori tillader oprettelse af brugerdefinerede tests på forskellige sprog, såsom 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. copper;
  5. conftest;
  6. Polaris.

Lad os komme i gang!

Kontrol af Deployments

Før vi begynder at sammenligne værktøjerne, lad os oprette et fundament, som vi kan teste dem på.

Det følgende manifest indeholder en række fejl og overtrædelser 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.

Manifestet ovenfor base-valid.yaml og andre manifester fra denne artikel kan findes i Git-repositorier.

Manifestet beskriver en webapplikation, hvis primære opgave er at svare med beskeden "Hello World" på port 5678. Det kan deployeres med følgende kommando:

kubectl apply -f hello-world.yaml

Og sådan kan vi tjekke, om det virker:

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

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

1. Kubeval

Grundlaget for kubeval er idéen om, at enhver interaktion med Kubernetes sker via dens REST API. Med andre ord kan vi bruge API-skemaet til at kontrollere, om den pågældende YAML overholder det. Lad os se et eksempel.

Installationsvejledningen for kubeval er tilgængelig på projektets hjemmeside.

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

Efter installationen lad os "fodre" den med manifestet, der er angivet ovenfor:

$ kubeval base-valid.yaml
PASS - base-valid.yaml indeholder et gyldigt Deployment (http-echo)
PASS - base-valid.yaml indeholder en gyldig Service (http-echo)

I tilfælde af succes afslutter kubeval med exit-kode 0. Vi kan tjekke det således:

$ 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 ved første øjekast? Kør:

$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml indeholder et ugyldigt Deployment (http-echo) - selector: selector er påkrævet
PASS - kubeval-invalid.yaml indeholder en gyldig Service (http-echo)

# lad os tjekke exit-koden
$ echo $?
1

Ressourcen består ikke.

Deployments, der bruger API-version apps/v1, skal inkludere en selector, der matcher pod'ets label. Manifestet ovenfor inkluderer ikke en selector, så kubeval gav en fejl og afsluttede med en ikke-nul kode.

Det er interessant at se, hvad der sker, hvis vi kører 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æcist den fejl, som kubeval advarede om. Den kan rettes ved at tilføje en selector:

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 sådanne fejl kan fanges tidligt i deploymentscyklussen.

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

Som standard kontrollerer kubeval ressourcer mod den seneste schema for Kubernetes API. Dog kan det i mange tilfælde være nødvendigt at kontrollere mod en specifik version af Kubernetes. Dette kan gøres med flaget --kubernetes-version:

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

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

For at se listen over versioner, som validering understøtter, kan du henvise til JSON-schemaet på GitHub, som kubeval bruger til validering. Hvis du skal køre kubeval offline, kan du downloade skemaerne og angive deres lokale placering med flaget --schema-location.

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

Derudover integreres Kubeval nemt i CI-pipelines. De, som ønsker at foretage tests, inden de sender manifester til klyngen, vil sætte pris på, at kubeval understøtter tre outputformater:

  1. Løst tekst;
  2. JSON;
  3. Test Anything Protocol (TAP).

Og ethvert af formaterne kan bruges til yderligere parsing af output for at danne en opsummering af resultaterne i den ønskede form.

En af ulemperne ved kubeval er, at det i øjeblikket ikke kan validere mod Custom Resource Definitions (CRDs). Men kubeval kan konfigureres til at ignorere dem..

Kubeval er et fremragende værktøj til at validere og evaluere ressourcer; dog skal det understreges, at en vellykket test ikke garanterer, at ressourcen opfylder bedste praksis.

For eksempel brugen af tagget latest I containeren overholder ikke de bedste praksisser. Men kubeval betragter ikke dette som en fejl og giver ikke besked om det. Det vil sige, at kontrollen af sådan YAML afsluttes uden advarsler.

Men hvad hvis man skal vurdere YAML og identificere overtrædelser som tag latest? Как проверить YAML-файл на соответствие лучшим практикам?

2. Kube-score

Kube-score analyserer YAML-manifestationer og vurderer dem ud fra indbyggede tests. Disse tests vælges baseret på sikkerhedsanbefalinger og bedste praksis, for eksempel:

  • Køre containeren ikke som root.
  • Tilstedeværelsen af sundhedstjek af pods.
  • Angivelse af anmodninger og begrænsninger for ressourcer.

Efter testen gives der tre resultater: OK, ADVARSEL og KRITISK.

Kube-score kan prøves online eller installeres lokalt.

På tidspunktet for skrivningen af den originale artikel var den nyeste 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
[KRITISK] Containerbilledetag
  · http-echo -> Billede med nyeste tag
      Det anbefales at bruge et fast tag for at undgå utilsigtede opgraderinger
[KRITISK] Pod NetworkPolicy
  · Pod'en har ikke en matchende netværkspolitik
      Opret en NetworkPolicy, der retter sig mod denne pod
[KRITISK] Pod Probes
  · Container mangler et readinessProbe
      Et readinessProbe bør bruges til at angive, hvornår tjenesten er klar til at modtage trafik.
      Uden det risikerer pod'en at modtage trafik, før den er startet. Det bruges også under
      opdateringer og kan forebygge nedetid, hvis en ny version af applikationen fejler.
      Mere information: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[KRITISK] Container Security Context
  · http-echo -> Container har ikke konfigureret sikkerhedskontekst
      Indstil securityContext for at køre containeren i en mere sikker kontekst.
[KRITISK] Containerressourcer
  · http-echo -> CPU-grænsen er ikke sat
      Ressourcegrænser anbefales for at undgå ressource DDOS. Sæt resources.limits.cpu
  · http-echo -> Hukommelsesgrænsen er ikke sat
      Ressourcegrænser anbefales for at undgå ressource DDOS. Sæt resources.limits.memory
  · http-echo -> CPU-anmodningen er ikke sat
      Resourceanmodninger anbefales for at sikre, at applikationen kan starte og køre uden
      at fejle. Sæt resources.requests.cpu
  · http-echo -> Hukommelsesanmodningen er ikke sat
      Resourceanmodninger anbefales for at sikre, at applikationen kan starte og køre uden at fejle.
      Sæt resources.requests.memory
[KRITISK] Deployment har PodDisruptionBudget
  · Ingen matchende PodDisruptionBudget blev fundet
      Det anbefales at definere et PodDisruptionBudget for at undgå uventet nedetid under Kubernetes
      vedligeholdelsesoperationer, såsom når en node drænes.
[ADVARSEL] Deployment har host PodAntiAffinity
  · Deployment har ikke en host podAntiAffinity sat
      Det anbefales at sætte en podAntiAffinity, der forhindrer flere pods fra et deployment i
      at blive planlagt på samme node. Dette øger tilgængeligheden, hvis noden bliver utilgængelig.

YAML bestået tests fra kubeval, mens kube-score peger på følgende mangler:

  • Ingen readiness checks er konfigureret.
  • Manglende anmodninger og grænser for CPU- og hukommelsesressourcer.
  • Ingen Pod disruption budgets er angivet.
  • Manglende regler for anti-affinity (anti-affinity) for at maksimere tilgængeligheden.
  • Containeren kører som root.

Alt dette er rimelige bemærkninger om mangler, som bør rettes for at gøre Deployment mere effektiv og pålidelig.

Kommandoen kube-score giver information på en letlæselig måde med inkluderede overtrædelser af typen ADVARSEL og KRITISK, hvilket hjælper meget under udviklingen.

De, der ønsker at bruge dette værktøj i CI-pipelinen, kan inkludere en mere kompakt output ved hjælp af flaget --output-format ci (i dette tilfælde vises også test med resultaterne 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-grænsen er ikke sat
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Hukommelsesgrænsen er ikke sat
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU-anmodningen er ikke sat
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Hukommelsesanmodningen er ikke sat
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Billede med den nyeste tag
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: Pod’en har ikke en matchende netværkspolitik
[CRITICAL] http-echo apps/v1/Deployment: Container mangler en readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Container har ikke konfigureret sikkerhedskontekst
[CRITICAL] http-echo apps/v1/Deployment: Ingen matchende PodDisruptionBudget blev fundet
[WARNING] http-echo apps/v1/Deployment: Deployment har ikke host podAntiAffinity sat
[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 ikke-nul exitkode ved fejlslagne tests. KRITISK. Det er også muligt at inkludere lignende håndtering for ADVARSEL.

Derudover er der mulighed for at kontrollere ressourcer for overensstemmelse med forskellige API-versioner (ligesom i kubeval). Men denne information er 'hardcoded' i selve kube-score: det er ikke muligt at vælge en anden version af Kubernetes. En sådan begrænsning kan blive et stort problem, hvis du planlægger at opdatere dit cluster eller har flere clusters med forskellige versioner af K8s.

Bemærk venligst, at der allerede er et issue med et forslag om at implementere denne mulighed.

Læs mere om kube-score på den officielle hjemmeside.

Kube-scores tests er et fremragende værktøj til at implementere bedste praksis, men hvad hvis det er nødvendigt at ændre en test eller tilføje egne regler? Desværre er det ikke muligt.

Kube-score er ikke udvideligt: det er ikke muligt at tilføje eller tilpasse politikker.

Hvis der er behov for at skrive brugerdefinerede tests for overholdelsespolitikker, kan du bruge et af følgende fire værktøjer: config-lint, copper, conftest eller polaris.

3. Config-lint

Config-lint er et værktøj til validering af konfigurationsfiler i formaterne YAML, JSON, Terraform, CSV og Kubernetes-manifester.

Det kan installeres ved hjælp af instruktioner på projektets hjemmeside.

Den nuværende version pr. tidspunktet for skrivningen af den originale artikel er 1.5.0.

Config-lint indeholder ikke indbyggede tests til kontrol af Kubernetes-manifester.

For at udføre tests skal der oprettes de relevante regler. De skrives i YAML-filer, kaldet "regelsæt" (rulesets), og har følgende struktur:

version: 1
description: Regler for Kubernetes-spec-filer
type: Kubernetes
files:
  - "*.yaml"
rules:
   # liste over regler

(rule.yaml)

Lad os se nærmere på det:

  • Felt type angiver, hvilken type konfiguration config-lint vil bruge. For K8s-manifester er det altid Kubernetes.
  • I feltet files udover selve filerne kan du angive en mappe.
  • Felt rules er beregnet til at angive brugerdefinerede tests.

Antag, at du ønsker at sikre dig, at billeder i Deployment altid hentes fra et pålideligt repository som my-company.com/myapp:1.0. Reglen for config-lint, der udfører denne kontrol, vil se således ud:

- id: MY_DEPLOYMENT_IMAGE_TAG
  severity: FAILURE
  message: Deployment skal bruge et gyldigt billede-tag
  resource: Deployment
  assertions:
    - every:
        key: spec.template.spec.containers
        expressions:
          - key: image
            op: starts-with
            value: "my-company.com/"

(rule-trusted-repo.yaml)

For hver regel skal følgende attributter angives:

  • id — en unik identifikator for reglen;
  • severity — kan være FAILURE, ADVARSEL og NON_COMPLIANT;
  • message — indholdet af denne linje vises, hvis reglen brydes;
  • resource — typen af ressource, som denne regel gælder for;
  • assertions — en liste over betingelser, der vil blive evalueret i forhold til denne ressource.

I reglen ovenfor assertion med navnet every kontrollerer, at alle containere i Deployment ('key: spec.templates.spec.containers') bruger pålidelige billeder (dvs. som starter med my-company.com/).

Det fulde regelsæt ser således ud:

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

 - id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
    severity: FAILURE
    message: Deployment skal bruge et gyldigt billedrepository
    resource: Deployment
    assertions:
      - every:
          key: spec.template.spec.containers
          expressions:
            - key: image
              op: starts-with
              value: "my-company.com/"

(ruleset.yaml)

For at teste reglen, lad os gemme den som check_image_repo.yaml. Lad os køre kontrollen på filen base-valid.yaml:

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

[
  {
  "AssertionMessage": "Hver expression fejler: Og udtryk fejler: billedet starter ikke med 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 skal bruge et gyldigt billederepositorium",
  "Status": "FAILURE"
  }
]

Kontrollen mislykkedes. Lad os nu teste den næste manifest med et korrekt billederepositorium:

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)

Kører den samme test med den foregående manifest. Ingen problemer opdaget:

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

Config-lint er et lovende framework, der muliggør oprettelse af brugerdefinerede tests til validering af YAML-manifester til Kubernetes ved hjælp af YAML DSL.

Men hvad skal man gøre, hvis der kræves mere kompleks logik og tests? Er YAML's muligheder ikke for små til dette? Hvad hvis man kunne oprette tests i et fuldt programmeringssprog?

4. Copper

Copper V2 er et framework til validering af manifester ved hjælp af brugerdefinerede tests (som config-lint).

Men i modsætning til det sidste bruger det ikke YAML til at beskrive tests. I stedet kan tests oprettes i JavaScript. Copper stiller et bibliotek til rådighed med flere grundlæggende værktøjer, der hjælper med at indsamle oplysninger om Kubernetes-objekter og rapportere fejl.

Trin-for-trin vejledningen til installation af Copper kan findes i den officielle dokumentation.

2.0.1 — den nyeste version af dette værktøj på tidspunktet for den originale artikel.

Ligesom config-lint har Copper ikke indbyggede tests. Lad os skrive en. Den skal kontrollere, at deployments kun bruger containerbilleder fra betroede repositorier som 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 + " er ikke fra my-company.com repo", 1)
            }
        });
    }
});

Nu, for at validere vores manifest base-valid.yaml, brug kommandoen copper validate:

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

Check no_company_repo mislykkedes med alvorlighed 1 på grund af, at billedet http-echo ikke er fra my-company.com repo
Validering mislykkedes

Det er klart, at man med Copper kan udføre mere komplekse tests - for eksempel kontrollere domænenavne i Ingress-manifester eller afvise pods, der kører i privilegeret tilstand.

Copper har indbygget forskellige hjælpefunktioner:

  • DockerImage læsser den specificerede inputfil og opretter et objekt med følgende attributter:
    • name — navnet på billedet,
    • tag — tag for billedet,
    • registry — billedregister,
    • registry_url — protokol (https://) og billedregister,
    • fqin — den fulde placering af billedet.
  • Funktion findByName hjælper med at finde en ressource efter den angivne type (kind) og navn (name) fra inputfilen.
  • Funktion findByLabels hjælper med at finde en ressource efter den angivne type (kind) og etiketter (labels).

Du kan få et overblik over alle tilgængelige hjælpefunktioner her.

Som standard indlæser den hele input-YAML-filen i variablen $$ og gør den tilgængelig for scripts (en velkendt metode for dem, der har erfaring med jQuery).

Den største fordel ved Copper er åbenlys: du behøver ikke at lære et specialiseret sprog, og du kan bruge forskellige muligheder fra JavaScript til at lave dine egne tests, såsom strengeinterpolering, funktioner osv.

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

Detaljer er tilgængelige på det officielle projektwebsted.

Men hvis du ikke er særlig glad for JavaScript og foretrækker et sprog, der er specielt beregnet til at lave forespørgsler og beskrive politikker, bør du kigge på conftest.

5. Conftest

Conftest er et framework til at verificere konfigurationsdata. Det er også velegnet til testning/validering af Kubernetes-manifester. Tests beskrives ved hjælp af et specialiseret forespørgselssprog Rego.

Du kan installere conftest ved hjælp af instruktioner, som angivet på projektets websted.

På tidspunktet for skrivningen af den oprindelige artikel var den senest tilgængelige version 0.18.2.

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

Opret en mappe conftest-checks, og i den — 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

FEJL - base-valid.yaml - billed 'hashicorp/http-echo' kommer ikke fra my-company.com repository
1 tests, 1 bestået, 0 advarsler, 1 fejl

Testen mislykkedes som forventet, da billederne kommer fra en ubetroet kilde.

I Rego-filen definerer vi en blok deny. Dens sandhed betragtes som en overtrædelse. Hvis der er flere blokke, deny kontrollerer conftest dem uafhængigt af hinanden, og sandheden af nogen af blokke fortolkes som en overtrædelse.

Udover standard output understøtter conftest JSON, TAP og tabel-format — en ekstremt nyttig funktion, hvis man har brug for at integrere rapporter i den eksisterende CI-pipeline. Den ønskede format kan angives med flaget --output.

For at lette fejlretningen af politikker har conftest et flag --trace. Det viser en trace af, hvordan conftest parser de angivne politikfiler.

Conftest-politikker kan offentliggøres og deles i OCI-lagre (Open Container Initiative) som artefakter.

Kommandoer push og pull giver mulighed for at offentliggøre en artefakt eller hente en eksisterende artefakt fra et fjernt lager. Lad os prøve at offentliggøre den politik, vi har oprettet, i et lokalt Docker-lager ved hjælp af conftest push.

Start et lokalt Docker-lager:

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

I et andet terminalvindue skal du gå til den tidligere oprettede mappe conftest-checks og køre følgende kommando:

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

Hvis kommandoen var vellykket, vil du se en meddelelse af denne type:

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

Opret nu en midlertidig mappe, og kør kommandoen conftest pull. Det vil downloade det pakket, der blev oprettet af den tidligere kommando:

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

I den midlertidige mappe vil der komme en undermappe policy, som indeholder vores politikfil:

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

Tests kan udføres direkte fra repository:

$ conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml
..
FEJL - base-valid.yaml - billed 'hashicorp/http-echo' kommer ikke fra my-company.com repository
2 tests, 1 bestået, 0 advarsler, 1 fejl

Desværre understøttes DockerHub ikke endnu. Så betragt dig selv heldig, hvis du bruger Azure Container Registry (ACR) eller dit eget lager.

Artefaktformatet er det samme som for Open Policy Agent-pakker (OPA), hvilket gør det muligt at bruge conftest til at køre tests fra eksisterende OPA-pakker.

Mere om deling af politikker og andre funktioner i conftest kan findes på det officielle projektwebsted.

6. Polaris

Det sidste værktøj, vi skal tale om i denne artikel, er Polaris. (Vi har allerede oversat hans annoncering fra sidste år til — ft. overs.)

Polaris kan installeres i en klynge eller bruges i kommandolinjetilstand. Som du allerede har gættet, tillader det statisk analyse af Kubernetes-manifester.

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

Med andre ord kombinerer Polaris fordelene fra begge typer værktøjer: med indbyggede og brugerdefinerede tests.

For at installere Polaris i kommandolinjetilstand, brug instruktionerne på projektets hjemmeside.

På tidspunktet for skrivning af denne artikel var version 1.0.3 tilgængelig.

Når installationen er afsluttet, kan du køre polaris på manifestet base-valid.yaml ved hjælp af følgende kommando:

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

Den vil returnere en JSON-streng 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": [
    /* lang liste */
  ]
}

Den fulde output er tilgængelig her.

Ligesom kube-score identificerer Polaris problemer i de områder, hvor manifestet ikke overholder bedste praksis:

  • Sundhedstjek for pods mangler.
  • Der er ikke angivet tags for containerbillederne.
  • Containeren kører som root.
  • Der er ikke specificeret requests og limits for hukommelse og CPU.

Hver test tildeles en kritikalitetsgrad afhængigt af dens resultater: warning eller danger. For at lære mere om de indbyggede tests, se dokumentationen.

Hvis du ikke har brug for detaljer, kan du angive flaget --format score. I dette tilfælde vil Polaris returnere et tal i området fra 1 til 100 — score (dvs. bedømmelse):

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

Jo tættere bedømmelsen er på 100, jo højere er graden af overholdelse. Hvis du tjekker exit-koden for kommandoen polaris audit, vil du finde, at den er lig med 0.

At få polaris audit den til at afslutte med en ikke-nul kode kan gøres med to flags:

  • Flaget --set-exit-code-below-score modtager et tærskelværdi som et argument i intervallet 1-100. I dette tilfælde afsluttes kommandoen med exit-kode 4, hvis vurderingen ligger under tærsklen. Dette er meget praktisk, når du har en tærskelværdi (lad os sige 75), og du har brug for at få et alert, hvis vurderingen falder under.
  • Flaget --set-exit-code-on-danger vil føre til, at kommandoen afsluttes med kode 3, hvis en af ​​fare-testene mislykkes.

Lad os nu prøve at oprette en brugerdefineret test, der kontrollerer, om billedet tages fra et betroet lager. Brugerdefinerede tests angives i YAML-format, mens selve testen beskrives ved hjælp af JSON Schema.

Det følgende YAML-kodefragment beskriver en ny test, der kaldes checkImageRepo:

checkImageRepo:
  successMessage: Billederegistret er gyldigt
  failureMessage: Billederegistret er ikke gyldigt
  category: Billeder
  target: Container
  schema:
    '$schema': http://json-schema.org/draft-07/schema
    type: object
    properties:
      image:
        type: string
        pattern: ^my-company.com/.+$

Lad os tage et nærmere kig på det:

  • successMessage — denne linje vil blive udskrevet, hvis testen afsluttes med succes;
  • failureMessage — denne besked vises ved fejl;
  • category — angiver en af ​​kategorierne: Billeder, Sundhedstjek, Sikkerhed, Netværk og Ressourcer;
  • target—- definerer, hvilken type objekt (spec) testen anvendes på. Mulige værdier: Container, Pod eller Controller;
  • Selve testen angives i objektet schema ved hjælp af JSON-schema. I denne test bruges nøgleordet pattern til at sammenligne kildebilledet med det krævede.

For at køre den nævnte test skal du oprette følgende Polaris-konfiguration:

checks:
  checkImageRepo: danger
customChecks:
  checkImageRepo:
    successMessage: Billederegistret er gyldigt
    failureMessage: Billederegistret er ikke gyldigt
    category: Billeder
    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 se på filen:

  • I feltet checks angiver testene og deres kritikalitetsniveau. Da det er ønskeligt at få en advarsel, når billedet tages fra en usikker kilde, sætter vi her niveauet danger.
  • Selve testen checkImageRepo angives derefter i objektet customChecks.

Gem filen som custom_check.yaml. Nu kan du køre polaris audit med en YAML-manifest, der kræver kontrol.

Lad os teste vores manifest base-valid.yaml:

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

Kommandoen polaris audit gennemførte kun den brugerdefinerede test, der blev angivet ovenfor, og den var ikke vellykket.

Hvis billedet rettes til my-company.com/http-echo:1.0, vil Polaris afsluttes med succes. Manifestet med ændringerne er allerede i repository, så du kan kontrollere den tidligere kommando på manifestet image-valid-mycompany.yaml.

Nu opstår spørgsmålet: hvordan kører man de indbyggede tests sammen med brugertilpassede? Det er nemt! Du skal blot tilføje identifikatorerne for de indbyggede tests til konfigurationsfilen. Resultatet vil se således ud:

checks:
  cpuRequestsMissing: warning
  cpuLimitsMissing: warning
  # Andre indbyggede checks..
  # ..
  # brugerdefinerede checks
  checkImageRepo: danger # !!!
customChecks:
  checkImageRepo:        # !!!
    successMessage: Billederegistreringen er gyldig
    failureMessage: Billederegistreringen er ikke gyldig
    category: Billeder
    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 fuld konfigurationsfil er tilgængelig her.

Kontroller manifestet base-valid.yaml, ved at bruge indbyggede og brugerdefinerede tests, kan gøres med kommandoen:

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

Polaris supplerer de indbyggede tests med brugerdefinerede, og kombinerer således det bedste fra to verdener.

På den anden side kan det være en begrænsning, at man ikke kan bruge mere kraftfulde sprog som Rego eller JavaScript, hvilket kan hæmme oprettelsen af mere sofistikerede tests.

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

CV

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

For eksempel, hvis man ser på Kubernetes-manifester, der går gennem pipeline, kunne kubeval være det første skridt i en sådan pipeline. Det ville sikre, at objektdefinitionerne overholder Kubernetes API-schemas.

Når en sådan kontrol er færdig, kan man gå videre til mere sofistikerede tests, såsom overholdelse af standard bedste praksis og særlige politikker. Og her ville kube-score og Polaris være nyttige.

For dem med komplekse krav og behov for detaljeret at tilpasse tests, ville copper, config-lint og conftest være passende.

Conftest og config-lint bruger YAML til at definere brugerdefinerede tests, mens copper giver adgang til et fuldt programmeringssprog, hvilket gør det til et ganske attraktivt valg.

På den anden side, bør man bruge et af disse værktøjer og derved oprette alle tests manuelt, eller vælge Polaris og blot tilføje det, der er nødvendigt? Der er ikke et entydigt svar på dette spørgsmål.

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

Værktøj
Formål
Ulemper
Brugertests

kubeval
Tjekker YAML-manifest for overensstemmelse med en bestemt version af API-schemaet
Understøtter ikke arbejde med CRD
Nej

kube-score
Analyserer YAML-manifest for overensstemmelse med bedste praksis
Det er ikke muligt at vælge sin egen version af Kubernetes API til at kontrollere ressourcer
Nej

copper
Generelt rammeværk til oprettelse af egne JavaScript-tests for YAML-manifest
Ingen indbyggede tests. Sparse dokumentation
Ja

config-lint
Generelt rammeværk til at skabe tests i et domænespecifikt sprog indlejret i YAML. Understøtter forskellige konfigurationsformater (f.eks. Terraform)
Ingen færdige tests. Indbyggede assertions og funktioner kan være utilstrækkelige
Ja

conftest
Rammeværk til at skabe egne tests i Rego (et specialiseret forespørgselssprog). Gør det muligt at dele politikker via OCI-bundter
Ingen indbyggede tests. Man skal lære Rego. Docker Hub understøttes ikke ved publicering af politikker
Ja

Polaris
Analyserer YAML-manifest for overensstemmelse med standard bedste praksis. Gør det muligt at lave egne tests med JSON Schema
Mulighederne for tests baseret på JSON Schema kan være utilstrækkelige
Ja

Da disse værktøjer ikke er afhængige af adgang til Kubernetes-klusteret, er de nemme at installere. De giver mulighed for at filtrere kildematerialer og giver hurtig feedback til forfattere af pull requests i projekter.

P.S. fra oversætteren

Læs også på vores blog:

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster