Инфраструктура редко ломается громко. Чаще она тихо уходит в сторону: кто-то вручную меняет security group, провайдер обновляет параметр по умолчанию, срочный хотфикс попадает в продакшен напрямую через консоль, а Terraform всё ещё считает, что мир выглядит как вчера. На первый взгляд всё работает. Но именно в такие моменты появляется Terraform drift — расхождение между тем, что описано в коде и state, и тем, что реально живёт в облаке.
Проблема drift не в самом факте изменения. Инфраструктура меняется постоянно, и это нормально. Опасность в другом: команда перестаёт понимать, чему верить — Terraform-коду, state-файлу, облачной консоли или словам коллеги из соседнего чата. Когда источник правды расплывается, каждый следующий deploy становится похож на прогулку по тёмной серверной с фонариком на телефоне.
Разберёмся, как обнаруживать drift, как превращать его в понятные отчёты, и что делать дальше: откатывать изменения, принимать их в код или аккуратно переносить ресурсы под управление Terraform.
Оглавление
- Что такое Terraform drift простыми словами
- Почему drift появляется даже в аккуратных командах
- Почему drift опасен
- Как Terraform обнаруживает drift
- Drift detection в CI/CD
- Как сделать отчётность по drift понятной
- Remediation: что делать, когда drift найден
- Сценарий 1. Откатить реальность к коду
- Сценарий 2. Принять реальность и обновить код
- Сценарий 3. Обновить state без изменения ресурсов
- Что делать с ресурсами, созданными вне Terraform
- Когда использовать `ignore_changes`
- Drift и refactoring: не путайте расхождение с переездом ресурсов
- Практический workflow для команды
- Политики и guardrails
- Типичные ошибки при работе с drift
- Пример процесса remediation
- Как понять, что процесс работает
- Terraform drift — это не враг, а сигнал
- Итог
Что такое Terraform drift простыми словами
Terraform drift — это ситуация, когда реальная инфраструктура больше не совпадает с тем состоянием, которое Terraform ожидает увидеть.
Представьте склад, где всё должно лежать по подписанным полкам. В учётной системе написано: «на третьей полке лежит один сервер с такими-то параметрами». Но кто-то ночью переставил его, добавил ещё одну коробку и поменял этикетку. Пока никто не сверяет склад с учётной системой, кажется, что порядок сохранён. Но первая же инвентаризация покажет сюрприз.
В мире Terraform такими «полками» являются:
- конфигурация в
.tfфайлах; - Terraform state;
- реальные ресурсы у провайдера — в AWS, Azure, Google Cloud, Kubernetes, VMware или другой платформе.
Drift появляется, когда эти три слоя расходятся.

Мини-пример
В Terraform описан security group rule:
resource "aws_security_group_rule" "ssh" { type = "ingress" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["10.0.0.0/8"] security_group_id = aws_security_group.app.id}Во время инцидента инженер вручную открывает доступ с 0.0.0.0/0, чтобы быстро подключиться к серверу. Проблему решили, но правило не вернули обратно.
Код говорит одно. Реальность — другое. Это и есть drift.
Готовы перейти на современную серверную инфраструктуру?
В King Servers мы предлагаем серверы как на AMD EPYC, так и на Intel Xeon, с гибкими конфигурациями под любые задачи — от виртуализации и веб-хостинга до S3-хранилищ и кластеров хранения данных.
- S3-совместимое хранилище для резервных копий
- Панель управления, API, масштабируемость
- Поддержку 24/7 и помощь в выборе конфигурации
Результат регистрации
...
Создайте аккаунт
Быстрая регистрация для доступа к инфраструктуре
Почему drift появляется даже в аккуратных командах
Terraform drift часто воспринимают как признак плохой дисциплины. На практике всё сложнее. Даже зрелые команды сталкиваются с расхождениями, потому что инфраструктура живёт не в вакууме.
Ручные изменения в облачной консоли
Самая очевидная причина — кто-то меняет ресурс напрямую. Иногда это срочный фикс. Иногда тест. Иногда «я только посмотрю» превращается в «я немного поправил».
Такое случается не потому, что инженеры безответственные. Часто причина в давлении времени. Когда продакшен лежит, кнопка в облачной консоли кажется короче, чем pull request, review и pipeline.
Но у ручного изменения есть цена: если его не зафиксировать в коде, Terraform однажды попытается вернуть инфраструктуру к старому описанию. И не всегда это будет безболезненно.

