Прим. прев.: С нарастващия брой YAML конфигурации за K8s средиите, необходимостта от автоматизирана проверка става все по-актуална. Авторът на този преглед не само е събрал съществуващите решения за тази задача, но и е разгледал как те функционират, използвайки пример с Deployment. Станаха много информативни за всички, на които им е интересна тази тема.

TL;DR: В статията се сравняват шест статични инструмента за проверка и оценка на YAML файлове на Kubernetes за съответствие с добри практики и изисквания.
Работните товари на Kubernetes обикновено се определят под формата на YAML документи. Един от проблемите с YAML е сложността при задаването на ограничения или взаимовръзки между файловете на манифестите.
Какво, ако трябва да се уверим, че всички образи, разгръщани в кластера, идват от доверен регистър?
Как да предотвратим изпращането на Deployment-и в кластера, за които не са зададени PodDisruptionBudgets?
Интеграцията на статично тестване позволява откриването на грешки и нарушения на политиките още в етапа на разработка. По този начин се увеличават гаранциите за точността и сигурността на определенията за ресурси и се увеличава вероятността production натоварванията да следват добри практики.
Екосистемата за статична проверка на YAML файлове на Kubernetes може да се раздели на следните категории:
- API валидатори. Инструменти в тази категория проверяват YAML манифеста за съответствие на изискванията на API сървъра на Kubernetes.
- Готови тестери. Инструментите в тази категория идват с готови тестове за сигурност, съответствие с добри практики и т.н.
- Персонализирани валидатори. Представителите на тази категория позволяват създаването на потребителски тестове на различни езици, например на Rego и Javascript.
В тази статия ще опишем и сравним шест различни инструмента:
- kubeval;
- kube-score;
- config-lint;
- copper;
- conftest;
- Polaris.
Добре, да започнем!
Проверка на Deployment-ите
Преди да преминем към сравнение на инструментите, нека създадем някаква основа, на която ще ги тестваме.
По-долу манифест съдържа редица грешки и несъответствия с добрите практики: колко от тях ще можете да намерите?
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)
Ще използваме този YAML за сравнение на различни инструменти.
Горепосоченият манифест
base-valid.yamlи други манифести от тази статия можете да намерите в .
Манифестът описва уеб приложение, чиято основна задача е да отговаря с "Hello World" на порт 5678. Може да бъде разположен с следната команда:
kubectl apply -f hello-world.yamlА ето как да проверите работата:
kubectl port-forward svc/http-echo 8080:5678Сега отидете на и потвърдете, че приложението работи. Но следва ли то на добрите практики? Нека проверим.
1. Kubeval
В основата е идеята, че всяко взаимодействие с Kubernetes става чрез неговия REST API. С други думи, можете да използвате схемата на API, за да проверите дали този YAML й отговаря. Нека да разгледаме пример.
kubeval са налични на сайта на проекта.
Към момента на написването на оригиналната статия беше налична версия 0.15.0.
След инсталирането нека "нахраним" манифеста, показан по-горе:
$ kubeval base-valid.yaml
PASS - base-valid.yaml contains a valid Deployment (http-echo)
PASS - base-valid.yaml contains a valid Service (http-echo)При успех kubeval ще приключи с exit-код 0. Можете да проверите както следва:
$ echo $?
0Сега да опитаме kubeval с друг манифест:
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)
Можете ли на пръв поглед да определите проблема? Стартираме:
$ 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)
# да проверим кодa на завръщане
$ echo $?
1Ресурсът не преминава проверката.
Deployment-ите, използващи версия на API apps/v1, трябва да включват селектор, съответстващ на етикета на pod-a. Горният манифест не включва селектор, затова kubeval съобщи за грешка и приключи с ненулев код.
Интересно е какво ще се случи, ако изпълним kubectl apply -f с този манифест?
Какво ж, да опитаме:
$ 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Това е грешката, за която предупреди kubeval. Можете да я коригирате, като добавите селектор:
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)
Предимството на инструменти като kubeval е, че такива грешки могат да бъдат уловени в ранните етапи на цикъла на разгръщане.
Освен това, за тези проверки не е необходим достъп до клъстера: те могат да се извършват офлайн.
По подразбиране kubeval проверява ресурсите за съответствие с най-новата схема на Kubernetes API. Въпреки това, в повечето случаи може да е необходимо да проверите за съответствие с конкретна версия на Kubernetes. Това може да стане с помощта на флага --kubernetes-version:
$ kubeval --kubernetes-version 1.16.1 base-valid.yamlОбърнете внимание, че версията трябва да бъде указана в формата Major.Minor.Patch.
За да видите списък с версиите, за които се поддържа проверка, посетете , която kubeval използва за валидация. Ако искате да стартирате kubeval офлайн, изтеглете схемите и посочете тяхното местоположение локално с помощта на флага --schema-location.
Освен отделни YAML файлове, kubeval също може да работи с директории и stdin.
Освен това, Kubeval лесно се интегрира в CI пайплайн. Тези, които искат да провеждат тестове преди изпращане на манифестите в клъстера, ще се радват да научат, че kubeval поддържа три формата на изход:
- Обикновен текст;
- JSON;
- Test Anything Protocol (TAP).
И може да се използва всеки от тези формати за допълнително парсиране на изхода, за да се формира обобщение на резултатите от желания вид.
Един от недостатъците на kubeval е, че в момента не може да проверява за съответствие с Custom Resource Definitions (CRDs). Въпреки това, kubeval може да бъде настроен .
Kubeval е отличен инструмент за проверка и оценка на ресурсите; обаче, трябва да се подчертае, че успешното преминаване на теста не гарантира, че ресурсът отговаря на най-добрите практики.
Например, използването на таг latest В контейнера не отговарят на най-добрите практики. Въпреки това kubeval не счита това за грешка и не съобщава за нея. Тоест проверката на такъв YAML ще приключи без предупреждения.
Но какво, ако трябва да оценим YAML и да открием нарушения като етикета latest? Как проверить YAML-файл на соответствие лучшим практикам?
2. Kube-score
анализира YAML манифести и ги оценява по вградени тестове. Тези тестове се избират въз основа на препоръки за сигурност и най-добри практики, например:
- Стартиране на контейнера не под root.
- Наличие на проверки за здравето на pod-овете.
- Задаване на заявки и ограничения на ресурсите.
След теста се издават три резултата: OK, WARNING и CRITICAL.
Kube-score може да се опита онлайн или да се инсталира локално.
По време на написването на оригиналната статия най-новата версия на kube-score беше 1.7.0.
Нека да го тестваме на нашия манифест 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 преминава проверки на kubeval, докато kube-score посочва следните недостатъци:
- Не са настроени проверки за готовност.
- Липсват заявки и ограничения за ресурси CPU и памет.
- Не са зададени бюджети за нарушаване на Pod.
- Липсват правила за антиподелно съществуване (anti-affinity) за максимизиране на наличността.
- Контейнерът работи с root права.
Всичко това са разумни забележки относно недостатъците, които трябва да бъдат отстранени, за да стане внедряването по-ефективно и надеждно.
Екип kube-score извежда информация в удобен за четене формат, включваща всички нарушения от тип WARNING и CRITICAL, което е много полезно по време на разработката.
Желаещите да използват този инструмент в рамките на CI пайплайна могат да активират по-компактен изход с помощта на флага --output-format ci (в този случай се изписват и тестовете с резултат 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 не е зададен
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Лимит за памет не е зададен
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Заявка за CPU не е зададена
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Заявка за памет не е зададена
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Образ с последния таг
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: Подът няма съответстваща мрежова политика
[CRITICAL] http-echo apps/v1/Deployment: Контейнерът липсва readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Контейнерът няма конфигуриран security context
[CRITICAL] http-echo apps/v1/Deployment: Не е намерен съответстващ PodDisruptionBudget
[WARNING] http-echo apps/v1/Deployment: Внедряването няма зададена podAntiAffinity за хост
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/ServiceПо аналогия с kubeval, kube-score връща ненулев код на изхода при наличие на тест, завършил с грешка. CRITICAL. Може също така да се активира подобна обработка и за WARNING.
Освен това, има възможност за проверка на ресурсите за съответствие с различни версии на API (както в kubeval). Обаче тази информация е 'hardcoded' в самия kube-score: не може да се избере друга версия на Kubernetes. Такова ограничение може да се окаже голям проблем, ако планирате да обновите клъстера или имате няколко клъстера с различни версии на K8s.
Обърнете внимание, че с предложение да се реализира тази възможност.
Повече информация за kube-score може да се намери на .
Тестовете на kube-score са отличен инструмент за внедряване на добри практики, но какво, ако е необходимо да внесете промени в теста или да добавите свои собствени правила? За съжаление, това не е възможно.
Kube-score не е разширяем: не можете да добавите или настроите политики.
Ако е необходимо да пишете потребителски тестове за проверки на съответствие с политиките, приети в компанията, можете да използвате един от следните четири инструмента: config-lint, copper, conftest или polaris.
3. Config-lint
Config-lint е инструмент за валидация на конфигурационни файлове във формат YAML, JSON, Terraform, CSV и манифести на Kubernetes.
Може да бъде инсталиран чрез на сайта на проекта.
Текущото издание към момента на написване на оригиналната статия е 1.5.0.
Config-lint няма вградени тестове за проверка на манифести на Kubernetes.
За провеждане на тестове е необходимо да се създадат съответните правила. Те се записват в YAML файлове, наречени „набори от правила“ (rulesets), и имат следната структура:
version: 1
description: Правила за файлове на Kubernetes спецификация
типа: Kubernetes
files:
- "*.yaml"
rules:
# списък с правила(rule.yaml)
Нека да я разгледаме по-подробно:
- Поле
типпосочва, какъв тип конфигурация ще използва config-lint. За манифестите K8s това е винагиKubernetes. - В полето
файловеосвен самите файлове, може да се посочи директория. - Поле
rulesпредназначено за задаване на потребителски тестове.
Да предположим, че искате да се уверите, че образите в Deployment-а винаги се изтеглят от доверен репозиторий, като my-company.com/myapp:1.0. Правилото за config-lint, което извършва такава проверка, ще изглежда по следния начин:
- id: MY_DEPLOYMENT_IMAGE_TAG
severity: FAILURE
message: Deployment трябва да използва валиден етикет на изображение
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(rule-trusted-repo.yaml)
За всяко правило трябва да бъдат посочени следните атрибути:
id— уникален идентификатор на правилото;сериозност— може да бъде FAILURE, WARNING и NON_COMPLIANT;message— при нарушение на правилото, съдържанието на този ред ще се покаже;ресурс— тип на ресурса, към който се прилага това правило;условия— списък от условия, които ще се оценяват относно дадения ресурс.
В правилото по-горе условие с имената проверява, че всички контейнери в Deployment-а (key: spec.templates.spec.containers) използват доверени образи (т.е. образи, които започват с my-company.com/).
Пълен набор правилата изглежда по следния начин:
version: 1
description: Правила за файлове на Kubernetes спецификация
type: Kubernetes
files:
- "*.yaml"
rules:
- id: DEPLOYMENT_IMAGE_REPOSITORY # !!!
seriousness: FAILURE
message: Deployment трябва да използва валиден репозиторий на образа
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"(ruleset.yaml)
За да тестваме теста, нека го запазим като check_image_repo.yaml. Нека стартираме проверка над файла 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"
}
]Проверката завърши неуспешно. Сега нека проверим следния манифест с правилно хранилище за образи:
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)
Стартираме същия тест с горепосочения манифест. Проблеми не са открити:
$ config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]Config-lint е обещаваща рамка, която ви позволява да създавате собствени тестове за проверка на YAML манифести на Kubernetes с помощта на YAML DSL.
Но какво да правим, ако необходима по-сложна логика и тестове? Не са ли възможностите на YAML твърде ограничени за това? Какво, ако можете да създавате тестове на пълен език за програмиране?
4. Copper
е рамка за валидиране на манифести с помощта на потребителски тестове (аналог на config-lint).
Обаче, за разлика от последното, тя не използва YAML за описание на тестовете. Вместо това тестовете могат да бъдат създавани на JavaScript. Copper предоставя библиотека с няколко основни инструмента, които помагат за извличане на информация за обекти в Kubernetes и докладване за грешки.
Последователността на стъпките за инсталиране на Copper можете да намерите в .
2.0.1 — най-новото издание на този инструмент към момента на писане на оригиналната статия.
Както и config-lint, Copper няма вградени тестове. Нека напишем един. Нека той провери дали deployment-ите използват контейнерни образи само от доверени хранилища като my-company.com.
Създайте файл check_image_repo.js със следното съдържание:
$$.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)
}
});
}
});Сега, за да проверим нашия манифест base-valid.yaml, използвайте командата copper validate:
$ copper validate --in=base-valid.yaml --validator=check_image_tag.js
Проверка no_company_repo не успя с тежест 1, тъй като изображението http-echo не е от хранилището my-company.comРазбираемо е, че с помощта на copper могат да се провеждат по-сложни тестове – например, да се проверяват домейн имена в манифестите Ingress или да се отхвърлят pod’и, работещи в привилегирован режим.
В Copper са вградени различни служебни функции:
DockerImageчете указан файл за вход и създава обект с следните атрибути:name— име на образа,tag— етикет на образа,registry— регистър на образи,registry_url— протокол (https://) и регистър на образи,fqin— пълното местоположение на образа.
- Функция
findByNameпомага за откриване на ресурс по даден тип (kind) и име (name) от входния файл. - Функция
findByLabelsпомага за откриване на ресурс по зададен тип (kind) и етикети (labels).
С всички налични служебни функции можете да се запознаете .
По подразбиране той зарежда целия входен YAML файл в променлива $$ и го прави достъпен за скриптове (познат метод за тези, които имат опит с jQuery).
Основното предимство на Copper е очевидно: не е нужно да усвоявате специализиран език и можете да използвате различни възможности на JavaScript за създаване на собствени тестове, като интерполация на низове, функции и т.н.
Трябва също да се отбележи, че текущата версия на Copper работи с версия ES5 на JavaScript движка, а не с ES6.
Подробности са налични на .
Въпреки това, ако не особено обичате JavaScript и предпочитате език, специално предназначен за написване на запитвания и описване на политики, трябва да обърнете внимание на conftest.
5. Conftest
Conftest е фреймворк за проверка на конфигурационни данни. Подходящ е и за тестване/верификация на манифести Kubernetes. Тестовете се описват с помощта на специализирания език за запитвания .
Инсталирането на conftest може да стане с помощта на , посочени на сайта на проекта.
Към момента на написване на оригиналната статия, последната налична версия беше 0.18.2.
Сходно с config-lint и copper, conftest не предлага никакви вградени тестове. Нека да го изпробваме и да напишем собствена политика. Както в предходните примери, ще проверим дали образите на контейнерите идват от надежден източник.
Създайте директория conftest-checks, а в нея – файл с име check_image_registry.rego със следното съдържание:
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])
}Сега нека тестваме base-valid.yaml чрез 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Тестът не успя, тъй като образите идват от ненадежден източник.
В Rego файла задаваме блок deny. Неговата истинност се разглежда като нарушение. Ако блоковете deny са няколко, conftest ги проверява независимо един от друг, и истинността на който и да е от блоковете се тълкува като нарушение.
В допълнение на стандартния изход, conftest поддържа JSON, TAP и табличен формат — изключително полезна възможност, ако искате да вградите отчетите в съществуващия CI пайплайн. Форматът може да се зададе с флага --output.
За улесняване на отстраняването на грешки в политиките в conftest има флаг --trace. Той извежда трасировка на начина, по който conftest парсира зададените файлове с политики.
Политиките на conftest могат да се публикуват и споделят в OCI регистри (Open Container Initiative) под формата на артефакти.
Отбори push и pull позволяват публикуването на артефакт или извличането на съществуващ артефакт от отдалечен регистър. Нека опитаме да публикуваме създадената от нас политика в локалния Docker регистър с помощта на conftest push.
Стартирайте локален Docker регистър:
$ docker run -it --rm -p 5000:5000 registryВ друг терминал преминете в създадената по-рано директория conftest-checks и изпълнете следната команда:
$ conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latestАко командата е успешна, ще видите съобщение от следен тип:
2020/06/10 14:25:43 pushed bundle with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609cСега създайте времена директория и изпълнете команда в нея conftest pull. Тя ще изтегли пакетът, създаден от предходната команда:
$ cd $(mktemp -d)
$ conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latestВ временната директория ще се появи поддиректория policy, съдържаща нашия файл с политика:
$ tree
.
└── policy
└── check_image_registry.regoТестовете могат да се провеждат директно от репозитория:
$ 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За съжаление, DockerHub в момента не се поддържа. Затова можете да смятате, че вие имате късмет, ако използвате (ACR) или собствен регистър.
Форматът на артефактите е същият като на (OPA), което позволява използването на conftest за изпълнение на тестове от съществуващи пакети OPA.
Повече за споделянето на политики и други характеристики на conftest можете да намерите на .
6. Polaris
Последният инструмент, който ще разгледаме в тази статия, е . (Неговото предишно анонсиране — бел. прев.)
Polaris може да бъде инсталиран в клъстер или да се използва в режим на команден ред. Както вече се досещате, той позволява статичен анализ на манифестите на Kubernetes.
При работа в режим на команден ред са налични вградени тестове, обхващащи области като сигурност и най-добри практики (по аналогия с kube-score). Освен това, можете да създавате собствени тестове (както в config-lint, copper и conftest).
С други думи, Polaris съчетава предимствата на двата вида инструменти: с вградени и персонализирани тестове.
За инсталиране на Polaris в режим на команден ред, използвайте .
Към момента на написване на оригиналната статия е налична версия 1.0.3.
След завършване на инсталацията можете да стартирате polaris на манифест base-valid.yaml с помощта на следната команда:
$ polaris audit --audit-path base-valid.yamlТя ще изведе ред в JSON формат с подробности за извършените тестове и техните резултати. Изходът ще има следната структура:
{
"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": [
/* дълъг списък */
]
}Пълният изход е наличен .
Както kube-score, Polaris идентифицира проблеми в области, където манифестът не отговаря на най-добрите практики:
- Липсват проверки за здравето на подовете.
- Не са зададени тагове за контейнерните образи.
- Контейнерът работи с root права.
- Не са зададени заявки и лимити за памет и CPU.
На всеки тест, в зависимост от резултата му, се присвоява степен на критичност: warning или danger. За повече информация относно наличните вградени тестове, обърнете се към .
Ако подробности не са нужни, можете да зададете флага --format score. В този случай Polaris ще изведе число в диапазона от 1 до 100 — score (т.е. оценка):
$ polaris audit --audit-path test-data/base-valid.yaml --format score
68Колкото оценката е по-близо до 100, толкова по-висока е степента на съответствие. Ако проверите exit-кода на командата polaris audit, ще се окаже, че той е равен на 0.
Да накарате polaris audit да завършва с ненулев код може да стане с помощта на два флага:
- FPIPE
--set-exit-code-below-scoreприема аргументи с прагово значение в диапазона 1-100. В такъв случай, командата ще завърши с exit-код 4, ако оценката е под прага. Това е много полезно, когато имате определено прагово значение (да кажем, 75) и искате да получите предупреждение, ако оценката падне под него. - FPIPE
--set-exit-code-on-dangerще доведе до завършване на командата с код 3, ако един от тестовете за опасност е неуспешен.
Сега нека да опитаме да създадем потребителски тест, който проверява дали образът идва от надежден репозиторий. Потребителските тестове се задават във формат YAML, а самият тест се описва с помощта на JSON Schema.
Следният фрагмент от YAML-код описва нов тест, наречен checkImageRepo:
checkImageRepo:
successMessage: Регистърът на изображенията е валиден
failureMessage: Регистърът на изображенията не е валиден
category: Изображения
target: Контейнер
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$Нека да го разгледаме по-подробно:
successMessage— тази строка ще бъде изведена, ако тестът завърши успешно;failureMessage— това съобщение ще се покаже в случай на неуспех;category— посочва една от категориите:Изображения,Здравословни проверки,Сигурност,НетворкингиРесурси;target— определя върху какъв тип обект (spec) се прилага тестът. Възможни стойности:Контейнер,ПодилиКонтролер;- Самият тест се задава в обект
schemaс помощта на JSON schema. В този тест ключовата думаpatternсе използва за сравнението на източника на образа с изискванията.
За да стартирате изброения по-горе тест, е необходимо да създадете следната конфигурация Polaris:
checks:
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Регистърът на изображенията е валиден
failureMessage: Регистърът на изображенията не е валиден
category: Изображения
target: Контейнер
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$(polaris-conf.yaml)
Нека разгледаме файла:
- В полето
checksопределят тестовете и техните нива на критичност. Понеже е желателно да получим предупреждение, когато образ се взима от ненадежден източник, задаваме тук нивоdanger. - Самият тест
checkImageRepoпосле се регистрира в обектаcustomChecks.
Запазете файла като custom_check.yaml. Сега може да стартирате polaris audit с YAML манифест, който изисква проверка.
Тествайте нашия манифест base-valid.yaml:
$ polaris audit --config custom_check.yaml --audit-path base-valid.yamlЕкип polaris audit изпълни единствено потребителския тест, зададен по-горе, и той не беше успешен.
Ако коригирате образа на my-company.com/http-echo:1.0, Polaris ще завърши успешно. Манифест с измененията вече има в , така че можете да проверите предишната команда в манифеста image-valid-mycompany.yaml.
Сега възниква въпросът: как да стартирате вградени тестове заедно с потребителските? Лесно! Просто трябва да добавите идентификаторите на вградените тестове в конфигурационния файл. В резултат той ще придобие следния вид:
checks:
cpuRequestsMissing: warning
cpuLimitsMissing: warning
# Други вградени проверки..
# ..
# потребителски проверки
checkImageRepo: danger # !!!
customChecks:
checkImageRepo: # !!!
successMessage: Регистърът на изображение е валиден
failureMessage: Регистърът на изображение не е валиден
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)
Примерен пълен конфигурационен файл е наличен .
Провери манифеста base-valid.yaml, използвайки вградени и потребителски тестове, може да се направи с командата:
$ polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yamlPolaris допълва вградените тестове с потребителски, обединявайки най-доброто от двата свята.
От друга страна, невъзможността да се използват по-мощни езици, като Rego или JavaScript, може да бъде ограничаващ фактор, пречещ на създаването на по-изтънчени тестове.
Допълнителна информация за Polaris е налична на .
Резюме
Въпреки че съществуват много инструменти за проверка и оценка на YAML файлове на Kubernetes, важно е да имате ясна представа за това как тестовете ще бъдат проектирани и изпълнени.
Например, ако вземем манифестите на Kubernetes, преминаващи през пайплайна, kubeval може да бъде първата стъпка в такъв пайплайн. Той би наблюдавал дали определенията на обектите отговарят на схемата на API на Kubernetes.
След завършването на подобна проверка може да се премине към по-изтънчени тестове, като съответствие на стандартни най-добри практики и специфични политики. И тук биха послужили kube-score и Polaris.
На тези, които имат сложни изисквания и необходимост от детайлно настройване на тестовете, биха им подхождали copper, config-lint и conftest..
Conftest и config-lint използват YAML за задаване на потребителски тестове, а copper предоставя достъп до пълен език за програмиране, което го прави доста привлекателен избор.
От друга страна, струва ли си да се възползвате от един от тези инструменти и следователно да създадете всички тестове ръчно, или е по-добре да изберете Polaris и да допишете само това, което е нужно? Няма еднозначен отговор на този въпрос.
По-долу таблицата съдържа кратко описание на всеки инструмент:
Инструмент
Предназначение
Недостатъци
Потребителски тестове
kubeval
Проверява YAML манифести за съответствие с определена версия на API схемата
Не може да работи с CRD
Не
kube-score
Анализира YAML манифести за съответствие с най-добрите практики
Няма възможност да изберете собствена версия на Kubernetes API за проверка на ресурсите
Не
медна
Общ фреймворк за създаване на собствени JavaScript тестове за YAML манифести
Няма вградени тестове. Оскъдна документация
Да
config-lint
Общ фреймворк за създаване на тестове на предметно-ориентиран език, вграден в YAML. Поддържа различни формати на конфигурации (напр. Terraform)
Няма готови тестове. Възможно е вградените assert-и и функции да не са достатъчни
Да
conftest
Фреймворк за създаване на собствени тестове на Rego (специализиран език за запитвания). Позволява споделяне на политики чрез OCI пакети
Няма вградени тестове. Трябва да се запознае с Rego. Docker Hub не се поддържа при публикуване на политики
Да
Polaris
Анализира YAML манифести за съответствие с общи най-добри практики. Позволява създаване на собствени тестове с помощта на JSON Schema
Възможностите за тестове, основани на JSON Schema, може да не са достатъчни
Да
Тъй като тези инструменти не зависят от достъп до Kubernetes клъстера, те са лесни за инсталиране. Позволяват филтриране на входните файлове и предоставят бърза обратна връзка на авторите на pull request-ове в проектите.
P.S. от преводача
Прочетете също в нашия блог:
- «»;
- «»;
- «».
Източник: habr.com
