Validering av Kubernetes YAML för att uppfylla bÀsta praxis och policyer

Obs. övers.: Med den ökande mÀngden YAML-konfigurationer för K8s-miljöer blir behovet av automatiserad verifiering allt mer aktuellt. Författaren av denna översyn har inte bara valt ut befintliga lösningar för detta problem, utan har ocksÄ tittat pÄ hur de fungerar med hjÀlp av ett exempel pÄ Deployment. Det blev ganska informativt för dem som Àr intresserade av detta Àmne.

Validering av Kubernetes YAML för att uppfylla bÀsta praxis och policyer

TL;DR: Artikeln jÀmför sex statiska verktyg för verifiering och utvÀrdering av YAML-filer i Kubernetes för att sÀkerstÀlla överensstÀmmelse med bÀsta praxis och krav.

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

Vad hÀnder om vi mÄste sÀkerstÀlla att alla bilder som distribueras i klustret hÀmtas frÄn ett betrott register?

Hur förhindrar vi att Deployment skickas till klustret utan att PodDisruptionBudgets har angetts?

Integrering av statisk testning gör det möjligt att upptÀcka fel och policyövertrÀdelser redan i utvecklingsstadiet. Detta ökar sÀkerheten och korrektheten i resursdefinitionerna och ökar sannolikheten för att produktionsbelastningar följer bÀsta praxis.

Ecosystemet för statisk verifiering av YAML-filer i Kubernetes kan delas in i följande kategorier:

  • API-validatorer. Verktyg i denna kategori kontrollerar YAML-manifest mot krav frĂ„n Kubernetes API-servern.
  • FĂ€rdiga testare. Verktyg i denna kategori kommer med fĂ€rdiga tester för sĂ€kerhet, överensstĂ€mmelse med bĂ€sta praxis, osv.
  • Anpassade validatorer. Representanter för denna kategori gör det möjligt att skapa anvĂ€ndarspecifika tester pĂ„ olika sprĂ„k, till exempel Rego och Javascript.

I denna artikel kommer vi att beskriva och jÀmföra sex olika verktyg:

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

NÄvÀl, lÄt oss börja!

Verifiering av Deployment

Innan vi börjar jÀmföra verktygen, lÄt oss skapa en bas för att testa dem.

Manifestet nedan innehÄller en rad fel och övertrÀdelser 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.

Manifestet ovan base-valid.yaml och andra manifest frÄn denna artikel finns i Git-repository.

Manifestet beskriver en webbapplikation vars huvuduppgift Àr att svara med meddelandet "Hello World" pÄ port 5678. Det kan deployeras med följande kommando:

kubectl apply -f hello-world.yaml

Och sÄ hÀr testar vi att det fungerar:

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 kontrollera.

1. Kubeval

Grunden för kubeval Àr idén att varje interaktion med Kubernetes sker via dess REST API. Med andra ord kan API-schema anvÀndas för att kontrollera om den angivna YAML överensstÀmmer med det. LÄt oss titta pÄ ett exempel.

Installationsanvisningar kubeval finns pÄ projektets webbplats.

Vid tidpunkten för skrivandet av den ursprungliga artikeln var version 0.15.0 tillgÀnglig.

NÀr installationen Àr klar, lÄt oss "mata" den med manifestet ovan:

$ kubeval base-valid.yaml
PASS - base-valid.yaml innehÄller en giltig Deployment (http-echo)
PASS - base-valid.yaml innehÄller en giltig Service (http-echo)

Vid framgÄng kommer kubeval att avslutas med exit-kod 0. Detta kan kontrolleras sÄ hÀr:

$ 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 vid en snabb blick? LÄt oss köra:

$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml innehÄller en ogiltig Deployment (http-echo) - selector: selector krÀvs
PASS - kubeval-invalid.yaml innehÄller en giltig Service (http-echo)

# lÄt oss kontrollera exit-koden
$ echo $?
1

Resursen klarar inte kontrollen.

Deployment:er som anvÀnder API-version apps/v1, mÄste inkludera en selektor som matchar pod:ens etikett. Manifestet ovan inkluderar inte en selektor, sÄ kubeval rapporterade ett fel och avslutades med en icke-noll exit-kod.

Det Àr intressant att se vad som hÀnder om man kör kubectl apply -f med detta manifest?

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 fel som kubeval varnade för. Du kan ÄtgÀrda det genom att lÀgga till 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)

Fördelen med verktyg som kubeval Àr att sÄdana fel kan fÄngas tidigt i distributionscykeln.

Dessutom krÀver dessa kontroller ingen Ätkomst till klustret: de kan utföras offline.

Som standard kontrollerar kubeval resurser för att sÀkerstÀlla att de följer den senaste schemat frÄn Kubernetes API. Men i de flesta fall kanske du vill utföra en kontroll mot en specifik version av Kubernetes. Detta kan göras med 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 att se en lista över versioner som stöds för kontroll, se JSON-schemat pÄ GitHub, som kubeval anvÀnder för validering. Om du behöver köra kubeval offline, ladda ner scheman och ange deras lokala plats med flaggan --schema-location.

Utöver enskilda YAML-filer kan kubeval ocksÄ fungera med kataloger och stdin.

Dessutom integreras Kubeval enkelt i CI-pipelines. De som vill testa innan de skickar manifest till klustret kommer att bli glada att veta att kubeval stöder tre utdataformat:

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

Och vilket av formaten kan anvÀndas för att vidarebearbeta utskriften för att skapa en sammanfattning av resultaten i önskat format.

En av nackdelarna med kubeval Àr att den för nÀrvarande inte kan kontrollera mot Custom Resource Definitions (CRDs). Men kubeval kan konfigureras för att ignorera dem..

Kubeval Àr ett utmÀrkt verktyg för att kontrollera och utvÀrdera resurser; det bör dock understrykas att ett godkÀnt test inte garanterar att resursen följer bÀsta praxis.

Till exempel, anvÀndningen av taggen latest i containern överensstÀmmer inte med bÀsta praxis. Men kubeval anser inte att detta Àr ett fel och rapporterar det inte. Det vill sÀga att kontrollen av en sÄdan YAML avslutas utan varningar.

Men vad hĂ€nder om du behöver utvĂ€rdera YAML och identifiera övertrĂ€delser som taggar? latest? КаĐș ĐżŃ€ĐŸĐČĐ”Ń€ĐžŃ‚ŃŒ YAML-фаĐčĐ» ĐœĐ° ŃĐŸĐŸŃ‚ĐČДтстĐČОД Đ»ŃƒŃ‡ŃˆĐžĐŒ праĐșтоĐșĐ°ĐŒ?

2. Kube-score

Kube-score analyserar YAML-manifest och utvÀrderar dem med inbyggda tester. Dessa tester vÀljs baserat pÄ sÀkerhetsrekommendationer och bÀsta praxis, till exempel:

  • Körning av containrar utan root-rĂ€ttigheter.
  • NĂ€rvaro av hĂ€lso kontroll av poddar.
  • Ange requestar och begrĂ€nsningar för resurser.

Efter testet ges tre resultat: OK, VARNING och KRITISK.

Kube-score kan testas online eller installeras lokalt.

Vid tidpunkten för skrivandet av den ursprungliga artikeln var den senaste versionen av kube-score 1.7.0.

LÄt oss testa det pÄ vÄrt manifest base-valid.yaml:

$ kube-score score base-valid.yaml

apps/v1/Deployment http-echo
[KRITISK] Container Image Tag
  · http-echo -> Bild med senaste taggen
      Det rekommenderas att anvÀnda en fast tagg för att undvika oavsiktliga uppgraderingar
[KRITISK] Pod NetworkPolicy
  · Podden har ingen matchande nÀtverkspolicy
      Skapa en NetworkPolicy som riktar sig till denna podd
[KRITISK] Pod Probes
  · Containern saknar en readinessProbe
      En readinessProbe bör anvÀndas för att indikera nÀr tjÀnsten Àr redo att ta emot trafik.
      Utan den riskerar podden att ta emot trafik innan den har startat. Den anvÀnds ocksÄ under
      uppgraderingar och kan förhindra driftstopp om en ny version av applikationen misslyckas.
      Mer information: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[KRITISK] Container Security Context
  · http-echo -> Containern har inget konfigurerat sÀkerhetskontext
      Ange securityContext för att köra containern i en mer sÀker kontext.
