Это вторая и заключительная часть знакомства с доступными сегодня Open Source-утилитами для организации хаос-инжиниринга в Kubernetes-кластерах. В первой статье было вкратце рассказано о появлении самой дисциплины — chaos engineering, — а также рассмотрены kube-monkey, chaoskube и Chaos Mesh. Теперь этот список пополнится обзором Litmus Chaos, Chaos Toolkit, мини-подборкой из хаос-игр и перечислением пяти других вариантов, заслуживающих внимания инженеров, заинтересованных в разовой или постоянной проверке своей инфраструктуры на устойчивость.
NB: Нумерацию проектов продолжим в соответствии с первой частью.
4. Litmus Chaos
- GitHub: https://github.com/litmuschaos/litmus
- Звёзды / контрибьюторы: ~1200 / 100+
- Язык: TypeScript
Litmus — еще один оператор, который создает, управляет и наблюдает за хаосом в Kubernetes. Делает он это, используя три типа Custom Resources:
-
ChaosExperiment
описывает сам эксперимент, действия и их расписание; -
ChaosEngine
объединяет приложение или Kubernetes-узел с конкретнымChaosExperiment
; -
ChaosResult
— ресурс, который хранит результаты эксперимента и в дальнейшем экспортируется оператором как метрика для Prometheus.
Наглядная схема, как работает Litmus:
Теперь же о практике. Установим оператор, следуя документации:
$ kubectl apply -f https://litmuschaos.github.io/litmus/litmus-operator-v1.9.0.yaml
$ kubectl -n litmus get po
NAME READY STATUS RESTARTS AGE
chaos-operator-ce-797875d477-b4cwx 1/1 Running 0 88s
Проверим наличие CRD:
$ kubectl get crds | grep chaos
chaosengines.litmuschaos.io 2020-10-27T08:58:39Z
chaosexperiments.litmuschaos.io 2020-10-27T08:58:39Z
chaosresults.litmuschaos.io 2020-10-27T08:58:39Z
В специальном хранилище под названием ChaosHub уже есть большое количество готовых экспериментов. Создадим отдельный namespace для экспериментов и последуем дальше за руководством, развернув эксперименты с хаба:
$ kubectl create ns nginx
$ kubectl apply -f https://hub.litmuschaos.io/api/chaos/1.9.0?file=charts/generic/experiments.yaml -n nginx
chaosexperiment.litmuschaos.io/pod-network-duplication created
chaosexperiment.litmuschaos.io/node-drain created
chaosexperiment.litmuschaos.io/node-io-stress created
chaosexperiment.litmuschaos.io/disk-fill created
chaosexperiment.litmuschaos.io/k8-pod-delete created
chaosexperiment.litmuschaos.io/node-taint created
chaosexperiment.litmuschaos.io/pod-autoscaler created
chaosexperiment.litmuschaos.io/pod-cpu-hog created
chaosexperiment.litmuschaos.io/pod-memory-hog created
chaosexperiment.litmuschaos.io/pod-network-corruption created
chaosexperiment.litmuschaos.io/pod-delete created
chaosexperiment.litmuschaos.io/pod-network-loss created
chaosexperiment.litmuschaos.io/disk-loss created
chaosexperiment.litmuschaos.io/k8-pod-delete unchanged
chaosexperiment.litmuschaos.io/pod-io-stress created
chaosexperiment.litmuschaos.io/k8-service-kill created
chaosexperiment.litmuschaos.io/pod-network-latency created
chaosexperiment.litmuschaos.io/k8-pod-delete unchanged
chaosexperiment.litmuschaos.io/k8-pod-delete unchanged
chaosexperiment.litmuschaos.io/node-cpu-hog created
chaosexperiment.litmuschaos.io/docker-service-kill created
chaosexperiment.litmuschaos.io/kubelet-service-kill created
chaosexperiment.litmuschaos.io/k8-pod-delete unchanged
chaosexperiment.litmuschaos.io/node-memory-hog created
chaosexperiment.litmuschaos.io/k8-pod-delete configured
chaosexperiment.litmuschaos.io/container-kill created
В этом весьма обширном YAML-файле содержится набор экспериментов, один из которых дублирует пакеты, приходящие в pod, другой — опустошает узел с приложением, третий — придавливает диск того же узла и так далее. Все эксперименты — ресурсы, находящиеся в пространстве имен (т.е. namespaced).
Дальнейшие шаги из того же руководства — добавим service account в наш namespace и сделаем более расширенный список прав на ресурсы (мы хотим больше хаоса!):
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: chaos-spawn
namespace: nginx
labels:
name: chaos-spawn
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: chaos-spawn
namespace: nginx
labels:
name: chaos-spawn
rules:
- apiGroups: ["","litmuschaos.io","batch","apps"]
resources: ["nodes","pods","deployments","pods/log","pods/exec","events","jobs","chaosengines","chaosexperiments","chaosresults"]
verbs: ["create","list","get","patch","update","delete","deletecollection"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: chaos-spawn
namespace: nginx
labels:
name: chaos-spawn
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: chaos-spawn
subjects:
- kind: ServiceAccount
name: chaos-spawn
namespace: nginx
$ kubectl apply -f rbac.yaml
serviceaccount/pod-delete-sa created
role.rbac.authorization.k8s.io/pod-delete-sa created
rolebinding.rbac.authorization.k8s.io/pod-delete-sa created
В качестве жертвы попробуем:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Убедимся, что этот Deployment выкатился:
$ kubectl -n nginx get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-85ff79dd56-9bcnn 1/1 Running 0 7s
nginx-deployment-85ff79dd56-lq8r5 1/1 Running 0 7s
nginx-deployment-85ff79dd56-pjwvd 1/1 Running 0 7s
Для ограничения радиуса поражения используется аннотирование ресурса:
$ kubectl -n nginx annotate deploy/nginx-deployment litmuschaos.io/chaos="true"
deployment.apps/nginx-deployment annotated
Следуя документации, делаем
ChaosEngine
(напомню, что это CR, который объединяет приложение с хаос-экспериментами):apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: nginx-chaos
namespace: nginx
spec:
appinfo:
appns: 'nginx'
applabel: 'app=nginx'
appkind: 'deployment'
annotationCheck: 'true'
engineState: 'active'
auxiliaryAppInfo: ''
chaosServiceAccount: chaos-spawn
monitoring: false
experiments:
- name: pod-delete
spec:
components:
env:
# set chaos duration (in sec) as desired
- name: TOTAL_CHAOS_DURATION
value: '30'
- name: FORCE
value: 'false'
- name: pod-cpu-hog
spec:
components:
env:
- name: CPU_CORES
value: '4'
- name: TARGET_CONTAINER
value: 'nginx'
- name: pod-memory-hog
spec:
components:
env:
- name: TARGET_CONTAINER
value: 'nginx'
Эксперименты в стандартном варианте этого ресурса показались мне нежным поглаживанием: хочется попробовать что-то более интересное, поэтому мы убьём приложение и немного нагрузим память и CPU.
Отдельно отмечу отсутствие строчки
jobCleanUpPolicy: 'delete'
в описании ChaosEngine
— она нужна, чтобы оператор не удалял «хаосита» после работы и мы увидели, что происходит:$ kubectl -n nginx get po
NAME READY STATUS RESTARTS AGE
nginx-chaos-runner 0/1 Completed 0 4m28s
nginx-deployment-85ff79dd56-lq8r5 1/1 Running 0 32m
nginx-deployment-85ff79dd56-nt9n9 1/1 Running 0 3m3s
nginx-deployment-85ff79dd56-ptt54 1/1 Running 0 3m32s
Итак, «хаосит» приводит друзей:
$ kubectl -n nginx get po
NAME READY STATUS RESTARTS AGE
nginx-chaos-runner 1/1 Running 0 15s
nginx-deployment-85ff79dd56-2kjgb 1/1 Running 0 2m18s
nginx-deployment-85ff79dd56-gmhn8 1/1 Running 0 2m34s
nginx-deployment-85ff79dd56-vt4jx 0/1 ContainerCreating 0 1s
nginx-deployment-85ff79dd56-wmfdx 1/1 Terminating 0 2m7s
pod-delete-vsxwf0-p9rt9 1/1 Running 0 7s
$ kubectl -n nginx get po
NAME READY STATUS RESTARTS AGE
nginx-chaos-runner 1/1 Running 0 87s
nginx-deployment-85ff79dd56-2kjgb 1/1 Running 0 3m30s
nginx-deployment-85ff79dd56-8nbll 1/1 Running 0 51s
nginx-deployment-85ff79dd56-gmhn8 1/1 Running 0 3m46s
pod-cpu-hog-lqds5k-d8hg6 1/1 Running 0 17s
Фрагмент логов выжигателя CPU:
time="2020-11-09T19:48:06Z" level=info msg="[Chaos]:Number of pods targeted: 1"
time="2020-11-09T19:48:06Z" level=info msg="[Chaos]: The Target application details" container=nginx Pod=nginx-deployment-85ff79dd56-8nbll CPU CORE=4
time="2020-11-09T19:48:06Z" level=info msg="[Chaos]:Waiting for: 60s"
Однако наш друг Prometheus говорит, что четыре обещанных ядра этот «свинтус» (hog) съесть не смог:
Причина осталось неизвестной, но может быть, мы когда-нибудь исследуем эту (по умолчанию используется https://github.com/alexei-led/pumba) или другую реализацию контейнерной хаос-обезьяны…
Что у нас происходит?
$ kubectl -n nginx get po
NAME READY STATUS RESTARTS AGE
nginx-chaos-runner 1/1 Running 0 2m41s
nginx-deployment-85ff79dd56-2kjgb 1/1 Running 0 4m44s
nginx-deployment-85ff79dd56-8nbll 1/1 Running 0 2m5s
nginx-deployment-85ff79dd56-gmhn8 1/1 Running 0 5m
pod-memory-hog-r3ngl5-kjhl7 1/1 Running 0 5s
Фрагмент логов «кабана», отъедающего память:
time="2020-11-09T19:49:33Z" level=info msg="[Chaos]:Number of pods targeted: 1"
time="2020-11-09T19:49:33Z" level=info msg="[Chaos]: The Target application details" container=nginx Pod=nginx-deployment-85ff79dd56-8nbll Memory Consumption(MB)=500
time="2020-11-09T19:49:33Z" level=info msg="[Chaos]:Waiting for: 60s"
time="2020-11-09T19:49:33Z" level=info msg="The memory consumption is: 500"
С памятью всё точно:
На этом эксперимент закончен:
$ kubectl -n nginx get po
NAME READY STATUS RESTARTS AGE
nginx-chaos-runner 0/1 Completed 0 4m20s
nginx-deployment-85ff79dd56-2kjgb 1/1 Running 0 6m23s
nginx-deployment-85ff79dd56-8nbll 1/1 Running 0 3m44s
nginx-deployment-85ff79dd56-gmhn8 1/1 Running 0 6m39s
А вот и официальные результаты вскрытия:
$ kubectl -n nginx get chaosresults.litmuschaos.io
NAME AGE
nginx-chaos-pod-cpu-hog 8m48s
nginx-chaos-pod-delete 9m49s
nginx-chaos-pod-memory-hog 7m21s
Вердикт для этого примера — «Pass»:
$ kubectl -n nginx get chaosresults.litmuschaos.io
NAME AGE
nginx-chaos-pod-cpu-hog 8m48s
nginx-chaos-pod-delete 9m49s
nginx-chaos-pod-memory-hog 7m21s
$ kubectl -n nginx describe chaosresults.litmuschaos.io nginx-chaos-pod-delete
Name: nginx-chaos-pod-delete
Namespace: nginx
Labels: app.kubernetes.io/component=experiment-job
app.kubernetes.io/part-of=litmus
app.kubernetes.io/version=1.9.1
chaosUID=26c21578-2470-4f08-957f-94267cadc4ff
controller-uid=7ef7d1c0-79c8-4e21-acfc-711b6b83f918
job-name=pod-delete-vsxwf0
name=nginx-chaos-pod-delete
Annotations: <none>
API Version: litmuschaos.io/v1alpha1
Kind: ChaosResult
Metadata:
Creation Timestamp: 2020-11-09T19:47:01Z
Generation: 2
Resource Version: 17209743
Self Link: /apis/litmuschaos.io/v1alpha1/namespaces/nginx/chaosresults/nginx-chaos-pod-delete
UID: 8e60299b-1751-42a3-a22b-29f5a64d86b5
Spec:
Engine: nginx-chaos
Experiment: pod-delete
Status:
Experimentstatus:
Fail Step: N/A
Phase: Completed
Verdict: Pass
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Awaited 10m pod-delete-vsxwf0-p9rt9 experiment: pod-delete, Result: Awaited
Normal Pass 9m42s pod-delete-vsxwf0-p9rt9 experiment: pod-delete, Result: Pass
Если этого показалось, то знайте, что в комплекте Litmus — прекрасное руководство, как замониторить хаос-эксперименты полным набором Prometheus + Grafana с имеющимися экспортерами и панелями. При наличии такового можно добавить всё это в уже имеющийся в кластере комплект, но потребуются некоторое время, напильник и рубанок.
Говоря про Litmus в целом, это не самый простой в освоении инструмент, но при внимательном чтении документации всё должно получиться. Кажется, проект предлагает
ChaosResults
, и логи у всех запускаемых pod'ов (они действительно подробны).P.S. Именно этот проект стал инициатором недавнего появления группы Kubernetes Chaos Engineering Meetup Group.
5. Chaos Toolkit
- GitHub: https://github.com/chaostoolkit/chaostoolkit/
- Звёзды / контрибьюторы: ~1100 / 10
- Язык: Python
Это набор инструментов на Python, с помощью которых можно разрабатывать Open API для проведения хаос-экспериментов. У него есть большое количество расширений для разных облачных провайдеров и окружений, в числе которых — интересный нам chaostoolkit-kubernetes (здесь уже GitHub-звёзд заметно меньше: ~150).
Установить Chaos Toolkit Operator для Kubernetes можно с помощью Kustomize (https://docs.chaostoolkit.org/deployment/k8s/operator/):
$ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
$ ./kustomize build kubernetes-crd/manifests/overlays/generic-rbac | kubectl apply -f
У родительского проекта имеется очень неплохая документация с примерами (https://github.com/chaostoolkit/chaostoolkit-tutorials).
Однако в целом это не конечное приложение для тех, кто эксплуатирует Kubernetes (или другую инфраструктуру), а именно набор инструментов для разработчика на Python, с продуманным подходом и большим количеством возможностей.
Также у проекта был раньше активен репозиторий ChaosHub, но сейчас он оказался в архиве (https://github.com/chaostoolkit/chaoshub-archive):
6. KubeInvaders (и собратья)
- GitHub: https://github.com/lucky-sideburn/KubeInvaders
- Звёзды / контрибьюторы: 600+ / <10
- Язык: JavaScript
Обзор завершит очень необычный инструмент, потому что он сделан в виде… игры!
Итак, скачиваем и устанавливаем чарт (указывая хост для Ingress и whitelist со списком пространств имен, разрешённых для работы приложения):
$ git clone https://github.com/lucky-sideburn/KubeInvaders.git
$ kubectl create namespace kubeinvaders
$ helm install --set-string target_namespace="test-monkeys" --namespace kubeinvaders --set ingress.hostName=invaders.kube.test.io --name kubeinvaders .
После этого достаточно зайти по указанному URL, чтобы увидеть впечатляющий способ убивать pod'ы:
Да! Это легендарная видеоигра Space Invaders. Pod'ы в ней выступают как инопланетные захватчики, а мы должны спасти Землю! (Ну, или просто потестировать, убивая pod'ы вручную или включив автопилот…)
Есть возможность усложнить игру:
Всё настраивается очень просто, есть клиенты для MacOS и Linux. В целом же, пусть с точки зрения функциональных возможностей приложение не так уж богато, сам процесс проходит гораздо веселее.
Как выяснилось, это далеко не единственный способ сделать хаос-инжиниринг веселым. Еще большую популярность среди желающих «поиграть в хаос» в Kubernetes (1200+ звёзд на GitHub) уже получил проект Kube DOOM, из названия которого понятна и суть: убивать pod'ы можно в старом добром шутере.
А чтобы список хаос-игр с Kubernetes был ещё более полным и разнообразным, закончим эту мини-категорию ссылкой на Cheeky Monkey.
7. Другие
Среди других проектов, которые по разным причинам не были включены в список выше, выделю:
- PowerfulSeal — за этим «могучим тюленем» с ~1400 GitHub-звездами скрывается весьма продвинутая Python-утилита для внедрения разнообразных проблем в Kubernetes-кластеры. Для проведения хаос-экспериментов имеет несколько режимов работы: путем определения политик в YAML и их автономного запуска, в интерактивном режиме («ломаю всё в ручном режиме и смотрю на последствия») или через навешивание лейблов на pod'ы, которые нужно убивать. Поддерживаются разные облачные провайдеры (AWS, Azure, GCP, OpenStack) и локальные окружения. Доступны метрики для Prometheus и Datadog.
- Pod-reaper — убиватель pod'ов с гибко настраиваемым набором cron'ов. Увидеть основные возможности можно в этом продвинутом примере. Написан на Go, не обновлялся с мая этого года.
- Kube-entropy — просто приложение для тестирования веб-сервисов в Kubernetes путем проверки изменений в HTTP-статусе для выбранных ingress’ов. Тоже написан на Go и тоже не обновлялся с мая этого года.
- Fabric8 Chaos Monkey — реализация chaos monkey для микросервисной платформы с открытым кодом Fabric8 (на базе Docker, Kubernetes и Jenkins). Устанавливается прямо в её веб-интерфейсе.
- Kubernetes от Gremlin — это уже не Open Source, а часть коммерческой услуги от известных специалистов в области chaos engineering. Предлагает всеобъемлющую проверку Kubernetes-кластеров на надежность и отказоустойчивость. Есть ограниченный бесплатный тариф.
Заключение
Уже доступен достаточно широкий спектр решений для хаос-экспериментов в Kubernetes: от простых «убивалок» до готовых операторов с разнообразными способами нанести вред всем окружениям и платформы для разработчика собственных хаос-экспериментов. Каждый сможет найти для себя что-то подходящее.
Я бы выделил два варианта использования инструмента для хаос-инжиниринга (в K8s):
- Требуется несложное и контролируемое тестирование приложения в конкретном пространстве имён, иногда «задевая» инфраструктурные. Для этого будет достаточно простых вариантов — мы бы выбрали kube-monkey, который отлично показывает себя в таком применении.
- Необходимо всесторонне и постоянно тестировать всё окружение вместе с инфраструктурой, для чего мы готовы потратить время и ресурсы на подготовку и внедрение. Тогда нашим выбором будет либо Chaos Mesh (весьма простой в освоении), либо Litmus (более сложный, но не менее удобный).
Вредите, разрушайте, ломайте, наносите добро — делайте свои приложения и инфраструктуры устойчивыми к любым невзгодам!
P.S.
Читайте также в нашем блоге:
- «Обзор инструментов для chaos engineering в Kubernetes. Часть 1: kube-monkey, chaoskube, Chaos Mesh»;
- «Chaos Engineering: искусство умышленного разрушения. Часть 1» (про концепцию chaos engineering и как он помогает находить/исправлять проблемы до того, как они приведут к сбоям production);
- «Chaos Engineering: искусство умышленного разрушения. Часть 2» (как chaos engineering способствует позитивным культурным изменениям внутри организаций);
- «Chaos Engineering: искусство умышленного разрушения. Часть 3» (практика chaos engineering с внесением неисправностей и существующими для этого инструментами).