Хаос на практике: зачем ломать production?
Всем привет! Меня зовут Олег Сидоренков, и я отвечаю за IT-инфраструктуру в компании ДомКлик.
Ломать — не строить! Так обычно говорят люди, пытаясь показать деструктивный процесс простым, не требующим усилий. Сегодня я хочу вам рассказать о пользе Chaos Engineering (хаос-инженерия), зачем это нужно и как подойти к своему первому в жизни эксперименту.
Хаос-инженерия — это дисциплина проведения экспериментов в распределенных информационных системах с целью укрепления уверенности в способности системы противостоять турбулентным условиям в эксплуатационной среде.
Развитие этой дисциплины началось в 2010 году, когда компания Netflix выпустила продукт под названием Chaos Monkey, который случайным образом завершает работу виртуальных машин и контейнеров, работающих внутри производственной среды. Это было связано с переходом Netflix на облачную инфраструктуру от Amazon, и команда хотела убедиться, что при потере инстанса AWS сервис не пострадает.
Представим, что у вас большая, распределенная инфраструктура. С чего начинать эксперимент? На какие этапы разбить цикл работ?
1. План работ
Для начала постарайтесь разбить свою инфраструктуру на слои.
Начинайте составлять план эксперимента с самых очевидных для вас мест, например, с тех компонентов инфраструктуры, в которых были сбои в эксплуатации. Затем переходите к элементам, которые были введены в production не так давно и уверенности в их безотказности нет. Также важно понимать, что нет необходимости проводить эксперимент, в результате которого вы заведомо уверены, например:
У вас есть сервис, который работает с БД. Архитектура изначально правильная, кластер из двух серверов: master и hot standby. Вы знаете, что с недоступной базой сервис работать не будет. Вы отключаете оба хоста и ставите галочку в чек-листе, что сервис действительно не работает.
Так делать не надо. Здесь вы ничего нового для себя не узнаете, разве что проверите свой кластер мониторинга. Цель планирования — узнать новые сценарии, при которых сервис в процессе эксплуатации может деградировать. Сам план может быть в виде таблице, рассмотрим на примере с БД:
Сервис | Кластер БД Postgres |
Сценарии отказа | Выход из строя первичного инстанса. |
Имитация сбоя | 1. Отключение сервера Master. 2. Отключение сетевого интерфейса. 3. Заполнение файловой системы на 100%. |
Ожидаемый результат | 1. Срабатывание системы мониторинга. 2. Сработал фейловер. Hot Standby успешно запромоутился до Primary не более чем за 1 минуту. 3. Коннекты приложения подцепились к новому Master-инстансу БД не более чем за 5 минут. |
Фактический результат | |
Команда | OPS + DEV |
Как можно заметить, всё начинается с простых ситуаций, которые могут часто встречаться на практике. Фактический результат заполняется по итогу эксперимента. Если всё прошло по плану, то можно переходить к другому сервису или гипотезам, а если нет, то составляем задачи на доработку и повторяем эксперимент.
2. Эксперимент
После составления плана определите, кто может вам понадобиться из смежных команд для оценки результата и помощи в восстановлении работоспособности сервиса. Будет удобней создать отдельный чат и фиксировать в нем все этапы эксперимента. Подробные описания отклонений могут помочь при устранении недочетов в отказоустойчивости сервиса.
А на каком стенде проводить? Всё зависит не только от идентичности эксплуатационной и другой среды, но и от количества общего трафика, загруженности сервисов, которые так или иначе могут повлиять на ход эксперимента. Поэтому вся его полнота раскроется только в эксплуатационной среде, но это не призыв бежать и срочно что-то ломать. Сначала потренируйтесь на самом близком по уровню схожести стенде.
В случае работы с production-средой никогда не забывайте про »план отката». Он обязательно должен быть, чтобы вы могли быстро восстановить работоспособность сервисов. То есть сам эксперимент должен быть полностью подконтролен, вы должны быть уверены, что у вас под рукой есть все средства для восстановления: процедуры и бэкап наготове, сетевой доступ на месте, как и старый-добрый ssh.
С чего можно начать?
1) Сетевые задержки
С развитием микросервисной архитектуры общая архитектура становится всё сложней. Конечно, всё делается из благих побуждений: удобная разработка, независимые друг от друга элементы сервиса. Но в какой-то момент может появиться такой микросервис, отказ которого приводит к цепной реакции и вся архитектура начинает валиться, как карточный домик. И тут хочется вспомнить крылатую фразу «сеть не идеальна». Причины могут быть разные, но суть остается одной: приложение должно уметь обрабатывать отказы смежных сервисов, чтобы это не приводило к полной деградации функциональности.
Сценарии отказа | Плохая доступность смежного сервиса/Полная недоступность |
Имитация сбоя | 1. Использовать утилиту 2. Имитируем полную сетевую недоступность смежного сервиса. |
Ожидаемый результат | 1. Приложение в случае таймаута использует retry-запрос. 2. Приложение обрабатывает ошибку смежного сервиса и это не приводит к падению основной функциональности. |
2) Недоступность хранилища данных
Файловое хранилище — практически незаменимый спутник большинства сервисов. Приведу в пример тестирование нашего сервиса FS. У нас есть два кластера хранилища: основной (S3) и резервный (NFS). Соответственно, архитектурная задумка заключается в возможности обращения к резервному хранилищу на чтение/запись, если с основным какие-то проблемы.
Сценарии отказа | Частичная недоступность основного файлового хранилища |
Имитация сбоя | Использовать утилиту |
Ожидаемый результат | Сервис продолжает работать. Ошибки обращения к основному хранилищу обрабатываются, задействуется резерв… |
Теперь смотрим на графики:
Фон ошибок обращения к основному хранилищу после запуска эксперимента.Количество ошибок в приложении.Здесь мы убедились, что резерв вполне справляется со своей обязанностью.
3) Нехватка ресурсов
Достаточно частая ситуация, которая возникает по разным причинам. Нехватка CPU, памяти или задержка времени ответа от диска — каждый админ видел подобное оповещение на своей борде мониторинга. Обычно это неминуемо приводит к деградации сервиса и увеличению ошибок. Для обладателей Kubernetes и микросервисной архитектуры есть множество инструментов для проведения хаос-экспериментов в кластере: Litmus Chaos и Chaos Mesh подойдут под разные сценарии отказов, а если захотите стать сами сеятелем хаоса, то можно посмотреть в сторону KubeInvaders и Kube DOOM. Для подконтрольного эксперимента также подойдет проверенный инструмент stress-ng
.
Сценарии отказа | Нехватка процессорного времени для сервиса |
Имитация сбоя |
|
Ожидаемый результат | Из-за нехватки CPU Kubernetes должен эвакуировать pod на другую ноду. Ожидается простой до 5 минут. |
В процессе подобных экспериментов наблюдаем за состоянием сервиса:
Health check приложения.Приложение ожидаемо отвечает ошибкой, но после эвакуации оно снова доступно.
4) Нагрузочное тестирование приложения
В идеальном мире все приложения перед попаданием в production должны проходить испытания на стенде нагрузочного тестирования (НТ). Это делается для определения рамок нормальной работы приложения. Есть ли изъяны в коде, или всё решается горизонтальным масштабированием, какой максимальный RPS способен выдавать сервис, когда начинаются ошибки, и так далее. Для тестирования, как правило, используют готовые решения: Apache JMeter, Яндекс.Танк, Gatling, The Grinder и другие. Перейдем к примеру:
Сценарии отказа | Создать ступенчатый Logon-шторм, используя скрипты JMeter. Помимо обычной авторизации генерируем внутренний трафик «хождения» пользователя по внутренним сервисам, чтобы уйти от синтетики и приблизить результат к боевому сценарию. |
Имитация сбоя | Запуск нескольких сценариев JMeter |
Ожидаемый результат | Приложение держит двойную нагрузку. Если сервис начинает деградировать, видим оповещения в панели мониторинга |
Получилось создать нагрузку на сервис до 6500 RPS, это в три. раза больше пиковой дневной нагрузки. Смотрим, как чувствует себя микросервис:
Появился троттлинг.В ходе эксперимента заметили, что появился троттлинг, при этом трафик по подам распределялся неравномерно. Это отклонение мы зафиксировали для дальнейшего изучения. Далее смотрим на график ошибок приложения:
График RPS по 5xx-кодам ответа.Фактический результат соответствует ожиданиям, но при этом найден интересный баг с трафиком на поды внутри кластера Kubernetes, и он отправляется прямиком в бэклог на исправление. Следующий эксперимент можно будет проводить в этом направлении.
3. Результаты
Существует два варианта исхода подобных испытаний:
Ожидаемый результат соответствует фактическому. Вы убедились, что сервис устойчив к данному виду неисправностей.
Сервис не справился. Вы зафиксировали все ключевые нюансы его падения и смогли быстро его восстановить.
Оба результата полезны. В первом случае вы стали более уверены в отказоустойчивости системы, во втором — извлекли уроки, создали задачи на исправление и наработали опыт быстрого восстановления в случае нештатной ситуации.
Заключение
У этой дисциплины есть определенные достоинства. Она позволяет упреждающе устранять потенциальные проблемы до появления негативного воздействия и повышает уверенность в надежности системы. На первый взгляд может показаться, что Chaos Engineering нужна только прикладным командам и команде инфраструктуры, но это не так. Рассмотрим пользу для каждой из сторон:
Пользователь: повышенная доступность и надежность обслуживания означает отсутствие простоев, нарушающих их эксплуатационный опыт.
Бизнес: Chaos Engineering может помочь предотвратить чрезвычайно большие потери доходов и затраты на обслуживание, создать более счастливых и вовлеченных инженеров.
IT-инженеры: выводы, полученные в результате экспериментов, могут помочь снизить количество инцидентов, найти узкие места (bottleneck), дать лучшее понимание сценариев отказа систем, улучшить дизайн архитектуры, модернизировать мониторинг для более быстрого определения проблем.