Validera Kubernetes YAML mot bästa praxis och policyer

Notera. transl.: Med det växande antalet YAML-konfigurationer för K8s-miljöer blir behovet av deras automatiska verifiering mer och mer akut. Författaren till den här recensionen valde inte bara befintliga lösningar för denna uppgift, utan använde också Deployment som ett exempel för att se hur de fungerar. Det visade sig vara mycket informativt för dem som är intresserade av detta ämne.

Validera Kubernetes YAML mot bästa praxis och policyer

TL; DR: Den här artikeln jämför sex statiska verktyg för att validera och utvärdera Kubernetes YAML-filer mot bästa praxis och krav.

Kubernetes arbetsbelastningar definieras vanligtvis i form av YAML-dokument. Ett av problemen med YAML är svårigheten att specificera begränsningar eller relationer mellan manifestfiler.

Vad händer om vi behöver se till att alla bilder som distribueras till klustret kommer från ett pålitligt register?

Hur kan jag förhindra att distributioner som inte har PodDisruptionBudgets skickas till klustret?

Integrering av statisk testning gör att du kan identifiera fel och policyöverträdelser i utvecklingsstadiet. Detta ökar garantin för att resursdefinitioner är korrekta och säkra, och gör det mer sannolikt att produktionsbelastningar följer bästa praxis.

Kubernetes statiska YAML filinspektions ekosystem kan delas in i följande kategorier:

  • API-validerare. Verktyg i den här kategorin kontrollerar YAML-manifestet mot kraven för Kubernetes API-server.
  • Färdiga testare. Verktyg från denna kategori kommer med färdiga tester för säkerhet, efterlevnad av bästa praxis, etc.
  • Anpassade validerare. Representanter för denna kategori låter dig skapa anpassade tester på olika språk, till exempel Rego och Javascript.

I den här artikeln kommer vi att beskriva och jämföra sex olika verktyg:

  1. kubeval;
  2. kube-poäng;
  3. config-lint;
  4. koppar;
  5. strid;
  6. polaris.

Nåväl, låt oss börja!

Kontrollera distributioner

Innan vi börjar jämföra verktyg, låt oss skapa lite bakgrund för att testa dem.

Manifestet nedan innehåller ett antal fel och bristande efterlevnad av bästa praxis: hur många av dem kan du hitta?

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 kommer att använda denna YAML för att jämföra olika verktyg.

Ovanstående manifest base-valid.yaml och andra manifest från den här artikeln finns i Git-förråd.

Manifestet beskriver en webbapplikation vars huvuduppgift är att svara med ett "Hello World"-meddelande till port 5678. Det kan distribueras med följande kommando:

kubectl apply -f hello-world.yaml

Och så - kolla arbetet:

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

Gå nu till http://localhost:8080 och bekräfta att applikationen fungerar. Men följer det bästa praxis? Låt oss kolla.

1. Kubeval

I hjärtat kubeval Tanken är att all interaktion med Kubernetes sker genom dess REST API. Med andra ord kan du använda ett API-schema för att kontrollera om en given YAML överensstämmer med det. Låt oss titta på ett exempel.

Installations instruktioner kubeval finns på projektets hemsida.

När den ursprungliga artikeln skrevs fanns version 0.15.0 tillgänglig.

När det är installerat, låt oss mata det med manifestet ovan:

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

Om det lyckas avslutas kubeval med exitkod 0. Du kan kontrollera det på följande sätt:

$ echo $?
0

Låt oss nu prova kubeval med ett annat 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 ögat? Låt oss lansera:

$ 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

Resursen verifieras inte.

Implementeringar med API-versionen apps/v1, måste inkludera en väljare som matchar poddens etikett. Manifestet ovan innehåller ingen väljare, så kubeval rapporterade ett fel och avslutade med en kod som inte var noll.

Jag undrar vad som händer om jag gör det kubectl apply -f med detta manifest?

Nåväl, låt oss försöka:

$ 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 är precis det felet som kubeval varnade för. Du kan fixa detta genom att lägga till en väljare:

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)

