Привет! Меня зовут Сергей Реусин и последние пять лет я занимаюсь эксплуатацией production-систем с непрерывной практикой инцидент-менеджмента. Каждый день, сталкиваясь с аномалиями и проблемами, невольно спрашиваешь себя: «Почему это происходит? А главное: как с этим дальше жить?». Три нелегких года работы в Купере (ex СберМаркет), где мне доверили строить культуру SRE и инцидент-менеджмента, помогли утвердиться во мнении и подходах, которые действительно помогают справляться с подобными вызовами. О них и поговорим!
Чтобы сложить цельную картину о создании устойчивых систем, мы пройдём по следующим шагам:
Определим, ради чего вся эта «доступность» и «стабильность» нужна
Попробуем устаканить терминологию, чтобы говорить на одном языке
Изучим возможные паттерны отказов систем и способы их митигации
Познакомимся с ключевыми личностями в подходах Resilience Engineering
Важные допущения в этой статье
Эта статья основана на моих докладах с HighLoad++ 2023 и DevOpsConf 2024, но не является их прямой расшифровкой и обогащена дополнительной информацией.
Некоторые материалы намеренно представлены в оригинале, чтобы не играть в испорченный телефон. Для простоты чтения буду использовать вольный перевод цитат, но с обязательным указанием источников со ссылками.
Часть примеров упрощена и помечена специальным знаком ✨ с целью сохранения стройного повествования. В интерактивных уточнениях обязательно представлены оригинальные идеи, из которых складывается утверждение.
Этот материал составлен с публичного одобрения авторов. Бóльшая часть материалов не является моим собственным трудом. В своей работе хочу провести параллели с другими доменными областями и ни в коем случае не хочу исказить оригинальные идеи авторов.
Так ли важна доступность?
Много копий уже было сломано о темы надёжности, стабильности, качества и доступности работы сервисов. Когда ты обеспечиваешь работу крупной платформы с миллиардным оборотом, игнорировать показатели доступности просто не получится: вам об этом напомнят либо сами люди, либо деградирующие метрики продуктов и систем.
Для сервиса, аналогичного Куперу, можно согласиться с представлением Уве Фридрихсена: «Бизнес-ценность достигается системой при наличии её в нужном окружении и доступности клиенту в нужное время».
В своем докладе Уве не говорит «нужное время», однако из контекста понятно: если функции системы недоступны, то ценность не достигается в принципе.
Подобное согласие позволяет лишь из определения решить, что на уровне организации нам обязательно следует отслеживать доступность, качество и потребность работы системы.
Доступность можно представить как выражение, на которое влияют 2 процесcа: наличие и обработка ошибок (MTTF), а так же процесс восстановления (MTTR).
Согласно этой формуле наша цель — максимальное увеличение времени между ошибками. То есть чем реже происходят сбои, тем доступнее наша система.
Но это очень рисковый путь. Большинство современных систем являются распределёнными✨, а значит на практике в них можно встретить проблемы, вызванные одним из широко известных заблуждений. Более того, многие из нас на себе ощущают, что сбои неизбежны и зачастую непредсказуемы! Доктор Ричард Кук, известный по своей работе «How Complex Systems Fail», постулирует:
«Failure is the normal function of your systems, not the abnormal one».
Но если появление сбоев неуправляемо, то какие альтернативы? Чтобы воздействовать на переменную MTTR
, мы можем уменьшить время восстановления, наделив системы устойчивостью — способностью справляться с непредвиденными ситуациями и восстанавливаться после сбоев.
Определение устойчивости не ново и уверен, большинство из вас с ним знакомы. Когда мы доходим до этого этапа, то как инженеры сразу ищем конкретные способы и инструменты для достижения цели — в нашем случае, для достижения устойчивости. А их много! Некоторые энтузиасты (как Уве) даже пробуют создать карты методов с описаниями и примерами.
Вот примеры таких карт
Я же хочу поделиться с вами мнением: если мы копнем глубже, то кроме практик получим куда более значимые идеи для построения и развития систем устойчивости у себя.
Говорим на одном языке
Нельзя просто так заявить что-то об инженерии устойчивости и сделать это без ссылок. Одна из мотиваций создания этого материала — трудность поиска информации в РФ сегменте интернета. Пожалуй, первым доступным докладом на эту тему был материал Алексея Кирпичникова.
Если мы работаем в компании с достаточно зрелыми процессами, чтобы переживать за доступность, то зачастую сами вводим эти понятия.
Пойдя по самому простому пути и взяв оригинальное «Availability», мы без труда найдем по перекрёстным ссылкам термины «Safety engineering», «Reliability engineering», «Resilience engineering» и ещё много всего. В таком утрированном примере видно, что без понимания предмета поиска не так-то просто разобраться в теме. А разбираться есть в чём: большинство упомянутых определений буквально говорят об одном и том же — умении системы не только падать, но и вставать.
Забегу вперед и скажу, что человеческое восприятие очень важно в создании устойчивой системы:
«Не сами эти вещи, а только наши представления о них делают нас счастливыми или несчастными» — Эпиктет. ✨
Истина — продукт интеллектуального анализа человеком его эмпирического опыта. Идеи о важности адаптации нашли отражение в самых разных сферах зания, далеко не только в IT:
«Резильентность» в физике — способность упругих тел восстанавливать свою форму после механического давления.
«Резильентность» в психологии и биологии подразумевает пластичность — умение адаптироваться к травмирующим событиям, считается врожденным свойством, которое можно развивать.
«Резильентность» в экономике понимается ближе к дословному переводу этого слова — «упругость», «эластичность», «гибкость».
В строительной инженерии вводится свойство rapidity — способность делать эффективные выводы для предотвращения сбоев в будущем.
Ещё Нейман в 1956 году упоминал неотвратимость ошибки и важность реагирования на них. Во многих доменах и науках мы оперируем едиными понятиями, зачастую выполняя похожую работу, добиваемся похожих выводов и характеристик эксплуатируемых систем!
Итого: все практические определения устойчивости исходят из «гибкости» субъектов и их способности переживать стресс.
Как с позиции устойчивости выглядит система
В подавляющем большинстве систем гибкость реализуется за счёт прямого участия человека и принимаемых им решений. Все, кто запускают релизы, проводят плановые работы, проектируют и тестирует сервисы с учётом рисков, сами являются частью ими создаваемой социотехнической системы.
У этого видения есть конкретная модель, явно описанная в работе Stella.report и более ранних материалах:
Для построения действительно устойчивой системы не следует игнорировать факт, что люди одновременно являются источниками и изменений, и реагирования на них. Именно поэтому снижение когнитивной нагрузки на инженера — помощь ему в решении аналитических задач или упрощение рутиных операций — может привести к куда более позитивному влиянию на повторяемость инцидентов, чем создание очередного тест-кейса или автоматического rollback.
Вот пара докладов на эту тему
Инженерия устойчивости
Текущий взгляд на вопрос — результат десятилетий исследовательской работы. Централизованно она началась в 1987 году группой энтузиастов из числа докторов наук на базе Лаборатория когнитивных систем университета Огайо: учёные в области медицины, автоматизации, разведки, авиации и атомной энергетики проводили исследования в области контроля инцидентов в своих доменах. Несмотря на регулярную частную работу друг с другом, первая совместная конференция из 14 участников состоялась в 2004 году.
Существуют несколько взглядов на природу устойчивости, которые описаны и обсуждаются сообществом, но все они дополняют друг друга.
Профессор Hollnagel предлагает 4 ключевых способности: если система наделена ими, то может считаться устойчивой.
1. The potential to respond — реагирование.
2. The potential to monitor — отслеживание.
3. The potential to learn — обучение.
4. The potential to anticipate — прогнозирование.
На первый взгляд они звучат банально и даже базово, но не всегда мы можем их правильно применить. Подобный пример приведу чуть ниже.
Доктор David Woods выделяет два критерия устойчивости:
Graceful extensibility (плавная расширяемость) — способность системы расширять свои возможности к адаптации, когда неожиданные события нарушают ее границы. Она содержит в себе способности управлять рисками, иметь адаптивные связанные компоненты и обходить различные неожиданные ограничения
Sustained adaptability (устойчивая адаптивность) — способность системы продолжать адаптироваться к неожиданностям в течение длительных периодов времени.
В системе, которая способна оперативно адаптироваться и делать это постоянно, влияние инцидентов выступает в роли драйвера изменений, а не только как источник потерь и нежелательных препятствий в работе. Если попытаться представить границы системы (на уровне технических ограничений или процессов), то расширяемость будет направлена на раздвигание границ, а адаптивность на удержание дистанции от их пересечения. Это выражается в характеристиках rebound
и robustness.
Паттерны отказов в современных системах
«Допустим!» — скажете вы, — «Но что конкретно мне с этим делать?». На практике применить это подходы довольно просто. Более того, скорее всего используете их по наитию. Сейчас вы это отрефлексируете и будете пользоваться этим ещё эффективнее :)
Переводя теорию в практические примеры, Вудс предлагает несколько базовых паттернов отказов:
Decompensation — «не вывезли»
«Потеря системой способности эффективно функционировать при появлении стрессовых ситуаций, выходящих за пределы её предполагаемых возможностей или дизайна».
Приведу пример из практики. В 2020-2021 годах в системах СберМаркет работа с ожиданиями существовала только в виде статичных трешхолд алертов. Мы ловили десятки инцидентов в разных местах системы, которые показывали наше незнание границ нагрузки или их некорректное проставление.
Определение ожиданий, требований и условий работы — это такая база, без которой сложно представить современную сложную систему. На практике для этого существуют десятки инструментов и специальные подходы: SRE предоставляет нам концепцию SLO и допустимый бюджет ошибок, регулярные тесты на достижимость пределов. Как раз это и подчёркивает Resilience engineering!
Практики существуют, они не новы, но концентрироваться на них полезно именно с позиции адаптации систем, а не мнимой уверенности предотвращения проблем или достижения высокой доступности.
Working at cross purposes — конфликт целей
«Различные компоненты системы стремятся достичь своих целей, но при этом несовместимы или даже противоречат друг другу» .
Мы как большая система в процессе изменений обросли собственной структурой, иерархией, набором правил. Работая со 100+ командами, обязательно столкнёшься с пересечением задач и даже интересов, что иногда приводит к конфликтам. В неустойчивой системе такое движение регулярно, а конкуренция целей приводит к пагубному влиянию на пересекающие функции.
Широкоизвестная методология DevOps одним из решений предлагает Shift Left. Получив возможность внедрять практики дизайна, тестирования и валидации раньше, а не последовательно друг за другом, мы способны предостеречь немалое количество потенциальных проблем. В этом вопросе Resilience engineering тоже не противопоставляет себя уже существующей информации, а дополняет и качественно описывает влияние таких проблем на наши системы.
Getting stuck in outdated behaviors — устаревшие правила
«Cистема или её компоненты продолжают применять стратегии, которые стали неактуальными или неэффективными из-за изменений в окружающей среде или условиях использования».
На примере нашего же Купера можно утверждать, что нагрузка неоднородна и в основном растет — на это сказывается сезонность нагрузки в сфере e-com.
Используя подходы устойчивости можно заранее подготовить систему к тому, что способы работать с определенной нагрузкой постоянно будут терять актуальность.
Если в 2021 году мы могли масштабировать систему физически или вообще позволить себе деградацию 50% без влияния на продуктовые метрики, то с увеличением числа клиентов такая возможность рискует исчезнуть. Поэтому каждый раз на планировании следует задавать себе вопрос про альтернативные способы и готовиться:
отрезать кусок нагрузки, которые не сможешь вывезти (graceful degradation);
использовать заранее подготовленные данные для балансировки потока (кеширование, шардирование);
а может и вовсе отказаться от ряда функций, заменив их более легкой версией (пересмотр архитектуры).
Мы прошли через похожие примеры.
Первый касается процессов с технической стороны:
→ Представим, мы внедряем канареечные развертывания для снижения влияния инцидентов и появления автоотката. Какое-то время это положительно сказывается на инцидентах и мы считаем, что успешно справились с проблемой «плохих релизов».
→ Но не применяя эту практику повсеместно, столкнёмся с тем, что подход feature flag
в разработке без аналогичного использования акторов точно так же откатит нас на прошлое хаотичное состояние — включение флага возможно сразу на всех клиентов и, если он безопасно доставляется канарейкой, то включение вернёт проблему «сломано всё и сразу».
→ Отслеживание Change Failure Rate поможет не упустить этот момент и вовремя адаптировать подходы.
Второй — с организацинной стороы:
→ В сезон выскоких нагрузок стандартный цикл итерации в 2 недели может вам сильно навредить. Более 50% задач в высокий сезон — ad-hoc.
→ Желание сохранить процесс ради процесса помешает сохранить предсказуемость и гибкость в выборе приоритетов, которая изначально в него закладывалась.
→ Переход на недельные итерации или выделение пула специалистов под эти задачи будет более адаптивным решение в новых условиях.
Как применять теорию на практике можно подсмотреть и у других
Например, разбирая упомянутое и в работах доктора Кука «известное состояние ошибки», инженеры из Яндекс.Go отрабатывают Metastable Failure State.
Давайте визуализируем это
Зная теорию, мы можем попытаться собрать всё воедино.
В любой момент времени наша социотехническая система балансирует среди множества ограничений вида ресурсной вместимости, бюджетов, ожиданий и границ нагрузок.
Если представить её за точку в пространстве, то она может двигаться под давлением этих границ или же в попытках избежать с их пересечения. Ярким известным примером будет невозможность расширения ресурсов с одновременным увеличением прибыльного потока, что нередко приводит к неспособности организации справиться с входящими техническими нагрузками.
Визуально это можно выглядеть так:
Тогда способность адаптироваться можно изобразить как создание отдельной границы собственных ожиданий и появление бюджета ошибок — та самая практика в виде SRE-подходов, которые позволяют заранее отойти от критической линии появления инцидента.
В реальности проблема заключается в том, что в ежеминутно меняющемся мире мы не всегда можем узнать положение границ, а тем более конкретного способа их нахождения. Для этого на практике мы используем какие-то подходы, например, нагрузочное тестирование, чтобы попытаться поэтапно определить границы и выстроить собственные ожидания. Всё наше представление — не более чем желания и предположения, которые устаревают с течением времени и при отсутствии регулярных перепроверок.
Если довериться такому представлению, то устойчивость системы строится на понимании:
Где мы находимся в действительности — реагирование.
Как изменяется происходящее вокруг — отслеживание.
Где именно проходит грань инцидента — прогнозирование.
Что мы делаем под давлением факторов влияния — обучение.
Как можно заметить, это прямое пересечение с предложением Холлнагела.
Ключевые личности, материалы и ссылки
Модель, описанную выше, изначально представил Jens Rasmussen. В коллаборации с другими исследователями она была адаптирована под современную теорию. Не менее ключевым примером может являться архетип устойчивости, предложенный доктором Ричардом Куком в работе A Few Observations on the Marvelous Resilience of Bone & Resilience Engineering:
Он описал кость как архетип устойчивости, ведь на самом деле (вопреки распространенному мнению о том, что кости статичны) они динамичны. Кости непрерывно заменяются в течение примерно десяти лет, балансируя между разрушением старой кости и созданием новой. Этот процесс, являющийся динамическим балансом, иллюстрирует ключевые принципы устойчивости, такие как адаптивность и постоянная трансформация в ответ на механическое напряжение. Реализуя свойство «network of adaptive units», кость является многоуровневой сетью без центрального элемента. Большое количество перекрестных связей позволяют ей быть хорошим примером отказоустойчивой системы, поскольку она демонстрирует как расширяемость, так и устойчивую адаптивность.
Эта метафора помогает лучше понять идею проектирования устойчивости: как системы могут быть одновременно надежными и гибкими, способными адаптироваться и развиваться перед лицом стресса. На примере взаимодействия с системой, которая сама по себе является устойчивой, Ричард приводит и пример инженерии, которая совершается над ней – за счет понимания только её принципов, без знания истинной природы объекта.
Ссылка на сам доклад
В содержании я слукавил. С активными участниками мы уже познакомились и можем узнать подробнее по приложенным ссылкам, а общая агрегация поддерживается на Github. Этот раздел оставил потому, что считаю важным подробное изучение вклада личностей — это помогает самому лучше понять, куда движется направление. А ещё предостеречь от судьбы других полезных практик, которые сейчас скрываются за десятками инструментов и абстрактным текстом, потеряв в массах изначальные идеи.
Теперь, обратившись к таким источникам, как map.r9y.dev, попробуйте посмотреть через призму адаптивности на вашу команду или компанию.
Вместо вывода
Я не претендую на собственный научный взгляд, хоть в процессе и старался подтвердить информацию с помощью авторитетных источников. Но уверенно называю инженерию устойчивости важнейшим инструментом для выживания, потому что аналогично доктору Вудсу убедился: «Reliable systems still fail».
Надежная и высокодоступная система не защищена от инцидентов и, более того, она может быть хрупкой:
Хрупкость появляется тогда, когда мы достигаем наших границ понимания и производительности.
Мы не можем прятаться за линейными упрощениями. Нам нужно воспринимать систему комплексно, явно учитывать её связи и всех «агентов», включая людей.
Данный доклад и статья — отправная точка для самостоятельной работы каждого из тех, кого эта тема заинтересует.
Tech-команда Купера (ex СберМаркет) ведет соцсети с новостями и анонсами. Если хочешь узнать, что под капотом высоконагруженного e-commerce, следи за нами в Telegram и на YouTube. А также слушай подкаст «Для tech и этих» от наших it-менеджеров.