Validați Kubernetes YAML în raport cu cele mai bune practici și politici

Notă. transl.: Odată cu numărul tot mai mare de configurații YAML pentru mediile K8s, necesitatea verificării lor automate devine din ce în ce mai urgentă. Autorul acestei recenzii nu numai că a selectat soluțiile existente pentru această sarcină, dar a folosit și Deployment ca exemplu pentru a vedea cum funcționează. S-a dovedit a fi foarte informativ pentru cei care sunt interesați de acest subiect.

Validați Kubernetes YAML în raport cu cele mai bune practici și politici

TL; DR: Acest articol compară șase instrumente statice pentru a valida și evalua fișierele Kubernetes YAML în raport cu cele mai bune practici și cerințe.

Încărcările de lucru Kubernetes sunt de obicei definite sub formă de documente YAML. Una dintre problemele cu YAML este dificultatea de a specifica constrângeri sau relații între fișierele manifest.

Ce se întâmplă dacă trebuie să ne asigurăm că toate imaginile implementate în cluster provin dintr-un registru de încredere?

Cum pot preveni trimiterea către cluster a implementărilor care nu au PodDisruptionBudgets?

Integrarea testării statice vă permite să identificați erorile și încălcările politicii în etapa de dezvoltare. Acest lucru mărește garanția că definițiile resurselor sunt corecte și sigure și face mai probabil ca sarcinile de lucru de producție să urmeze cele mai bune practici.

Ecosistemul de inspecție a fișierelor static YAML Kubernetes poate fi împărțit în următoarele categorii:

  • validatori API. Instrumentele din această categorie verifică manifestul YAML cu cerințele serverului API Kubernetes.
  • Testere gata. Instrumentele din această categorie vin cu teste gata făcute pentru securitate, conformitatea cu cele mai bune practici etc.
  • Validatoare personalizate. Reprezentanții acestei categorii vă permit să creați teste personalizate în diferite limbi, de exemplu, Rego și Javascript.

În acest articol vom descrie și compara șase instrumente diferite:

  1. kubeval;
  2. scor kube;
  3. config-lint;
  4. cupru;
  5. concurs;
  6. polaris.

Ei bine, să începem!

Verificarea implementărilor

Înainte de a începe să comparăm instrumentele, să creăm un fundal pe care să le testăm.

Manifestul de mai jos conține o serie de erori și nerespectarea celor mai bune practici: câte dintre ele puteți găsi?

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)

Vom folosi acest YAML pentru a compara diferite instrumente.

Manifestul de mai sus base-valid.yaml iar alte manifeste din acest articol pot fi găsite în Arhivele Git.

Manifestul descrie o aplicație web a cărei sarcină principală este să răspundă cu un mesaj „Hello World” la portul 5678. Poate fi implementat cu următoarea comandă:

kubectl apply -f hello-world.yaml

Și așa - verificați lucrarea:

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

Acum du-te la http://localhost:8080 și confirmați că aplicația funcționează. Dar respectă cele mai bune practici? Sa verificam.

1. Kubeval

La inima kubeval Ideea este că orice interacțiune cu Kubernetes are loc prin intermediul API-ului REST. Cu alte cuvinte, puteți utiliza o schemă API pentru a verifica dacă un anumit YAML este conform cu acesta. Să ne uităm la un exemplu.

Instructiuni de instalare kubeval sunt disponibile pe site-ul proiectului.

La momentul scrierii articolului original, versiunea 0.15.0 era disponibilă.

Odată instalat, haideți să-i transmitem manifestul de mai sus:

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

Dacă reușește, kubeval va ieși cu codul de ieșire 0. Îl puteți verifica după cum urmează:

$ echo $?
0

Să încercăm acum kubeval cu un manifest diferit:

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)

Puteți observa problema cu ochii? Hai sa lansam:

$ 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

Resursa nu este verificată.

Implementări folosind versiunea API apps/v1, trebuie să includă un selector care se potrivește cu eticheta podului. Manifestul de mai sus nu include selectorul, așa că kubeval a raportat o eroare și a ieșit cu un cod diferit de zero.

Mă întreb ce se va întâmpla dacă o fac kubectl apply -f cu acest manifest?

Ei bine, hai să încercăm:

$ 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

Aceasta este exact eroarea despre care a avertizat Kubeval. Puteți remedia problema adăugând un 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)

