Обзор инструментов для chaos engineering в Kubernetes. Часть 2: Litmus Chaos, Chaos Toolkit, KubeInvaders и другие

от автора

Это вторая и заключительная часть знакомства с доступными сегодня Open Source-утилитами для организации хаос-инжиниринга в Kubernetes-кластерах. В первой статье было вкратце рассказано о появлении самой дисциплины — chaos engineering, — а также рассмотрены kube-monkey, chaoskube и Chaos Mesh. Теперь этот список пополнится обзором Litmus Chaos, Chaos Toolkit, мини-подборкой из хаос-игр и перечислением пяти других вариантов, заслуживающих внимания инженеров, заинтересованных в разовой или постоянной проверке своей инфраструктуры на устойчивость.

NB: Нумерацию проектов продолжим в соответствии с первой частью.

4. Litmus Chaos

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

Это набор инструментов на 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 (и собратья)

Обзор завершит очень необычный инструмент, потому что он сделан в виде… игры!
Итак, скачиваем и устанавливаем чарт (указывая хост для 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 (1000+ звёзд на GitHub) уже получил проект Kube DOOM, из названия которого понятна и суть: убивать pod’ы можно в старом добром шутере.

А чтобы список хаос-игр с Kubernetes был ещё более полным и разнообразным, закончим эту мини-категорию ссылкой на Cheeky Monkey.

7. Другие

Среди других проектов, которые по разным причинам не были включены в список выше, выделю:

  1. PowerfulSeal — за этим «могучим тюленем» с ~1400 GitHub-звездами скрывается весьма продвинутая Python-утилита для внедрения разнообразных проблем в Kubernetes-кластеры. Для проведения хаос-экспериментов имеет несколько режимов работы: путем определения политик в YAML и их автономного запуска, в интерактивном режиме («ломаю всё в ручном режиме и смотрю на последствия») или через навешивание лейблов на pod’ы, которые нужно убивать. Поддерживаются разные облачные провайдеры (AWS, Azure, GCP, OpenStack) и локальные окружения. Доступны метрики для Prometheus и Datadog.
  2. Pod-reaper — убиватель pod’ов с гибко настраиваемым набором cron’ов. Увидеть основные возможности можно в этом продвинутом примере. Написан на Go, не обновлялся с мая этого года.
  3. Kube-entropy — просто приложение для тестирования веб-сервисов в Kubernetes путем проверки изменений в HTTP-статусе для выбранных ingress’ов. Тоже написан на Go и тоже не обновлялся с мая этого года.
  4. Fabric8 Chaos Monkey — реализация chaos monkey для микросервисной платформы с открытым кодом Fabric8 (на базе Docker, Kubernetes и Jenkins). Устанавливается прямо в её веб-интерфейсе.
  5. Kubernetes от Gremlin — это уже не Open Source, а часть коммерческой услуги от известных специалистов в области chaos engineering. Предлагает всеобъемлющую проверку Kubernetes-кластеров на надежность и отказоустойчивость. Есть ограниченный бесплатный тариф.

Заключение

Уже доступен достаточно широкий спектр решений для хаос-экспериментов в Kubernetes: от простых «убивалок» до готовых операторов с разнообразными способами нанести вред всем окружениям и платформы для разработчика собственных хаос-экспериментов. Каждый сможет найти для себя что-то подходящее.

Я бы выделил два варианта использования инструмента для хаос-инжиниринга (в K8s):

  1. Требуется несложное и контролируемое тестирование приложения в конкретном пространстве имён, иногда «задевая» инфраструктурные. Для этого будет достаточно простых вариантов — мы бы выбрали kube-monkey, который отлично показывает себя в таком применении.
  2. Необходимо всесторонне и постоянно тестировать всё окружение вместе с инфраструктурой, для чего мы готовы потратить время и ресурсы на подготовку и внедрение. Тогда нашим выбором будет либо Chaos Mesh (весьма простой в освоении), либо Litmus (более сложный, но не менее удобный).

Вредите, разрушайте, ломайте, наносите добро — делайте свои приложения и инфраструктуры устойчивыми к любым невзгодам!

P.S.

Читайте также в нашем блоге:

ссылка на оригинал статьи https://habr.com/ru/company/flant/blog/529062/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *