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

Я регулярно вижу один и тот же сюжет. Сервис падает в третий раз за квартал, дежурный поднимает его за десять минут, потому что уже помнит, что перезапускать, и инцидент закрывается раньше, чем кто-то успел встревожиться. Каждый из трёх разборов честный и по отдельности ничего страшного не показывает. Плохо другое: нигде не записано, что это один и тот же отказ, и четвёртый раз придёт так же буднично, как третий.

Problem Tracking — учёт таких отказов отдельными записями. Проблема здесь — причина или условие, общее для нескольких инцидентов. У записи свой владелец и свой жизненный цикл: заметили серию, разобрали, нашли обходное решение (workaround), исправили, убедились, что серия прекратилась. Словарь пришёл из ITIL, и я беру из него ровно три слова: проблема, известная ошибка (known error) и обходное решение. Остальное — нумерация процессов и отдельная роль на каждый шаг — в продуктовой команде, по моим наблюдениям, не приживается.

Границы с соседями такие. Incident Response отвечает за инцидент: вернуть сервис сейчас. Blameless Postmortem разбирает один инцидент и порождает задачи (action items). Action Items Tracking следит, чтобы эти задачи были выполнены. Запись о проблеме живёт поверх всех трёх: она связывает несколько инцидентов и несколько разборов, и закрыть её можно одним способом — дождаться, что инциденты перестали приходить. Выполненных задач для этого мало.

Главный навык на уровне L4 — закрывать проблему по наблюдению, а не по смерженному исправлению. «Починили» и «перестало повторяться» разделяет время, и я считаю, что вся практика держится на этом зазоре: запись, закрытую в день выкатки, никто не откроет заново, когда отказ вернётся под другим названием. Остальное в списке ниже полезно, но вторично.

L3

  • Закрывая инцидент, ищет похожие за последние месяцы и привязывает его к существующей записи о проблеме; если записи нет, а отказ уже встречался — заводит её со ссылками на оба инцидента.
  • Находит в реестре обходное решение для известной ошибки и применяет его; если оно не помогло, пишет об этом в запись, а не в личные заметки.

L4

  • Заводит запись с рабочим минимумом полей: симптом, связанные инциденты, владелец, статус, обходное решение, влияние в минутах простоя или в доле бюджета ошибок.
  • Переводит проблему в статус known error только при описанном и проверенном обходном решении и ставит дату следующего пересмотра.
  • Назначает окно наблюдения в момент выкатки исправления и закрывает запись, когда окно прошло без повторов.

L5

  • Держит триггеры открытия записи явными и пересматривает их, когда реестр зарастает или пустует: критический инцидент, повтор за период, заметная доля бюджета ошибок на одной причине.
  • Ведёт регулярный смотр реестра: возраст записей, известные ошибки без движения, проблемы, по которым продолжают приходить инциденты. По каждой уходит с решением: чиним, дробим на части или принимаем риск.
  • Переводит влияние проблемы в величины, понятные тем, кто распределяет время команд: часы дежурных, число обращений, деньги. С этими числами идёт договариваться о месте в плане.
  • Распределяет повторяющиеся инциденты между разными людьми, чтобы знание о проблеме не оседало в одной голове.