Avantajul instrumentelor precum kubeval este că erorile de acest fel pot fi surprinse la începutul ciclului de implementare.

În plus, aceste verificări nu necesită acces la cluster; ele pot fi efectuate offline.

În mod implicit, kubeval verifică resursele cu cea mai recentă schemă API Kubernetes. Cu toate acestea, în majoritatea cazurilor, poate fi necesar să verificați o anumită versiune Kubernetes. Acest lucru se poate face folosind steag --kubernetes-version:

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

Vă rugăm să rețineți că versiunea trebuie specificată în format Major.Minor.Patch.

Pentru o listă a versiunilor pentru care este acceptată verificarea, consultați Schema JSON pe GitHub, pe care kubeval îl folosește pentru validare. Dacă trebuie să rulați kubeval offline, descărcați schemele și specificați locația lor locală folosind steag --schema-location.

Pe lângă fișierele YAML individuale, kubeval poate funcționa și cu directoare și stdin.

În plus, Kubeval se integrează cu ușurință în conducta CI. Cei care doresc să execute teste înainte de a trimite manifeste către cluster vor fi încântați să afle că kubeval acceptă trei formate de ieșire:

  1. Text simplu;
  2. JSON;
  3. Testează orice protocol (TAP).

Și oricare dintre formate poate fi utilizat pentru analiza ulterioară a rezultatelor pentru a genera un rezumat al rezultatelor de tipul dorit.

Unul dintre dezavantajele kubeval este că în prezent nu poate verifica conformitatea cu definițiile personalizate de resurse (CRD). Cu toate acestea, este posibil să configurați kubeval ignoră-i.

Kubeval este un instrument excelent pentru verificarea și evaluarea resurselor; Cu toate acestea, trebuie subliniat că trecerea testului nu garantează că resursa respectă cele mai bune practici.

De exemplu, folosind eticheta latest într-un container nu urmează cele mai bune practici. Cu toate acestea, kubeval nu consideră aceasta o eroare și nu o raportează. Adică, verificarea unui astfel de YAML se va finaliza fără avertismente.

Dar ce se întâmplă dacă doriți să evaluați YAML și să identificați încălcări precum eticheta latest? Cum verific un fișier YAML cu cele mai bune practici?

2. Scorul Kube

Scorul Kube analizează manifestele YAML și le evaluează în raport cu testele încorporate. Aceste teste sunt selectate pe baza ghidurilor de securitate și a celor mai bune practici, cum ar fi:

  • Rularea containerului nu ca root.
  • Disponibilitatea controalelor de sănătate a podului.
  • Stabilirea cererilor și a limitelor de resurse.

Pe baza rezultatelor testelor, sunt date trei rezultate: OK, AVERTISMENT и CRITIC.

Puteți încerca Kube-score online sau îl puteți instala local.

La momentul scrierii articolului original, cea mai recentă versiune a kube-score era 1.7.0.

Să încercăm pe manifestul nostru 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 trece testele kubeval, în timp ce kube-score indică următoarele defecte:

  • Verificările de pregătire nu sunt configurate.
  • Nu există solicitări sau limite pentru resursele CPU și memorie.
  • Bugetele de întrerupere a podului nu sunt specificate.
  • Nu există reguli de separare (anti-afinitate) pentru a maximiza disponibilitatea.
  • Containerul rulează ca root.

Toate acestea sunt puncte valide despre deficiențele care trebuie abordate pentru a face Implementarea mai eficientă și mai fiabilă.

Echipă kube-score afișează informații într-o formă care poate fi citită de om, inclusiv toate încălcările de tip AVERTISMENT и CRITIC, care ajută foarte mult în timpul dezvoltării.

