Хабрахабр

Chaos engineering

Последнее, что хочется увидеть во время дебага кода — это хаос. Но что если этот хаос управляемый и запущен руками самого разработчика? Зачем умышленно устраивать турбулентность в слаженной работе своего приложения, как добиться душевного спокойствия при релизе важных фич и где точно вам пригодится практика хаос-инженерии, читайте в разговоре ведущих подкаста AppsCast с Павлом Осиповым PavelOsipov.

Сегодня у нас в гостях Павел Осипов из Облака Mail.ru, с которым мы поговорим о chaos engineering.
Алексей Кудрявцев: Всем привет!

Я лет шесть руковожу разработкой Облака Mail.ru. Павел Осипов: Всем привет! Такая практика позволяет проводить серию контролируемых экспериментов по выявлению работоспособности вашей системы в условиях враждебного окружения. За это время мы накопили много практик эконом-тестирования и одна из них — chaos engineering. Например, вы вряд ли регулярно смотрите, как ведет себя система в условиях нестабильной сети. По итогам этих опытов вы получаете полезные инсайты. После каждого своего отпуска на море я привожу целый «портфель» логов о том, что пошло не так с приложением. Если ваш пользователь часто ездит в метро или отдыхает в условиях гостиничного вайфая, сеть не так стабильна как на рабочем месте программиста.

Лично мне разведение ручного хаоса позволяет получить дополнительную дозу уверенности, что все будет идти хорошо, даже если вовне приложения все плохо.

Есть ситуации, когда я доверяю ручному хаосу больше, чем автоматическим тестам.

Зрим в корень хаоса

Алексей Кудрявцев: Откуда корни такой практики?

Мы привыкли к понятию технического долга, а на Западе есть еще dark debt — скрытый долг, который неизбежно возникает в сложных системах. Павел Осипов: Это серверная практика, где проблем в разы больше. Он возникает на стыке компонентов или hardware и software и может повлечь за собой каскад проблем: что-то ломается на одном компоненте, накладывается на другой, и вот система лежит целиком. В отличие от технического долга, где мы осознанно заимствуем время себя будущего у себя настоящего, скрытый долг невидим на этапе создания системы.

Тогда система, которая проверяла валидность конфигурационных файлов, начала их по ошибке удалять, причем не только в кэширующей подсистеме, но и в той базе данных, которая была первичным источником. Например, в 2016 году из-за каскадного отключения баз данных 2,5 часа лежал Facebook.

У них три дата-центра, которые должны быть в боеготовности 24/7, но раз в квартал случается какой-нибудь отказ. Мне очень нравится интервью с Олегом Анастасьевым из Одноклассников о проведении учений по предотвращению инфраструктурных аварий. С одной стороны, это кажется страшным, так как если произойдет что-то непредсказуемое, ляжет весь дата-центр и не будет доступен на проде. Такие учения они проводят на продакшене. Если такое произойдет в условиях боевой жизни, то включить обратно просто так не получится, а разбор причин отключения затянется надолго. Но с другой стороны, этот процесс контролируемый и если что-то пойдет не так, то вы это сразу увидите, остановите, и все восстановится.

Польза хаоса в мобильной разработке

Даниил Попов: Пока речь про серверную разработку, где популярны микросервисы и возможно каскадное отключение. Можешь привести еще примеры, что проверять через chaos engineering в мобильной разработке?

В тестовых условиях наши действия могут быть очень щадящими по отношению к приложению: зашли в настройки аккаунта, нажали кнопку «выйти», приложение вышло и при просмотре экрана логина вроде бы все хорошо. Павел Осипов: Мой любимый пример — разлогины приложений. Например, клиент поменял через веб-интерфейс пароль или произошло большое количество разлогинов на других устройствах и refresh token вытеснился. У пользователей часто бывают более экзотические ситуации. Этот разлогин случается не в окне с аккаунтом пользователя, а, например, в момент работы полноэкранного просмотрщика фотографий.

Тот же просмотрщик с completion-блоком мог прихватить жизненно важный сервис, который в итоги утек. Мы нашли множество ситуаций, когда разлогины в разных местах приложения приводят к таким последствиям как утечки памяти.

В системе есть сервис, который прозрачно для прикладных высокоуровневых сервисов обновляет access-токен приложения с помощью refresh-токена приложения. Условия мы моделируем с помощью хаос-инженерии. Мы внедрили хаос, при котором сервис вместо обновления токена с определенной долей вероятности портит его, а каждый разработчик несколько раз в день сталкивается с разлогином в неожиданном месте.

Если при этом ViewController имел ссылку на сервисы, которые по логике архитектуры обязаны существовать в системе в одном экземпляре, то проблем не избежать. Благодаря этому мы открыли интересное поведение UIKit в iOS: если при пересвечивании рутованного ViewController’а на окне модально запрезенчено другое окно, то рутованный ViewController утекает и остается жить в системе навеки вечные. Например, в Облаке есть сервис автозагрузки фотографий, и, если в системе останется жить два таких сервиса, они будут выполнять кучу ненужной работы и посадят батарею устройства в два раза быстрее чем положено.

При появлении iOS 8 были проблемы с extensions: на некоторых устройствах, когда все permissions в настройках приложения были даны, на старте система заявляла, что в shared app group у приложения доступа нет. Еще курьезный случай.

Типология хаоса

Даниил Попов: Хаос вносится в систему автоматизировано на основе процентов или конфига, но нужен ли взгляд человека, чтобы понять, что пошло не так?

В случае с операционной системой, которая говорила, что у приложения нет доступа к shared app group, и extensions не могли получить доступ к общим ресурсам и базе данных, использовался ручной хаос, который включался с помощью галочки в системных настройках приложения. Павел Осипов: Хаос бывает разным: и ручным, и автоматическим. Это легко могли смоделировать ребята из QA-команды.

В частности, это ошибки, которые моделируются из микросервисов нашего бэкенда, и хаос, связанный с обновлением токена. Есть автоматизированный хаос. Поехавшую верстку можно определить через визуальное наблюдение. Последствия бывают разные. Например, у нас в приложении автоматически определяются утечки памяти. Есть места, которые позволяют выявлять аномалии в автоматическом режиме. Один менеджерит время жизни глобальных сервисов, которое совпадает с временем жизни самого приложения, другой контейнер менеджерит сервисы, совпадающие во времени жизни с юзером. В системе есть два IoC-контейнера. Каждый IoC-контейнер, создавая сервис, проверяет, что тот существует в одном экземпляре.

В каком-то месте внезапно произошел разлогин и разработчик для продолжения работы заново вошел в аккаунт. Вернемся к примеру с разлогинами. В этот момент IoC-контейнер сообщает, что произошла утечка памяти, и сервис, который в теории должен существовать в одном экземпляре, обнаружен еще раз.

Когда приходит время хаоса?

Алексей Кудрявцев: Что послужило триггером для внедрения практики?

Как можно побороться с теми же проблемами разлогина? Павел Осипов: Мы пришли к этому через необходимость удешевлять тестирование. Можно написать unit-тесты на утечки, можно заморочиться и написать UI-тесты.

Хаос-инжиниринг — самая дешевая практика, так как он не завязан на юзкейсы, а действует автоматизировано для всех юзкейсов сообща.

Второй триггер — до внедрения практики в нашем crash-report часто наблюдались похожие крэши с одинаковой корневой причиной. Например, что крэш произошел не из-за разлогина системы в профиле, а из-за того, что пользователь пролистывал в это время галерею фотографий. Ситуации разные, и невозможно протестить все комбинации разлогинов. Вот и захотелось придумать то, что автоматизирует процесс.

В этой практике мы изменяем маленькие кусочки кода и смотрим, как это влияет на тесты. У хаос-инженирии есть родственная практика — мутационное тестирование. Если после изменения тесты выполняются корректно, значит, для этих фрагментов кода тестов недостаточно.

Отличие хаос-инжиниринга от мутационного тестирования в том, что мы автоматизировано меняем не сам продакш-код, а его окружение.

Алексея Кудрявцев: Можно ли было локализовать причину и пофиксить без chaos engineering?

Каждый случай по-своему уникален. Павел Осипов: Нет единой причины, которая провоцирует крэшы. Предусмотреть все комбинации иерархии окон, которые у вас есть во время разлогина, невозможно. Например, модальная кнопка оказалась поверх окна, и это привело к тому, что во время разлогина утек рутованный ViewController. Chaos engineering локализовал паттерны, при которых происходят утечки и крэши.

Алексей Кудрявцев: Как долго вы уже используете эту практику?

При этом это не только внушительный, но и позитивный опыт. Павел Осипов: Мы начали её использовать на заре проекта в 2012 году, потому что разрабатывать надо было быстро, а времени на широкомасштабное тестирование не выделялось.

Даниил Попов: Если у меня в приложении что-то крэшнулось и надо завести в JIRA задачу, что починить в будущем, как эту ситуацию воспроизвести?

Chaos engineering активируется в момент дебага приложения и деактивируется в момент сборки релизной версии, поэтому такие ситуации можно увидеть через логи в консоли среды разработки, из которых можно прикинуть, как поставить таску в JIRA. Павел Осипов: Нет универсального рецепта.

