company_banner

Обзор инструментов для 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 (1200+ звёзд на 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.


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

    Флант
    DevOps-as-a-Service, Kubernetes, обслуживание 24×7

    Комментарии 2

      +1
      VMware Mangle тоже кое-чего умеет по K8s. Бесплатен и в целом open source.
        0
        Не знали о таком, спасибо!

        It is designed to introduce faults with very little pre-configuration and can support any infrastructure that you might have including K8S, Docker, vCenter or any Remote Machine with ssh enabled.

        Вот ссылка для тех, кому интересно: vmware.github.io/mangle

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое