Перейти к содержимому

«Алерт без runbook — фоновый шум» — это фраза, которую я повторяю чаще всего на ревью алертов. Сам runbook — не идея «давайте напишем инструкции», а конкретный документ с конкретными командами, ожидаемыми выводами и точками, где дежурный принимает решение. В три ночи приходит pager, человек открывает ссылку и за десять секунд понимает, что перед ним: команда, которую можно скопировать, или эссе про архитектуру сервиса. Лист про эту разницу.

Главный навык на уровне L4 — писать runbook так, чтобы по нему мог пройти новый дежурный без контекста. Если на каждом шаге приходится вспоминать архитектуру сервиса, догадываться, что имел в виду автор, и выбирать, какой dashboard открыть, — runbook сломан. Хороший runbook — это серия конкретных команд и явных решений «если видишь X, переходи к шагу N; если Y — к шагу M».

L3

  • Использует существующие runbook’и команды для реагирования на инциденты; следует шагам, не выходит за их пределы без эскалации.
  • Сообщает владельцу runbook о найденной неточности или устаревшем шаге сразу после использования (не «потом, на ревью»).

L4

  • Пишет runbook для известного типа инцидента: симптом → шаги диагностики → шаги mitigation → как откатить → escalation. Обновляет runbook после новых инцидентов.
  • Пишет по шаблону команды и проверяет каждый шаг на исполнимость: конкретная команда или явное решение, не «понять и подумать».

L5

  • Строит культуру, в которой алерт без runbook в команде просто не принимается. Проводит аудит runbook’ов на актуальность по расписанию.
  • Тестирует runbook’и в game day / wheel of misfortune; не доверяет ни одному runbook, которым никто не проходил по факту.
  • Встраивает ссылку на runbook прямо в алерт (например, через runbook_url annotation в Prometheus AlertRule или поле runbook в Alertmanager).

L6+

  • Внедряет систему работы с runbook: платформа, шаблоны, метрики использования, автоматическая связь с системой алертинга.
  • Держит SLO для самого репозитория с runbook’ами (например, «≥ 95% алертов имеют ссылку на актуальный runbook»); отслеживает деградацию покрытия.
  • Betsy Beyer et al. — Site Reliability Engineering (O’Reilly, 2016), глава 11 «Being On-Call». Раздел «Documenting» — фундамент всей культуры работы с runbook.
  • Betsy Beyer et al. — The Site Reliability Workbook (O’Reilly, 2018), глава 8 «On-Call». Продолжение: playbook содержит severity, impact, debugging suggestions, mitigation. Утверждение «каждый алерт получает playbook» как норма.
  • PagerDuty — Incident Response Documentation. Публичный guide по incident response; даёт референс формата runbook («Being On-Call → Before / During / After»). По моим наблюдениям, многие команды берут именно его как стартовый шаблон.
  • Markdown в репозитории команды — самый простой и работающий формат. Один runbook = один файл, ревью через pull request, история в git. Я вижу, что большинство зрелых команд так и живёт, а отдельную платформу заводят единицы.
  • Rundeck — open-source платформа для исполняемых runbook’ов (job runner + access control + audit). Имеет смысл, когда часть шагов автоматизируется и нужно фиксировать исполнение.
  • StackStorm — event-driven automation platform; runbook как сценарий, запускаемый по триггеру. Альтернатива Rundeck для команд, у которых уже есть шина событий.
  • Prometheus AlertRule runbook_url annotation — стандартный паттерн: каждому алерту в prometheus.yml прописывается ссылка на runbook. Alertmanager пробрасывает её в нотификацию (Slack/Pager).