Алексей Кудрявцев: Пытаетесь ли создать воспроизводимое поведение, чтобы ваша система хаоса оповещала о проблемных состояниях и предлагала внести в конфиг на старте, чтобы это состояние повторить?

Если архитектура позволяет записывать все действия, которые предваряли критические события, тогда это возможно. Павел Осипов: Звучит космически и возможно в архитектурах типа Redux. Такое практиковалось в мою бытность работы serverside-программистом в телекоме. У нас не так. Мы добились того, когда тест с рандомным входом крэшил систему, а в программе, которая отвечала за автоматизацию тестирования, откладывались все необходимые параметры входного запроса, чтобы можно воспроизвести. Там были тесты, которые рандомизировали вход на подсистему и проверяли адекватный выход.

Применяем хаос в приложении

Даниил Попов: Правильно, что такой хаос вносится в код руками?

На основании конфига он решает запроксировать клиентский запрос на сервер или самостоятельно ответить ерундой. Павел Осипов: Да, в нашем сетевом клиенте встроена функциональность, куда можно подать конфиг, где описан параметр хаоса, который должен воспроизводится. Бессмысленно моделировать ошибки невалидности авторизационных данных, если запросы микросервиса не требуют авторизации. Слой для работы с сетью таков, что можно кастомизировать хаос, который привносится микросервисом в бекенде.

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

Алексей Кудрявцев: Что вы рандомизируете кроме сети и файлов?

У нас закончена работа по выносу файловой системы в отдельные подсистемы, и я пробую моделировать разного рода ошибки при попытке приложения записать или считать файл. Павел Осипов: Мы отлаживали практику по рандомизации ответов от конкретных эндпоинтов, чтобы смоделировать поведение и хаос каждого микросервиса в отдельности. Вручную моделируется доступ к shared app group в приложении, и очень хочется начать моделировать поведение приложения, когда она стартует с экстремально малым дисковым пространством, при котором невозможно даже базу данных создать.

Алексей Кудрявцев: Это все, чем вы занимаетесь?

Мы еще не разгребли все те баги, которые найдены с помощью существующего хаоса. Павел Осипов: В принципе да. Конечно, интересно повышать хаос и переносить на другие подсистемы, но тогда мы не будем успевать фиксить столько, сколько хаос будет находить.

Всегда же можно найти место, где можно создать очередную турбулентность для приложения. Где вообще место хаоса? Мы сделали хаос для разлогинов, потому что наблюдали большое количество сходных проблем. Важно отталкиваться от проблем.

Если мониторинг показывает, что в других подсистемах особых проблем не возникает, то нет смысла тратить время на моделирование непредвиденных обстоятельств.

Это не касается биллинга, где важна корректная работа.

Алексей Кудрявцев: С другой стороны, мы не в курсе, что творится у пользователей — это сам по себе хаос, потому что ты не знаешь, куда его встроить, а куда нет, и остается только его симулировать.

Конечно, можно воспроизвести и самые экзотические кейсы, но если они единичны, то, возможно, и не являются критичными, и нет смысла их моделировать. Павел Осипов: Всегда нужно смотреть на ROI.

Сложности внедрения хаоса

Алексей Кудрявцев: Что из уже сделанного вам далось легко, а что вызвало трудности?

Сложно адаптироваться к тому, что у тебя куча ошибок. Павел Осипов: Привыкание к хаосу — это необычно для новичка, так как это не повсеместно применяемая практика. Только со временем привыкаешь, что все это бурления, и ответы от сервера моделируются самой системой. Почти на каждом экране можно получить пачку «пятисоток» или непонятных «404-х», сервер отвечает через раз.

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

Еще момент, который вызывает недовольства, это использование хаоса в инфраструктурных сервисах с большим количеством сайд эффектов.

Даниил Попов: Получается, у разработчиков на дебаге всегда по умолчанию включен хаос?

Временами, когда тебе вообще не до хаоса и тех экзотических ситуаций, которые он тебе может воспроизвести, это раздражает. Павел Осипов: Совершенно верно. С другой стороны, хаос может выявить проблему далеко не в том месте, где ты ее ищешь, и не у того разработчика, который эту фичу разрабатывает. Приходится терпеть, но всегда можно отрегулировать уровень хаоса, если твой экран интенсивно работает с сетью. Об этом и не узнаешь, если хаос будет включен только в конкретный момент разработки. Бывает, твоя фича, в которую добавлен хаос, приводит к последствиям, которые влияют на фичу твоего коллеги.

