Runbook vs playbook: что писать для on-call инженера
«Сервис недоступен», «база переключилась на реплику», «алерт HighDiskUsage сработал». Что делать в три ночи on-call инженеру? Если ответа нет — он будит других, разбирается на лету, и инцидент длится дольше. Если есть пошаговый сценарий — действует за 5 минут, и вопрос закрыт.
Документация для on-call — это не «справочник на всякий случай». Это инструмент работы дежурного, и от его качества зависит время на инцидент, частота эскалаций и количество выгораний. Слова «runbook» и «playbook» в индустрии используют как синонимы или с разными значениями в разных компаниях. Разберу, чем они отличаются по моему опыту, какой минимум документации нужен on-call, и как это поддерживать.
Runbook vs playbook
Чёткой стандартизации нет, но обычно различают так:
Runbook — пошаговое руководство для конкретного сценария. «Что делать, если сработал алерт X». Структурный документ, минимум прозы, максимум команд для копирования. Цель — действовать без раздумий.
Playbook — описание процесса с вариантами и решениями. «Как обрабатывать инциденты priority-1». Включает roles, communication, escalation, decision points. Цель — координация людей и принятие решений.
Простая аналогия: runbook — это рецепт пирога, playbook — это план мероприятия с гостями. Первый говорит «положи муку», второй — «как реагировать, если кончилась мука».
Что нужно on-call в первую очередь
На практике дежурный сталкивается с двумя сценариями:
- Известный алерт. Включается типичный паттерн «сработало X — делай Y» — нужен runbook.
- Неизвестная ситуация. Что-то ломается, никто не знает, что — нужен playbook по incident management.
Команды без документации обходятся «на чате»: что-то падает, дежурный пишет в общий канал, кто-то из старших разработчиков отвечает. Это работает, пока команда маленькая. С ростом — становится узким местом.
Структура runbook-а
Шаблон, который у меня работает на разных проектах:
# Runbook: HighDatabaseLatency
## Symptoms
- p99 query latency > 1s for > 5 minutes
- Alert: `HighDatabaseLatency` in Grafana
- Users may report slow page loads
## Most likely causes (in order)
1. Long-running query blocking others
2. Connection pool exhaustion
3. Disk IO saturation
4. Application bug causing query storm
## Diagnostic commands
Check active long queries:
<pre><code class="language-sql">SELECT pid, now() - query_start AS duration, state, query
FROM pg_stat_activity
WHERE state = 'active' AND query_start < now() - interval '30 seconds'
ORDER BY duration DESC;</code></pre>
Check connection pool:
`kubectl exec -it pgbouncer-0 -- psql -U pgbouncer -p 6432 -c 'SHOW POOLS;'`
Check disk IO:
`Grafana dashboard → Database → Disk IO panel`
## Mitigation
If long query found:
- Confirm with team owner of the service.
- Kill query: `SELECT pg_cancel_backend(pid);` (graceful)
- If persists: `SELECT pg_terminate_backend(pid);` (forceful)
If connection pool exhausted:
- Check if app deploy preceded the alert.
- Bounce affected app pods: `kubectl rollout restart deployment/<app>`
- If pool size is wrong: see runbook `IncreaseConnectionPool`.
## Escalation
If unresolved in 15 minutes — page database team:
- PagerDuty: `database-team`
- Slack: `#db-help`
## Related
- [Postmortem 2026-02-14: Long query during deploy](/postmortems/2026-02-14)
- [Runbook: IncreaseConnectionPool](/runbooks/conn-pool)
Семь секций: симптомы, наиболее вероятные причины, диагностика, mitigation, эскалация, связанные документы. Без воды.
Что критично в runbook-е
Команды для копирования. Не «проверьте состояние пула», а конкретный kubectl exec ... SHOW POOLS. В три ночи никто не вспомнит синтаксис.
Конкретные пороги. Не «если высокая нагрузка», а «если CPU > 80% дольше 5 минут».
Decision tree. «Если X — делайте A. Если Y — делайте B». Чтобы дежурный не гадал.
Эскалация с конкретными контактами. Не «обратитесь к команде базы данных», а «PagerDuty: database-team, Slack: #db-help».
Тайминг. «Если за 15 минут не решено — эскалируйте». Без таймера дежурный сам не знает, когда уже звать на помощь.
Чего не нужно в runbook-е
Объяснений «как работает компонент». Если нужны — отдельная страница explanation, на которую runbook ссылается. В runbook — действия, не теория.
Истории про то, как мы пришли к такой архитектуре. Дежурному не нужно знать, что в 2023 году мы перешли с MongoDB.
Слишком общих фраз. «Проверьте логи на наличие ошибок» — бесполезно. «Откройте Loki, фильтр service=notifications level=error за последние 30 минут» — полезно.
Множественных опций. «Можно использовать инструмент A, B или C». Дежурный не знает, какой выбрать. Один способ.
Структура playbook-а по incident management
Playbook — это координационный документ. Структура другая.
# Playbook: Production Incident Response
## Severity levels
- **P0** — total service outage, data loss risk. 24/7 immediate response.
- **P1** — partial outage, major degradation. Response within 1 hour, business hours 24/7.
- **P2** — minor degradation, no user impact. Response next business day.
## Roles during incident
- **Incident Commander (IC)** — coordinates response, makes decisions.
- **Tech Lead (TL)** — investigates, applies fixes.
- **Communications Lead (CL)** — updates stakeholders, status page.
- **Scribe** — records timeline, decisions.
For P2 — IC and TL can be same person.
For P0 — must have all four roles, no exceptions.
## Initial response (first 15 minutes)
1. On-call confirms alert is real (not noise).
2. Declares incident, posts in #incidents channel.
3. Assigns IC role (initially — themselves).
4. Pages additional people based on severity.
5. Opens incident channel in Slack: `#inc-YYYY-MM-DD-short-description`.
## During the incident
- IC keeps focus on resolution, defers post-analysis.
- Updates every 30 minutes in incident channel.
- TL investigates, doesn't implement fix without IC approval (for P0).
- Communications go through CL only.
## Resolution
- Verify metrics back to baseline for > 30 minutes.
- IC declares incident closed in channel.
- Schedule postmortem within 5 business days.
## After the incident
- Postmortem author assigned (usually IC or TL).
- Postmortem reviewed by team within 2 weeks.
- Action items tracked in main project board.
Этот документ нужен команде, в которой инциденты случаются регулярно и требуют координации нескольких людей. Маленьким командам (1-2 разработчика на сервис) playbook избыточен — там всё в одной голове.
Severity matrix
На что чаще всего ругаются on-call: «было ли это P0 или P1»? Без матрицы — спор на ровном месте.
| Severity | User impact | Response | Examples |
|----------|--------------------------------|------------|-----------------------------------|
| P0 | Total outage, data loss risk | 24/7 ASAP | Login broken, payments down |
| P1 | Major degradation | 1h, 24/7 | Slow API, partial feature broken |
| P2 | Minor issue, no user impact | Next day | Internal tool slow, dashboard 404 |
| P3 | Cosmetic | Next sprint| Minor UI glitch |
Конкретные примеры важны, чтобы не было спора «это P1 или P2». Когда не знаешь — округляй вверх. Лишний раз объявить P1 и закрыть проще, чем недореагировать на P0.
Где это всё хранить
Опции:
- Markdown в репозитории сервиса. Хорошо для runbook-ов, привязанных к конкретному сервису. Плохо для playbook-ов, общих для всей организации.
- Отдельный репозиторий runbook-ов. Хорошо для центрального доступа. Все runbook-и команды в одном месте.
- Backstage TechDocs. Если есть — интегрируется с каталогом сервисов.
- Confluence. Удобно для playbook-ов уровня организации, но устаревает быстрее, чем хотелось бы.
Лично я делаю гибрид: runbook-и — в репозитории сервиса, в папке docs/runbooks/; playbook incident management — в общем репозитории платформенной команды.
Связь алертов и runbook-ов
Самое полезное — ссылка на runbook прямо в алерте.
- alert: HighDatabaseLatency
expr: histogram_quantile(0.99, rate(db_query_duration_bucket[5m])) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "Database latency is high"
runbook_url: "https://docs.internal/runbooks/HighDatabaseLatency"
Когда алерт срабатывает, в нотификации (PagerDuty, Slack) — кликабельная ссылка на runbook. Дежурный открывает за один клик. Без неё — сначала нужно понять, какой runbook относится к этому алерту, потом найти его в репозитории.
Поддержание актуальности
Runbook быстро устаревает: сервис мигрировал, имена изменились, команды переименовались. Нужен процесс.
- После каждого инцидента — апдейт связанного runbook-а. «Что было непонятно дежурному, добавляем в runbook». Это action item на постмортем.
- Раз в квартал — review runbook-ов на предмет устаревания. Команда быстро проходит по списку, помечает «устарело», переписывает.
- Game days. Имитация инцидента, дежурный использует runbook. Если что-то непонятно — runbook не работает, поправляем.
Без процесса — runbook через год становится «общим описанием с устаревшими командами», и дежурные перестают на него полагаться.
Что делать новой команде с нулём документов
Если команда только начинает обкладываться runbook-ами:
- Список топ-5 алертов по частоте за последний месяц.
- На каждый — runbook по шаблону. 30-60 минут на каждый.
- Простой playbook incident response: severity matrix + основные роли.
- Связь алертов с runbook-ами (поле
runbook_url). - В каждом постмортеме — апдейт связанного runbook-а как action item.
За месяц у команды есть базовый набор. Дальше расширяется по запросу: новый алерт без runbook-а — добавляем, и так до покрытия 80% инцидентов.
Чек-лист зрелости документации on-call
- Есть runbook на каждый алерт, который может разбудить дежурного ночью.
- Алерты содержат ссылку на runbook.
- Runbook-и в репозитории, в Markdown.
- В каждом — секция эскалации с конкретными каналами и таймером.
- Severity matrix существует и согласована командой.
- Playbook incident response описывает роли, начальные действия, коммуникации.
- После каждого инцидента связанный runbook обновляется.
- Runbook-и проходят game day-ревью раз в квартал.
- Новые члены команды могут разобрать инцидент по runbook-ам без помощи старших.
Документация для on-call — это не дополнительная нагрузка, это инструмент работы. Команда без runbook-ов проигрывает в скорости реакции и держит знание в головах нескольких ключевых людей. Как только эти люди уходят или выгорают — команда оказывается беспомощной. Runbook и playbook не делают команду суперэффективной, но защищают от провалов в самые неудобные моменты.