[KRITISK] Container Resources
  · http-echo -> CPU-begrÀnsning Àr inte angiven
      ResursbegrÀnsningar rekommenderas för att undvika resurs-DDoS. Ange resources.limits.cpu
  · http-echo -> MinnebegrÀnsning Àr inte angiven
      ResursbegrÀnsningar rekommenderas för att undvika resurs-DDoS. Ange resources.limits.memory
  · http-echo -> CPU-request Àr inte angiven
      ResursförfrÄgningar rekommenderas för att sÀkerstÀlla att applikationen kan starta och köra utan
      krasch. Ange resources.requests.cpu
  · http-echo -> Minne-request Àr inte angiven
      ResursförfrÄgningar rekommenderas för att sÀkerstÀlla att applikationen kan starta och köra utan krasch.
      Ange resources.requests.memory
[KRITISK] Deployment har PodDisruptionBudget
  · Ingen matchande PodDisruptionBudget hittades
      Det rekommenderas att definiera en PodDisruptionBudget för att undvika ovÀntad driftstopp under Kubernetes
      underhÄllsÄtgÀrder, sÄsom nÀr en nod urladdas.
[VARNING] Deployment har host PodAntiAffinity
  · Deployment har inte en host podAntiAffinity angiven
      Det rekommenderas att ange en podAntiAffinity som förhindrar att flera poddar frÄn en deployment
      schemalÀggs pÄ samma nod. Detta ökar tillgÀngligheten om noden blir otillgÀnglig.

YAML passerar kubeval-kontroller, medan kube-score pÄpekar följande brister:

  • Inga ready checks Ă€r konfigurerade.
  • Det saknas förfrĂ„gningar och begrĂ€nsningar för CPU- och minnesresurser.
  • Det finns inga definierade Pod disruption budgets.
  • Det finns inga regler för separat existens. (anti-affinity) för att maximera tillgĂ€ngligheten.
  • Containern körs som root.

Detta Àr rimliga kommentarer om brister som bör ÄtgÀrdas för att göra Deployment mer effektiv och pÄlitlig.

Team kube-score visar information pÄ ett lÀsbart sÀtt med alla typer av övertrÀdelser inkluderade VARNING och KRITISK, vilket Àr mycket hjÀlpsamt under utvecklingen.

