Статьи

Terraform в команде: разделение state, радиус поражения и проверенные планы

Как разделить state в Terraform, запускать планы в CI и применять только проверенное, чтобы изменения инфраструктуры стали рутиной, а не риском.

Примеры обобщённые и иллюстративные. Они не взяты из среды какого-либо клиента: подстройте пороги и параметры под свою систему.

Файл state — настоящая граница

Каждый terraform apply может изменить что угодно в том state, с которым работает. Поэтому единицей риска является state, а не модуль. При одном state на всё окружение опечатка в DNS-записи и изменение продакшен-базы проходят через один и тот же план — а он считается минутами.

Делите по жизненному циклу и радиусу поражения

Группируйте ресурсы, которые меняются и отказывают вместе. Распространённая схема разделяет в каждом окружении:

  • Фундамент: аккаунты, сети, DNS-зоны — меняются редко.
  • Данные: базы, бакеты, очереди — меняются осторожно и защищены от удаления.
  • Вычисления и сервисы: кластеры, функции, балансировщики — меняются часто.

Каждый слой читает выходные значения нижнего и никогда не управляет его ресурсами. Окружения используют одни и те же модули, но с отдельными state и учётными данными, чтобы apply в staging не мог затронуть продакшен.

Удалённый state, блокировки и версии

  • Храните state в удалённом бэкенде с включёнными блокировками и версионированием — никогда в Git и никогда на ноутбуке.
  • Коммитьте lock-файл зависимостей (.terraform.lock.hcl) и фиксируйте версии модулей, чтобы план сегодня и план через месяц выполняли один и тот же код.
  • Защищайте ресурсы с состоянием через prevent_destroy и встроенную защиту от удаления у провайдера.

План на каждый pull request, apply того, что проверено

Запускайте terraform plan в CI для каждого изменения и публикуйте результат в pull request. После одобрения применяйте сохранённый план, а не планируйте заново, чтобы продакшен получил ровно то, что прочитали ревьюеры; если state за это время изменился, Terraform отклонит устаревший план. Пайплайн должен аутентифицироваться краткоживущими учётными данными через OIDC-федерацию, а не долгоживущими ключами в секретах.

terraform init -input=false
terraform plan -input=false -lock-timeout=5m -out=tfplan
terraform show -no-color tfplan > plan.txt   # attach to the pull request

# after approval, applying the same saved plan:
terraform apply -input=false tfplan

Регулярно ищите дрейф

Изменения через консоль всё равно случаются — обычно во время инцидентов. Плановая задача с terraform plan -detailed-exitcode их находит: код выхода 0 означает отсутствие изменений, 2 — реальная инфраструктура отличается от кода, 1 — ошибку. Превращайте 2 в тикет, а затем либо внесите изменение в код, либо откатите его.

Политики до apply

Правила вроде «никаких публичных бакетов» или «у каждого ресурса есть тег владельца» машина проверяет лучше, чем ревьюер в конце долгого дня. Инструменты policy as code, например Open Policy Agent через Conftest, могут проверять JSON-представление плана (terraform show -json) в CI и блокировать merge.

Контакты

Нужно второе мнение о вашей системе?

Пришлите короткое описание системы. Опытный инженер ответит письменно в течение рабочего дня.

Обсудить инфраструктуру