Автоматические изменения со стороны провайдера
Некоторые параметры могут меняться без участия команды. Провайдер обновил значение по умолчанию, добавил вычисляемый атрибут, поменял формат ответа API — и Terraform при следующем plan видит разницу.
Пример из жизни: у managed-сервиса появляется новый системный тег или меняется порядок элементов в списке. Ресурс работает как раньше, но план начинает шуметь.
Такой drift не всегда опасен, но он засоряет картину. А когда в отчёте десять «безобидных» изменений, легко пропустить одно действительно важное.
Изменения вне Terraform
Инфраструктуру может менять не только человек. Есть скрипты, autoscaling, Kubernetes controllers, cloud policies, security tools, backup-системы, операторы и внутренние платформы.
Например, политика безопасности автоматически добавляет тег owner ко всем ресурсам. Terraform об этом не знает и каждый раз показывает изменение. Формально это drift. По смыслу — результат работы другого управляющего слоя.
Здесь важно договориться: кто владеет конкретным атрибутом? Terraform? Провайдер? Внутренняя платформа? Security automation?
Без этого IaC превращается в спор нескольких дирижёров, которые одновременно машут палочками перед одним оркестром.

Неправильный или устаревший state
State — чувствительная часть Terraform. Он хранит связь между кодом и реальными объектами. Если state повреждён, устарел, скопирован вручную или используется несколькими процессами без блокировки, drift может проявляться странно.
Например, ресурс существует в облаке, но Terraform больше не видит его в state. Или наоборот: state считает, что объект есть, а провайдер сообщает, что его удалили.
Поэтому backend, блокировка state и понятный workflow — не бюрократия, а страховка.

Почему drift опасен
Drift редко выглядит драматично в момент появления. Он становится опасным позже — когда команда запускает очередной terraform apply и получает неожиданный план.
Неожиданные изменения при deploy
Terraform стремится привести реальность к конфигурации. Если реальность изменилась вручную, следующий apply может откатить эти изменения.
Иногда это хорошо. Например, если кто-то случайно открыл лишний порт, Terraform вернёт безопасное состояние.
Но бывает наоборот. Ручное изменение могло быть нужным хотфиксом, который забыли перенести в код. Тогда apply удалит его, и проблема вернётся.
Вопрос, который стоит задавать после каждого drift: это случайный мусор или новая реальность, которую нужно признать?

Риск для безопасности
Security drift — один из самых неприятных видов расхождения.
Открытый порт, ослабленная IAM policy, отключённое шифрование, изменённый firewall rule, публичный bucket — всё это может не ломать сервис напрямую. Более того, приложение может работать идеально. Но риск уже появился.
Здесь Terraform drift становится не просто DevOps-задачей, а частью compliance и security governance.
Потеря доверия к IaC
Если планы Terraform регулярно показывают неожиданные изменения, команда постепенно перестаёт воспринимать их как источник правды.
Сначала инженеры говорят: «Это опять шум, можно игнорировать». Потом пропускают важное изменение. Потом боятся запускать apply без ручной проверки в облачной консоли.
Так IaC теряет главный смысл — предсказуемость.