De som vill anvÀnda detta verktyg i CI-pipelinen kan aktivera en mer komprimerad utdata med hjÀlp av flaggan --output-format ci (i det hÀr fallet visas ocksÄ tester med resultat 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Àns Àr inte angiven
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) MinnegrÀns Àr inte angiven
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU-begÀran Àr inte angiven
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) MinnebegÀran Àr inte angiven
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Bild med senaste taggen
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: Podden har ingen matchande nÀtverkspolicy
[CRITICAL] http-echo apps/v1/Deployment: Containern saknar en readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Containern har ingen konfigurerad sÀkerhetskontext
[CRITICAL] http-echo apps/v1/Deployment: Ingen matchande PodDisruptionBudget hittades
[WARNING] http-echo apps/v1/Deployment: Deployment har inte en host podAntiAffinity instÀlld
[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 icke-noll exitkod nÀr det finns ett test som misslyckas KRITISK. Liknande behandling kan ocksÄ aktiveras för VARNING.

Dessutom finns det möjlighet att kontrollera resurser mot olika versioner av API (precis som i kubeval). Men denna information Àr 'hardcode' i kube-score: det gÄr inte att vÀlja en annan version av Kubernetes. En sÄdan begrÀnsning kan bli ett stort problem om du planerar att uppgradera klustret eller om du har flera kluster med olika versioner av K8s.

Observera att det finns redan en issue med förslaget att implementera denna funktion.

Mer information om kube-score kan fÄs pÄ den officiella webbplatsen.

Kube-scores tester Àr ett utmÀrkt verktyg för att införa bÀsta praxis, men vad hÀnder om du behöver göra Àndringar i testet eller lÀgga till egna regler? TyvÀrr gÄr inte det.

Kube-score Àr inte utbyggbart: det gÄr inte att lÀgga till eller anpassa policies.

Om det behövs att skriva egna tester för att kontrollera överensstÀmmelse med företagets antagna policies kan du anvÀnda nÄgot av följande fyra verktyg: config-lint, copper, conftest eller polaris.

3. Config-lint

Config-lint Àr ett verktyg för validering av konfigurationsfiler i YAML-, JSON-, Terraform-, CSV-format och Kubernetes-manifest.

Det kan installeras genom instruktionerna pÄ projektets webbplats.

Den aktuella versionen vid tidpunkten för skrivandet av den ursprungliga artikeln Àr 1.5.0.

Config-lint innehÄller inte inbyggda tester för att kontrollera Kubernetes-manifest.

För att utföra nÄgra tester behövs specifika regler. Dessa skrivs i YAML-filer, kallade "regelset" (rulesets), och har följande struktur:

version: 1
description: Regler för Kubernetes-specfiler
type: Kubernetes
files:
  - "*.yaml"
rules:
   # lista över regler

(rule.yaml)

LÄt oss titta nÀrmare pÄ den:

  • FĂ€ltet typ anger vilken typ av konfiguration som config-lint kommer att anvĂ€nda. För K8s-manifest Ă€r det alltid Kubernetes.
  • I fĂ€ltet filer förutom sjĂ€lva filerna kan en katalog anges.
  • FĂ€ltet rules Ă€r avsett för att ange anvĂ€ndartester.

Anta att du vill försÀkra dig om att bilderna i deployment alltid laddas ner frÄn ett betrodat register som my-company.com/myapp:1.0. Reglen för config-lint som utför en sÄdan kontroll skulle se ut som följer:

- id: MY_DEPLOYMENT_IMAGE_TAG
  severity: FAILURE
  message: Deployment mÄste anvÀnda en giltig bildtagg
  resource: Deployment
  assertions:
    - every:
        key: spec.template.spec.containers
        expressions:
          - key: image
            op: starts-with
            value: "my-company.com/"

(rule-trusted-repo.yaml)

För varje regel mÄste följande attribut anges:

  • id — en unik identifierare för regeln;
  • severity — kan vara FAILURE, VARNING och NON_COMPLIANT;
  • meddelande — vid regelfel visas innehĂ„llet i denna rad;
  • resource — typen av resurs som regeln tillĂ€mpas pĂ„;
  • assertions — en lista över villkor som ska utvĂ€rderas för denna resurs.

I regeln ovan assertion som kallas every kontrollerar att alla containrar i deployment (key: spec.templates.spec.containers) anvÀnder betrodda bilder (d.v.s. som börjar med my-company.com/).

Det fullstÀndiga regelsetet ser ut sÄ hÀr:

version: 1
description: Regler för Kubernetes-specfiler
type: Kubernetes
files:
  - "*.yaml"
rules:

 - id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
    severity: FAILURE
    message: Deployment mÄste anvÀnda ett giltigt bildregister
    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 regeln, lÄt oss spara den som check_image_repo.yaml. LÄt oss köra kontrollen pÄ filen. base-valid.yaml:

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

[
  {
  "AssertionMessage": "Varje uttryck misslyckas: Och uttrycket misslyckas: bilden börjar inte 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 mÄste anvÀnda ett giltigt bildförrÄd",
  "Status": "FAILURE"
  }
]

Kontrollen misslyckades. LÄt oss nu kontrollera nÀsta manifest med ett korrekt 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 det ovanstÄende manifestet. Inga problem upptÀckta:

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

Config-lint Àr ett lovande ramverk som gör det möjligt att skapa egna tester för att validera YAML-manifester i Kubernetes med YAML DSL.

Men vad gör man om mer komplex logik och tester behövs? Är inte YAML:s möjligheter för begrĂ€nsade för detta? TĂ€nk om man kunde skapa tester pĂ„ ett fullt programmeringssprĂ„k?

4. Copper

Copper V2 Àr ett ramverk för validering av manifester med hjÀlp av anvÀndardefinierade tester (liknande config-lint).

Dock skiljer det sig frÄn det senaste genom att det inte anvÀnder YAML för att beskriva tester. IstÀllet kan tester skapas i JavaScript. Copper tillhandahÄller ett bibliotek med flera grundlÀggande verktyg, som hjÀlper till att lÀsa information om Kubernetes-objekt och rapportera fel.

Stegen för att installera Copper kan hittas i den officiella dokumentationen.

2.0.1 — den senaste versionen av detta verktyg vid tidpunkten för skrivandet av den ursprungliga artikeln.

Precis som config-lint har Copper inga inbyggda tester. LÄt oss skriva ett. LÄt det kontrollera att deployment anvÀnder containermagasin endast frÄn betrodda förrÄd sÄ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',"Bild " + $.metadata.name + " Àr inte frÄn my-company.com förrÄd", 1)
            }
        });
    }
});