Cei care doresc să folosească acest instrument în cadrul conductei CI pot activa o ieșire mai comprimată folosind steag --output-format ci (în acest caz, sunt afișate și testele cu rezultatul 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

Similar cu kubeval, kube-score returnează un cod de ieșire diferit de zero atunci când există un test care eșuează CRITIC. De asemenea, puteți activa procesarea similară pentru AVERTISMENT.

În plus, este posibil să verificați resursele pentru conformitatea cu diferite versiuni API (ca în kubeval). Cu toate acestea, aceste informații sunt codificate în kube-score în sine: nu puteți selecta o versiune diferită de Kubernetes. Această limitare poate fi o mare problemă dacă intenționați să vă actualizați clusterul sau dacă aveți mai multe clustere cu versiuni diferite de K8s.

Vă rugăm să rețineți faptul că există deja o problemă cu o propunere de a realiza această oportunitate.

Mai multe informații despre kube-score pot fi găsite la site-ul oficial.

Testele Kube-score sunt un instrument excelent pentru implementarea celor mai bune practici, dar ce se întâmplă dacă trebuie să faceți modificări testului sau să adăugați propriile reguli? Din păcate, acest lucru nu se poate face.

Kube-score nu este extensibil: nu îi puteți adăuga politici sau le puteți ajusta.

Dacă trebuie să scrieți teste personalizate pentru a verifica conformitatea cu politicile companiei, puteți utiliza unul dintre următoarele patru instrumente: config-lint, copper, conftest sau polaris.

3.Config-lint

Config-lint este un instrument pentru validarea fișierelor de configurare YAML, JSON, Terraform, CSV și manifestelor Kubernetes.

Îl poți instala folosind instrucțiuni pe site-ul proiectului.

Versiunea actuală din momentul scrierii articolului original este 1.5.0.

Config-lint nu are teste încorporate pentru validarea manifestelor Kubernetes.

Pentru a efectua orice teste, trebuie să creați reguli adecvate. Sunt scrise în fișiere YAML numite „seturi de reguli” (seturi de reguli)și au următoarea structură:

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

(rule.yaml)

Să o studiem mai atent:

  • Câmp type specifică ce tip de configurație va folosi config-lint. Pentru manifestările K8, aceasta este mereu Kubernetes.
  • În domeniul files Pe lângă fișierele în sine, puteți specifica un director.
  • Câmp rules destinat stabilirii de teste de utilizator.

Să presupunem că doriți să vă asigurați că imaginile din Deployment sunt întotdeauna descărcate dintr-un depozit de încredere, cum ar fi my-company.com/myapp:1.0. O regulă config-lint care efectuează o astfel de verificare ar arăta astfel:

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

Fiecare regulă trebuie să aibă următoarele atribute:

  • id — identificatorul unic al regulii;
  • severity - Pot fi EȘECUL, AVERTISMENT и NE_CONFORMĂ;
  • message — dacă o regulă este încălcată, conținutul acestei linii este afișat;
  • resource — tipul de resursă căreia i se aplică această regulă;
  • assertions — o listă de condiții care vor fi evaluate în legătură cu această resursă.

În regula de mai sus assertion denumit every verifică dacă toate containerele sunt în implementare (key: spec.templates.spec.containers) utilizați imagini de încredere (adică, începând cu my-company.com/).

Setul complet de reguli arată astfel:

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)

Pentru a încerca testul, să-l salvăm ca check_image_repo.yaml. Să verificăm fișierul 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"
  }
]

Verificarea a eșuat. Acum să verificăm următorul manifest cu depozitul de imagini corect:

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)

Efectuăm același test cu manifestul de mai sus. Nu s-au găsit probleme:

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

Config-lint este un cadru promițător care vă permite să vă creați propriile teste pentru a valida manifestele Kubernetes YAML folosind YAML DSL.

Dar dacă aveți nevoie de o logică și de teste mai complexe? Nu este YAML prea limitat pentru asta? Ce se întâmplă dacă ai putea crea teste într-un limbaj de programare complet?

4. cupru

Cupru V2 este un cadru pentru validarea manifestelor folosind teste personalizate (similar cu config-lint).

Cu toate acestea, diferă de acesta din urmă prin faptul că nu folosește YAML pentru a descrie teste. Testele pot fi scrise în JavaScript. Copper oferă o bibliotecă cu mai multe instrumente de bază, care vă ajută să citiți informații despre obiectele Kubernetes și să raportați erori.

Pașii pentru instalarea Copper pot fi găsiți în documentație oficială.

2.0.1 este cea mai recentă versiune a acestui utilitar la momentul scrierii articolului original.

La fel ca config-lint, Copper nu are teste încorporate. Să scriem unul. Lăsați-l să verifice dacă implementările folosesc imagini container exclusiv din depozite de încredere, cum ar fi my-company.com.

Creați un fișier check_image_repo.js cu urmatorul continut:

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