Как Terraform обнаруживает drift
Terraform не имеет магического радара, который постоянно следит за облаком. Обычно drift обнаруживается во время планирования, когда Terraform читает состояние удалённых объектов через provider API и сравнивает его с тем, что знает сам.
Команда terraform plan создаёт execution plan. При обычном режиме Terraform сначала обновляет информацию о существующих удалённых объектах, затем сравнивает конфигурацию с текущим состоянием и предлагает действия, которые приведут инфраструктуру к описанию в коде.
На практике это значит: если объект изменили вручную, Terraform часто увидит это на следующем plan.
Обычный terraform plan
Базовая команда:
terraform planОна отвечает на вопрос: «Что нужно сделать, чтобы реальная инфраструктура соответствовала текущему Terraform-коду?»
Если drift есть, Terraform может показать блок вроде:
Note: Objects have changed outside of TerraformПосле этого в плане будут предложены действия: обновить ресурс, пересоздать его, удалить лишнее или изменить state.
Важно не читать план по диагонали. Drift может быть спрятан среди обычных изменений в коде. Поэтому для регулярной проверки соответствия реальности лучше отделять drift detection от планирования новых изменений.

terraform plan -refresh-only
Режим -refresh-only помогает сфокусироваться именно на расхождении между state и реальными объектами.
terraform plan -refresh-onlyЭта команда отвечает на другой вопрос: «Что изменилось в реальности по сравнению с тем, что записано в state?»
Она не планирует приводить инфраструктуру к коду. Она показывает, как изменился бы state, если принять текущую реальность как факт.
Хорошая аналогия: обычный terraform plan — это план ремонта квартиры по проекту. plan -refresh-only — это обход квартиры с блокнотом: что уже не соответствует старой описи?

terraform apply -refresh-only
Команда:
terraform apply -refresh-onlyобновляет state в соответствии с реальностью, не изменяя сами ресурсы.
Звучит удобно, но использовать её нужно осознанно. Если просто принять drift в state, не разобравшись в причине, можно узаконить ошибку. Например, открытый доступ к базе данных станет «новой нормой» для Terraform state, хотя в коде команда может всё ещё видеть другую картину.
Правило простое: apply -refresh-only — не кнопка «исправить всё». Это инструмент синхронизации state после анализа.
Drift detection в CI/CD
Ручная проверка полезна, но она быстро надоедает. Команда может помнить о drift неделю, потом появляется релиз, инцидент, отпуск, срочная миграция — и проверка исчезает.
Поэтому drift detection лучше встроить в регулярный процесс.
Зачем нужен -detailed-exitcode
Флаг -detailed-exitcode делает Terraform удобным для автоматизации:
terraform plan -refresh-only -detailed-exitcodeЛогика такая:
0— команда выполнилась, изменений нет;1— ошибка;2— команда выполнилась, изменения есть.
Для CI это почти идеальный светофор. Зелёный — всё совпадает. Красный — pipeline сломан. Жёлтый — drift найден, нужен разбор.
Пример shell-логики:
terraform init -input=falseterraform plan -refresh-only -detailed-exitcode -no-color -out=tfplancode=$?if [ "$code" -eq 0 ]; then echo "No drift detected"elif [ "$code" -eq 2 ]; then echo "Drift detected" terraform show -no-color tfplan > drift-report.txt exit 0else echo "Terraform plan failed" exit 1fiЗдесь drift не обязательно ломает pipeline. Часто лучше создать отчёт и отправить уведомление, а не блокировать всё подряд. Особенно если проверка запускается по расписанию.

Где запускать проверки
Есть несколько рабочих вариантов:
- По расписанию — например, ночью или раз в несколько часов.
- Перед релизом — чтобы не смешивать drift с изменениями в коде.
- После инцидента — если во время восстановления были ручные правки.
- После крупных миграций — когда часть ресурсов могла быть изменена сторонними инструментами.
Для небольших проектов достаточно ежедневной проверки. Для критичной инфраструктуры лучше запускать drift detection чаще и разделять окружения: production, staging, shared services.