Nu, för att kontrollera vÄrt manifest base-valid.yaml, anvÀnd kommandot copper validate:

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

Kontroll av no_company_repo misslyckades med allvarlighetsgrad 1 eftersom bilden http-echo inte kommer frÄn my-company.com förrÄd
Valideringen misslyckades

Det Ă€r klart att man med Copper kan genomföra mer komplexa tester – till exempel kontrollera domĂ€nnamn i Ingress-mani-fester eller avvisa pods som körs i privilegierat lĂ€ge.

Copper har inbyggda olika tjÀnstefunktioner:

  • DockerImage lĂ€ser den angivna ingĂ„ngsfilen och skapar ett objekt med följande attribut:
    • name — bildnamn,
    • tag — bildtagg,
    • registry — bildregister,
    • registry_url — protokoll (https://) och bildregister,
    • fqin — fullstĂ€ndig plats för bilden.
  • Funktionen findByName hjĂ€lper till att hitta en resurs efter angiven typ (typ) och namn (name) frĂ„n ingĂ„ngsfilen.
  • Funktionen findByLabels hjĂ€lper till att hitta en resurs efter angiven typ (typ) och etiketter (labels).

Alla tillgÀngliga tjÀnstefunktioner kan ses hÀr.

Som standard laddar den hela den ingÄngna YAML-filen till en variabel $$ och gör den tillgÀnglig för skript (en bekant metod för dem som har erfarenhet av jQuery).

Den stora fördelen med Copper Àr uppenbar: du behöver inte lÀra dig ett specialiserat sprÄk och kan anvÀnda olika JavaScript-möjligheter för att skapa egna tester, sÄsom strÀnginterpolation, funktioner osv.

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

Detaljer finns tillgÀngliga pÄ det officiella projektets webbplats.

Men om du inte Àr sÀrskilt förtjust i JavaScript och föredrar ett sprÄk speciellt utformat för att skapa förfrÄgningar och beskriva policyer, bör du titta pÄ conftest.

5. Conftest

Conftest Àr ett ramverk för att kontrollera konfigurationsdata. Det passar Àven för testning/verifiering av Kubernetes-manifest. Tester beskriver med ett specialiserat frÄgesprÄk Rego.

Du kan installera conftest med hjÀlp av instruktionerna, som anges pÄ projektets webbplats.

Vid skrivandet av den ursprungliga artikeln var den senaste tillgÀngliga versionen 0.18.2.

PÄ samma sÀtt som config-lint och copper, kommer conftest utan nÄgra inbyggda tester. LÄt oss prova det och skriva vÄr egen policy. Som i de tidigare exemplen kommer vi att kontrollera om containerbilder tas frÄn en pÄlitlig kÀlla.

Skapa en katalog conftest-checks, och i den – 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 lÄt oss testa base-valid.yaml via 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 som förvÀntat eftersom bilderna kommer frÄn en osÀker kÀlla.

I Rego-filen definierar vi blocket deny. Dess giltighet betraktas som ett brott. Om det finns flera block sĂ„ kontrollerar conftest dem oberoende av varandra, och giltigheten av vilket block som helst tolkas som ett brott. deny Förutom standardutdata stöder conftest JSON, TAP och tabellformat — en oerhört anvĂ€ndbar funktion om du behöver integrera rapporter i en befintlig CI-pipeline. Den önskade formatet kan anges med flaggan

--output För att underlÀtta felsökning av policyer erbjuder conftest en flagga.

--trace . Den visar en spÄrning av hur conftest tolkar de angivna policyfilerna.Conftest-policys kan publiceras och delas i OCI-register (Open Container Initiative) som artefakter.

tillÄter att publicera en artefakt eller hÀmta en befintlig artefakt frÄn ett fjÀrrregister. LÄt oss försöka publicera den policy vi skapade till ett lokalt Docker-register med hjÀlp av

Kommandon push och pull conftest push Kör ett lokalt Docker-register:.

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

I en annan terminal, gÄ till den tidigare skapade katalogen

$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latest conftest-checks och kör följande kommando:

Om kommandot lyckades kommer du att se ett meddelande av följande typ:

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

Skapa nu en temporÀr katalog och kör kommandot

conftest pull . Det kommer att ladda ner paketet som skapades av föregÄende kommando:$ cd $(mktemp -d) $ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latest

I den temporÀra katalogen kommer det att finnas en undermapp

, som innehĂ„ller vĂ„r policyfil: policy$ tree . └── policy └── check_image_registry.rego

Tester kan köras direkt frÄn lagret:

$ conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml .. FAIL - base-valid.yaml - image 'hashicorp/http-echo' kommer inte frÄn my-company.com-repository 2 tester, 1 godkÀnd, 0 varningar, 1 misslyckande

TyvÀrr stöds DockerHub för tillfÀllet inte. SÄ betrakta det som tur om du anvÀnder

Azure Container Registry (ACR) eller din egen register. Artefakternas format Àr detsamma som för

paket av Open Policy Agent (OPA), vilket gör att conftest kan anvÀndas för att köra tester frÄn befintliga OPA-paket. Mer om delning av policyer och andra funktioner i conftest kan du lÀsa pÄ

6. Polaris det officiella projektets webbplats.

Det sista verktyget som kommer att tas upp i den hÀr artikeln Àr

(Vi har redan översatt dess tillkĂ€nnagivande frĂ„n förra Ă„ret. Polaris. (Đ•ĐłĐŸ ĐżŃ€ĐŸŃˆĐ»ĐŸĐłĐŸĐŽĐœĐžĐč Đ°ĐœĐŸĐœŃ ĐŒŃ‹ ужД пДрДĐČĐŸĐŽĐžĐ»Đž — anm. övers.)

Polaris kan installeras i en kluster eller anvÀndas i kommandoradslÀge. Som du sÀkert redan gissat, lÄter den dig statiskt analysera Kubernetes-manifest.

NÀr du arbetar i kommandoradslÀge finns det inbyggda tester som tÀcker omrÄden som sÀkerhet och bÀsta praxis (pÄ samma sÀtt som kube-score). Dessutom kan du skapa egna tester (som config-lint, copper och conftest).

Med andra ord kombinerar Polaris fördelarna med bÄda kategorier av verktyg: med inbyggda och anvÀndarspecifika tester.

För att installera Polaris i kommandoradslÀge, anvÀnd anvisningarna pÄ projektets webbplats..

Vid tidpunkten för skrivandet av den ursprungliga artikeln finns 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 ge en rad i JSON-format med en detaljerad beskrivning av de testsom genomförts och deras resultat. Utdata 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": [
    /* lÄng lista */
  ]
}