Смысл хаоса в том, чтобы выявлять непредвиденные последствия при взаимодействии большого количества компонентов.

Если включать хаос дозированно и точечно, то эти редкие, но меткие выстрелы будут незаметны.

Даниил Попов: Не мешает ли хаос читабельности кода?

У нас, за счет долгого опыта использования, хаос органично вплетен в систему и изолирован настолько, что ты не замечаешь его в коде. Павел Осипов: Когда хаос внедряется вне системы, прилепляется к готовой, то да, это выглядит неаккуратно.

Не усложняет ли это логику приложения? Алексей Кудрявцев: Вы отлавливаете много редких кейсов, фиксите их, и код обрастает костылями.

Конечно, все зависит от мастерства разработчика, который умеет исправлять код так, чтобы это не мозолило глаза. Павел Осипов: Это всегда большая часть нашего кода, но иначе крупные продакшн-приложения и не пишутся.

Плюсы внедрения хаоса

Даниил Попов: Есть ли количественные показатели, которые улучшились после внедрения chaos engineering?

Павел Осипов: Для меня самая главная метрика — это внутреннее душевное спокойствие, когда я отправляю фичу в релиз.

Чем аргументировать внедрение хаос-инженерии в компании? Алексей Кудрявцев: Бизнесу душевное спокойствие не продашь.

Те же крэши с разлогинами после внедрения практики хаоса практически исчезли из нашей JIRA. Павел Осипов: Chaos engineering высвобождает время тестировщиков, так как появляются автоматические тесты.

Одно дело, когда готовая фича уходит в тестирование, и через длительное время тебе сообщают о количестве найденных багов, совсем иначе, когда у вас есть робот-тестер, который работает на протяжении всего дебага программы. Хаос-инженерия благотворно влияет на релизный цикл, так как ты получаешь быструю обратную связь.

При такой загрузке все самые невероятные комбинации точно будут зафиксированы. У меня ощущение уверенности от результатов unit-тестов намного ниже, чем от включенного на 50% хаоса при загрузке тысячи файлов.

У кого учиться и с чего начать?

Алексей Кудрявцев: Какие инструменты вы для этого использовали? Взяли открытые библиотеки или сами написали и выложили в open source?

Единственный, который я знаю — Netflix Chaos Monkey, который рандомно «бегает» по AWS instance и терминирует их, смотрит, все ли пошло хорошо, если определенное число контейнеров погашено. Павел Осипов: Мы выложили в open source сетевую библиотеку, а специализированных инструментов и нет. Я считаю, что написание конфигов там, где вы соприкасаетесь со смежными системами, не требует глубокой автоматизации.

Даниил Попов: Где подробнее почитать про chaos engineering?

Во-вторых, книги Learning Chaos Engineering и Chaos Engineering Observability. Павел Осипов: Во-первых, сайт Principles of Chaos, на который ссылаются все ресурсы по этой теме.

Всегда нужно понимать, в каких местах внедрять хаос. Вообще, хаос-инженерия — это практика здравого смысла и фундаментальных знаний там нет. и нужно сначала понять, что нужно внедрять именно у вас. В тоже время хаос для каждого приложения уникален?

Алексей Кудрявцев: С чего начать, если ты все-таки решился внедрить хаос?

После выявления корня зла необходимо понять, как смоделировать ситуации, которые приводят к проблемам. Павел Осипов: Начните с анализа проблем в системе, какие крэши и почему возникают. А третьим шагом аккуратно внедрить хаос и держать его под контролем.

Куда лучше не соваться? Алексей Кудрявцев: Болеть в приложении может многое, но как приоритизировать?

Важно соотношение цены и выхлопа. Павел Осипов: Нет нереальных вещей. Если ты что-то не до конца понимаешь, то начнешь провоцировать хаос, который в природе невозможен и приведет к бесполезной борьбе. Если есть богатый системный API, то обкладывать его своими обертками дорого. Например, если весь UIKit или API с покупками покрыть хаосом.

Хаос — это не рандомное тыканье на клавишу, а четкое понимание моделируемых ситуаций.

Алексей Кудрявцев: Насколько ты советуешь эту практику внедрять?

Павел Осипов: Я вообще советую начинать именно с внедрения хаос-инженерии, а не unit-тестов, так как это самая дешевая практика.

Ловите Павла Осипова на осенней AppsConf в Санкт-Петербурге 21-21 октября, где он представит свой новый доклад о Key-value базах данных. Заинтересовала тема хаос-инженерии?

Теги
Показать больше

Похожие статьи

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

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

Кнопка «Наверх»
Закрыть