Не превращайте drift detection в шумовую сирену
Самая частая ошибка — включить проверку, получать десятки уведомлений и через неделю перестать их читать.
Drift detection должен быть полезным, а не громким. Если план постоянно показывает одно и то же «ожидаемое» изменение, разберитесь с ним: добавьте ignore_changes, поправьте provider version, уточните ownership атрибута или обновите код.
Хороший отчёт по drift похож на короткую записку от внимательного коллеги: что изменилось, где, насколько это важно и кто должен посмотреть.
Как сделать отчётность по drift понятной
Сам по себе вывод Terraform может быть тяжёлым для восприятия. Инженер разберётся. Менеджер платформы, security-команда или владелец сервиса — не всегда.
Поэтому отчётность должна переводить Terraform-plan на человеческий язык.
Что должно быть в отчёте
Минимальный полезный отчёт включает:
- workspace или путь к Terraform-проекту;
- окружение: production, staging, dev;
- время проверки;
- список ресурсов с drift;
- тип изменения: update, delete, create, replace;
- краткое описание риска;
- рекомендуемое действие;
- ссылку на полный plan или артефакт CI.
Например:
Environment: productionStack: network-coreResource: aws_security_group_rule.sshChange: cidr_blocks changed from 10.0.0.0/8 to 0.0.0.0/0Risk: high — SSH exposed broadlyRecommended action: revert manually or apply Terraform after approvalТакой отчёт уже можно отправить в Slack, Jira, GitHub Issue или систему мониторинга.

Используйте JSON, если нужен нормальный парсинг
Для автоматической обработки удобно сохранять plan и читать его в JSON:
terraform plan -refresh-only -out=tfplanterraform show -json tfplan > tfplan.jsonДальше можно собрать небольшой скрипт, который извлекает resource_changes, классифицирует изменения и формирует отчёт.
Главное — не пытаться парсить цветной консольный вывод регулярками. Это дорога, на которой легко потерять вечер и немного уважения к жизни.
Разделяйте критичность
Не каждый drift одинаково важен.
Изменение тега last_scanned_at и открытие базы данных наружу — оба могут выглядеть как Terraform diff. Но реагировать на них нужно по-разному.
Практичная шкала может быть такой:
- Low: теги, описания, вычисляемые поля, косметика.
- Medium: параметры производительности, размеры инстансов, настройки autoscaling.
- High: сеть, IAM, публичный доступ, шифрование, backup, deletion protection.
- Critical: изменения, которые уже нарушают compliance или создают прямой риск инцидента.
Эта классификация помогает не кричать на каждую мелочь и не молчать там, где нужно действовать быстро.

Remediation: что делать, когда drift найден
Обнаружить drift — только половина работы. Дальше начинается самая важная часть: решить, какая версия правды правильная.
Есть три основных сценария.
Сценарий 1. Откатить реальность к коду
Если изменение было случайным или опасным, самый чистый путь — вернуть инфраструктуру к Terraform-конфигурации.
Пример: кто-то вручную открыл 0.0.0.0/0 для SSH. В коде разрешён только корпоративный диапазон. Здесь не нужно принимать drift. Нужно закрыть доступ.
Варианты действий:
terraform planterraform applyили ручной откат через консоль, если требуется немедленная реакция, а затем проверка через Terraform.
Но даже если исправление сделано вручную, лучше завершить цикл через plan. Иначе легко оставить другой незамеченный хвост.