Acum să testăm manifestul nostru base-valid.yaml, utilizați comanda 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

Este clar că cu ajutorul cuprului puteți efectua teste mai complexe - de exemplu, verificarea numelor de domenii în manifestele Ingress sau respingerea podurilor care rulează în modul privilegiat.

Cuprul are diverse funcții de utilitate încorporate în el:

  • DockerImage citește fișierul de intrare specificat și creează un obiect cu următoarele atribute:
    • name - numele imaginii,
    • tag - etichetă de imagine,
    • registry - registru de imagini,
    • registry_url - protocol (https://) și registrul de imagini,
    • fqin — locația completă a imaginii.
  • Funcție findByName ajută la găsirea unei resurse după un anumit tip (kind) și nume (name) din fișierul de intrare.
  • Funcție findByLabels ajută la găsirea unei resurse după un tip specificat (kind) și etichete (labels).

Puteți vizualiza toate funcțiile de serviciu disponibile aici.

În mod implicit, încarcă întregul fișier YAML de intrare într-o variabilă $$ și îl face disponibil pentru scripting (o tehnică familiară pentru cei cu experiență jQuery).

Principalul avantaj al Copper este evident: nu este nevoie să stăpânești un limbaj specializat și poți folosi diverse caracteristici JavaScript pentru a-ți crea propriile teste, precum interpolarea șirurilor, funcții etc.

De asemenea, trebuie remarcat faptul că versiunea actuală a lui Copper funcționează cu versiunea ES5 a motorului JavaScript, nu cu ES6.

Detalii disponibile la site-ul oficial al proiectului.

Cu toate acestea, dacă nu vă place JavaScript și preferați un limbaj special conceput pentru a crea interogări și pentru a descrie politici, ar trebui să acordați atenție concursului.

5.Concurs

Conftest este un cadru pentru testarea datelor de configurare. Potrivit și pentru testarea/verificarea manifestelor Kubernetes. Testele sunt descrise folosind un limbaj de interogare specializat Rego.

Puteți instala concurs folosind instrucțiunilistate pe site-ul proiectului.

La momentul scrierii articolului original, cea mai recentă versiune disponibilă era 0.18.2.

Similar cu config-lint și cupru, conftest vine fără teste încorporate. Să încercăm și să scriem propria noastră politică. Ca și în exemplele anterioare, vom verifica dacă imaginile containerului sunt preluate dintr-o sursă de încredere.

Creați un director conftest-checks, iar în el există un fișier numit check_image_registry.rego cu urmatorul continut:

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

Acum să testăm base-valid.yaml prin 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

Testul a eșuat, probabil, deoarece imaginile provin dintr-o sursă neîncrezătoare.

În fișierul Rego definim blocul deny. Adevărul său este considerat o încălcare. Dacă blocuri deny mai multe, concursul le verifică independent unul de celălalt, iar adevărul oricăruia dintre blocuri este tratat ca o încălcare.

Pe lângă rezultatul implicit, conftest acceptă formatul JSON, TAP și tabel - o caracteristică extrem de utilă dacă trebuie să încorporați rapoarte într-o conductă CI existentă. Puteți seta formatul dorit folosind steag --output.

Pentru a facilita depanarea politicilor, concursul are un steag --trace. Afișează o urmă a modului în care conftest analizează fișierele de politică specificate.

Politicile de concurs pot fi publicate și partajate în registrele OCI (Open Container Initiative) ca artefacte.

comenzi push и pull vă permit să publicați un artefact sau să preluați un artefact existent dintr-un registru de la distanță. Să încercăm să publicăm politica pe care am creat-o în registrul local Docker folosind conftest push.

Porniți registrul Docker local:

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

Într-un alt terminal, mergeți la directorul pe care l-ați creat mai devreme conftest-checks și rulați următoarea comandă:

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

Dacă comanda a avut succes, veți vedea un mesaj ca acesta:

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

Acum creați un director temporar și rulați comanda în el conftest pull. Acesta va descărca pachetul creat de comanda anterioară:

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

Un subdirector va apărea în directorul temporar policycare conține fișierul nostru de politică:

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

Testele pot fi executate direct din depozit:

$ 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

Din păcate, DockerHub nu este încă acceptat. Așa că considerați-vă norocos dacă utilizați Azure Container Registry (ACR) sau propriul registru.

Formatul artefactului este același ca Deschideți pachetele Policy Agent (OPA), care vă permite să utilizați conftest pentru a rula teste din pachetele OPA existente.

Puteți afla mai multe despre partajarea politicilor și alte funcții ale concursului la site-ul oficial al proiectului.

6. Polaris

Ultimul instrument despre care va fi discutat în acest articol este Polaris. (Anunțul lui de anul trecut noi deja tradus - aproximativ traducere)

Polaris poate fi instalat într-un cluster sau utilizat în modul linie de comandă. După cum probabil ați ghicit, vă permite să analizați static manifestele Kubernetes.

Când rulați în modul linie de comandă, sunt disponibile teste încorporate care acoperă domenii precum securitatea și cele mai bune practici (similar cu kube-score). În plus, vă puteți crea propriile teste (ca în config-lint, copper și conftest).

Cu alte cuvinte, Polaris combină beneficiile ambelor categorii de instrumente: cu teste încorporate și personalizate.

Pentru a instala Polaris în modul linie de comandă, utilizați instrucțiuni pe site-ul proiectului.

În momentul scrierii articolului original, versiunea 1.0.3 este disponibilă.

Odată ce instalarea este finalizată, puteți rula polaris pe manifest base-valid.yaml cu următoarea comandă:

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

Va scoate un șir în format JSON cu o descriere detaliată a testelor efectuate și a rezultatelor acestora. Ieșirea va avea următoarea structură:

{
  "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": [
    /* длинный список */
  ]
}

Ieșire completă disponibilă aici.

La fel ca kube-score, Polaris identifică probleme în zonele în care manifestul nu îndeplinește cele mai bune practici:

  • Nu există controale de sănătate pentru păstăi.
  • Etichetele pentru imaginile containerului nu sunt specificate.
  • Containerul rulează ca root.
  • Cererile și limitele pentru memorie și CPU nu sunt specificate.

Fiecărui test, în funcție de rezultatele sale, i se atribuie un grad de criticitate: de avertizare sau pericol. Pentru a afla mai multe despre testele încorporate disponibile, vă rugăm să consultați documentație.

Dacă nu sunt necesare detalii, puteți specifica steag --format score. În acest caz, Polaris va scoate un număr cuprins între 1 și 100 - scor (adică evaluare):

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

Cu cât scorul este mai aproape de 100, cu atât este mai mare gradul de acord. Dacă verificați codul de ieșire al comenzii polaris audit, se dovedește că este egal cu 0.

forta polaris audit Puteți încheia lucrul cu cod diferit de zero folosind două semnalizatoare:

  • pavilion --set-exit-code-below-score ia ca argument o valoare de prag în intervalul 1-100. În acest caz, comanda va ieși cu codul de ieșire 4 dacă scorul este sub prag. Acest lucru este foarte util atunci când aveți o anumită valoare de prag (să zicem 75) și trebuie să primiți o alertă dacă scorul scade sub.
  • pavilion --set-exit-code-on-danger va determina eșuarea comenzii cu codul 3 dacă unul dintre testele de pericol eșuează.

Acum să încercăm să creăm un test personalizat care verifică dacă imaginea este preluată dintr-un depozit de încredere. Testele personalizate sunt specificate în format YAML, iar testul în sine este descris folosind schema JSON.

Următorul fragment de cod YAML descrie un nou test numit 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/.+$

Să aruncăm o privire mai atentă la el:

  • successMessage — această linie va fi tipărită dacă testul se finalizează cu succes;
  • failureMessage — acest mesaj va fi afișat în caz de defecțiune;
  • category — indică una dintre categorii: Images, Health Checks, Security, Networking и Resources;
  • target--- determină ce tip de obiect (spec) se aplică testul. Valori posibile: Container, Pod sau Controller;
  • Testul în sine este specificat în obiect schema folosind schema JSON. Cuvântul cheie în acest test este pattern folosit pentru a compara sursa imaginii cu cea necesară.

Pentru a rula testul de mai sus, trebuie să creați următoarea configurație Polaris:

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)

