Nota traducătorului.: Odată cu creșterea numărului de configurații YAML pentru medii K8s, devine tot mai relevantă necesitatea verificării automate a acestora. Autorul acestui rezumat a selectat nu doar soluțiile existente pentru această sarcină, ci a examinat și cum funcționează acestea în cazul unui Deployment. A rezultat o prezentare foarte informativă pentru cei interesați de acest subiect.

TL;DR: Articolul compară șase instrumente statice de verificare și evaluare a fișierelor YAML Kubernetes, în funcție de cele mai bune practici și cerințe.
Sarcinile de lucru Kubernetes sunt de obicei definite sub formă de documente YAML. Una dintre problemele cu YAML este dificultatea de a impune restricții sau relații între fișierele manifest.
Ce facem dacă trebuie să ne asigurăm că toate imaginile desfășurate în cluster provin dintr-un registru de încredere?
Cum prevenim trimiterea în cluster a Deployment-urilor pentru care nu sunt definite PodDisruptionBudgets?
Integrarea testării statice permite identificarea erorilor și a încălcărilor politicilor încă din stadiul de dezvoltare. Astfel, se îmbunătățește garanția corectitudinii și siguranței definițiilor de resurse și se crește șansa ca sarcinile de producție să respecte cele mai bune practici.
Ecosistemul de verificare statică a fișierelor YAML Kubernetes poate fi împărțit în următoarele categorii:
- Validatori API. Instrumentele din această categorie verifică manifestul YAML pentru conformitate cu cerințele serverului API Kubernetes.
- Testerii gata făcuți. Instrumentele din această categorie vin cu teste gata făcute pentru securitate, conformitate cu cele mai bune practici etc.
- Validatori personalizați. Reprezentanții acestei categorii permit crearea de teste personalizate în diverse limbaje, cum ar fi Rego și Javascript.
În acest articol vom descrie și compara șase instrumente diferite:
- kubeval;
- kube-score;
- config-lint;
- copper;
- conftest;
- Polaris.
Ei bine, să începem!
Verificarea Deployment-urilor
Înainte de a începe comparația instrumentelor, să creăm o bază pe care să le testăm.
Manifestul de mai jos conține o serie de erori și neconformități cu cele 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 menționat anterior
base-valid.yamlși alte manifeste din acest articol pot fi găsite în .
Manifestul descrie o aplicație web a cărei sarcină principală este de a răspunde cu mesajul „Hello World” pe portul 5678. Poate fi desfășurat cu următoarea comandă:
kubectl apply -f hello-world.yamlIată cum să verifici funcționarea acestuia:
kubectl port-forward svc/http-echo 8080:5678Acum, te rog să mergi la și confirmă că aplicația funcționează. Dar respectă aceasta cele mai bune practici? Hai să verificăm.
1. Kubeval
În centrul stă ideea că orice interacțiune cu Kubernetes are loc prin API-ul său REST. Cu alte cuvinte, putem folosi schema API pentru a verifica dacă acest YAML este conform. Să luăm un exemplu.
kubeval sunt disponibile pe site-ul proiectului.
La momentul scrierii articolului original, versiunea 0.15.0 era disponibilă.
După instalare, haideți să „alimentăm” manifestul menționat mai sus:
$ kubeval base-valid.yaml
PASS - base-valid.yaml conține un Deployment valid (http-echo)
PASS - base-valid.yaml conține un Service valid (http-echo)În caz de succes, kubeval se va încheia cu un cod de ieșire 0. Îl poți verifica astfel:
$ echo $?
0Hai să încercăm acum kubeval cu un alt 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)
Poți identifica problema cu ochiul liber? Rulăm:
$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml conține un Deployment invalid (http-echo) - selector: selector este necesar
PASS - kubeval-invalid.yaml conține un Service valid (http-echo)
# să verificăm codul de întoarcere
$ echo $?
1Resursa nu trece testul.
Deploymentele care folosesc versiunea API apps/v1, trebuie să includă un selector care să corespundă etichetei pod-ului. Manifestul de mai sus nu include selectorul, de aceea kubeval a raportat o eroare și a ieșit cu un cod de ieșire non-zero.
Interesant ce se va întâmpla dacă rulăm kubectl apply -f cu acest manifest?
Ei bine, haideți să încercăm:
$ kubectl apply -f kubeval-invalid.yaml
eroare: eroare validând "kubeval-invalid.yaml": eroare validând datele: ValidationError(Deployment.spec):
lipsește câmpul obligatoriu "selector" în io.k8s.api.apps.v1.DeploymentSpec; dacă alegi să ignori aceste erori,
oprește validarea cu --validate=falseAceasta este exact eroarea de care a avertizat kubeval. O poți corecta 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ă astfel de erori pot fi detectate în stadii timpurii ale ciclului de desfășurare.
În plus, pentru aceste verificări nu este necesar accesul la cluster: acestea pot fi efectuate offline.
În mod implicit, kubeval verifică resursele pentru conformitatea cu cea mai recentă schemă a API-ului Kubernetes. Cu toate acestea, în cele mai multe cazuri, s-ar putea să fie nevoie să efectuezi verificări pentru a respecta o versiune specifică a Kubernetes. Acest lucru se poate face cu ajutorul flag-ului --kubernetes-version:
$ kubeval --kubernetes-version 1.16.1 base-valid.yamlObservați că versiunea trebuie specificată în formatul Major.Minor.Patch.
Pentru a vizualiza lista versiunilor pentru care se suportă verificarea, consultați , pe care kubeval o folosește pentru validare. Dacă trebuie să rulezi kubeval offline, descarcă schemele și specifică locația lor locală folosind flag-ul --schema-location.
În plus față de fișierele YAML individuale, kubeval poate funcționa și cu directoare și stdin.
De asemenea, Kubeval se integrează ușor în pipeline-ul CI. Cei care doresc să efectueze teste înainte de a trimite manifeștele în cluster vor fi încântați să afle că kubeval suportă trei formate de ieșire:
- Text simplu;
- JSON;
- Test Anything Protocol (TAP).
Și oricare dintre formatele poate fi utilizat pentru un parsing ulterior al ieșirii, pentru a forma un rezumat al rezultatelor dorite.
Unul dintre dezavantajele kubeval este că, în prezent, acesta nu poate verifica conformitatea cu definițiile resurselor personalizate (CRD-uri). Cu toate acestea, kubeval poate fi configurat .
Kubeval este un instrument excelent pentru verificarea și evaluarea resurselor; totuși, trebuie subliniat că trecerea unui test nu garantează că resursa respectă cele mai bune practici.
De exemplu, utilizarea etichetei latest în container nu respectă cele mai bune practici. Totuși, kubeval nu consideră aceasta o eroare și nu o raportează. Cu alte cuvinte, verificarea acestui YAML se va încheia fără avertismente.
Dar ce se întâmplă dacă trebuie să evaluăm YAML-ul și să identificăm încălcări cum ar fi eticheta latest? Как проверить YAML-файл на соответствие лучшим практикам?
2. Kube-score
analizează manifeste YAML și le evaluează pe baza testelor integrate. Aceste teste sunt selectate pe baza recomandărilor de securitate și a celor mai bune practici, de exemplu:
- Rularea containerului fără privilegii de root.
- Existența verificărilor de sănătate pentru pod-uri.
- Definirea cerințelor și limitelor resurselor.
În urma testului se emit trei rezultate: OK, AVERTISMENT și CRITIC.
Kube-score poate fi încercat online sau instalat local.
La momentul redactării articolului original, cea mai recentă versiune kube-score era 1.7.0.
Să-l testăm pe manifestul nostru base-valid.yaml:
$ kube-score score base-valid.yaml
apps/v1/Deployment http-echo
[CRITIC] Eticheta imaginii containerului
· http-echo -> Imagine cu eticheta latest
Se recomandă utilizarea unei etichete fixe pentru a evita upgrade-uri accidentale
[CRITIC] Pod NetworkPolicy
· Pod-ul nu are o politică de rețea corespunzătoare
Creați o NetworkPolicy care vizează acest pod
[CRITIC] Verificări Pod
· Containerul lipsește o readinessProbe
O readinessProbe ar trebui să fie utilizată pentru a indica când serviciul este pregătit să primească trafic.
Fără aceasta, Pod-ul riscă să primească trafic înainte de a fi pornit. De asemenea, este utilizată în timpul
desfășurărilor și poate preveni timpul de nefuncționare dacă o nouă versiune a aplicației eșuează.
Mai multe informații: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITIC] Contextul de securitate al containerului
· http-echo -> Containerul nu are un context de securitate configurat
Setează securityContext pentru a rula containerul într-un context mai sigur.
[CRITIC] Resursele containerului
· http-echo -> Limită CPU nu este setată
Se recomandă limitele de resurse pentru a evita DDOS-ul de resurse. Setează resources.limits.cpu
· http-echo -> Limită de memorie nu este setată
Se recomandă limitele de resurse pentru a evita DDOS-ul de resurse. Setează resources.limits.memory
· http-echo -> Cerere CPU nu este setată
Se recomandă cererile de resurse pentru a asigura că aplicația poate porni și rula fără
a se bloca. Setează resources.requests.cpu
· http-echo -> Cerere de memorie nu este setată
Se recomandă cererile de resurse pentru a asigura că aplicația poate porni și rula fără a se bloca.
Setează resources.requests.memory
[CRITIC] Desfășurarea are PodDisruptionBudget
· Nu a fost găsit un PodDisruptionBudget corespunzător
Se recomandă definirea unui PodDisruptionBudget pentru a evita timpul de nefuncționare neașteptat în timpul
operațiunilor de întreținere Kubernetes, cum ar fi atunci când se drenează un nod.
[AVERTISMENT] Desfășurarea are PodAntiAffinity pe gazdă
· Desfășurarea nu are setat podAntiAffinity pe gazdă
Se recomandă setarea unui podAntiAffinity care să împiedice programarea mai multor pod-uri dintr-o desfășurare
pe același nod. Acest lucru crește disponibilitatea în cazul în care nodul devine indisponibil.YAML-ul trece testele kubeval, în timp ce kube-score indică următoarele deficiențe:
- Nu sunt configurate verificările de disponibilitate.
- Lipsesc cererile și limitele pentru resursele CPU și memorie.
- Nu sunt stabilite bugetele de întrerupere pentru Pod.
- Lipsesc regulile de anti-aggresie. (anti-afinitate) pentru a maximiza disponibilitatea.
- Contenitorul rulează sub root.
Toate acestea sunt observații rezonabile despre deficiențele care ar trebui corectate pentru ca Deployment să devină mai eficient și mai fiabil.
Comanda kube-score afișează informațiile într-un format ușor de citit, incluzând toate neconformitățile de tip AVERTISMENT și CRITIC, ceea ce ajută foarte mult în timpul dezvoltării.
Cei care doresc să folosească acest instrument în cadrul pipeline-ului CI pot activa o ieșire mai compactă cu ajutorul flag-ului --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) Limită CPU nu este setată
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Limită de memorie nu este setată
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Cerere CPU nu este setată
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Cerere de memorie nu este setată
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Imagine cu eticheta latest
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: Pod-ul nu are o politică de rețea corespunzătoare
[CRITICAL] http-echo apps/v1/Deployment: Contenitorul lipsește un readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Contenitorul nu are un context de securitate configurat
[CRITICAL] http-echo apps/v1/Deployment: Niciun PodDisruptionBudget corespunzător nu a fost găsit
[WARNING] http-echo apps/v1/Deployment: Deployment nu are un host podAntiAffinity setat
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/ServiceLa fel ca kubeval, kube-score returnează un cod de ieșire nenul în cazul în care un test finalizat cu o eroare. CRITICDe asemenea, se poate activa o astfel de procesare și pentru AVERTISMENT.
În plus, există posibilitatea verificării resurselor pentru conformitate cu diferite versiuni de API (așa cum se întâmplă și în kubeval). Totuși, această informație este 'hardcode' în kube-score: nu se poate alege o altă versiune de Kubernetes. O asemenea restricție poate deveni o problemă majoră dacă doriți să actualizați cluster-ul sau dacă aveți mai multe clustere cu versiuni diferite de K8s.
Rețineți că cu o propunere de a implementa această posibilitate.
Despre kube-score se poate afla mai multe pe .
Testele kube-score sunt un instrument excelent pentru implementarea celor mai bune practici, dar ce se întâmplă dacă trebuie să faceti modificări la test sau să adăugați propriile reguli? Din păcate, acest lucru nu este posibil.
Kube-score nu este extensibil: nu pot fi adăugate politici sau adaptate.
Dacă este necesar să scrieți teste personalizate pentru verificarea conformității cu politicile acceptate de companie, puteți folosi 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 în format YAML, JSON, Terraform, CSV și a manifestelor Kubernetes.
Îl puteți instala folosind de pe site-ul proiectului.
Versiunea curentă la momentul scrierii articolului original este 1.5.0.
Config-lint nu conține teste încorporate pentru verificarea manifestelor Kubernetes.
Pentru a efectua orice teste, este necesar să creați reguli corespunzătoare. Acestea sunt scrise în fișiere YAML, numite «seturi de reguli» (rulesets), și au următoarea structură:
version: 1
description: Reguli pentru fișierele de specificație Kubernetes
type: Kubernetes
files:
- "*.yaml"
rules:
# lista regulilor(rule.yaml)
Să o examinăm mai atent:
- Câmp
typeindică ce tip de configurație va folosi config-lint. Pentru manifestele K8s, aceasta este întotdeaunaKubernetes. - În câmpul
filesîn afară de fișierele propriu-zise, poate fi specificat un director. - Câmp
ruleseste destinat pentru definirea testelor personalizate.
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. Regula pentru config-lint, care efectuează o astfel de verificare, va arăta astfel:
- id: MY_DEPLOYMENT_IMAGE_TAG
severity: FAILURE
message: Deployment trebuie să folosească un tag de imagine valid
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(rule-trusted-repo.yaml)
Pentru fiecare regulă trebuie specificate următoarele atribute:
id— un identificator unic al regulii;severity— poate fi FAILURE, AVERTISMENT și NON_COMPLIANT;message— în cazul încălcării regulii se va afișa conținutul acestei linii;resource— tipul resursei căreia i se aplică această regulă;assertions— o listă de condiții care vor fi evaluate în raport cu această resursă.
În regula de mai sus assertion called verifică dacă toate containerele din Deployment (key: spec.templates.spec.containers) utilizează imagini de încredere (adică, care încep cu my-company.com/).
Setul complet de reguli arată astfel:
version: 1
description: Reguli pentru fișierele de specificație Kubernetes
type: Kubernetes
files:
- "*.yaml"
rules:
- id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
severity: FAILURE
message: Deployment trebuie să folosească un depozit de imagini valid
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(ruleset.yaml)
Pentru a testa regula, să o salvăm ca check_image_repo.yaml. Să executăm verificarea pe fișier base-valid.yaml:
$ config-lint -rules check_image_repo.yaml base-valid.yaml
[
{
"AssertionMessage": "Fiecare expresie eșuează: Expresia And eșuează: imaginea nu începe cu 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": "Implementarea trebuie să utilizeze un repository de imagini valid",
"Status": "FAILURE"
}
]Verificarea a eșuat. Acum să verificăm următorul manifest cu un repository 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)
Executăm aceeași testare cu manifestul de mai sus. Nu s-au detectat probleme:
$ config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]Config-lint este un cadru promițător care permite crearea de teste personalizate pentru verificarea manifestelor YAML Kubernetes cu ajutorul YAML DSL.
Dar ce se întâmplă dacă avem nevoie de o logică și teste mai complexe? Nu cumva capabilitățile YAML sunt prea limitate pentru asta? Ce-ar fi dacă am putea crea teste într-un limbaj de programare complet?
4. Copper
— este un cadru pentru validarea manifestelor folosind teste personalizate (similar cu config-lint).
Cu toate acestea, se deosebește prin faptul că nu utilizează YAML pentru a descrie teste. În schimb, testele pot fi create în JavaScript. Copper oferă o librărie cu câteva instrumente de bază, care ajută la citirea informațiilor despre obiectele Kubernetes și la raportarea erorilor.
Secvența pașilor pentru instalarea Copper poate fi găsită în .
2.0.1 — cea mai recentă versiune a acestui utilitar la momentul redactării articolului original.
La fel ca și config-lint, Copper nu are teste încorporate. Să scriem unul. Acesta să verifice că implementările folosesc imagini de container exclusiv din repository-uri de încredere precum my-company.com.
Creați un fișier check_image_repo.js cu următorul conținut:
$$.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',"Imaginea " + $.metadata.name + " nu este din repository-ul my-company.com", 1)
}
});
}
});Acum, pentru a verifica manifestul nostru base-valid.yaml, folosiți comanda copper validate:
$ copper validate --in=base-valid.yaml --validator=check_image_tag.js
Verificarea no_company_repo a eșuat cu severitate 1 din cauza că Imaginea http-echo nu este din repository-ul my-company.com
Validarea a eșuatEste clar că, cu ajutorul copper, pot fi efectuate teste mai complexe - de exemplu, verificarea numelui domeniilor în manifestele Ingress sau respingerea pod-urilor care funcționează în mod privilegiat.
Copper include diverse funcții de asistență:
DockerImagecitește fișierul de intrare specificat și creează un obiect cu următoarele atribute:name— numele imaginii,tag— eticheta imaginii,registry— registry-ul imaginilor,registry_url— protocolul (https://) și registry-ul imaginilor,fqin— locația completă a imaginii.
- Funcția
findByNameajută la găsirea unei resurse după tipul specificat (kind) și nume (name) din fișierul de intrare. - Funcția
findByLabelsajută la găsirea unei resurse după tipul specificat (kind) și etichete (labels).
Cu toate funcțiile de asistență disponibile, puteți consulta .
Implicit, acesta încarcă întregul fișier YAML de intrare într-o variabilă $$ și îl face disponibil pentru scripturi (o metodă cunoscută pentru cei care au experiență cu jQuery).
Principalul avantaj al Copper este evident: nu trebuie să învățați un limbaj specializat și puteți utiliza diverse funcționalități JavaScript pentru a crea propriile teste, cum ar fi interpolarea șirurilor, funcțiile etc.
De asemenea, este important de menționat că versiunea actuală a Copper funcționează cu versiunea ES5 a motorului JavaScript, nu cu ES6.
Detalii sunt disponibile pe .
Cu toate acestea, dacă nu sunteți foarte pasionat de JavaScript și preferați un limbaj destinat în mod special creării de interogări și descrierii politicilor, ar trebui să luați în considerare conftest.
5. Conftest
Conftest este un cadru pentru verificarea datelor de configurare. Este potrivit și pentru testarea/verificarea manifestelor Kubernetes. Testele sunt descrise folosind un limbaj specializat de interogare .
Puteți instala conftest folosind , disponibile pe site-ul proiectului.
La momentul redactării articolului original, cea mai recentă versiune disponibilă era 0.18.2.
În mod similar cu config-lint și copper, conftest vine fără teste încorporate. Să încercăm și să scriem propria politică. Ca în exemplele anterioare, vom verifica dacă imaginile containerelor sunt preluate dintr-o sursă de încredere.
Creează un director conftest-checks, iar în acesta - un fișier cu numele check_image_registry.rego cu următorul conținut:
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 failureTestul a eșuat așa cum era de așteptat, deoarece imaginile provin dintr-o sursă nesigură.
În fișierul Rego, definim blocul deny. Valabilitatea sa este considerată o încălcare. Dacă există mai multe blocuri, deny conftest le verifică independent unul de celălalt, iar valabilitatea oricărui bloc este interpretată ca o încălcare.
Pe lângă ieșirea implicită, conftest suportă JSON, TAP și format tabelar — o caracteristică extrem de utilă, dacă trebuie să integrați rapoartele în pipeline-ul CI existent. Puteți seta formatul dorit folosind flagul --output.
Pentru a facilita depanarea politicilor, conftest include un flag --trace. Acesta va afișa o trasare a modului în care conftest parcurge fișierele de politici specificate.
Politicile conftest pot fi publicate și partajate în registre OCI (Open Container Initiative) sub formă de artefacte.
Comenzi push și pull permit publicarea unui artefact sau extragerea unui artefact existent dintr-un registru la distanță. Să încercăm să publicăm politica pe care am creat-o în registrul local Docker folosind conftest push.
Rulați registrul local Docker:
$ docker run -it --rm -p 5000:5000 registryÎntr-un alt terminal, navigați la directorul creat anterior conftest-checks și executați următoarea comandă:
$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latestDacă comanda a fost executată cu succes, veți vedea un mesaj de tipul următor:
2020/06/10 14:25:43 pushed bundle with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609cAcum creați un director temporar și executați în el comanda conftest pull. Aceasta va descărca pachetul creat de comanda anterioară:
$ cd $(mktemp -d)
$ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latestÎn directorul temporar va apărea un subdirector policy, care va conține fișierul nostru de politici:
$ tree
.
└── policy
└── check_image_registry.regoTeste pot fi efectuate direct din repository:
$ conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml
..
FAIL - base-valid.yaml - imaginea 'hashicorp/http-echo' nu provine din registrul my-company.com
2 teste, 1 trecut, 0 avertismente, 1 eșecDin păcate, DockerHub nu este în prezent suportat. Deci, considerați-vă norocoși dacă folosiți (ACR) sau propriul dvs. registru.
Formatul artefactelor este același ca și cel al (OPA), ceea ce permite utilizarea conftest pentru a rula teste din pachete OPA existente.
Mai multe despre partajarea politicilor și alte caracteristici ale conftest puteți afla pe .
6. Polaris
Ultimul instrument despre care vom discuta în acest articol este . (Anunțul său de anul trecut l-am — notă de traducere.)
Polaris poate fi instalat într-un cluster sau utilizat în modul linie de comandă. Așa cum ați ghicit, acesta permite analiza statică a manifestelor Kubernetes.
Atunci când se lucrează în modul linie de comandă, sunt disponibile teste încorporate care acoperă domenii precum securitatea și cele mai bune practici (similar cu kube-score). De asemenea, puteți crea teste personalizate (ca în config-lint, copper și conftest).
Cu alte cuvinte, Polaris combină avantajele ambelor categorii de instrumente: cu teste încorporate și personalizate.
Pentru a instala Polaris în modul linie de comandă, utilizați .
La momentul redactării acestui articol, versiunea disponibilă este 1.0.3.
După finalizarea instalării, puteți rula polaris pe manifestul base-valid.yaml folosind comanda următoare:
$ polaris audit --audit-path base-valid.yamlAceasta va produce un șir în format JSON cu o descriere detaliată a testelor efectuate și rezultatele lor. Iată cum va arăta structura de ieșire:
{
"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": [
/* listă lungă */
]
}Ieșirea completă este disponibilă .
Similar cu kube-score, Polaris identifică probleme în domeniile în care manifestul nu respectă cele mai bune practici:
- Lipsesc verificările de sănătate pentru poduri.
- Nu sunt specificate etichetele pentru imaginile containere.
- Contenitorul rulează sub root.
- Nu sunt specificate cerințele și limitele pentru memorie și CPU.
Fiecărui test îi este atribuit un grad de gravitate în funcție de rezultatele sale: warning sau danger. Pentru a afla mai multe despre testele încorporate disponibile, consultați .
Dacă nu aveți nevoie de detalii, puteți specifica flag-ul --format score. În acest caz, Polaris va produce un număr în intervalul de la 1 la 100 — score (adică evaluarea):
$ polaris audit --audit-path test-data/base-valid.yaml --format score
68Cu cât evaluarea este mai aproape de 100, cu atât mai ridicată este gradul de conformitate. Dacă verificați codul de ieșire al comenzii polaris audit, veți observa că acesta este 0.
Pentru a face polaris audit să se încheie cu un cod de ieșire diferit de zero, puteți folosi două flag-uri:
- Steagul
--set-exit-code-below-scoreacceptă ca argument un prag în intervalul 1-100. În acest caz, comanda se va încheia cu codul de ieșire 4, dacă evaluarea se află sub prag. Acest lucru este foarte util atunci când aveți un anumit prag (să spunem, 75) și aveți nevoie de o alertă dacă evaluarea scade sub această valoare. - Steagul
--set-exit-code-on-dangerva duce la finalizarea echipei cu codul 3, dacă unul dintre testele de tip danger eșuează.
Acum haideți să încercăm să creăm un test personalizat care verifică dacă imaginea provine dintr-un repository de încredere. Testele personalizate sunt definite în format YAML, iar testul în sine este descris folosind JSON Schema.
Următorul fragment de cod YAML descrie un nou test numit checkImageRepo:
checkImageRepo:
successMessage: Registry-ul imaginii este valid
failureMessage: Registry-ul imaginii nu este valid
category: Imagini
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$Să ne uităm mai îndeaproape la acesta:
successMessage— acest text va fi afișat dacă testul se finalizează cu succes;failureMessage— acest mesaj va fi afișat în caz de eșec;category— indică una dintre categorii:Imagini,Verificări de sănătate,Securitate,NetworkingșiResurse;destinația— definește tipul de obiect la care se aplică testul (spec) Posibile valori:Container,PodsauController;- Testul este definit într-un obiect
schemafolosind JSON schema. În acest test, cuvântul cheiepatterneste folosit pentru a compara sursa imaginii cu cea cerută.
Pentru a rula testul de mai sus, trebuie să creați următoarea configurație Polaris:
checks:
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Registry-ul imaginii este valid
failureMessage: Registry-ul imaginii nu este valid
category: Imagini
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 câmpul
checksdefineste testele și nivelul lor de criticitate. Deoarece este de dorit să primim un avertisment atunci când imaginea provine dintr-o sursă nesigură, setăm aici niveluldanger. - Testul în sine
checkImageRepoapoi este scris în obiectulcustomChecks.
Salvați fișierul ca custom_check.yaml. Acum putem rula 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.yamlComanda polaris audit a efectuat doar testul personalizat definit mai sus, iar acesta nu a avut succes.
Dacă corectăm imaginea la my-company.com/http-echo:1.0, Polaris va finaliza cu succes. Manifestul cu modificările este deja disponibil în , așa că puteți verifica comanda anterioară pe manifest. image-valid-mycompany.yaml.
Acum apare întrebarea: cum să rulați testele încorporate împreună cu cele personalizate? Ușor! Trebuie doar să adăugați identificatorii testelor încorporate în fișierul de configurație. Ca rezultat, acesta va avea următorul aspect:
verificări:
cpuRequestsMissing: avertizare
cpuLimitsMissing: avertizare
# Alte verificări integrate..
# ..
# verificări personalizate
checkImageRepo: pericol # !!!
verificăriPersonalizate:
checkImageRepo: # !!!
successMessage: Registrul de imagini este valid
failureMessage: Registrul de imagini nu este valid
category: Imagini
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)
Un exemplu complet al fișierului de configurare este disponibil .
Verifică manifestul base-valid.yaml, utilizând teste integrate și personalizate, se poate face cu comanda:
$ polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yamlPolaris completează testele integrate cu cele personalizate, combinând astfel cele mai bune aspecte din ambele lumi.
Pe de altă parte, imposibilitatea de a folosi limbaje mai puternice, cum ar fi Rego sau JavaScript, poate deveni un factor limitativ în crearea de teste mai sofisticate.
Informații suplimentare despre Polaris sunt disponibile pe .
Rezumat
Deși există numeroase instrumente pentru verificarea și evaluarea fișierelor YAML Kubernetes, este important să ai o înțelegere clară despre cum vor fi proiectate și executate testele.
De exemplu, dacă luăm manifestele Kubernetes care trec prin pipeline, kubeval ar putea fi primul pas într-un astfel de pipeline. Ar urmări dacă definițiile obiectelor respectă schema API Kubernetes.
După finalizarea unei astfel de verificări, s-ar putea trece la teste mai sofisticate, cum ar fi conformitatea cu cele mai bune practici standard și politici specifice. Și aici s-ar putea folosi kube-score și Polaris.
Celor care au cerințe complexe și necesitatea de a personaliza în detaliu testele li s-ar potrivi copper, config-lint și conftest.
Conftest și config-lint folosesc YAML pentru a defini teste personalizate, iar copper oferă acces la un limbaj de programare complet, ceea ce îl face o alegere destul de atrăgătoare.
Pe de altă parte, merită să folosești unul dintre aceste instrumente și, prin urmare, să creezi toate testele manual, sau să preferi Polaris și să adaugi doar ceea ce este necesar? Nu există un răspuns definitiv la această întrebare.
Tabelul de mai jos conține o descriere scurtă a fiecărui instrument:
Instrument
Scop
Dezavantaje
Teste personalizate
kubeval
Verifică manifestele YAML pentru conformitatea cu o anumită versiune a schemei API
Nu poate lucra cu CRD
Nu
kube-score
Analizează manifestele YAML pentru conformitatea cu cele mai bune practici
Nu poți alege propria versiune API Kubernetes pentru a verifica resursele
Nu
copper
Un cadru comun pentru crearea propriilor teste JavaScript pentru manifestele YAML
Nu există teste încorporate. Documentație limitată
Da
config-lint
Un cadru comun pentru crearea testelor în limbajul orientat pe obiecte, încorporat în YAML. Suportă diverse formate de configurații (de exemplu, Terraform)
Nu există teste gata făcute. Este posibil să nu fie suficiente aserțiuni și funcții încorporate
Da
conftest
Cadru pentru crearea propriilor teste în Rego (un limbaj specializat de interogare). Permite partajarea politicilor prin OCI bundles
Nu există teste încorporate. Este nevoie să înveți Rego. Docker Hub nu este acceptat la publicarea politicilor
Da
Polaris
Analizează manifestele YAML pentru conformitatea cu cele mai bune practici standard. Permite crearea de teste proprii folosind JSON Schema
Capacitățile testelor bazate pe JSON Schema pot să nu fie suficiente
Da
Deoarece aceste instrumente nu depind de accesul la clusterul Kubernetes, sunt ușor de instalat. Permit filtrarea fișierelor sursă și oferă feedback rapid autorilor pull request-urilor din proiecte.
P.S. de la traducător
Citiți și în blogul nostru:
- «»;
- «»;
- «».
Sursa: habr.com
