Инциденты и постмортемы: как надёжность делают процессом

Технические паттерны устойчивости не работают без процесса вокруг них: как устроен инцидент-менеджмент (роли, severity, коммуникация), почему постмортемы должны быть блеймлесс (иначе люди прячут причины), как из инцидента рождаются action items и runbooks, и как политика error budget превращает надёжность из лозунга в решения о релизах. SRE-сторона отказоустойчивости

Можно расставить circuit breaker’ы, настроить репликацию и написать идеальные бэкапы — и всё равно превращать каждый инцидент в хаос, терять причины и повторять одни и те же ошибки, если вокруг нет процесса. Надёжность в зрелых командах — это не только код, но и дисциплина: как реагируют на инцидент, как разбирают его потом и как из разбора рождаются изменения. Причём ключевая деталь контринтуитивна: разбор должен быть безобвинительным, иначе люди начинают прятать настоящие причины, и организация перестаёт учиться. Эта статья — про SRE-сторону отказоустойчивости.

Финальная статья серии «System design: resilience» — про процесс, который заставляет технические паттерны работать. Опирается на SLO и error budgetготовится, с 13 октября. Готовые к присвоению шаблоны — шаблон постмортема и пример политики error budget — лежат в architecture/resilience/incident.

Гравюра в стиле «Полдень»: круглый стол под одинокой лампой. В центре разобранный механизм, детали разложены по порядку; от нескольких неисправных частей тянутся тонкие терракотовые нити, сходящиеся в одну цепочку. Вокруг стола люди, все смотрят на механизм — никто ни на кого не показывает. Сверху узкая полоса с делениями читается как таймлайн

В статье

Инцидент-менеджмент

Инцидент отличается от бага тем, что он идёт сейчас и его надо тушить параллельно с выяснением причин. Хаос возникает не от сложности проблемы, а от неопределённости: непонятно, кто главный, кто пишет пользователям и когда звать подмогу.

Severity задаёт, что происходит дальше. Полезно, когда уровень определяет не «насколько нам страшно», а конкретные обязательства: будим ли on-call немедленно, обязателен ли ведущий, как часто идёт статус. Три уровня обычно достаточно; больше — начинают спорить о классификации вместо тушения.

Роли важнее должностей:

  • Incident commander (IC) — принимает решения и держит картину целиком. Он не чинит руками: как только IC уходит в отладку, инцидентом перестают управлять.
  • Scribe — ведёт таймлайн в реальном времени. Задним числом восстановить точные моменты почти невозможно, а именно они потом дают TTD и TTR.
  • Communications — говорит с внешним миром: статус, поддержка, руководство.

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

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

Коммуникация

Тушить и объяснять — разные работы, и их нельзя валить на одного человека. Пока инженер отвечает на вопросы «ну что там?», он не чинит.

Что работает:

  • Единый канал инцидента, где идёт вся техническая работа, и отдельный поток статусов наружу.
  • Регулярный ритм статусов (например, каждые 30 минут для SEV1) даже когда сказать нечего: «работаем, гипотеза такая» лучше молчания, потому что молчание порождает поток вопросов.
  • Честность с пользователями. Признать деградацию дешевле, чем делать вид, что всё в порядке: доверие теряется не от сбоя, а от ощущения, что его скрывают.

Почему разбор безобвинительный

Блеймлесс — не про вежливость, а про то, откуда берётся информация. Расчёт простой: разбор питается тем, что расскажут люди. Если за рассказ наказывают, рассказывать перестанут — не из злого умысла, а из инстинкта. Причины уйдут в тень, разбор станет ритуалом, и организация потеряет способность учиться на собственных сбоях.

Практический критерий: если в разборе появилось имя человека как объяснение («Петров выкатил плохой конфиг»), формулировка ещё не доведена. Доведённая звучит как свойство системы: «конфиг попадал в прод без валидации и канареечной выкатки». Разница не косметическая — из первой формулировки следует «поговорить с Петровым», из второй — конкретное изменение, которое защитит и следующего.

Правильный вопрос про человеческую ошибку не «почему он ошибся», а «почему это было легко сделать и трудно заметить». Человеческая ошибка — это симптом устройства системы, а не причина.

Анатомия разбора

Хороший постмортем состоит из фактов, а не впечатлений:

  • Таймлайн — что и когда произошло: первый симптом, момент обнаружения (и чем обнаружили — алертом или жалобой), объявление инцидента, гипотезы, смягчение, полное восстановление.
  • Две величины из таймлайна. TTD (time to detect) — сколько система «горела» молча; TTR (time to recover) — сколько шли до восстановления. Большой TTD означает проблему с наблюдаемостью, а не с починкой, и лечится другими мерами.
  • Способствующие факторы вместо «первопричины». Реальный инцидент — это цепочка условий: триггер (деплой, всплеск, отказ зависимости) плюс то, что позволило ему перерасти: не было таймаута, молчал алерт, устарел runbook. Поиск единственного виноватого фактора обычно останавливает разбор слишком рано.
  • Что сработало хорошо. Отдельный раздел — не для настроения: удачный откат и живой runbook стоит зафиксировать, чтобы не потерять при следующей перестройке.

Готовая структура — в шаблоне постмортема из приложения к статье: architecture/resilience/incident.

Action items и runbooks

Разбор без изменений — потраченное время. Требования к action items:

  • Конкретность. «Быть внимательнее» и «улучшить мониторинг» невыполнимы и непроверяемы. Выполнимо: «добавить таймаут и предохранитель на вызов X», «алерт на burn-rate SLO».
  • Владелец и срок. Без них пункт не существует.
  • Приоритет по эффекту, а не по простоте: сначала то, что убирает способствующий фактор, а не то, что быстрее закрыть.

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

Error budget как политика

Спор «фичи против стабильности» решается не силой убеждения, а заранее согласованным правилом. Error budget — допустимая доля неуспеха по SLO (при 99.9% за месяц это примерно 43 минуты недоступности). Пока бюджет есть — катим фичи и принимаем разумный риск; исчерпан — замораживаем фичи и чиним надёжность, пока он не восстановится.

Ценность в том, что решение принимается не в момент спора, а заранее и всеми сразу. Заморозка перестаёт быть чьим-то волевым актом и становится тем, на что команда уже согласилась. Механика SLI/SLO, burn-rate и алертов — в статье про SLO и error budgetготовится, с 13 октября; пример политики с порогами — в приложении к этой.

Связь с постмортемом прямая: инцидент, сжёгший заметную долю бюджета, требует разбора, а его action items — первые кандидаты в работу во время заморозки. Чинить логично ровно то, что бюджет и потратило.

Checklist

  • Severity определяет обязательства (будить/не будить, ритм статусов), а не эмоцию.
  • Роли назначаются явно; IC управляет и не чинит руками; решения — одна голова.
  • Эскалация описана и дешёвая: звать подмогу не стыдно.
  • Тушение и коммуникация разведены; статусы идут по ритму даже без новостей.
  • Постмортем блеймлесс: в объяснениях свойства системы, а не фамилии.
  • В разборе есть таймлайн, TTD/TTR и цепочка способствующих факторов, а не одна «первопричина».
  • Action items конкретны, с владельцем и сроком; повторяющийся класс инцидентов превращён в runbook.
  • Политика error budget согласована заранее: когда катим, когда замораживаем и кто снимает заморозку.

Первоисточники

Обсуждение в Telegram

Присоединиться →

Комментарии