Den fullstÀndiga utdata Àr tillgÀnglig. hÀr.

Precis som kube-score identifierar Polaris problem dÀr manifestet inte uppfyller bÀsta praxis:

  • Det saknas hĂ€lsokontroller för pods.
  • Inga taggar angivna för containerbilder.
  • Containern körs som root.
  • Inga begĂ€rningar och begrĂ€nsningar angivna för minne och CPU.

Varje test tilldelas en kritikalitetsgrad beroende pÄ dess resultat: warning eller danger. För att veta mer om de tillgÀngliga inbyggda testerna, hÀnvisa till dokumentationen.

Om detaljerna inte behövs kan du ange flaggan --format score. I sĂ„ fall kommer Polaris att ge ett nummer i intervallet 1 till 100 — score (d.v.s. betyg):

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

Ju nÀrmare betyget Àr 100, desto högre överensstÀmmelse. Om du kontrollerar exit-koden för kommandot polaris audit, kommer det att visa att den Àr 0.

För att fÄ polaris audit att avsluta med en icke-nollkod kan du anvÀnda tvÄ flaggor:

  • Flagga --set-exit-code-below-score tar ett tröskelvĂ€rde mellan 1-100 som argument. I sĂ„ fall avslutas kommandot med exit-kod 4 om betyget Ă€r under tröskeln. Detta Ă€r mycket praktiskt nĂ€r du har ett tröskelvĂ€rde (sĂ€g 75) och behöver fĂ„ en alert om betyget sjunker under detta.
  • Flagga --set-exit-code-on-danger det kommer att leda till att teamet avslutas med kod 3 om nĂ„got av danger-testen misslyckas.