Я регулярно встречаю команды, у которых 200+ active алертов в Prometheus, а 70–80% из них либо без runbook, либо с мёртвым: ссылки на несуществующие сервисы, deprecated команды, dashboard URL, отдающий 404. Смена превращается в «разбуди и пусть гадает». Инженер ack’ает, копает 10–30 минут, чаще всего упирается в шум, а runbook откладывается «до следующего раза» — которого не бывает. MTTR на алерт на такой смене — десятки минут. После систематической чистки по правилу «или runbook, или удаляем алерт» цифра падает в несколько раз, но именно после работы, а не после решения «найти на это время».

Короткие правила:

  • Runbook = детальные шаги, не нарратив. Если для исполнения шага надо «знать архитектуру» или «вспомнить контекст», runbook сломан: on-call в три ночи не думает, он следует.
  • Каждый шаг исполним и заканчивается критерием проверки. Шаг «проверить логи» без указания где, какие и что искать — бесполезен. Правильно: «выполни kubectl logs -n prod app-foo --tail=200 | grep ERROR; если видишь connection refused — переходи к шагу 3, иначе к шагу 5».

Шаг «как откатить безопасно» я считаю обязательным, и его пропускают чаще всего. Каждое изменяющее действие в runbook идёт в паре с откатным шагом и критерием, по которому дежурный решает откатывать. Без этой пары runbook ведёт mitigation только вперёд. А ситуация, когда mitigation сделал хуже, встречается регулярно, и разбираться в ней приходится тому же человеку в те же три ночи.

Подробнее:

Привязка к симптому, а не к причине. Дежурный не видит «база упала». Он видит «p99 latency > 500ms» или «5xx rate > 1%». Runbook с названием «падение базы» для него не существует: связь между тем, что на экране, и тем, что в wiki, придётся достраивать самому, и это те самые пятнадцать минут, за которые инцидент успевает вырасти. Поэтому runbook называется по симптому — по имени алерта. Симптомов мало, причин много, и от симптома документ уже ведёт к диагностике причин.

Регулярный аудит и владелец. Устаревший runbook хуже отсутствующего: он даёт ложную уверенность и ведёт не туда. Я встречаю это часто. Ссылка на dashboard, который год назад переехал в другой namespace; на скрипт, который удалили из репозитория; на ротацию команды, которая расформировалась. Лечится скучно: явная периодичность пересмотра (квартал или полугодие), явный владелец, отвечающий за актуальность, и обязательное обновление того runbook, который использовали в последнем инциденте.

Тестирование в game day. Runbook, написанный год назад и положенный в wiki, в момент инцидента запросто окажется неработоспособным — команда не работает, шаги ведут не туда, dashboard давно другой. Game day (wheel of misfortune, прогон сценария из прошлого постмортема) находит эту гниль без боевой обстановки. Непротестированный runbook — обещание, а не инструмент.

  • SLI-based Alerting — обязательная пара: каждый SLO-алерт ведёт к runbook; алерт без runbook удаляется как фоновый шум.
  • Incident Response — runbook — главный инструмент в моменте инцидента; качество runbook прямо определяет MTTR.
  • Postmortem Culture — каждый постмортем порождает обновление runbook (новый или правки существующего); без обновления lesson learned не закреплён.
  • Dev Team Partnership — co-ownership: runbook’и пишутся совместно с продуктовой командой; иначе SRE дежурит вслепую по чужому сервису.
  • Toil Automation — шаги, которые дежурный выполняет одинаково каждый раз, переезжают в код: «runbook говорит сделать X — пусть делает скрипт».
  • Playbooks — runbook отвечает «как делать», playbook — «что решать и кого звать». Runbook’и встраиваются в playbook’и как ссылки на конкретные шаги; разделение явное.
  • Я не знаю хорошего ответа на «когда runbook превращается в automated remediation». В тривиальных случаях — alert + 3-step runbook → Lambda или k8s operator. В нетривиальных — runbook содержит ветвление по контексту, и автоматизация рискует выстрелить в ногу при первом edge-case. Граница «можно автоматизировать» / «надо оставить человеческое решение» в публичной литературе чёткой не вижу. Если есть опыт — расскажите PR’ом.