Кратко

  • Функция, создававшая отдельного продюсера Kafka на каждый API-запрос, довела число дополнительных продюсеров почти до 4,2 млн в час на пике, истощила память брокеров и нарушила обработку событий, уведомления, интеграции, API, мобильные каналы и публикацию статуса.
  • Первое реагирование восстановило сервис, не выявив и не устранив триггер; повторный сбой в тот же день связал аномальный трафик Kafka с этой функцией и привёл к откату проблемного кода в PagerDuty.

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

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

Рассказ PagerDuty о сбоях 28 августа 2025 года — концентрированный пример. Функция, предназначенная для последующего анализа использования API-ключей, создавала нового продюсера Kafka на каждый API-запрос. На пике, по данным PagerDuty, Kafka отслеживала почти 4,2 млн дополнительных продюсеров в час — в 84 раза больше обычного числа новых продюсеров. Нагрузка на метаданные усилила давление на память брокеров Kafka, довела сборку мусора виртуальной машины Java до перегрузки, исчерпала память кучи и прокатилась каскадом по кластеру, обеспечивавшему асинхронную работу всего сервиса.

Видимый результат был не одним аккуратным сбоем, а смесью отклонённых входящих событий, задержанной обработки, задержанных уведомлений, ошибок API, дублированных или задержанных вебхуков, нарушенных интеграций и обновлений статуса, которые реагировавшие составляли, но клиенты не могли увидеть.

Хронология важна, потому что одно и то же техническое состояние проявилось дважды за один день. Первый инцидент начался в 03:53 UTC. PagerDuty стабилизировала Kafka, восстановила зависимые сервисы, обработала устаревшие задачи и отчиталась о нормальной работе к 10:10 UTC. Компания не выявила и не устранила триггер этой функции во время реагирования. Меньший повторный сбой начался в 16:38 UTC. Реагировавшие повторили прежние меры, обнаружили аномальную структуру трафика, откатили проблемный код и ограничили влияние на клиентов примерно за 50 минут. PagerDuty сообщает, что все сервисы были полностью восстановлены к 20:24 UTC.

Первое восстановление вернуло сервис, но не устранило окончательно исходное условие. Второе реагирование связало симптомы инфраструктуры с изменением ПО.

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

Различие принципиально: ответственность должна следовать за контролем над механизмом, а не за самым узнаваемым названием технологии в стеке.

Доказательства подробны, но это всё же отчёт компании

Фактическая основа этой реконструкции — инженерный постмортем PagerDuty, опубликованный 5 сентября 2025 года. Это первичная операционная запись организации, управлявшей пострадавшей системой. В ней указаны время начала и восстановления, механизм функции, путь диагностики первого реагирования, причина, по которой откат не был выполнен тогда, повторный сбой и многочисленные показатели влияния. Эти детали позволяют провести более строгий анализ, чем набор жалоб в соцсетях или сводка о сбое без источников.

У этого источника есть неизбежное ограничение. Постмортем компании — не независимый аудит. Он подтверждает, что PagerDuty публично заявляла, но сам по себе не может установить опыт каждого клиента, каждое внутреннее решение или каждую последующую потерю. В постмортеме сказано, что PagerDuty сохранила ранее принятые события и данные. Это утверждение не означает, что каждое переданное событие было принято: PagerDuty отдельно сообщает, что часть входящих событий могла быть отклонена, включая ответы 502 от Events API на пике. Это также не значит, что задержанное уведомление никому не навредило.

Это значит более узкое утверждение компании о данных, уже принятых платформой.

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

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

До 03:53 UTC: отчётная функция вышла на критический путь

PagerDuty называет Kafka магистралью своей асинхронной архитектуры. Это описание устанавливает первый важный факт контроля. Kafka не была периферией сервиса. Зависящая от неё работа включала пути обработки, которые связывали входящие события с уведомлениями, интеграциями, вебхуками, чат-системами, мобильными действиями и другими возможностями. Поэтому изменение, увеличившее нагрузку на эту магистраль, несло иной потенциальный радиус поражения, чем изменение, изолированное в некритичном отчётном интерфейсе.