Fördelen med verktyg som kubeval är att sådana fel kan fångas upp tidigt i distributionscykeln.

Dessutom kräver dessa kontroller inte åtkomst till klustret, de kan utföras offline.

Som standard kontrollerar kubeval resurser mot det senaste Kubernetes API-schema. Men i de flesta fall kan du behöva kontrollera mot en specifik Kubernetes-version. Detta kan göras med hjälp av flaggan --kubernetes-version:

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

Observera att versionen måste anges i formatet Major.Minor.Patch.

För en lista över versioner för vilka verifiering stöds, se JSON-schema på GitHub, som kubeval använder för validering. Om du behöver köra kubeval offline, ladda ner schemana och ange deras lokala plats med flaggan --schema-location.

Förutom individuella YAML-filer kan kubeval även arbeta med kataloger och stdin.

Dessutom integreras Kubeval enkelt i CI-pipelinen. De som vill köra tester innan de skickar manifest till klustret kommer att vara glada att veta att kubeval stöder tre utdataformat:

  1. Oformatterad text;
  2. JSON;
  3. Testa Anything Protocol (TAP).

Och vilket format som helst kan användas för ytterligare analys av utdata för att generera en sammanfattning av resultaten av den önskade typen.

En av nackdelarna med kubeval är att den för närvarande inte kan kontrollera efterlevnad med Custom Resource Definitions (CRDs). Det är dock möjligt att konfigurera kubeval ignorera dem.

Kubeval är ett utmärkt verktyg för att kontrollera och utvärdera resurser; Det bör dock betonas att ett godkänt test inte garanterar att resursen överensstämmer med bästa praxis.

Till exempel genom att använda taggen latest i en behållare följer inte bästa praxis. Kubeval anser dock inte att detta är ett fel och rapporterar det inte. Det vill säga, verifieringen av sådan YAML kommer att slutföras utan varningar.

Men vad händer om du vill utvärdera YAML och identifiera överträdelser som taggen latest? Hur kontrollerar jag en YAML-fil mot bästa praxis?

2. Kube-poäng

Kube-poäng analyserar YAML-manifest och utvärderar dem mot inbyggda tester. Dessa tester väljs utifrån säkerhetsriktlinjer och bästa praxis, som:

  • Kör behållaren inte som root.
  • Tillgänglighet för pods hälsokontroller.
  • Ställa in förfrågningar och gränser för resurser.

Baserat på testresultaten ges tre resultat: OK, VARNING и KRITISK.

Du kan prova Kube-score online eller installera det lokalt.

När den ursprungliga artikeln skrevs var den senaste versionen av kube-score 1.7.0.

Låt oss prova det på vårt 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 klarar kubeval-tester, medan kube-score pekar på följande brister:

  • Beredskapskontroller är inte konfigurerade.
  • Det finns inga förfrågningar eller begränsningar för CPU-resurser och minne.
  • Pod-avbrottsbudgetar är inte specificerade.
  • Det finns inga regler för separation (anti-affinitet) för att maximera tillgängligheten.
  • Behållaren körs som root.

Dessa är alla giltiga punkter om brister som måste åtgärdas för att göra distributionen mer effektiv och tillförlitlig.

Team kube-score visar information i läsbar form inklusive alla typer av överträdelser VARNING и KRITISK, vilket hjälper mycket under utvecklingen.