LÄt oss nu försöka skapa ett anvÀndartest som kontrollerar om bilden hÀmtas frÄn ett betrott förrÄd. AnvÀndartest definieras i YAML-format och sjÀlva testet beskrivs med JSON Schema.

Följande YAML-kod beskriver ett nytt test som kallas checkImageRepo:

checkImageRepo:
  successMessage: BildförrÄdet Àr giltigt
  failureMessage: BildförrÄdet Àr inte giltigt
  category: Bilder
  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 visas om testet lyckas;
  • failureMessage — detta meddelande kommer att visas i hĂ€ndelse av ett misslyckande;
  • category — anger en av kategorierna: Bilder, HĂ€lsokontroller, SĂ€kerhet, NĂ€tverkande och Resurser;
  • target—- anger vilken typ av objekt (spec) testet tillĂ€mpas pĂ„. Möjliga vĂ€rden: Container, Pod eller Controller;
  • SjĂ€lva testet definieras i objektet schema med hjĂ€lp av JSON-schema. I detta test anvĂ€nds nyckelordet mönster för att jĂ€mföra bildkĂ€llan med det som krĂ€vs.

För att köra testet ovan mÄste följande konfiguration av Polaris skapas:

checks:
  checkImageRepo: danger
customChecks:
  checkImageRepo:
    successMessage: BildförrÄdet Àr giltigt
    failureMessage: BildförrÄdet Àr inte giltigt
    category: Bilder
    target: Container
    schema:
      '$schema': http://json-schema.org/draft-07/schema
      type: object
      properties:
        image:
          type: string
          pattern: ^my-company.com/.+$

(polaris-conf.yaml)

LÄt oss gÄ igenom filen:

  • I fĂ€ltet checks anger tester och deras kritikalitetsnivĂ„. Eftersom det Ă€r önskvĂ€rt att fĂ„ en varning nĂ€r bilden hĂ€mtas frĂ„n en osĂ€ker kĂ€lla, sĂ€tter vi hĂ€r nivĂ„n danger.
  • SjĂ€lva testet checkImageRepo anges sedan i objektet customChecks.

Spara filen som custom_check.yaml. Nu kan vi köra polaris audit med YAML-manifestet som krÀver kontroll.

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

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

Team polaris audit har endast genomfört det ovan nÀmnda anvÀndartestet, och det misslyckades.

Om bilden korrigeras till my-company.com/http-echo:1.0, kommer Polaris att avslutas framgÄngsrikt. Manifestet med Àndringarna finns redan i förrÄdet, sÄ att du kan kontrollera den föregÄende kommandon med manifestet. image-valid-mycompany.yaml.

Nu uppstÄr frÄgan: hur kör man inbyggda tester tillsammans med anvÀndartester? LÀtt! Du behöver bara lÀgga till identiteterna för de inbyggda testen i konfigurationsfilen. Resultatet kommer att se ut som följande:

kontroller:
  cpuRequestsMissing: varning
  cpuLimitsMissing: varning
  # Andra inbyggda kontroller..
  # ..
  # anpassade kontroller
  checkImageRepo: fara # !!!