Новая функция должна была поддерживать анализ и отчётность по тенденциям использования API-ключей. PagerDuty ожидала, что её объём будет примерно сопоставим с использованием API-ключей. На первый взгляд это разумная цель продукта: записать сведения об использовании, отправить их в топик Kafka и проанализировать позже, не задерживая исходный запрос. Проблема ответственности возникла не из-за цели, а из-за единицы работы в реализации. Вместо переиспользования продюсера для публикации сообщений функция создавала нового продюсера Kafka на каждый API-запрос.

Это различие легко сжать в одно предложение и легко недооценить. Продюсер не был просто временным локальным объектом без последствий за пределами создавшего его запроса. Kafka должна была отслеживать метаданные каждого продюсера. Повторение этой операции в масштабе API-запросов превратило прикладной трафик в давление на управление и память внутри кластера очередей сообщений. Измеренный пик PagerDuty — почти 4,2 млн дополнительных продюсеров в час — был в 84 раза выше обычной частоты новых продюсеров. Функция не просто добавила ожидаемый поток сообщений об использовании.

Она изменила число идентичностей продюсеров, которыми брокерам приходилось управлять.

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

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

В постмортеме раскрыто поэтапное развёртывание: с 1 % 21 августа до 5 %, затем 25 % 27 августа и 75 % 28 августа; но не раскрыты точный набор предпроизводственных тестов, цепочка согласований и пороги алертов. Было бы необоснованно утверждать, что тестирования не было вовсе или что некий названный сотрудник проигнорировал известную опасность. Обороняемый вывод более узкий: какие бы меры контроля ни существовали, они не помешали схеме «продюсер на запрос» добраться до общей магистрали Kafka, а исходная картина мониторинга не позволила быстро опознать эту схему как источник системного давления на память.

Это способствующее условие, а не само триггерное событие. Код создал возможность аномального роста продюсеров. Живой API-трафик её активировал. Kafka накапливала метаданные. Давление на память брокеров росло. Сборка мусора начинала поглощать ресурсы, не восстанавливая стабильный запас памяти. Затем истощение кучи перевело проблему из неэффективного поведения в отказ сервиса. У каждого шага мог быть свой сигнал. Ответственность отчасти зависит от того, были ли эти сигналы видны вместе или разделены между командами приложений и инфраструктуры.

03:53 UTC: первый сбой выглядел меньше, чем был

PagerDuty указывает 03:53 UTC как начало первого инцидента. Отказ одной из её систем очередей сообщений Kafka вызвал каскадные проблемы, нарушившие или задержавшие обработку новых входящих событий для некоторых клиентов в регионах обслуживания в США. «Некоторые клиенты» и «регионы обслуживания в США» — важные ограничения. Запись не подтверждает утверждение, что все клиенты PagerDuty по всему миру потеряли сервис. Она подтверждает серьёзную деградацию многих функций в рамках сообщённого компанией охвата.

Ранние алерты указывали на отказ одного брокера и возможную аппаратную неисправность. Этот диагноз был достаточно правдоподобен, чтобы направить первое реагирование. Инженеры расширили кластер и удалили один брокер. Эти действия устранили видимый отказавший компонент и увеличили ёмкость. Они не убрали поведение функции, непрерывно создававшей новых продюсеров. Когда дополнительные брокеры исчерпали память, инцидент перестал выглядеть как проблема одного узла. Тогда PagerDuty распознала системную проблему ПО.

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

Назвать раннюю интерпретацию неразумной значило бы выйти за пределы доказательств. Аппаратные неисправности и отказы брокеров — обычные гипотезы, когда алертит один брокер. Вопрос ответственности в том, сделала ли конструкция наблюдаемости системную альтернативу доступной достаточно быстро. Рост создания продюсеров до 84 раз от обычной частоты был характерным сигналом. Потребление кучи брокеров и перегрузка сборки мусора были связанными сигналами. Развёртывание функции — релевантным сигналом изменения. Источник не сообщает, когда каждый из них стал виден реагировавшим и сопоставила ли их одна консоль.