De som vill använda detta verktyg inom CI-pipeline kan aktivera mer komprimerad utdata med flaggan --output-format ci (i detta fall visas även tester 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 likhet med kubeval returnerar kube-score en utgångskod som inte är noll när det finns ett test som misslyckas KRITISK. Du kan också aktivera liknande bearbetning för VARNING.

Dessutom är det möjligt att kontrollera resurser för överensstämmelse med olika API-versioner (som i kubeval). Denna information är dock hårdkodad i själva kube-poängen: du kan inte välja en annan version av Kubernetes. Denna begränsning kan vara ett stort problem om du tänker uppgradera ditt kluster eller om du har flera kluster med olika versioner av K8s.

Observera att det finns redan ett problem med ett förslag om att förverkliga denna möjlighet.

Mer information om kube-score finns på officiella hemsida.

Kube-poängtester är ett utmärkt verktyg för att implementera bästa praxis, men vad händer om du behöver göra ändringar i testet eller lägga till dina egna regler? Tyvärr kan detta inte göras.

Kube-poäng går inte att utöka: du kan inte lägga till policyer eller justera dem.

Om du behöver skriva anpassade tester för att verifiera överensstämmelse med företagets policyer kan du använda något av följande fyra verktyg: config-lint, koppar, conftest eller polaris.

3.Config-lint

Config-lint är ett verktyg för att validera YAML, JSON, Terraform, CSV-konfigurationsfiler och Kubernetes-manifest.

Du kan installera den med hjälp av instruktioner på projektets hemsida.

Den nuvarande versionen när den ursprungliga artikeln skrivs är 1.5.0.

Config-lint har inga inbyggda tester för att validera Kubernetes-manifest.

För att utföra några tester är det nödvändigt att skapa lämpliga regler. De är skrivna i YAML-filer som kallas "regeluppsättningar" (regeluppsättningar)och har följande struktur:

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

(rule.yaml)

Låt oss studera det närmare:

  • Fält type anger vilken typ av konfiguration som config-lint kommer att använda. För K8s manifesterar detta är alltid Kubernetes.
  • Inom området files Förutom själva filerna kan du ange en katalog.
  • Fält rules avsedd för att ställa in användartester.

Låt oss säga att du vill se till att bilder i Deployment alltid laddas ner från ett pålitligt arkiv som my-company.com/myapp:1.0. En config-lint-regel som utför en sådan kontroll skulle se ut så här:

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

Varje regel måste ha följande attribut:

  • id — Unik identifierare för regeln.
  • severity - Kanske FEL, VARNING и NON_COMPLIANT;
  • message — om en regel överträds visas innehållet på denna rad;
  • resource — Vilken typ av resurs som denna regel gäller.
  • assertions — En lista över villkor som kommer att utvärderas i förhållande till denna resurs.

I regeln ovan assertion med titeln every kontrollerar att alla behållare är i distribution (key: spec.templates.spec.containers) använd betrodda bilder (dvs. börjar med my-company.com/).

Hela regeluppsättningen ser ut så här:

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)

För att testa testet, låt oss spara det som check_image_repo.yaml. Låt oss kontrollera 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 misslyckades. Låt oss nu kolla in följande manifest med rätt bildförråd:

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ör samma test med ovanstående manifest. Inga problem hittades:

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

Config-lint är ett lovande ramverk som låter dig skapa dina egna tester för att validera Kubernetes YAML-manifest med YAML DSL.

Men vad händer om du behöver mer komplex logik och tester? Är inte YAML för begränsat för detta? Tänk om du kunde skapa tester i ett fullständigt programmeringsspråk?

4. Koppar

Koppar V2 är ett ramverk för att validera manifest med hjälp av anpassade tester (liknande config-lint).

Den skiljer sig dock från den senare genom att den inte använder YAML för att beskriva tester. Tester kan skrivas i JavaScript istället. Copper tillhandahåller ett bibliotek med flera grundläggande verktyg, som hjälper dig att läsa information om Kubernetes-objekt och rapportera fel.

Stegen för att installera Copper finns i officiell dokumentation.

2.0.1 är den senaste utgåvan av det här verktyget när den ursprungliga artikeln skrevs.

Liksom config-lint har Copper inga inbyggda tester. Låt oss skriva en. Låt den kontrollera att distributioner använder behållaravbildningar uteslutande från betrodda lagringsplatser som my-company.com.

Skapa en fil check_image_repo.js med följande innehåll:

$$.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 ska vi testa vårt manifest base-valid.yaml, använd kommandot 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 är tydligt att man med hjälp av koppar kan utföra mer komplexa tester – till exempel kontrollera domännamn i Ingress-manifest eller avvisa pods som körs i privilegierat läge.