Когда этот сценарий подходит
- изменение явно ошибочное;
- drift ухудшает безопасность;
- изменение было временным хотфиксом;
- Terraform-код действительно отражает желаемое состояние;
- нет бизнес-причины сохранять ручную правку.
Ключевой вопрос: «Если бы мы писали инфраструктуру с нуля сегодня, оставили бы это изменение?» Если ответ «нет», откатывайте.
Сценарий 2. Принять реальность и обновить код
Иногда drift — не ошибка, а полезное изменение, которое просто сделали не тем путём.
Например, во время нагрузки инженер увеличил размер database instance. Метрики улучшились, команда решила оставить новый размер. Значит, правильная remediation — не откатывать базу, а обновить Terraform-код.
Было:
instance_class = "db.t3.medium"Стало:
instance_class = "db.t3.large"После изменения кода нужно запустить обычный plan и убедиться, что Terraform больше не предлагает лишних действий.
terraform planЕсли план чистый или ожидаемый — drift закрыт правильно.
Когда этот сценарий подходит
- ручное изменение оказалось нужным;
- бизнес уже зависит от новой настройки;
- откат создаст риск;
- команда согласна, что это новое желаемое состояние;
- изменение можно выразить в Terraform-коде.
Здесь важно не просто «подогнать код под облако», а провести нормальный review. Иначе Terraform станет не источником дизайна, а архивом случайных решений.
Сценарий 3. Обновить state без изменения ресурсов
Иногда ресурсы в реальности корректны, код тоже корректен, а state отстал или потерял часть информации. Тогда может помочь refresh-only workflow.
terraform plan -refresh-onlyterraform apply -refresh-onlyЭтот вариант особенно полезен, когда drift связан с вычисляемыми атрибутами или изменениями, которые provider прочитал по-новому.
Но здесь нужна осторожность. Обновление state — это не косметика. State влияет на будущие планы. Если принять в него неправильную реальность, Terraform начнёт строить решения на кривом фундаменте.
Хорошее правило: перед apply -refresh-only сохраните plan, просмотрите изменения и убедитесь, что они не скрывают реальную проблему.
Что делать с ресурсами, созданными вне Terraform
Отдельный класс drift — ресурсы, которые вообще не управляются Terraform, но должны управляться.
Например, команда вручную создала S3 bucket, firewall rule или load balancer. Ресурс работает, но в коде его нет. Terraform не может управлять тем, чего не знает.
В таком случае есть два пути:
- удалить ручной ресурс и создать его через Terraform;
- импортировать существующий ресурс в Terraform state и добавить конфигурацию.
terraform import
Классический вариант:
terraform import aws_s3_bucket.logs my-company-logsНо перед импортом нужно написать соответствующий resource block в конфигурации. Import связывает реальный объект с адресом в state, но сам по себе не создаёт полноценный аккуратный код за вас.
После import почти всегда нужен plan:
terraform planОн покажет, совпадает ли написанная конфигурация с реальным объектом.
import block
В новых workflow часто удобнее использовать declarative import через import block:
import { to = aws_s3_bucket.logs id = "my-company-logs"}resource "aws_s3_bucket" "logs" { bucket = "my-company-logs"}Плюс такого подхода — импорт становится частью review. Команда видит, какой объект куда импортируется, и может обсудить это до применения.
Для крупных окружений это особенно полезно. Импорт перестаёт быть локальной магией на ноутбуке одного инженера и становится нормальным изменением в репозитории.
Когда использовать ignore_changes
Terraform позволяет игнорировать изменения отдельных атрибутов через lifecycle:
resource "aws_instance" "app" { # ... lifecycle { ignore_changes = [tags["last_scanned_at"]] }}Это полезно, когда атрибутом действительно управляет другой процесс.
Например, security scanner обновляет технический тег. Или Kubernetes controller меняет поле, которое Terraform не должен контролировать.
Но ignore_changes легко превратить в ковёр, под который заметают проблемы. Особенно опасно игнорировать IAM policies, network rules, encryption settings и другие чувствительные параметры.
Перед добавлением ignore_changes задайте три вопроса:
- Кто владеет этим атрибутом?
- Почему Terraform не должен им управлять?
- Как мы узнаем, если изменение станет опасным?
Если ответов нет, лучше не игнорировать.
Drift и refactoring: не путайте расхождение с переездом ресурсов
Иногда Terraform показывает, что ресурс будет удалён и создан заново, хотя вы всего лишь переименовали resource block или перенесли его в модуль.
Это не классический drift. Это проблема адресации в state.
Например, было:
resource "aws_security_group" "app" { name = "app-sg"}Стало:
module "network" { source = "./modules/network"}Если не объяснить Terraform, что старый ресурс переехал, он может решить: старый нужно удалить, новый — создать.
Для таких случаев есть moved block:
moved { from = aws_security_group.app to = module.network.aws_security_group.app}Это аккуратный способ сказать: «Ресурс тот же, просто теперь у него другой адрес в коде».
Такой подход снижает риск случайного destroy при рефакторинге и делает историю изменений понятной для команды.
Практический workflow для команды
Ниже — простой процесс, который можно внедрить без тяжёлой платформенной бюрократии.
1. Разделите обычные изменения и drift checks
Не смешивайте feature changes и drift detection в одном отчёте. Если pull request меняет инфраструктуру, plan должен показывать изменения от PR. Если ночная проверка ищет drift, она не должна одновременно катить новую конфигурацию.
Иначе команда будет спорить: это drift, изменение из ветки или побочный эффект provider-а?
2. Запускайте scheduled plan -refresh-only
Для каждого важного workspace настройте регулярный запуск:
terraform init -input=falseterraform plan -refresh-only -detailed-exitcode -no-color -out=tfplanЧастота зависит от риска. Production-сеть и IAM можно проверять чаще. Dev-окружение — реже.
3. Сохраняйте артефакты
Сохраняйте:
- текстовый plan;
- JSON plan;
- exit code;
- версию Terraform;
- версию provider-ов;
- commit hash конфигурации.
Когда через неделю кто-то спросит «а когда это изменилось?», у вас будет не догадка, а история.
4. Отправляйте короткое уведомление
Уведомление должно быть компактным:
Drift detected in production/network-coreResources affected: 2High risk: 1Report: <link>Owner: platform-teamНе нужно вставлять весь plan в чат. Чат — для сигнала. Полный отчёт — по ссылке.
5. Назначайте владельца
Drift без владельца быстро становится фоном. У каждого workspace или модуля должен быть owner: команда, канал, on-call rotation или конкретная группа.
Если владельца нет, remediation будет зависеть от случайного энтузиазма.
6. Закрывайте drift как задачу
У drift должен быть статус:
- detected;
- triaged;
- accepted;
- remediated;
- ignored with reason;
- false positive.
Это особенно важно для compliance. Проверка без follow-up не доказывает контроль. Она доказывает только то, что где-то был лог.
Политики и guardrails
Drift detection показывает проблему после факта. Но часть drift можно предотвратить.
Ограничьте ручные изменения
Не всем нужен доступ на изменение production-инфраструктуры через консоль. Для большинства задач достаточно read-only доступа и Terraform workflow.
Это не про недоверие к инженерам. Это про снижение количества случайных обходных путей.
Хороший компромисс — break-glass доступ: в обычном режиме изменения идут через IaC, а аварийный доступ включается временно, логируется и требует последующего review.
Используйте policy as code
Policy as code помогает ловить опасные изменения до apply. Например:
- запретить публичные buckets;
- требовать шифрование;
- ограничить CIDR для административных портов;
- требовать теги владельца и окружения;
- запрещать удаление deletion protection для критичных баз.
Такие политики не заменяют drift detection, но уменьшают шанс, что неправильное состояние будет закреплено через Terraform.
Следите за provider versions
Обновление provider-а может изменить diff. Иногда план начинает показывать новые поля или иначе читать старые.
Поэтому версии provider-ов лучше фиксировать и обновлять осознанно:
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }}После обновления provider-а полезно отдельно прогнать drift check, чтобы понять, где реальные изменения, а где новый взгляд provider-а на те же ресурсы.
Типичные ошибки при работе с drift
Ошибка 1. Сразу нажимать apply
Drift найден — рука тянется запустить terraform apply. Иногда это правильно, но не всегда.
Сначала нужно понять источник изменения. Иначе можно откатить нужный хотфикс или, наоборот, принять опасное состояние.
Ошибка 2. Игнорировать «маленькие» изменения
Маленькие изменения бывают шумом. А бывают первым следом большой проблемы.
Например, изменение одного security group rule может выглядеть как короткий diff. Но последствия у него крупнее, чем у пересоздания десятка тестовых ресурсов.
Оценивайте не размер diff, а смысл.
Ошибка 3. Не документировать решение
Если команда решила принять drift, причина должна быть видна в pull request, issue или отчёте.
Через месяц никто не вспомнит, почему параметр изменили вручную. А Terraform-код без контекста будет выглядеть как случайность.
Ошибка 4. Использовать ignore_changes как обезболивающее
ignore_changes убирает боль из плана, но не всегда лечит причину.
Если атрибут действительно внешний — отлично. Если он просто неудобный — вы теряете контроль.
Пример процесса remediation
Допустим, nightly drift check сообщает:
Resource: aws_db_instance.mainChange: backup_retention_period changed from 7 to 1Risk: highДальше нормальный процесс выглядит так:
- Проверить, кто и когда изменил параметр в cloud audit logs.
- Понять причину: ошибка, временный фикс, стоимость, тест или требование бизнеса.
- Сравнить с политикой: минимальный retention для production — 7 дней.
- Принять решение: вернуть значение 7.
- Запустить
terraform plan, убедиться, что изменение ожидаемое. - Применить через стандартный pipeline.
- Закрыть задачу с ссылкой на plan и audit log.
Ничего героического. Просто спокойная инженерная гигиена.
Именно так drift перестаёт быть пожаром и становится обычной управляемой процедурой.
Как понять, что процесс работает
Хороший drift management заметен не по красивым dashboard-ам, а по поведению команды.
Признаки зрелости:
- инженеры не боятся запускать
terraform plan; - drift checks работают регулярно;
- уведомления читают, а не мутят;
- у каждого drift есть владелец;
- опасные изменения разбираются быстро;
ignore_changesиспользуется точечно;- ручные production-правки фиксируются и переносятся в код;
- после инцидентов есть отдельная проверка инфраструктуры.
Если всё это звучит слишком идеально, начните с малого: один production workspace, ежедневный plan -refresh-only, короткий отчёт в Slack и правило «каждый drift должен получить решение».
Через пару недель вы уже увидите, где инфраструктура живёт своей жизнью.
Terraform drift — это не враг, а сигнал
Drift не всегда означает, что кто-то сделал ошибку. Иногда он показывает, что инфраструктура развивается быстрее, чем код. Иногда — что другой инструмент управляет тем же ресурсом. Иногда — что в команде нет ясного ownership.
В любом случае drift полезен, если его не прятать.
Terraform хорош не только тем, что создаёт ресурсы. Он помогает держать инфраструктуру в понятном, проверяемом состоянии. А drift detection — это регулярная сверка карты с местностью. Карта может быть устаревшей. Местность может быть изменена неправильно. Но пока вы сверяете одно с другим, вы управляете ситуацией.
Итог
Terraform drift — обычная часть жизни инфраструктуры, особенно в командах, где есть production, срочные изменения, несколько инструментов автоматизации и реальные бизнес-сроки. Важно не мечтать о мире без drift, а построить процесс, который быстро его обнаруживает, понятно показывает и помогает принять правильное решение.
Используйте terraform plan для проверки будущих изменений, terraform plan -refresh-only для регулярной сверки state с реальностью, -detailed-exitcode для CI/CD, JSON-отчёты для автоматизации и аккуратный remediation workflow для каждого найденного расхождения.
Инфраструктура становится надёжнее не от того, что в ней никогда ничего не меняется вручную. Она становится надёжнее, когда команда видит эти изменения, понимает их смысл и спокойно возвращает систему к осознанному состоянию. Это вполне достижимый уровень зрелости — и начать можно уже с ближайшей drift-проверки.