L6+

  • Сводит проблемы нескольких команд к общему формату: одни и те же поля, связь «инцидент → проблема» прямо в инструменте, общие правила для статуса «риск принят».
  • Назначает владельца проблемам, которые пересекают границы команд, — там, где лежит причина, а не там, где виден симптом.
  • Добивается, чтобы решение «не чиним» принимал тот, кто отвечает за последствия, и чтобы оно пересматривалось по дате, а не по следующей аварии.
  • Betsy Beyer et al. (eds) — Site Reliability Engineering (O’Reilly, 2016), глава 16 «Tracking Outages», автор Gabe Krabbe. Про Outalator — внутренний инструмент Google, который принимает все алерты, склеивает их в инциденты и даёт размечать тегами. Если выбирать одну главу по теме, советую эту: в ней прямо сказано, что постмортемы пишут только по крупным инцидентам, а частые и мелкие в них не попадают.
  • Gene Kim, Kevin Behr, George Spafford — The Phoenix Project (IT Revolution, 2013). Роман, а не справочник. К теме относится линия Брента — инженера, через которого идёт любая авария. Лучшее из известных мне объяснений, почему отказ, который всегда чинит один человек, для организации остаётся невидимым.
  • Cloudflare — Post mortem on the Cloudflare Control Plane and Analytics Outage (2023) и Major data center power failure (again): Cloudflare Code Orange tested (2024). Два разбора одной площадки с разницей в пять месяцев. Читать обязательно парой: первый формулирует проблему, второй показывает, как её закрытие проверили повторным отказом.
  • X5 Tech — Problem Management или как превратить проблемы в возможности (Хабр, 2024). Запуск процесса в большой поддержке, рассказанный без глянца: до перезапуска к проблемам было привязано не больше 3% инцидентов. Возвращаюсь к этой статье за двумя вещами — калькулятором стоимости владения проблемой и комитетом, который решает, что можно признать известной ошибкой.
  • Atlassian — What is problem management?. Открытый пересказ процесса из ITIL: шаги, known error, workaround. Сам ITIL платный, словарь проще сверять здесь. Страница ценна ещё и оговоркой авторов: отдельный тяжёлый процесс превращается в бэклог, куда записи о проблемах уходят умирать.
  • John Allspaw — Each necessary, but only jointly sufficient (Kitchen Soap, 2012). Противовес полю «корневая причина» в карточке проблемы: у сложной системы одной причины нет. Держу под рукой как прививку от записи, в которой серия инцидентов сведена к одной строчке.
  • Трекер команды с отдельным типом записи — Jira, Linear или GitHub Issues с меткой problem и ссылками на инциденты. По моим наблюдениям, команды с несколькими инцидентами в месяц чаще берут именно его: запись о проблеме лежит рядом с задачами, которые её закрывают, и второго инструмента не просит.
  • Jira Service Management, ServiceNow — ITSM-системы, где проблема заведена готовой сущностью со связью на инциденты. Имеет смысл, когда поток обращений идёт через линии поддержки и привязывать инцидент к проблеме приходится сотни раз в день. Для одной продуктовой команды избыточны.
  • Дашборд поверх реестра — возраст открытых записей, инциденты по известным ошибкам, повторы по закрытым проблемам. По моим наблюдениям, его собирают последним, хотя без него смотр реестра превращается в чтение списка вслух.

Лучший известный мне публичный пример того, чем проблема отличается от инцидента, — две аварии Cloudflare на одной площадке. 2 ноября 2023 года дата-центр Flexential в Орегоне, где Cloudflare арендует место, остался без питания. Панель управления и API были недоступны не меньше шести часов, полностью сервисы восстановили только 4 ноября. В разборе инцидентом назван отказ питания, а проблема сформулирована отдельно: часть продуктов зависела от сервисов, которые жили только на этой площадке, а её полное отключение ни разу не проверяли.

Интереснее, что сделали дальше. Под проблему объявили режим Code Orange: руководитель, который вёл инцидент, получил право снять на эту работу любого инженера. В феврале провели проверочное отключение. А 26 марта 2024 года площадка обесточилась снова, уже по-настоящему, и через семь минут API и панель работали без участия людей — об этом второй разбор. В нём же названо то, что осталось: аналитика по-прежнему зависела от площадки, и её простой авторы называют ожидаемым. По сути это запись об известной ошибке, опубликованная наружу.

Из этой истории я забираю три вещи. Питание — чужая зона, повлиять на него Cloudflare не могла; проблемой оказалось то, что лежало в её собственной архитектуре. У проблемы был один владелец, и полномочий ему хватало, чтобы двигать чужие планы. И закрытие проверяли дважды: сначала учебным отключением, потом настоящим.

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

Со статусом known error я вижу путаницу, которая дорого обходится. Под этими словами живут два разных состояния. В пересказе ITIL у Atlassian это проблема с описанной причиной и обходным решением: чинить будем, а пока живём так. В статье X5 Tech известной ошибкой называют проблему, которую решили не устранять, потому что устранение обойдётся дороже, чем жизнь с ней. Оба состояния законны. В одном статусе они слипаются, и через полгода никто не скажет, какие записи ждут исправления, а какие списаны. Мне ближе два разных статуса, и у каждого — дата пересмотра. У X5 есть и защита от злоупотребления: признать проблему известной ошибкой может только комитет, который собирается раз в две недели. Иначе велик соблазн не искать причину, а сменить записи статус.