Koppar har olika hjälpfunktioner inbyggda:

  • DockerImage läser den angivna indatafilen och skapar ett objekt med följande attribut:
    • name - bildens namn,
    • tag - bildtagg,
    • registry - bildregister,
    • registry_url - protokoll (https://) och bildregistret,
    • fqin — fullständig plats för bilden.
  • Funktion findByName hjälper till att hitta en resurs efter en given typ (kind) och namn (name) från indatafilen.
  • Funktion findByLabels hjälper till att hitta en resurs av en specificerad typ (kind) och etiketter (labels).

Du kan se alla tillgängliga servicefunktioner här.

Som standard laddar den in hela YAML-indatafilen till en variabel $$ och gör det tillgängligt för skript (en bekant teknik för de med jQuery-erfarenhet).

Den största fördelen med Copper är uppenbar: du behöver inte behärska ett specialiserat språk och du kan använda olika JavaScript-funktioner för att skapa dina egna tester, såsom stränginterpolation, funktioner, etc.

Det bör också noteras att den nuvarande versionen av Copper fungerar med ES5-versionen av JavaScript-motorn, inte ES6.

Detaljer finns på projektets officiella webbplats.

Men om du inte riktigt gillar JavaScript och föredrar ett språk som är speciellt utformat för att skapa frågor och beskriva policyer, bör du vara uppmärksam på confet.

5. Confest

Conftest är ett ramverk för att testa konfigurationsdata. Även lämplig för att testa/verifiera Kubernetes-manifest. Tester beskrivs med hjälp av ett specialiserat frågespråk Rego.

Du kan installera confetest med instruktionerfinns på projektets hemsida.

När den ursprungliga artikeln skrevs var den senaste tillgängliga versionen 0.18.2.

I likhet med config-lint och koppar kommer conftest utan några inbyggda tester. Låt oss prova det och skriva vår egen policy. Som i tidigare exempel kommer vi att kontrollera om behållarbilderna är tagna från en pålitlig källa.

Skapa en katalog conftest-checks, och i den finns en fil med namnet check_image_registry.rego med följande innehåll:

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

Nu ska vi testa base-valid.yaml genom 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

Testet misslyckades förutsägbart eftersom bilderna kom från en otillförlitlig källa.

I Rego-filen definierar vi blocket deny. Dess sanning anses vara en kränkning. Om blockerar deny flera, confetest kontrollerar dem oberoende av varandra, och sanningen i något av blocken behandlas som en kränkning.

Förutom standardutgången stöder conftest JSON, TAP och tabellformat - en extremt användbar funktion om du behöver bädda in rapporter i en befintlig CI-pipeline. Du kan ställa in önskat format med flaggan --output.

För att göra det lättare att felsöka policyer har conftest en flagga --trace. Den matar ut ett spår av hur conftest analyserar de angivna policyfilerna.

Tävlingspolicyer kan publiceras och delas i OCI-register (Open Container Initiative) som artefakter.

kommandon push и pull låter dig publicera en artefakt eller hämta en befintlig artefakt från ett fjärrregister. Låt oss försöka publicera policyn vi skapade till det lokala Docker-registret med hjälp av conftest push.

Starta ditt lokala Docker-register:

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

I en annan terminal, gå till katalogen du skapade tidigare conftest-checks och kör följande kommando:

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

Om kommandot lyckades kommer du att se ett meddelande så här:

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

Skapa nu en tillfällig katalog och kör kommandot i den conftest pull. Det kommer att ladda ner paketet skapat av föregående kommando:

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

En underkatalog visas i den tillfälliga katalogen policysom innehåller vår policyfil:

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

Tester kan köras direkt från förvaret:

$ 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

Tyvärr stöds inte DockerHub ännu. Så se dig själv lycklig om du använder Azure Container Registry (ACR) eller ditt eget register.

Artefaktformatet är detsamma som Öppna Policy Agent-paket (OPA), som låter dig använda confetest för att köra tester från befintliga OPA-paket.

Du kan lära dig mer om policydelning och andra funktioner i conftest på projektets officiella webbplats.

6. Polaris

Det sista verktyget som kommer att diskuteras i den här artikeln är Polaris. (Hans förra årets tillkännagivande vi redan översatt - cirka. översättning)

Polaris kan installeras i ett kluster eller användas i kommandoradsläge. Som du kanske har gissat låter det dig statiskt analysera Kubernetes-manifest.

När du kör i kommandoradsläge finns inbyggda tester tillgängliga som täcker områden som säkerhet och bästa praxis (liknar kube-score). Dessutom kan du skapa dina egna tester (som i config-lint, copper och confetest).

Med andra ord kombinerar Polaris fördelarna med båda kategorierna av verktyg: med inbyggda och anpassade tester.

För att installera Polaris i kommandoradsläge, använd instruktioner på projektets hemsida.

När den ursprungliga artikeln skrivs är version 1.0.3 tillgänglig.

När installationen är klar kan du köra polaris på manifestet base-valid.yaml med följande kommando:

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

Det kommer att mata ut en sträng i JSON-format med en detaljerad beskrivning av de tester som utförts och deras resultat. Utgången kommer att ha följande 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": [
    /* длинный список */
  ]
}

