Ваша облачная инфраструктура расходится с кодом. Вот как это обнаружить.
Вы написали инфраструктуру как код. Вы запустили terraform plan, проверили вывод и применили изменения. Ресурсы появились в облачной консоли. Команда празднует очередной успешный деплой. Работа сделана.
Но так ли это?
Через неделю кто-то с административным доступом заходит на сервер и вручную правит конфигурацию, чтобы срочно исправить проблему. Команда безопасности добавляет правило файрвола через веб-интерфейс облака, никому не сообщив. Ваш облачный провайдер помечает API-эндпоинт как устаревший, и конфигурация, которая отлично работала в прошлом месяце, теперь молча ничего не делает.
Ни одно из этих изменений не затронуло ваш репозиторий. Ни одно не прошло код-ревью. Ни одно не записано там, где команда сможет его найти позже. Ваша инфраструктура теперь отличается от того, что описано в коде. У вас проблема.
У этой ситуации есть название: дрейф (drift). Это означает, что фактическое состояние вашей инфраструктуры больше не соответствует желаемому состоянию, определённому в коде. Дрейф опасен, потому что он незаметно разрушает обещание инфраструктуры как кода. Если вам нужно воссоздать окружение с нуля, результат будет другим. Если произойдёт инцидент, вы не сможете доверять тому, что запуск того же кода восстановит безопасное состояние. Вы потеряли способность надёжно воспроизводить инфраструктуру.
Как возникает дрейф на практике
Дрейф вызывают не злоумышленники и не некомпетентные команды. Он возникает из-за обычных, благонамеренных действий, которые обходят пайплайн.
Разработчику нужно быстро что-то протестировать, и он вручную меняет правило группы безопасности. Администратор базы данных корректирует параметр, чтобы справиться с внезапным скачком нагрузки. Инженер платформы патчит сервер напрямую, потому что автоматический процесс патчинга занимает слишком много времени. Каждое из этих действий в данный момент имеет смысл. Каждое из них создаёт разрыв между тем, что говорит ваш код, и тем, что на самом деле работает.
Проблема накапливается со временем. Одно ручное изменение становится двумя, потом десятью. Через несколько месяцев инфраструктура, работающая в продакшене, мало напоминает код в вашем репозитории. В следующий раз, когда кто-то запустит terraform apply, ожидая чистое состояние, он получит длинный список неожиданных изменений. Никто не знает, какие изменения намеренные, а какие — случайные. Доверие к коду инфраструктуры подрывается.
Обнаружение дрейфа до того, как он вызовет проблемы
Решение — не запрещать ручные изменения. Иногда нужно действовать быстро, а пайплайн слишком медленный. Решение — автоматически и регулярно обнаруживать дрейф, чтобы знать о нём до того, как он приведёт к инциденту.
Обнаружение дрейфа — это процесс, который сравнивает фактическое состояние вашей инфраструктуры с желаемым состоянием в коде. Он запускается по расписанию или по определённым событиям. Когда находятся различия, записываются детали: какой ресурс изменился, какая часть конфигурации отличается и каким должно быть правильное значение.
Большинство инструментов инфраструктуры как кода поддерживают обнаружение дрейфа нативно. У Terraform есть terraform plan, который показывает различия между состоянием и конфигурацией. У Pulumi есть команды preview. У AWS CloudFormation есть встроенное обнаружение дрейфа. Ключ в том, чтобы запускать эти проверки автоматически, а не только когда кто-то вспомнит об этом.
Вот простая команда, которую можно запустить в CI-пайплайне для автоматического обнаружения дрейфа:
#!/bin/bash
# Запуск terraform plan с выходом по ненулевому коду при обнаружении дрейфа
terraform init -input=false
terraform plan -detailed-exitcode -input=false -out=tfplan
PLAN_EXIT_CODE=$?
if [ $PLAN_EXIT_CODE -eq 2 ]; then
echo "Обнаружен дрейф! Инфраструктура не соответствует коду."
# Отправка оповещения в Slack или систему управления инцидентами
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"Обнаружен дрейф в продакшен-окружении. Запустите terraform apply для синхронизации."}' \
YOUR_SLACK_WEBHOOK_URL
exit 1
elif [ $PLAN_EXIT_CODE -eq 1 ]; then
echo "Ошибка при выполнении terraform plan."
exit 1
else
echo "Дрейф не обнаружен. Инфраструктура соответствует коду."
fi
Этот скрипт использует флаг -detailed-exitcode, чтобы различать чистое состояние (код возврата 0), ошибку (код 1) и дрейф (код 2).
Встраивание обнаружения дрейфа в ваш пайплайн
Практический пайплайн обнаружения дрейфа выглядит так:
Вот визуальное представление пайплайна обнаружения дрейфа:
Настройте регулярные проверки. Запускайте обнаружение дрейфа каждые несколько часов или ежедневно, в зависимости от критичности инфраструктуры. Для продакшен-окружений лучше более частые проверки. Для стейджинга может быть достаточно ежедневных.
Запускайте по подозрительным событиям. Некоторые облачные провайдеры генерируют события при изменении ресурсов вне вашего пайплайна. Используйте вебхуки или журналы событий для запуска проверки дрейфа при возникновении таких событий.
Сообщайте о результатах. При обнаружении дрейфа отправляйте уведомление команде. Используйте Slack, email или создавайте задачу в трекере. Уведомление должно содержать информацию о том, какие ресурсы изменились и какими должны быть ожидаемые значения.
Дайте команде решить, что делать. Не весь дрейф вреден. Ручное изменение может быть легитимным и должно быть включено в код. Другое изменение может быть случайным и требует отката. Команда должна видеть дрейф и принимать решение.
Автоматическая синхронизация: действуйте с осторожностью
Некоторые команды идут дальше и автоматизируют исправление. Когда пайплайн обнаруживает дрейф, он немедленно запускает apply, чтобы вернуть инфраструктуру в желаемое состояние. Этот подход хорошо работает для окружений, которые должны оставаться консистентными, например, стейджинг или строго контролируемые продакшен-системы.
Но у автоматической синхронизации есть риски. Рассмотрим автоскейлинг: ваш код инфраструктуры определяет минимальное и максимальное количество инстансов. Группа автоскейлинга добавляет инстансы в зависимости от нагрузки. Запуск обнаружения дрейфа видит лишние инстансы как дрейф и завершает их. Ваши пользователи столкнутся с простоем, потому что система делала именно то, что должна была.
Правило большого пальца: автоматизируйте синхронизацию только для ресурсов, которые никогда не должны меняться вне пайплайна. Для всего остального уведомляйте команду и дайте ей решить.
Практический чек-лист обнаружения дрейфа
Вот краткий чек-лист, который поможет начать работу с обнаружением дрейфа:
- Выберите расписание для проверок дрейфа (каждые 6 часов для продакшена, ежедневно для стейджинга)
- Настройте уведомления в нужный канал (Slack, email или система управления инцидентами)
- Определите, для каких окружений будет автоматическая синхронизация, а для каких — ручное рассмотрение
- Протестируйте процесс обнаружения дрейфа, сделав небольшое ручное изменение и проверив, приходит ли оповещение
- Еженедельно просматривайте отчёты о дрейфе всей командой, чтобы выявить паттерны или повторяющиеся проблемы
Что даёт обнаружение дрейфа
Обнаружение дрейфа не предотвращает ручные изменения. Оно не устраняет необходимость реагирования на инциденты. Что оно делает — даёт вам видимость разрыва между вашим кодом и реальностью. Когда вы знаете о дрейфе, вы можете решить, принять его, откатить или обновить код, чтобы отразить его.
Без обнаружения дрейфа ваша инфраструктура как код — это фикция. Вы можете верить, что ваша система воспроизводима, но у вас нет способа это проверить. С обнаружением дрейфа ваш код остаётся единственным источником истины, потому что вы активно поддерживаете эту истину.
В следующий раз, когда кто-то скажет «мы используем инфраструктуру как код», спросите их: «Откуда вы знаете, что ваша инфраструктура всё ещё соответствует вашему коду?» Если они не смогут ответить, у них есть дрейф. А дрейф — это бомба замедленного действия, которая взорвётся во время следующего инцидента.