Să analizăm fișierul:

  • În domeniul checks sunt prescrise teste şi nivelul lor de criticitate. Deoarece este de dorit să primim un avertisment atunci când o imagine este luată dintr-o sursă neîncrezătoare, setăm nivelul aici danger.
  • Testul în sine checkImageRepo apoi înregistrat în obiect customChecks.

Salvați fișierul ca custom_check.yaml. Acum poți fugi polaris audit cu un manifest YAML care necesită verificare.

Să testăm manifestul nostru base-valid.yaml:

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

Echipă polaris audit a rulat doar testul utilizator specificat mai sus și nu a reușit.

Dacă remediați imaginea la my-company.com/http-echo:1.0, Polaris se va finaliza cu succes. Manifestul cu schimbările este deja în depoziteastfel încât să puteți verifica comanda anterioară pe manifest image-valid-mycompany.yaml.

Acum apare întrebarea: cum să rulați teste încorporate împreună cu cele personalizate? Uşor! Trebuie doar să adăugați identificatorii de test încorporați în fișierul de configurare. Ca urmare, va lua următoarea 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)

Este disponibil un exemplu de fișier de configurare complet aici.

Verificați manifestul base-valid.yamlfolosind teste încorporate și personalizate, puteți folosi comanda:

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

Polaris completează testele încorporate cu teste personalizate, combinând astfel cele mai bune din ambele lumi.