Full utgång tillgänglig här.

Precis som kube-score identifierar Polaris problem inom områden där manifestet inte uppfyller bästa praxis:

  • Det finns inga hälsokontroller för baljor.
  • Taggar för behållarbilder är inte specificerade.
  • Behållaren körs som root.
  • Förfrågningar och begränsningar för minne och CPU anges inte.

Varje test, beroende på dess resultat, tilldelas en grad av kritik: varning eller fara. För att lära dig mer om de tillgängliga inbyggda testerna, se dokumentation.

Om detaljer inte behövs kan du ange flaggan --format score. I det här fallet kommer Polaris att mata ut ett tal som sträcker sig från 1 till 100 − göra (dvs bedömning):

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

Ju närmare poängen är 100, desto högre grad av överensstämmelse. Om du kontrollerar utgångskoden för kommandot polaris audit, visar det sig att det är lika med 0.

tvinga polaris audit Du kan avsluta arbetet med kod som inte är noll med två flaggor:

  • flag --set-exit-code-below-score tar som argument ett tröskelvärde i intervallet 1-100. I det här fallet kommer kommandot att avslutas med exitkod 4 om poängen är under tröskeln. Detta är mycket användbart när du har ett visst tröskelvärde (säg 75) och du behöver få en varning om poängen går under.
  • flag --set-exit-code-on-danger kommer att göra att kommandot misslyckas med kod 3 om ett av farotesterna misslyckas.

Låt oss nu försöka skapa ett anpassat test som kontrollerar om bilden är tagen från ett pålitligt arkiv. Anpassade tester specificeras i YAML-format, och själva testet beskrivs med JSON Schema.

Följande YAML-kodavsnitt beskriver ett nytt test som kallas 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/.+$

Låt oss ta en närmare titt på det:

  • successMessage — Denna rad kommer att skrivas ut om testet slutförs framgångsrikt.
  • failureMessage — Detta meddelande kommer att visas i händelse av fel;
  • category - indikerar en av kategorierna: Images, Health Checks, Security, Networking и Resources;
  • target--- bestämmer vilken typ av objekt (spec) test tillämpas. Möjliga värden: Container, Pod eller Controller;
  • Själva testet anges i objektet schema använder JSON-schema. Nyckelordet i detta test är pattern används för att jämföra bildkällan med den som krävs.

För att köra ovanstående test måste du skapa följande 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)

Låt oss analysera filen:

  • Inom området checks tester och deras kritikalitet föreskrivs. Eftersom det är önskvärt att få en varning när en bild är tagen från en opålitlig källa ställer vi in ​​nivån här danger.
  • Själva testet checkImageRepo registreras sedan i objektet customChecks.

Spara filen som custom_check.yaml. Nu kan du springa polaris audit med ett YAML-manifest som kräver verifiering.

Låt oss testa vårt manifest base-valid.yaml:

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

Team polaris audit körde endast användartestet som anges ovan och det misslyckades.

Om du fixar bilden till my-company.com/http-echo:1.0, kommer Polaris att slutföras framgångsrikt. Manifestet med förändringarna är redan inne förrådså att du kan kontrollera det föregående kommandot på manifestet image-valid-mycompany.yaml.

Nu uppstår frågan: hur kör man inbyggda tester tillsammans med anpassade? Lätt! Du behöver bara lägga till de inbyggda testidentifierarna till konfigurationsfilen. Som ett resultat kommer det att ha följande 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)

Ett exempel på en komplett konfigurationsfil finns tillgänglig här.

Kontrollera manifestet base-valid.yamlmed inbyggda och anpassade tester kan du använda kommandot:

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

Polaris kompletterar de inbyggda testerna med anpassade tester och kombinerar därigenom det bästa av två världar.

Å andra sidan kan oförmågan att använda mer kraftfulla språk som Rego eller JavaScript vara en begränsande faktor som förhindrar skapandet av mer sofistikerade tester.

Mer information om Polaris finns på projektwebbplats.

Sammanfattning

Även om det finns många tillgängliga verktyg för att inspektera och utvärdera Kubernetes YAML-filer, det är viktigt att ha en klar förståelse för hur testerna kommer att utformas och utföras.

Till exempel, om du tar Kubernetes-manifest som går igenom en pipeline kan kubeval vara det första steget i en sådan pipeline. Det skulle övervaka om objektdefinitioner överensstämmer med Kubernetes API-schema.

När en sådan granskning väl är klar kan man gå vidare till mer sofistikerade tester, till exempel efterlevnad av standardiserade bästa praxis och specifika policyer. Det är här kube-score och Polaris skulle komma väl till pass.

För dem som har komplexa krav och behöver anpassa tester i detalj skulle koppar, config-lint och confetest vara lämpliga.

Conftest och config-lint använder YAML för att definiera anpassade tester, och koppar ger dig tillgång till ett fullständigt programmeringsspråk, vilket gör det till ett ganska attraktivt val.

Å andra sidan, är det värt att använda ett av dessa verktyg och därför skapa alla tester manuellt, eller föredrar Polaris och bara lägga till det som behövs till det? Det finns inget tydligt svar på denna fråga.

Tabellen nedan ger en kort beskrivning av varje verktyg:

Verktyg
öde
Begränsningar
Användartester

kubeval
Validerar YAML-manifester mot en specifik version av API-schemat
Kan inte fungera med CRD
Ingen

kube-poäng
Analyserar YAML-manifester mot bästa praxis
Det går inte att välja din Kubernetes API-version för att kontrollera resurser
Ingen

koppar
Ett allmänt ramverk för att skapa anpassade JavaScript-tester för YAML-manifest
Inga inbyggda tester. Dålig dokumentation
Ja

config-lint
Ett allmänt ramverk för att skapa tester på ett domänspecifikt språk inbäddat i YAML. Stöder olika konfigurationsformat (t.ex. Terraform)
Det finns inga färdiga tester. Inbyggda påståenden och funktioner kanske inte räcker
Ja

strid
Ett ramverk för att skapa dina egna tester med hjälp av Rego (ett specialiserat frågespråk). Tillåter delning av policyer via OCI-paket
Inga inbyggda tester. Jag måste lära mig Rego. Docker Hub stöds inte vid publicering av policyer
Ja

Polaris
Recensioner YAML manifesterar sig mot standard bästa praxis. Låter dig skapa dina egna tester med JSON Schema
Testfunktioner baserade på JSON Schema kanske inte är tillräckliga
Ja

Eftersom dessa verktyg inte är beroende av tillgång till Kubernetes-klustret är de enkla att installera. De låter dig filtrera källfiler och ge snabb feedback till författarna av pull-förfrågningar i projekt.

PS från översättaren

Läs även på vår blogg:

Källa: will.com

Lägg en kommentar