Закрытие — по наблюдению. Статус «исправление выкачено» промежуточный. Окно наблюдения я привязываю к прошлой частоте отказа: если он приходил раз в две недели, месяц тишины уже о чём-то говорит, а неделя не говорит ничего. Окно записывается в момент выкатки, вместе с признаком, по которому повтор будет опознан. Без признака вернувшийся отказ заведут новым инцидентом с новым названием, и запись останется закрытой.

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

Метрик процессу хватает трёх: сколько инцидентов пришло по уже закрытым проблемам, сколько — по известным ошибкам, и каков возраст открытых записей. Первая говорит, честно ли закрываем. Вторая — во что обходится «живём так». Третья — движется ли реестр вообще. Четвёртую подсказывает опыт X5 Tech: долю инцидентов, привязанных к какой-либо проблеме. До перезапуска процесса она у них не превышала 3%, целью для первых групп поддержки поставили 60%. Там же есть деталь, которую легко проглядеть: привязка инцидента к проблеме занимала около пяти минут — столько же, сколько в среднем уходило на сам инцидент. При такой цене люди перестают привязывать, и метрика охвата врёт. В X5 чинили инструмент, а не дисциплину.

Поле «корневая причина» упрощает больше, чем помогает. В карточке проблемы почти всегда есть поле «корневая причина» (root cause), и оно подталкивает вписать одну строчку. Серия инцидентов редко сводится к одной причине. У истории Cloudflare их минимум три: зависимость от одной площадки, непроверенное полное отключение и порядок, при котором продукты выпускались без обязательной привязки к отказоустойчивому кластеру. Мне ближе два поля вместо одного: «факторы вклада» списком и «что именно перестанет повторяться» одной фразой. Вторая формулировка потом становится критерием закрытия.

У практики есть нижняя граница, и я не уверен, где именно она проходит. Команде, у которой два инцидента в месяц и все помнят оба, реестр проблем не нужен: хватит метки в трекере и привычки спрашивать при закрытии инцидента, было ли такое раньше. Выделенная функция с аналитиками и комитетом окупается на масштабе X5, где счёт обращений идёт на сотни тысяч. Между этими полюсами лежит большинство команд, и там отдельный тяжёлый процесс скорее вредит. По моим наблюдениям, реестр начинает умирать ровно тогда, когда проблемами владеет не тот, кто может их исправить.

  • Blameless Postmortem — разбирает один инцидент; запись о проблеме собирает несколько таких разборов под одной причиной.
  • Action Items Tracking — следит за выполнением задач. Проблема бывает открыта и при закрытых задачах, и это сигнал, что задачи били мимо.
  • Incident Response — закрытие инцидента — единственный момент, когда привязка к проблеме стоит дёшево; позже её уже никто не сделает.
  • Postmortem Database — архив, в котором повторы находят; этот лист — про то, что происходит с повтором после находки.
  • Runbooks — обходное решение известной ошибки живёт в runbook, запись о проблеме на него ссылается.
  • Toil Tracking — обходное решение, которое дежурный выполняет руками каждую неделю, — это toil с известным источником.
  • SLO / Budget Review — там видно, какая доля бюджета ошибок ушла на одну проблему, и там же её ставят в план.
  • Trend Analysis (TBD) — поиск серий по всему потоку инцидентов; в этом листе серия уже найдена.

Окно наблюдения для редких отказов я для себя не закрыл. Если отказ приходил раз в квартал, ждать полгода до закрытия записи формально правильно и на практике бессмысленно: за полгода сменится и сервис, и команда. Хорошего правила у меня нет.

Рядом лежит проблема, причина которой находится у поставщика. Cloudflare не могла починить чужое питание и чинила свою зависимость от него, но так переформулировать удаётся не всегда. Что писать в запись, когда остаётся ждать чужого исправления, и чем она тогда отличается от принятого риска, я пока не знаю.

И про сам словарь. У ITIL появилась новая редакция, Version 5, и выходит она по частям. Судя по описанию на itil.com, практики переходят в неё почти без изменений, но текста редакции я не читал и не знаю, сдвинулись ли определения проблемы и известной ошибки. Если у вас есть доступ к первоисточнику, поправьте меня через PR.