Но он показывает, что связь не была установлена до того, как несколько брокеров исчерпали память.

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

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

Влияние оказалось цепочкой неравнозначных отказов

У инцидентной платформы есть как минимум два важных потока. Она должна принимать и обрабатывать сигналы и превращать их в полезные действия через уведомления и интеграции. Первый сбой PagerDuty затронул оба. На пике часть входящих событий могла быть отклонена с ответами 502 от Events API. Другие события были приняты, но задержаны. Исходящие уведомления, вебхуки, чат-интеграции, включая Slack и Microsoft Teams, операции REST API, подтверждение и закрытие инцидентов в мобильном приложении и ряд корпоративных интеграций были нарушены в разных пропорциях и с разной длительностью.

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

PagerDuty сообщает, что около 14 % событий были задержаны. Отклонение событий достигало пика примерно в 95 % в течение 38 минут. Эти цифры нельзя объединять в утверждение, что 95 % всех событий были безвозвратно потеряны. Они измеряют разные состояния. Компания также сообщает, что около 16 % событий, поступавших по email, были задержаны и менее 1 % не обработаны. Для событий изменений 6,5 % были отклонены в течение 55 минут. Каждое число ограничено категорией и длительностью из постмортема.

На исходящем пути около 23 % уведомлений были задержаны минимум на пять минут в течение 209 минут. PagerDuty сообщает, что уведомления не терялись полностью. Это утверждение успокаивает в одном измерении и серьёзно в другом. Система уведомлений может в конечном счёте доставить каждое сообщение и всё равно не выполнить задачу, чувствительную ко времени. Пять минут — не абстрактная задержка, когда сообщение должно мобилизовать реакцию. Публичная запись не устанавливает, что произошло в инциденте конкретного клиента, поэтому она не может обосновать выдуманную чрезвычайную ситуацию или финансовую потерю.

Но она устанавливает продолжительный период, в котором почти четверть уведомлений, по измерению PagerDuty, пересекла порог задержки в пять минут.

REST API показывал повышенную частоту ошибок около 150 минут. PagerDuty сообщает, что 18,87 % запросов на создание возвращали ответы 5xx в течение 130 минут, а 4,35 % запросов на обновление — в течение 190 минут. Пострадали и мобильные сценарии: 6,06 % пользователей не могли подтвердить или закрыть инциденты через мобильное приложение. Эти отказы могут взаимодействовать. Если уведомление задержано, запрос подтверждения не проходит, а интеграция повторяет позже, запись клиента о том, что и когда знали реагировавшие, может стать менее надёжной, даже если базовые данные инцидента в итоге сохранились.

PagerDuty также перечисляет задержанные или потерянные интеграционные события для Jira, ServiceNow, Salesforce и Zendesk в течение примерно 100 минут. Вебхуки задерживались, терялись или дублировались около 100 минут. Чат-системы испытывали задержки и дубли сообщений. Это не взаимозаменяемые удобства. Клиенты часто встраивают такие выходные данные в создание тикетов, эскалацию, назначение ответственных и аудиторские журналы. Источник PagerDuty не измеряет качество последующей сверки у каждого клиента.

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

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

Страница статуса отказала в момент, когда статус был важен

Первый инцидент нарушил и внешнюю коммуникацию PagerDuty. Компания сообщает, что обновления готовились внутри, но не появлялись публично на странице статуса. Были привлечены дополнительные инженерные команды, и реагировавшие использовали резервные процедуры, чтобы добавлять обновления вручную. PagerDuty фиксирует задержку обновлений страницы статуса примерно в 100 минут.

Это был сбой реагирования, отдельный от корневой причины в Kafka. Дефект функции логически не требовал задержки публичных сообщений. Задержка возникла потому, что процесс, превращавший внутренние знания об инциденте во внешнюю информацию о статусе, не завершился успешно, а резервный путь требовал ручного вмешательства. Страница статуса должна снижать неопределённость клиентов, когда основной сервис деградирует. Если публикация зависит от пути, связанного с пострадавшей средой, или от внешнего процесса, который независимо не проверяется, клиенты могут одновременно потерять и сервис, и авторитетное объяснение.

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