Pe de altă parte, incapacitatea de a folosi limbaje mai puternice precum Rego sau JavaScript poate fi un factor limitativ care împiedică crearea de teste mai sofisticate.

Mai multe informații despre Polaris sunt disponibile la site-ul proiectului.

Rezumat

Deși există multe instrumente disponibile pentru inspectarea și evaluarea fișierelor YAML Kubernetes, este important să avem o înțelegere clară a modului în care vor fi proiectate și executate testele.

De exemplu, dacă luați manifeste Kubernetes care trec printr-o conductă, kubeval ar putea fi primul pas într-o astfel de conductă. Ar monitoriza dacă definițiile obiectelor sunt conforme cu schema API Kubernetes.

Odată ce o astfel de revizuire este finalizată, se poate trece la teste mai sofisticate, cum ar fi conformitatea cu cele mai bune practici standard și politici specifice. Aici ar fi de folos kube-score și Polaris.

Pentru cei care au cerințe complexe și au nevoie să personalizeze testele în detaliu, copper, config-lint și conftest ar fi potrivite.

Conftest și config-lint folosesc YAML pentru a defini teste personalizate, iar copper vă oferă acces la un limbaj de programare complet, făcându-l o alegere destul de atractivă.

Pe de altă parte, merită să folosiți unul dintre aceste instrumente și, prin urmare, să creați manual toate testele sau să preferați Polaris și să adăugați doar ceea ce este necesar? Nu există un răspuns clar la această întrebare.

Tabelul de mai jos oferă o scurtă descriere a fiecărui instrument:

Instrument
destin
Limitări
Teste de utilizator

kubeval
Validează manifestele YAML în raport cu o anumită versiune a schemei API
Nu pot lucra cu CRD
Nu

scor kube
Analizează manifestările YAML în raport cu cele mai bune practici
Nu se poate selecta versiunea API-ului Kubernetes pentru a verifica resurse
Nu

cupru
Un cadru general pentru crearea de teste JavaScript personalizate pentru manifestele YAML
Fără teste încorporate. Proasta documentare
Da

config-lint
Un cadru general pentru crearea de teste într-un limbaj specific domeniului încorporat în YAML. Acceptă diverse formate de configurare (de exemplu, Terraform)
Nu există teste gata făcute. Afirmațiile și funcțiile încorporate pot să nu fie suficiente
Da

concurs
Un cadru pentru crearea propriilor teste folosind Rego (un limbaj de interogare specializat). Permite partajarea politicilor prin pachete OCI
Fără teste încorporate. Trebuie să învăț Rego. Docker Hub nu este acceptat la publicarea politicilor
Da

Polaris
Evaluează manifestările YAML în raport cu cele mai bune practici standard. Vă permite să vă creați propriile teste folosind schema JSON
Capacitățile de testare bazate pe schema JSON pot să nu fie suficiente
Da

Deoarece aceste instrumente nu se bazează pe accesul la clusterul Kubernetes, sunt ușor de instalat. Acestea vă permit să filtrați fișierele sursă și să oferiți feedback rapid autorilor solicitărilor de extragere în proiecte.

PS de la traducator

Citește și pe blogul nostru:

Sursa: www.habr.com

Adauga un comentariu