MAATRIX / Блог / Как писать разбор инцидента, чтобы из него учились

Как писать разбор инцидента, чтобы из него учились

MAATRIX

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

Зачем нужен разбор инцидента и чем он не является

Разбор инцидента (postmortem, incident review) — документ, который команда пишет после устранения проблемы с одной целью: понять, что именно в процессах, инструментах и архитектуре позволило проблеме случиться и остаться незамеченной, и изменить это так, чтобы похожая ситуация либо не повторилась, либо была обнаружена и устранена быстрее в следующий раз. Разбор не предотвращает вообще любые будущие сбои — он закрывает конкретный класс проблем, с которым команда только что столкнулась.

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

Хороший разбор смотрит и в прошлое, и в будущее: фиксирует, что произошло на самом деле, и превращает это знание в конкретное изменение. Без первого не будет второго — если хронология и причина размыты, action items окажутся либо лозунгами вроде «повысить внимательность», либо промахнутся мимо настоящей проблемы.

Blameless-принцип: почему нельзя искать виноватого

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

Механизм простой и жестокий. Как только в компании закрепляется практика, что разбор заканчивается наказанием конкретного человека — выговором, депремированием, разбором «кто накосячил» перед начальством, — люди рационально начинают вести себя иначе. Инженер, который сам по ошибке отключил алертинг на час, в blame-культуре промолчит об этом или сформулирует расплывчато: «мониторинг не сработал» вместо «я вручную отключил алерт на время техработ и забыл включить обратно». Формально это тоже правда, но она не даёт понять реальный механизм отказа — и та же причина может повториться незамеченной.

Это не гипотетическая проблема, а динамика, знакомая по авиации и медицине задолго до IT: там, где ошибка означает наказание, свидетели перестают о ней сообщать, и система становится менее безопасной, а не более — она теряет доступ к информации, нужной для исправления. Именно поэтому в авиации действует культура добровольных отчётов без наказания за сам факт отчёта — эту логику индустрия ПО и заимствовала под названием blameless postmortem.

Практически это означает: в тексте разбора не должно быть формулировок, которые называют человека причиной проблемы, даже завуалированно.

Плохо (обвинительная формулировка):

  • «Иван выкатил миграцию без ревью и уронил базу»
  • «Дежурный проспал алерт и продлил простой на 40 минут»
  • «Разработчик не протестировал код перед деплоем»

Хорошо (системная формулировка того же факта):

  • «Процесс деплоя миграций на тот момент не требовал обязательного ревью для изменений схемы БД — это позволило потенциально опасному запросу попасть в прод»
  • «Алерт по этому каналу не эскалируется повторно и не дублируется на второй канал, если дежурный не отреагировал за 5 минут — из-за этого сработавшее уведомление осталось непрочитанным 40 минут»
  • «В pipeline деплоя нет обязательного шага автотестов для этого сервиса — изменение попало в прод без прогона регрессионных тестов»

Во втором варианте каждый раз называется система — процесс, конфигурация алертинга, состав pipeline, — а не человек, при этом факт не искажается. Суть blameless-подхода не в том, чтобы никого не обвинять и всё замять, а в том, чтобы задавать правильный вопрос: не «кто это сделал», а «что в системе позволило этому случиться и не быть замеченным раньше». Если один инженер одним действием уронил прод-базу, значит, в системе нет защиты от такого действия — а защита нужна именно потому, что люди ошибаются, это рабочая гипотеза, вокруг которой строится инженерия надёжности. Похожий взгляд — не искать «крайнего», а чинить процесс — разбирался в статье про почему мониторинг есть, а инцидент всё равно никто не заметил.

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

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Хронология событий: факты без интерпретации

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

Что обязательно попадает в хронологию:

  • момент, когда проблема реально началась технически (если известен — часто выясняется только в процессе расследования);
  • момент обнаружения — кто или что заметило проблему и в какое время;
  • ключевые действия по диагностике и купированию — что проверяли, что сработало и что нет;
  • момент, когда воздействие на пользователей прекратилось (mitigated) — не всегда совпадает с полным разрешением;
  • момент полного разрешения (resolved) — когда причина устранена и риск повтора снят.

Формат — простая таблица времени в UTC или в едином часовом поясе команды (важно указать явно, иначе при разборе через месяц никто не вспомнит, в каком поясе были отметки):