Подготовленное сообщение не имеет операционной ценности для клиента, который не может его увидеть.

Задержка также усложняет диагностику у клиентов. Когда платформа управления инцидентами ведёт себя непоследовательно, клиенты должны определить, перестали ли их собственные отслеживаемые системы отправлять события, отказала ли интеграция или задержалась платформа. Своевременный независимый сигнал статуса может сузить этот поиск. Отсутствующее обновление толкает каждого клиента к локальным проверкам, обращениям в поддержку или догадкам. Такое дублирование диагностической работы — предсказуемое следствие сбоя коммуникации, даже если постмортем его не оценивает количественно.

Стабилизация в 10:10 UTC не означала устранения триггера

PagerDuty сообщает, что все сервисы и системные возможности вернулись к нормальной работе к 10:10 UTC. Для этого потребовалось стабилизировать Kafka и восстановить зависимые от неё сервисы. По мере возобновления обработки клиенты могли получать задержанные уведомления и оповещения, пока PagerDuty разбирала устаревшие сообщения. Некоторые могли получить дубли вебхуков. Поэтому у восстановления был хвост очередей: инфраструктура могла быть стабильной, пока старая работа продолжала поступать в системы клиентов.

Этот хвост — условие восстановления, а не доказательство нового сбоя. Сообщения из очереди нужно обработать или намеренно отбросить по явной политике. PagerDuty сообщает, что ранее принятые события и данные не были потеряны, поэтому обработка бэклога согласуется с сохранностью. Но сохранность порождает вопросы о порядке и своевременности. Клиент, получающий старое оповещение, должен иметь достаточно контекста, чтобы понять, что оно старое. Автоматизированная конечная точка, получающая повтор или дубль, нуждается в идемпотентном поведении или процессе сверки. Платформа и клиент контролируют разные части этой границы.

Более существенное ограничение состояло в том, что проблемная функция не была откачена. PagerDuty прямо объясняет почему: во время первого инцидента триггер не был очевиден, и реагировавшие сосредоточились на стабилизации Kafka. Это утверждение следует воспринимать всерьёз, а не переписывать как намерение или безразличие. Реагирующим на инциденты часто приходится выбирать между восстановлением критической общей системы и расследованием каждой возможной вышестоящей причины. Немедленная стабилизация может быть рациональным приоритетом, когда причинная картина неполна.

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

Это первый сбой восстановления, если быть точным. Он не означает, что восстановительные работы не вернули сервис к 10:10. Он означает, что гарантия восстановления не установила, что триггер устранён, до того как инцидент был признан операционно нормальным. Публичный источник не сообщает, какие условия мониторинга или заморозки изменений действовали в этом интервале. Но он показывает, что тот же класс проблемы с Kafka повторился в 16:38.

16:38 UTC: повторный сбой превратил смягчение в диагностику

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

Повтор обострил доказательства. Объяснение через брокера или аппаратуру больше не могло удобно покрыть весь день. Та же платформа испытала связанный сбой Kafka после первого вмешательства в кластер. У реагировавших теперь были недавний базовый уровень, известные меры смягчения и меньшее окно поиска вокруг изменений и поведения трафика. PagerDuty сообщает, что обнаружила источник аномальных паттернов трафика во время этого реагирования. Как только код функции был связан со всплеском продюсеров, откат устранил исходное условие в ПО, а не только его последствия для памяти.

Различие между «влияние ограничено» и «полностью восстановлено» снова важно. Влияние второго события на клиентов было ограничено примерно за 50 минут, по словам компании. PagerDuty сообщает о полном восстановлении всех сервисов в 20:24 UTC. Эти утверждения могут сосуществовать. Инцидент может перестать причинять новый острый вред, пока зависимые системы, очереди, интеграции и проверки продолжают возвращаться к норме. Сжатие записи до 50-минутного сбоя опустило бы этот интервал восстановления. Называть весь интервал одинаково тяжёлым тоже было бы неточно.

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

Следовательно, мало пользы в том, чтобы ради риторического баланса считать причину спорной. Ответственное различие — между подтверждённым отчётом компании и независимой проверкой, которой нет в использованной здесь публичной записи. PagerDuty публично признала механизм функции. Неизвестное касается внутренней контрольной записи и последствий для клиентов, а не альтернативных обвинений в саботаже, преступлении или умышленных действиях. Ничто в опубликованных доказательствах не поддерживает такие утверждения.

Причинный реестр

Корневой причиной была логическая ошибка функции: создание продюсера Kafka на каждый API-запрос вместо переиспользования продюсера для публикации сообщений об использовании. Эта реализация заставила обычный объём запросов порождать чрезвычайные объёмы метаданных продюсеров. PagerDuty контролировала код функции и архитектуру сервиса, в котором он работал. Это самая глубокая задокументированная причина, поскольку устранение ошибочного поведения убрало исходный механизм.

Триггерным событием было исполнение этого кода в проде в масштабе. API-запросы снова и снова создавали продюсеров, пока Kafka на пике не отслеживала почти 4,2 млн дополнительных продюсеров в час. Триггером не было злонамеренное событие трафика в публичном изложении, и он не был назван дефектом продукта Kafka. Это была встреча поведения функции PagerDuty с продовым объёмом запросов.

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

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

Сбой обнаружения был диагностическим. Алерты изначально указывали реагировавшим на один брокер и возможную аппаратную неисправность. Система обнаружила симптомы отказа, но межслойная корреляция между недавней функцией, ускорением роста числа продюсеров, давлением на кучу брокеров и поведением сборки мусора не дала правильной причины в начале первого события. PagerDuty осознала системный характер только после того, как дополнительные брокеры исчерпали память. Источник аномального трафика она нашла лишь во время повторного сбоя.

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

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

Следствием стал портфель ограниченных влияний, а не единый бинарный сбой. Входящая работа могла отклоняться или задерживаться. Исходящие уведомления могли опаздывать, не теряясь навсегда. API могли возвращать ошибки. Интеграции могли задерживать, терять или дублировать работу. Мобильные пользователи могли не иметь возможности подтвердить или закрыть инцидент. Публичная информация о статусе могла отставать от внутреннего знания. Эти эффекты важны именно потому, что PagerDuty находится между обнаружением и реагированием для своих клиентов.

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

Ответственность следует за контролем, который был у PagerDuty

PagerDuty контролировала дизайн функции. Она решала, как данные об использовании API будут создаваться и отправляться в Kafka. Она контролировала ревью кода, тестовую среду, метод развёртывания и продовую наблюдаемость, хотя публичный источник не раскрывает содержание каждого контроля. Она контролировала общую архитектуру Kafka, ёмкость и алертинг вокруг неё. Она контролировала реагирование на инцидент, процесс публикации статуса, откат и постмортем. Эти контроли делают PagerDuty основным ответственным субъектом за предотвращение, обнаружение, сдерживание, объяснение и исправление этого сбоя.

Основная ответственность не равна неограниченной ответственности за каждое последующее событие. Постмортем не оценивает деловые потери клиентов и не показывает, что каждое задержанное сообщение причинило ущерб. Он не устанавливает договорных последствий. Аналитическое распределение не должно перепрыгивать от «23 % уведомлений были задержаны минимум на пять минут» к общей денежной сумме.

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

У клиентов остались некоторые контроли, но не равнозначные. Клиент мог независимо мониторить собственные системы, сохранять локальные очереди событий, реализовать логику ретраев для ответов 502, сделать потребителей вебхуков идемпотентными, поддерживать альтернативные контакты для эскалации и не считать страницу статуса одного вендора единственным источником истины. Это разумные контроли зависимости. Они не переносят на клиента ответственность за дефект «продюсер на запрос». Клиенты могли смягчить свою подверженность; они не могли проверить или откатить внутреннюю функцию PagerDuty.

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

Kafka нельзя приписывать продуктовый отказ на основе этой записи. Постмортем PagerDuty описывает отслеживание метаданных и поведение памяти Kafka как среду, в которой ошибка функции стала разрушительной. Он не говорит, что Kafka нарушила задокументированную гарантию или содержала дефект, вызвавший событие. Называть это «сбоем Kafka» может быть операционно удобно, поскольку брокеры Kafka исчерпали кучу, но как вывод об ответственности это неполно. Действующая корневая причина была в создании продюсеров PagerDuty и в отсутствии эффективного ограничения этой схемы.

Проблема страницы статуса тоже относится к PagerDuty. Клиенты не контролировали, появятся ли внутренние черновики публично. Устойчивый дизайн коммуникации не должен предполагать, что те же условия, нарушающие сервис, оставят нетронутой каждую зависимость публикации. Доказательства не говорят нам, тестировался ли резервный процесс PagerDuty регулярно. Они говорят, что резерв понадобился и что обновления задерживались примерно на 100 минут. Ответственность после события требует большего, чем заявление, что ручная публикация в итоге сработала; требуются доказательства, что независимый путь достаточно быстр в реалистичных условиях отказа.

Есть и обязанность ответственности в измерениях. Постмортем PagerDuty необычно конкретен в отношении процентов ошибок и длительности. Эта точность помогает пострадавшим организациям избежать интерпретации «всё или ничего». Она также порождает дополнительные вопросы. Рассчитывались ли проценты по всем релевантным запросам или по ограниченной совокупности? Могут ли клиенты получить данные по своему тенанту? Как классифицировались задержанные, потерянные, отклонённые и дублированные выходные данные? Опубликованная сводка на эти вопросы не отвечает.

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

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

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

Чего публичная запись разрешить не может

Постмортем не называет каждого пострадавшего клиента и не оценивает каждый регион количественно. Он говорит, что некоторые клиенты в регионах обслуживания в США испытали нарушение или задержку. Любое более широкое утверждение вышло бы за пределы записи. Он не перечисляет отдельные инциденты, для которых уведомление пришло слишком поздно, и не считает независимо экономический ущерб. Эти пробелы не следует заполнять гипотетическими пострадавшими, поданными как факт.

Запись также не раскрывает полную историю управления функцией. Мы не знаем точное обсуждение на ревью кода, тестовые сценарии, форму нагрузочного теста, этапы развёртывания, передачи дежурным или пороги решений между 03:53 и 10:10. Мы знаем исход: функция достигла прода, число продюсеров взлетело, ранние сигналы были похожи на отказ брокера или аппаратуры, и триггер не был выявлен во время первого инцидента. Этого достаточно, чтобы проверить дизайн контроля, но недостаточно, чтобы обвинить человека в осознанном принятии риска.

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

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

Доказательства со стороны клиентов остаются ещё одной неизвестной. Клиент с локальными журналами запросов, кодами ответов PagerDuty, идентификаторами вебхуков и временными метками уведомлений мог бы точнее реконструировать собственную подверженность. Этих доказательств нет в опубликованном постмортеме. Отсутствие публичного пообъектного реестра не следует читать как доказательство того, что никто не пострадал, и не следует считать разрешением выдумывать вред. Это причина удерживать выводы на уровне, который поддерживают доказательства.

Восстановление полно, только когда устойчивы причина, очередь и запись

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

Ко второму инциденту у реагировавших был известный сценарий стабилизации. Они быстрее ограничили влияние, нашли источник аномального трафика и откатили проблемный код. Полное восстановление в 20:24 закрыло операционный день в более сильном состоянии, чем первое восстановление. Это не стирает более ранний сбой. Это его проясняет: восстановление ёмкости и кластера может выиграть время, но причинное восстановление требует удалить нагрузку, из-за которой ёмкость оказалась недостаточной.

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

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

Центральный урок сдержан, но требователен. Платформа, используемая для управления инцидентами, сама стала источником неопределённости во время двух собственных инцидентов. Задокументированной корневой причиной была логическая ошибка в коде функции PagerDuty. Общая архитектура Kafka и неполная межслойная диагностика способствовали. Первое реагирование восстановило сервис, не убрав триггер. Второе связало аномальный трафик с функцией и откатило её. Никаких необоснованных обвинений не нужно.

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

Источники