Nota di traduzione.: Con l'aumento del numero di configurazioni YAML per ambienti K8s, diventa sempre più rilevante la necessità di verificarle in modo automatizzato. L'autore di questa recensione non si è limitato a selezionare soluzioni esistenti per questo compito, ma ha anche esaminato, attraverso un esempio di Deployment, come funzionano. Il risultato è stato piuttosto informativo per coloro a cui interessa questo tema.

TL;DR: Nell'articolo vengono confrontati sei strumenti statici di verifica e valutazione dei file YAML di Kubernetes per la conformità alle migliori pratiche e ai requisiti.
I carichi di lavoro di Kubernetes sono solitamente definiti sotto forma di documenti YAML. Uno dei problemi con YAML è la complessità nel definire restrizioni o relazioni tra i file di manifest.
Cosa fare se abbiamo bisogno di assicurarci che tutte le immagini distribuite nel cluster provengano da un registro attendibile?
Come prevenire l'invio nel cluster di Deployment per i quali non sono stati definiti i PodDisruptionBudgets?
L'integrazione dei test statici consente di individuare errori e violazioni delle politiche già nella fase di sviluppo. In questo modo si aumentano le garanzie di correttezza e sicurezza delle definizioni delle risorse e si aumenta la probabilità che i carichi di produzione seguano le migliori pratiche.
L'ecosistema per la verifica statica dei file YAML di Kubernetes può essere suddiviso nelle seguenti categorie:
- Validatori API. Gli strumenti in questa categoria verificano il manifest YAML per la conformità ai requisiti del server API di Kubernetes.
- Tester prontos. Gli strumenti di questa categoria vengono forniti con test pronti per la sicurezza, la conformità alle migliori pratiche, ecc.
- Validatori personalizzati. I rappresentanti di questa categoria consentono di creare test personalizzati in vari linguaggi, ad esempio in Rego e Javascript.
In questo articolo descriveremo e confronteremo sei strumenti diversi:
- kubeval;
- kube-score;
- config-lint;
- copper;
- conftest;
- Polaris.
Bene, iniziamo!
Verifica dei Deployment
Prima di procedere al confronto degli strumenti, creiamo una base su cui testarli.
Il manifest riportato di seguito contiene una serie di errori e incongruenze rispetto alle migliori pratiche: quanti di essi riuscirete a trovare?
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)
Utilizzeremo questo YAML per confrontare diversi strumenti.
Il manifesto sopra citato
base-valid.yamle altri manifesti di questo articolo possono essere trovati in .
Il manifesto descrive un'applicazione web la cui funzione principale è rispondere con "Hello World" sulla porta 5678. Può essere distribuito con il seguente comando:
kubectl apply -f hello-world.yamlOra vediamo come controllare se funziona:
kubectl port-forward svc/http-echo 8080:5678Ora visita e conferma che l'applicazione stia funzionando. Ma rispetta le buone pratiche? Controlliamolo.
1. Kubeval
Alla base di c'è l'idea che qualsiasi interazione con Kubernetes avvenga tramite la sua API REST. In altre parole, puoi utilizzare lo schema API per verificare se questo YAML è conforme. Vediamo un esempio.
kubeval sono disponibili sul sito del progetto.
All'epoca della scrittura del documento originale era disponibile la versione 0.15.0.
Dopo aver installato, vediamo di "inserirvi" il manifesto sopra citato:
$ kubeval base-valid.yaml
PASS - base-valid.yaml contiene un Deployment valido (http-echo)
PASS - base-valid.yaml contiene un Service valido (http-echo)In caso di successo, kubeval terminerà con un codice di uscita 0. Puoi verificarlo nel seguente modo:
$ echo $?
0Proviamo ora kubeval con un altro manifesto:
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)
Puoi riconoscere il problema a colpo d'occhio? Eseguiamo:
$ kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml contiene un Deployment non valido (http-echo) - selector: selettore richiesto
PASS - kubeval-invalid.yaml contiene un Service valido (http-echo)
# controlliamo il codice di ritorno
$ echo $?
1Il risorsa non passa il controllo.
I Deployment che utilizzano la versione API apps/v1, devono includere un selettore che corrisponda all'etichetta del pod. Il manifesto sopra non include un selettore, quindi kubeval ha segnalato un errore ed è terminato con un codice diverso da zero.
Sarebbe interessante vedere cosa succede se esegui kubectl apply -f con questo manifesto?
Bene, proviamo:
$ kubectl apply -f kubeval-invalid.yaml
errore: errore di convalida "kubeval-invalid.yaml": errore di convalida dati: ValidationError(Deployment.spec):
manca il campo richiesto "selector" in io.k8s.api.apps.v1.DeploymentSpec; se decidi di ignorare questi errori,
disattiva la convalida con --validate=falseÈ esattamente l'errore di cui avvisava kubeval. Puoi correggerlo aggiungendo un selettore:
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)
Il vantaggio di strumenti come kubeval è che è possibile rilevare errori simili nelle fasi iniziali del ciclo di distribuzione.
Inoltre, per queste verifiche non è necessario l'accesso al cluster: possono essere eseguite offline.
Di default, kubeval verifica le risorse per la conformità all'ultima versione dello schema dell'API Kubernetes. Tuttavia, nella maggior parte dei casi potrebbe essere necessario eseguire una verifica per una versione specifica di Kubernetes. Puoi farlo utilizzando il flag --kubernetes-version:
$ kubeval --kubernetes-version 1.16.1 base-valid.yamlNota che la versione deve essere specificata nel formato Major.Minor.Patch.
Per visualizzare l'elenco delle versioni supportate, fai riferimento alla , che kubeval utilizza per la convalida. Se hai bisogno di eseguire kubeval offline, scarica gli schemi e specifica la loro posizione locale utilizzando il flag --schema-location.
Oltre ai singoli file YAML, kubeval può anche lavorare con directory e stdin.
Inoltre, Kubeval si integra facilmente nei pipeline CI. Coloro che desiderano eseguire test prima di inviare i manifesti nel cluster saranno felici di sapere che kubeval supporta tre formati di output:
- Testo normale;
- JSON;
- Test Anything Protocol (TAP).
E uno qualsiasi dei formati può essere utilizzato per analizzare ulteriormente l'output, al fine di formare un riepilogo dei risultati desiderati.
Uno dei lati negativi di kubeval è che attualmente non è in grado di verificare la conformità delle Custom Resource Definitions (CRD). Tuttavia, puoi configurare kubeval .
Kubeval è un ottimo strumento per controllare e valutare le risorse; va sottolineato, però, che un test di successo non garantisce che la risorsa segua le migliori pratiche.
Ad esempio, l'uso del tag latest nel contenitore non rispetta le migliori pratiche. Tuttavia kubeval non lo considera un errore e non ne dà notizia. Ovvero, la verifica di tale YAML si concluderà senza avvertimenti.
Ma cosa fare se è necessario valutare YAML e individuare violazioni come il tag latest? Как проверить YAML-файл на соответствие лучшим практикам?
2. Kube-score
analizza i manifesti YAML e li valuta mediante test incorporati. Questi test vengono scelti in base a raccomandazioni sulla sicurezza e migliori pratiche, come ad esempio:
- Esecuzione del contenitore non come root.
- Presenza di controlli di salute nei pod.
- Definizione di request e limit sui risorse.
Al termine del test vengono forniti tre risultati: OK, WARNING e CRITICAL.
Kube-score può essere provato online o installato localmente.
Al momento della scrittura dell'articolo originale, la versione più recente di kube-score era 1.7.0.
Mettiamolo alla prova sul nostro manifesto base-valid.yaml:
$ kube-score score base-valid.yaml
apps/v1/Deployment http-echo
[CRITICAL] Container Image Tag
· http-echo -> Immagine con tag latest
Si raccomanda di utilizzare un tag fisso per evitare aggiornamenti accidentali
[CRITICAL] Pod NetworkPolicy
· Il pod non ha una policy di rete corrispondente
Crea una NetworkPolicy che targetti questo pod
[CRITICAL] Pod Probes
· Il contenitore manca di un readinessProbe
Un readinessProbe dovrebbe essere utilizzato per indicare quando il servizio è pronto a ricevere traffico.
Senza di esso, il Pod corre il rischio di ricevere traffico prima di essere avviato. Viene utilizzato anche durante
i rilasci, e può prevenire tempi di inattività se una nuova versione dell'applicazione fallisce.
Maggiori informazioni: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITICAL] Container Security Context
· http-echo -> Il contenitore non ha un contesto di sicurezza configurato
Imposta securityContext per eseguire il contenitore in un contesto più sicuro.
[CRITICAL] Container Resources
· http-echo -> Limite CPU non impostato
I limiti sulle risorse sono raccomandati per evitare DDOS di risorse. Imposta resources.limits.cpu
· http-echo -> Limite di memoria non impostato
I limiti sulle risorse sono raccomandati per evitare DDOS di risorse. Imposta resources.limits.memory
· http-echo -> Richiesta CPU non impostata
Le richieste sulle risorse sono raccomandate per assicurarsi che l'applicazione possa avviarsi e funzionare senza
arrestarsi. Imposta resources.requests.cpu
· http-echo -> Richiesta di memoria non impostata
Le richieste sulle risorse sono raccomandate per assicurarsi che l'applicazione possa avviarsi e funzionare senza arrestarsi.
Imposta resources.requests.memory
[CRITICAL] Deployment ha PodDisruptionBudget
· Nessun PodDisruptionBudget corrispondente trovato
Si raccomanda di definire un PodDisruptionBudget per evitare inattività imprevista durante le operazioni di
manutenzione di Kubernetes, come quando si svuota un nodo.
[WARNING] Deployment ha host PodAntiAffinity
· Il Deployment non ha impostato anti-affinità pod del host
Si raccomanda di impostare un podAntiAffinity che impedisca a più pod di un Deployment di
essere pianificati sullo stesso nodo. Ciò aumenta la disponibilità nel caso in cui il nodo diventi non disponibile.YAML supera i controlli kubeval, mentre kube-score indica le seguenti carenze:
- Non sono impostati i controlli di prontezza.
- Mancano richieste e limiti per le risorse CPU e memoria.
- Non sono definiti i budget di interruzione dei pod.
- Mancano le regole di esistenza separata (anti-affinità) per massimizzare la disponibilità.
- Il contenitore viene eseguito con i privilegi di root.
Tutti questi sono commenti ragionevoli sui difetti che dovrebbero essere risolti affinché il Deployment sia più efficace e affidabile.
Team kube-score fornisce informazioni in un formato leggibile includendo tutte le violazioni di tipo WARNING e CRITICAL, il che è molto utile durante lo sviluppo.
Coloro che desiderano utilizzare questo strumento all'interno di una pipeline CI possono abilitare un output più compatto usando il flag --output-format ci (in questo caso sono anche mostrati i test con il risultato 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) Limite CPU non impostato
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Limite di memoria non impostato
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Richiesta CPU non impostata
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Richiesta di memoria non impostata
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Immagine con tag latest
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: Il pod non ha una policy di rete corrispondente
[CRITICAL] http-echo apps/v1/Deployment: Il contenitore è privo di readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Il contenitore non ha un contesto di sicurezza configurato
[CRITICAL] http-echo apps/v1/Deployment: Nessun PodDisruptionBudget corrispondente trovato
[WARNING] http-echo apps/v1/Deployment: Il Deployment non ha impostato un host podAntiAffinity
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/ServiceAnalogamente a kubeval, kube-score restituisce un codice di uscita non nullo se c'è un test che è fallito. CRITICALÈ possibile abilitare un'elaborazione simile anche per WARNING.
Inoltre, c'è la possibilità di controllare le risorse per verificare la conformità a diverse versioni dell'API (come in kubeval). Tuttavia, questa informazione è 'hardcoded' in kube-score: non è possibile scegliere un'altra versione di Kubernetes. Tale limitazione può rappresentare un grande problema se si intende aggiornare il cluster o se si hanno più cluster con versioni diverse di K8s.
Si prega di notare che con la proposta di implementare questa possibilità.
Maggiori informazioni su kube-score possono essere trovate su .
I test di kube-score sono un ottimo strumento per implementare le migliori pratiche, ma cosa fare se è necessario apportare modifiche a un test o aggiungere regole personalizzate? Purtroppo, non è possibile farlo.
Kube-score non è estensibile: non è possibile aggiungere o adattare le politiche.
Se è necessario scrivere test personalizzati per le verifiche di conformità alle politiche adottate in azienda, è possibile utilizzare uno dei seguenti quattro strumenti: config-lint, copper, conftest o polaris.
3. Config-lint
Config-lint è uno strumento per la validazione dei file di configurazione nei formati YAML, JSON, Terraform, CSV e nei manifesti di Kubernetes.
Può essere installato seguendo sul sito del progetto.
La versione attuale al momento della scrittura dell'articolo originale è 1.5.0.
Config-lint non contiene test integrati per la verifica dei manifesti di Kubernetes.
Per eseguire qualsiasi test, è necessario creare le regole corrispondenti. Queste vengono salvate in file YAML chiamati "insiemi di regole" (rulesets), e hanno la seguente struttura:
version: 1
description: Regole per i file di specifica Kubernetes
type: Kubernetes
files:
- "*.yaml"
rules:
# elenco delle regole(rule.yaml)
Esaminiamola più da vicino:
- Campo
typeindica quale tipo di configurazione utilizzerà config-lint. Per i manifesti K8s, questo sempreKubernetes. - Nel campo
filesoltre ai file stessi, è possibile specificare una directory. - Campo
rulesè destinato a definire test personalizzati.
Supponiamo che tu voglia assicurarti che le immagini nel Deployment vengano sempre scaricate da un repository di fiducia come my-company.com/myapp:1.0. La regola per config-lint che esegue tale verifica avrà la seguente forma:
- id: MY_DEPLOYMENT_IMAGE_TAG
severity: FAILURE
message: Il Deployment deve utilizzare un tag di immagine valido
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(rule-trusted-repo.yaml)
Per ogni regola devono essere specificati i seguenti attributi:
id— identificatore univoco della regola;severity— può essere FAILURE, WARNING e NON_COMPLIANT;message— se la regola viene violata, verrà visualizzato il contenuto di questa riga;resource— tipo di risorsa a cui si applica questa regola;assertions— elenco delle condizioni che saranno valutate rispetto a questa risorsa.
Nella regola sopra assertion denominato verifica che tutti i contenitori nel Deployment (key: spec.templates.spec.containers) utilizzino immagini di fiducia (ossia, che iniziano con my-company.com/).
Il ruleset completo ha la seguente forma:
version: 1
description: Regole per i file di specifica Kubernetes
type: Kubernetes
files:
- "*.yaml"
rules:
- id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
severity: FAILURE
message: Il Deployment deve utilizzare un repository di immagine valido
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(ruleset.yaml)
Per testare il test, salviamolo come check_image_repo.yaml. Avviamo la verifica sul file. base-valid.yaml:
$ config-lint -rules check_image_repo.yaml base-valid.yaml
[
{
"AssertionMessage": "Ogni espressione fallisce: l'espressione And fallisce: l'immagine non inizia con 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": "Il deployment deve utilizzare un repository di immagini valido",
"Status": "FAILURE"
}
]Il controllo è fallito. Ora verifichiamo il seguente manifesto con un repository di immagini corretto:
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)
Stiamo eseguendo lo stesso test con il manifesto sopra riportato. Nessun problema riscontrato:
$ config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]Config-lint è un framwork promettente che consente di creare test personalizzati per la verifica dei manifesto YAML di Kubernetes utilizzando YAML DSL.
Ma cosa fare se è necessaria una logica e test più complessi? Non è forse YAML troppo limitato per questo? Cosa succederebbe se si potessero creare test in un vero linguaggio di programmazione?
4. Copper
è un framework per la validazione dei manifesti utilizzando test personalizzati (simile a config-lint).
Tuttavia, a differenza dell'ultimo, non utilizza YAML per descrivere i test. Invece, i test possono essere creati in JavaScript. Copper fornisce una libreria con alcuni strumenti di base, per aiutare a leggere le informazioni sugli oggetti Kubernetes e segnalare errori.
La sequenza di passaggi per installare Copper può essere trovata in .
2.0.1 è l'ultima versione di questo strumento al momento della scrittura dell'articolo originale.
Come config-lint, Copper non ha test integrati. Scriviamo un test. Dovrebbe verificare che i deployment utilizzino immagini container esclusivamente da repository fidati come my-company.com.
Crea un file check_image_repo.js con il seguente contenuto:
$$.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',"L'immagine " + $.metadata.name + " non proviene dal repository my-company.com", 1)
}
});
}
});Ora, per verificare il nostro manifesto base-valid.yaml, usa il comando copper validate:
$ copper validate --in=base-valid.yaml --validator=check_image_tag.js
Il controllo no_company_repo è fallito con gravità 1 a causa dell'immagine http-echo non proveniente dal repository my-company.com
Validazione fallitaÈ chiaro che con copper è possibile eseguire test più complessi, ad esempio verificare i nomi di dominio nei manifesti Ingress o rifiutare i pod che funzionano in modalità privilegiata.
Copper include diverse funzioni di servizio:
DockerImagelegge il file di input specificato e crea un oggetto con i seguenti attributi:name— nome dell'immagine,tag— tag dell'immagine,registry— registro delle immagini,registry_url— protocollo (https://) e registro delle immagini,fqin— posizione completa dell'immagine.
- La funzione
findByNameaiuta a trovare una risorsa di un determinato tipo (tipo) e nome (name) dal file di input. - La funzione
findByLabelsaiuta a trovare una risorsa per un tipo specificato (tipo) e etichette (labels).
È possibile consultare tutte le funzioni di servizio disponibili .
Per impostazione predefinita, carica l'intero file YAML di input in una variabile $$ e la rende disponibile per gli script (un metodo comune per chi ha esperienza con jQuery).
Il principale vantaggio di Copper è evidente: non è necessario imparare un linguaggio specializzato e si possono utilizzare varie capacità di JavaScript per creare i propri test, come l'interpolazione delle stringhe, le funzioni, ecc.
È inoltre importante notare che l'attuale versione di Copper funziona con la versione ES5 del motore JavaScript, e non con l'ES6.
I dettagli sono disponibili su .
Tuttavia, se non amate molto JavaScript e preferite un linguaggio appositamente progettato per la creazione di query e la descrizione delle politiche, dovreste prestare attenzione a conftest.
5. Conftest
Conftest è un framework per la verifica dei dati di configurazione. È adatto anche per il testing/verifica dei manifesti Kubernetes. I test sono descritti attraverso un linguaggio di query specializzato .
È possibile installare conftest seguendo le istruzioni , disponibili sul sito del progetto.
Al momento della stesura dell'articolo originale, l'ultima versione disponibile era la 0.18.2.
Analogamente a config-lint e copper, conftest viene fornito senza alcun test integrato. Proviamo a usarlo e scriviamo la nostra politica. Come nei precedenti esempi, verificheremo se le immagini dei container provengono da una fonte affidabile.
Crea una directory conftest-checks, e al suo interno un file chiamato check_image_registry.rego con il seguente contenuto:
package main
deny[msg] {
input.kind == "Deployment"
image := input.spec.template.spec.containers[_].image
not startswith(image, "my-company.com/")
msg := sprintf("l'immagine '%v' non proviene dal repository my-company.com", [image])
}Adesso proviamo a testare base-valid.yaml tramite conftest:
$ conftest test --policy ./conftest-checks base-valid.yaml
FAIL - base-valid.yaml - l'immagine 'hashicorp/http-echo' non proviene dal repository my-company.com
1 test, 1 superato, 0 avvertimenti, 1 fallitoIl test è fallito come previsto, poiché le immagini provengono da una fonte non attendibile.
Nel file Rego definiamo il blocco deny. La sua verità è considerata una violazione. Se ci sono più blocchi, conftest li verifica indipendentemente l'uno dall'altro e la verità di uno qualsiasi dei blocchi è interpretata come una violazione. deny Oltre all'output predefinito, conftest supporta JSON, TAP e il formato tabellare, una funzionalità estremamente utile se si desidera integrare i report in un pipeline CI esistente. È possibile specificare il formato desiderato utilizzando il flag
--output Per facilitare il debug delle politiche, in conftest è disponibile il flag.
--trace . Esso fornisce la tracciabilità di come conftest analizza i file di policy specificati.Le politiche di conftest possono essere pubblicate e condivise nei registri OCI (Open Container Initiative) come artefatti.
consentono di pubblicare un artefatto o di estrarre un artefatto esistente da un registro remoto. Proviamo a pubblicare la nostra politica creata in un registro Docker locale utilizzando
Team push e pull conftest push Avvia il registro Docker locale:.
$ docker run -it --rm -p 5000:5000 registry
In un'altra console, vai nella directory creata in precedenza$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latest conftest-checks ed eseguire il seguente comando:
Se il comando è andato a buon fine, vedrai un messaggio del tipo:2020/06/10 14:25:43 bundle pushed with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609c
Ora crea una directory temporanea ed esegui al suo interno il comandoconftest pull . Questo scaricherà il pacchetto creato dal comando precedente:$ cd $(mktemp -d) $ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latest
Nella directory temporanea apparirà una sottodirectory, contenente il nostro file di policy: policy$ tree . └── policy └── check_image_registry.rego
I test possono essere eseguiti direttamente dal repository:$ conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml .. FAIL - base-valid.yaml - l'immagine 'hashicorp/http-echo' non proviene dal repository my-company.com 2 test, 1 superato, 0 avvisi, 1 errore
Sfortunatamente, DockerHub non è ancora supportato. Quindi consideratevi fortunati se utilizzateAzure Container Registry Il formato degli artefatti è lo stesso dei
pacchetti Open Policy Agent Per ulteriori informazioni sulla condivisione delle politiche e altre caratteristiche di conftest, puoi consultare
6. Polaris .
L'ultimo strumento di cui parleremo in questo articolo è
(Il suo annuncio dell'anno scorso è stato . già tradotto — Nota di traduzione.)
Polaris può essere installato in un cluster o utilizzato in modalità command line. Come avete già immaginato, consente di analizzare staticamente i manifesti di Kubernetes.
Quando si lavora in modalità command line, sono disponibili test integrati che coprono aree come la sicurezza e le migliori pratiche (analogamente a kube-score). Inoltre, è possibile creare test personalizzati (come in config-lint, copper e conftest).
In altre parole, Polaris combina i vantaggi di entrambe le categorie di strumenti: con test incorporati e personalizzati.
Per installare Polaris in modalità command line, segui .
Al momento della scrittura dell'articolo originale, era disponibile la versione 1.0.3.
Dopo aver completato l'installazione, puoi eseguire polaris sul manifesto base-valid.yaml utilizzando il seguente comando:
$ polaris audit --audit-path base-valid.yamlRestituirà una stringa in formato JSON con una descrizione dettagliata dei test eseguiti e dei loro risultati. L'output avrà la seguente struttura:
{
"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": [
/* lungo elenco */
]
}L'output completo è disponibile .
Come kube-score, Polaris identifica le problematiche nelle aree in cui il manifesto non segue le migliori pratiche:
- Mancano i controlli di salute per i pod.
- Non sono stati specificati tag per le immagini dei container.
- Il contenitore viene eseguito con i privilegi di root.
- Non sono stati specificati richieste e limiti per la memoria e la CPU.
Ad ogni test, a seconda dei risultati, viene assegnato un livello di gravità: warning o danger. Per ulteriori informazioni sui test integrati disponibili, consultare .
Se non sono necessarie ulteriori dettagli, è possibile specificare il flag --format score. In questo caso Polaris restituirà un numero compreso tra 1 e 100 — score (cioè, valutazione):
$ polaris audit --audit-path test-data/base-valid.yaml --format score
68Maggiore è la valutazione vicina a 100, maggiore è il livello di conformità. Se controlli il codice di uscita del comando polaris audit, risulterà 0.
Forzare polaris audit l'uscita con un codice non zero può essere fatto utilizzando due flag:
- Bandiera
--set-exit-code-below-scoreaccetta come argomento un valore soglia nel range 1-100. In questo caso il comando terminerà con un codice di uscita 4 se la valutazione è inferiore alla soglia. Questo è molto utile quando hai un certo valore soglia (diciamo, 75) e desideri ricevere un avviso se la valutazione scende sotto. - Bandiera
--set-exit-code-on-dangerporterà a un codice di uscita 3 se uno dei test di pericolo non avrà successo.
Ora proviamo a creare un test personalizzato che verifichi se l'immagine proviene da un repository di fiducia. I test personalizzati sono definiti in formato YAML e il test stesso è descritto tramite JSON Schema.
Il seguente frammento di codice YAML descrive un nuovo test chiamato checkImageRepo:
checkImageRepo:
successMessage: Il registro delle immagini è valido
failureMessage: Il registro delle immagini non è valido
category: Immagini
target: Contenitore
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$Diamo un'occhiata più da vicino:
successMessage— questa stringa verrà visualizzata se il test ha successo;failureMessage— questo messaggio verrà mostrato in caso di fallimento;category— indica una delle seguenti categorie:Immagini,Controlli di Salute,Sicurezza,NetworkingeRisorse;target—- definisce a quale tipo di oggetto (spec) si applica il test. Valori possibili:Contenitore,PodoController;- Il test stesso è definito nell'oggetto
schemautilizzando lo schema JSON. In questo test, la parola chiavepatternviene utilizzata per confrontare la sorgente dell'immagine con quella richiesta.
Per eseguire il test sopra citato, è necessario creare la seguente configurazione di Polaris:
checks:
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Il registro delle immagini è valido
failureMessage: Il registro delle immagini non è valido
category: Immagini
target: Contenitore
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$(polaris-conf.yaml)
Esaminiamo il file:
- Nel campo
checksdefiniscono i test e il loro livello di criticità. Poiché è preferibile ricevere un avviso quando l'immagine proviene da una fonte non affidabile, impostiamo qui il livellodanger. - Il test stesso
checkImageRepoquindi si definisce nell'oggettocustomChecks.
Salva il file come custom_check.yaml. Ora puoi avviare polaris audit con il manifesto YAML che richiede la verifica.
Testiamo il nostro manifesto base-valid.yaml:
$ polaris audit --config custom_check.yaml --audit-path base-valid.yamlTeam polaris audit ha eseguito solo il test personalizzato definito sopra e non ha avuto successo.
Se si corregge l'immagine in my-company.com/http-echo:1.0, Polaris avrà successo. Il manifesto con le modifiche è già presente in , quindi puoi controllare il comando precedente nel manifesto. image-valid-mycompany.yaml.
Ora sorge la domanda: come eseguire i test integrati insieme ai test personalizzati? È semplice! Devi solo aggiungere gli identificatori dei test integrati nel file di configurazione. Di conseguenza, apparirà come segue:
controlli:
cpuRequestsMissing: avviso
cpuLimitsMissing: avviso
# Altri controlli integrati..
# ..
# controlli personalizzati
checkImageRepo: pericolo # !!!
controlliPersonalizzati:
checkImageRepo: # !!!
successMessage: Il registro delle immagini è valido
failureMessage: Il registro delle immagini non è valido
category: Immagini
target: Contenitore
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$(config_with_custom_check.yaml)
Esempio di file di configurazione completo disponibile .
Verificare il manifesto base-valid.yaml, utilizzando test integrati e personalizzati tramite il comando:
$ polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yamlPolaris arricchisce i test integrati con quelli personalizzati, combinando così il meglio di entrambi i mondi.
D'altra parte, l'impossibilità di utilizzare linguaggi più potenti come Rego o JavaScript potrebbe rappresentare un fattore limitante per la creazione di test più sofisticati.
Ulteriori informazioni su Polaris sono disponibili su .
Riepilogo
Sebbene ci siano molti strumenti per verificare e valutare file YAML di Kubernetes, è importante avere un'idea chiara di come i test verranno progettati ed eseguiti..
Ad esempio, Se consideriamo i manifesti Kubernetes che passano attraverso la pipeline, kubeval potrebbe essere il primo passo in tale pipeline.. Si occuperebbe di monitorare se le definizioni degli oggetti sono conformi allo schema API di Kubernetes.
Dopo aver completato un simile controllo, si potrebbe passare a test più sofisticati, come la conformità a migliori pratiche e specifiche politiche. E qui tornerebbero utili kube-score e Polaris.
Coloro che hanno requisiti complessi e necessità di personalizzare i test potrebbero considerare copper, config-lint e conftest..
Conftest e config-lint utilizzano YAML per definire test personalizzati, mentre copper offre accesso a un linguaggio di programmazione completo, rendendolo una scelta piuttosto allettante.
D'altra parte, vale la pena utilizzare uno di questi strumenti e quindi scrivere tutti i test manualmente o preferire Polaris e aggiungere solo ciò che serve? Non c'è una risposta chiara a questa domanda..
La tabella sottostante fornisce una breve descrizione di ciascun strumento:
Strumento
Scopo
Svantaggi
Test personalizzati
kubeval
Controlla i manifesti YAML per la conformità a una specifica versione dello schema API.
Non supporta CRD.
No
kube-score
Analizza i manifesti YAML per la conformità alle migliori pratiche.
Non consente di scegliere la propria versione dell'API Kubernetes per la verifica delle risorse.
No
copper
Framework generale per la creazione di test JavaScript personalizzati per i manifesti YAML
Nessun test integrato. Documentazione scarsa
Sì
config-lint
Framework generale per la creazione di test in un linguaggio orientato agli oggetti incorporato in YAML. Supporta vari formati di configurazione (ad esempio, Terraform)
Nessun test pronto all'uso. Le asserzioni e le funzioni integrate potrebbero non essere sufficienti
Sì
conftest
Framework per la creazione di test personalizzati in Rego (linguaggio di query specializzato). Consente di condividere politiche tramite OCI bundles
Nessun test integrato. È necessario imparare Rego. Docker Hub non supportato per la pubblicazione delle politiche
Sì
Polaris
Analizza i manifesti YAML per la conformità alle migliori pratiche standard. Consente di creare test personalizzati utilizzando JSON Schema
Le capacità dei test basati su JSON Schema potrebbero non essere sufficienti
Sì
Poiché questi strumenti non dipendono dall'accesso al cluster Kubernetes, sono facili da installare. Consentono di filtrare i file sorgente e forniscono un rapido feedback agli autori delle pull request nei progetti.
P.S. dal traduttore
Leggi anche nel nostro blog:
- «»;
- «»;
- «».
Fonte: habr.com