| Время (UTC) | Событие |
|---|---|
| 02:14 | Начались 502 от API согласно логам nginx (обнаружено post-factum) |
| 02:31 | Алерт в Telegram: доля 5xx > 5% на /api/orders |
| 02:33 | Дежурный инженер увидел алерт, начал диагностику |
| 02:41 | Обнаружено: под БД достиг лимита max_connections (200/200) |
| 02:47 | Перезапущен pgbouncer, соединения освобождены — 5xx прекратились |
| 02:50 | Подтверждено восстановление по метрикам, простой закрыт как mitigated |
| 10:20 | Найдена причина исчерпания пула — см. корневую причину ниже, resolved |

Mitigated (02:50) и resolved (10:20) — разные моменты, и это нормально: проблему часто быстро купируют, не понимая ещё до конца, почему она возникла, а расследование корневой причины занимает часы или дни уже без давления «пользователи страдают прямо сейчас». Указывать оба момента честно — часть хорошей хронологии.

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

Реальное воздействие на пользователей и бизнес

Второй раздел — честная оценка того, насколько серьёзной была проблема на самом деле, без преуменьшения и без драматизации. Воздействие определяет приоритет action items из раздела ниже: проблема, задевшая 0.1% запросов на 3 минуты, и проблема, положившая checkout на час, заслуживают разного объёма работы над предотвращением повтора. Заниженная оценка «да несерьёзно, пара минут» обычно оказывается способом избежать неприятного разговора, а не отражением реальности.

Что стоит включить:

  • сколько времени длилось воздействие на пользователей (до момента mitigated, а не resolved);
  • какая доля пользователей/запросов была затронута — числом из метрик («28% запросов к /checkout получили 500 в течение 16 минут»), а не словами «многие» или «часть»;
  • что именно пользователь видел или не мог сделать — конкретное действие («не могли оформить заказ», «получали письма с задержкой до 40 минут»);
  • была ли потеря данных, и если да — какого рода и в каком объёме;
  • есть ли измеримые бизнес-последствия — упущенные заказы, обращения в поддержку; здесь уместно оговорить, что цифра ориентировочная, если это оценка.

Если у сервиса есть публичная status-страница, запись из неё с точными метками — хороший объективный якорь, независимый от внутренних логов. Стоит также писать «SEV-уровень» инцидента (SEV1 — критично, весь сервис недоступен; SEV2 — деградация ключевой функции; SEV3 — незначительное воздействие) — это помогает быстро оценивать серьёзность по списку прошлых разборов.

Корневая причина: копаем до технического механизма

Здесь чаще всего разбор проваливается по качеству, даже без всякой охоты на виноватых — просто потому что первая правдоподобная причина, приходящая в голову во время тушения пожара, обычно неполная. «Сервер упал» — не корневая причина, а симптом. Хорошая корневая причина отвечает на вопрос «почему» столько раз, сколько нужно, чтобы дойти до механизма, который действительно можно исправить.

Плохо (симптом вместо причины):

  • «Сервер упал из-за нехватки памяти»
  • «База данных стала недоступна»
  • «Диск заполнился, сервис перестал писать логи и упал»

Хорошо (доведено до технического механизма):

  • «Процесс упал по OOM, потому что фоновая задача экспорта отчётов грузила весь датасет в память вместо постраничной обработки; лимит памяти контейнера не был выставлен, поэтому OOM убил весь под целиком»
  • «БД стала недоступна, потому что пул соединений pgbouncer был исчерпан долгими запросами от новой аналитической выгрузки, не использовавшей read-replica и не имевшей таймаута на клиенте»
  • «Диск заполнился логами из-за отсутствия ротации на новом сервисе (см. типичную грабля «логи без ротации») — при 100% диска systemd не смог создать файл блокировки, и сервис ушёл в краш-луп»

Практический метод — простое «5 почему»: берёте первый ответ и спрашиваете «почему» ещё раз, пока не упрётесь в механизм, который можно изменить. «Сервер упал» → почему? «Кончилась память» → почему? «Процесс экспорта грузил весь датасет разом» → почему? «Не было лимита памяти на контейнер» → почему не было лимита? «В шаблоне деплоя новых сервисов лимиты не заданы по умолчанию» — вот это уже action item.

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

Конкретные action items: кто, что, когда