anpassadeKontroller:
  checkImageRepo:        # !!!
    successMessage: Bildregister Àr giltigt
    failureMessage: Bildregister Àr inte giltigt
    category: Bilder
    target: BehÄllare
    schema:
      '$schema': http://json-schema.org/draft-07/schema
      type: object
      properties:
        image:
          type: string
          pattern: ^my-company.com/.+$

(config_with_custom_check.yaml)

Exempel pÄ en fullstÀndig konfigurationsfil Àr tillgÀnglig hÀr.

Kontrollera manifestet base-valid.yaml, med hjÀlp av inbyggda och anpassade tester kan göras med kommandot:

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

Polaris kompletterar inbyggda tester med anpassade tester och kombinerar dÀrmed det bÀsta av tvÄ vÀrldar.

Å andra sidan kan avsaknaden av mer kraftfulla sprĂ„k som Rego eller JavaScript bli en begrĂ€nsande faktor som hindrar skapandet av mer avancerade tester.

Ytterligare information om Polaris finns tillgÀnglig pÄ projektets webbplats.

Sammanfattning

Även om det finns mĂ„nga verktyg för att kontrollera och bedöma YAML-filer för Kubernetes, Ă€r det viktigt att ha en tydlig uppfattning om hur testerna kommer att utformas och genomföras.

Till exempel, om man tar Kubernetes-manifest som gÄr genom pipelinen, kan kubeval bli det första steget i en sÄdan pipeline. Det skulle övervaka om objektd definitioner överensstÀmmer med Kubernetes API:s schema.

Efter att en sÄdan kontroll har genomförts kan man gÄ vidare till mer avancerade tester, sÄsom överensstÀmmelse med standardbÀsta praxis och specifika policyer. HÀr skulle kube-score och Polaris vara till nytta.

För dem med komplexa krav och behov av att finjustera tester skulle copper, config-lint och conftest vara lÀmpliga.

Conftest och config-lint anvÀnder YAML för att definiera anpassade tester, medan copper ger tillgÄng till ett fullstÀndigt programsprÄk, vilket gör det till ett ganska attraktivt val.

Å andra sidan, ska man anvĂ€nda nĂ„got av dessa verktyg och dĂ€rmed skapa alla tester manuellt, eller föredra Polaris och bara skriva in vad som behövs? Det finns inget entydigt svar pĂ„ denna frĂ„ga.

Tabellen nedan innehÄller en kort beskrivning av varje verktyg:

Verktyget
Syftet
Nackdelar
Anpassade tester

kubeval
Kontrollerar YAML-manifesten för överensstÀmmelse med en viss version av API-schemat
Kan inte hantera CRD
Ingen

kube-score
Analys av YAML-manifest för överensstÀmmelse med bÀsta praxis
Det gÄr inte att vÀlja sin egen version av Kubernetes API att kontrollera resurser mot
Ingen

copper
Ett allmÀnt ramverk för att skapa egna JavaScript-tester för YAML-manifest
Inga inbyggda tester. Sparsam dokumentation
Ja

config-lint
Ett allmÀnt ramverk för att skapa tester i ett domÀnspecifikt sprÄk som Àr inbyggt i YAML. Stöder olika konfigurationsformat (t.ex. Terraform)
Inga fÀrdiga tester. Inbyggda assertions och funktioner kan vara otillrÀckliga
Ja

conftest
Ett ramverk för att skapa egna tester med Rego (ett specialiserat frÄgesprÄk). Möjliggör delning av policyer via OCI-bundlar
Inga inbyggda tester. Man mÄste lÀra sig Rego. Docker Hub stöds inte vid publicering av policyer
Ja

Polaris
Analyserar YAML-manifest för att sÀkerstÀlla att de följer standardens bÀsta praxis. Möjliggör skapande av egna tester med hjÀlp av JSON Schema
Möjligheterna för tester baserade pÄ JSON Schema kan vara otillrÀckliga
Ja

Eftersom dessa verktyg inte Àr beroende av Ätkomst till Kubernetes-klustret, Àr de lÀtta att installera. De kan filtrera kÀllfiler och ger snabb feedback till författare av pull requests i projekten.

P.S. frÄn översÀttaren

LÀs Àven i vÄr blogg:

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster