Как одна команда случайно удалила production

За годы работы я собрал внушительную коллекцию рассказанных мне лично или прочитанных в обсуждениях коллег по индустрии историй о том, как одно единственное действие приводило к полному или почти полному уничтожению рабочего окружения продакшена. Хочу пересказать несколько собирательных, максимально обезличенных сюжетов, потому что суть подобных историй повторяется из компании в компанию с пугающим постоянством, и понимание общих паттернов ценнее знания конкретных деталей конкретного случая. Один из самых часто встречающихся сюжетов начинается с попытки очистить устаревшие тестовые ресурсы для экономии бюджета компании. Инженер, ответственный за подобную уборку, пишет скрипт автоматической очистки ресурсов, помеченных как временные или устаревшие, ориентируясь на определенный набор меток или соглашение об именовании. Проблема возникает, когда критично важный production ресурс по случайности или по недосмотру оказывается помечен той же самой меткой, которая используется скриптом как критерий для удаления, обычно потому, что кто-то когда-то в спешке скопировал шаблон конфигурации из тестового окружения, забыв изменить метки на соответствующие продакшену. Скрипт, не имея возможности отличить настоящий тестовый ресурс от production ресурса с ошибочно скопированной меткой, честно и добросовестно выполняет свою работу, удаляя все, что формально попадает под заданный критерий. Другой распространенный сюжет связан с путаницей между несколькими одновременно открытыми терминальными сессиями, подключенными к разным окружениям. Инженер, работающий параллельно с тестовым и производственным окружением в разных вкладках терминала, переключается между ними в процессе отладки некой проблемы, и в какой-то момент, отвлекшись или устав после долгого рабочего дня, выполняет разрушительную команду не в том окне, в котором предполагал, будучи полностью уверен, что работает с безопасным тестовым окружением, а на самом деле находясь в сессии, подключенной к продакшену. Третий сюжет, который мне особенно запомнился по своей коварности, связан с автоматизированным процессом развертывания, который был настроен так, что перед каждым новым развертыванием сначала полностью очищал предыдущее состояние, что было абсолютно разумной практикой для нестабильного экспериментального окружения на самой ранней стадии разработки проекта. Проблема возникла, когда этот же самый процесс развертывания, изначально написанный для крайне ранней и некритичной стадии проекта, со временем без должного пересмотра начал использоваться и для продакшена уже выросшего и ставшего критичным для бизнеса сервиса, унаследовав опасную логику полной очистки состояния, которая была абсолютно уместна на старте проекта, но стала катастрофической миной замедленного действия для зрелого производственного сервиса. Четвертый сюжет связан с недооценкой каскадных зависимостей между ресурсами. Инженер, намереваясь удалить один конкретный, казалось бы, изолированный и уже неиспользуемый ресурс, не до конца осознавал, что от этого ресурса зависят несколько других, формально не связанных с ним напрямую в документации, но фактически опирающихся на его существование в силу исторически сложившейся, нигде явно не задокументированной архитектурной особенности, о которой помнили от силы один два человека в компании, давно уже занятых совершенно другими задачами. Что объединяет все эти истории вне зависимости от конкретных технических деталей, это отсутствие достаточно надежного барьера, который остановил бы разрушительное действие до того, как оно стало необратимым. В каждом случае причиной был не злой умысел, а вполне обычная человеческая невнимательность или недостаточно продуманная автоматизация, к которым нельзя относиться как к редкому исключению, а нужно относиться как к неизбежной и регулярно повторяющейся реальности любой достаточно долго существующей и достаточно сложной инфраструктуры.