Разбор без раздела действий на будущее — просто рассказ о прошлом, каким бы честным он ни был. Смысл всей предыдущей работы — превратить понимание причины в измеримое изменение системы. Здесь тоже легко скатиться в бесполезную формулировку, только не обвинительную, а расплывчатую.

Плохо (не действие, а лозунг):

  • «Быть внимательнее при деплое миграций»
  • «Улучшить мониторинг»
  • «Повысить качество ревью кода»

Хорошо (конкретное, проверяемое, с владельцем и сроком):

| Действие | Ответственный | Срок |
|---|---|---|
| Добавить обязательный лимит memory/cpu в шаблон Helm-чарта для новых сервисов | Петров (платформа) | до 12.09 |
| Настроить алерт на % использования пула pgbouncer > 80% | Сидорова (SRE) | до 08.09 |
| Вынести аналитические выгрузки на read-replica, запретить прямые запросы к мастеру из BI-инструмента | Козлов (данные) | до 20.09 |
| Добавить в CI обязательный шаг: миграции схемы требуют approve от второго инженера | Иванов (бэкенд) | до 10.09 |
| Добавить кейс «пул соединений исчерпан долгими BI-запросами» в регрессионные проверки перед релизом инфраструктуры | Сидорова (SRE) | до 15.09 |

Каждый пункт можно однозначно проверить — «сделано» или «не сделано» — в отличие от «быть внимательнее», которое нельзя ни выполнить, ни провалить формально. Тот же принцип — конкретный случай идёт в постоянную проверку, а не в разовое обещание быть внимательнее — разбирался применительно к качеству ответов ИИ-моделей в статье про батарею тестов для своей LLM: нашли провал — добавили его тест-кейсом в регрессионный набор. С инфраструктурой логика та же: нашли failure mode — превратили в алерт, тест, лимит или обязательный шаг процесса.

Владелец должен быть конкретным человеком, а не отделом целиком («SRE-команда») — иначе ответственность размазана и её нет ни у кого. Срок должен быть реалистичным, но не бесконечным — важная задача попадает в ближайший спринт, а не в бэклог «когда-нибудь». Имеет смысл назначить отдельного человека ответственным за проверку статуса всех пунктов через оговорённый срок: без этого action items имеют тенденцию тихо забываться.

Разбирайте не только крупные инциденты

Самая частая практическая ошибка — писать разборы только для по-настоящему серьёзных, «пожарных» инцидентов, а мелкие сбои (пятиминутный всплеск 500-х, разовый деплой с откатом, ложный алерт) оставлять без документа вовсе, потому что «несерьёзно, не стоит бюрократии». Это ошибка сразу по двум причинам.

Во-первых, мелкий сбой — дешёвый источник того же системного знания, что и крупный, но без цены крупного простоя. Разобрав пятиминутный всплеск 500-х по той же методике, часто находишь ровно ту же уязвимость, которая через два месяца при более высокой нагрузке превратится в часовой простой.

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

Практический ориентир: для мелких инцидентов документ можно сократить до одной страницы — короткая хронология, строка воздействия, пара строк причины, один-два action item. Полный формат с таблицей по часам стоит держать для инцидентов выше определённого порога серьёзности (SEV1/SEV2), иначе именно избыточная бюрократия для мелочей и убьёт саму привычку писать разборы.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Через сколько времени после инцидента нужно писать разбор?

Пока хронология свежа в памяти — обычно в течение 24–48 часов после resolved. Если тянуть неделями, детали стираются, а разбор рискует не состояться вовсе.

Кто должен писать разбор — тот, кто чинил инцидент?

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

Нужно ли показывать разбор всей компании, а не только команде?

Для значимых инцидентов — да, системные уроки одной команды часто применимы к другим; для мелких разборов достаточно видимости внутри команды.

Что делать, если причина — реальная ошибка одного человека, например случайно набранная не та команда?

Формулировать системно всё равно: не «Иван набрал не ту команду», а «в проде остаётся возможность выполнить разрушительное действие одной командой без подтверждения» — и решение искать в защите (dry-run, ограничение прав), а не в осуждении человека.

Как понять, что разбор написан хорошо?

Покажите документ человеку, не участвовавшему в инциденте. Если он может объяснить, что случилось, насколько серьёзно, из-за какого механизма и что теперь изменится — разбор состоялся.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →