Управление state в Terraform: remote backend, блокировки и workspaces
Продвинутое3 минРедакция Innovialabs
Коротко
State — это карта соответствия между вашим кодом и реальной инфраструктурой. Храните его в remote backend с блокировкой и шифрованием, разделяйте по окружениям и компонентам, а расхождения исправляйте через plan, import и refresh, а не ручной правкой файла.
Что такое state и почему он важен
State (terraform.tfstate) — файл, в котором Terraform хранит соответствие между ресурсами в коде и реальными объектами в облаке: идентификаторы, атрибуты, зависимости. Без него Terraform не знает, что уже создано, и при следующем apply попытается создать всё заново.
Из этого следуют три правила:
- State — критичный артефакт. Потеря state не удаляет инфраструктуру, но отрывает её от управления.
- State содержит секреты. Пароли баз данных, ключи и другие чувствительные атрибуты могут храниться в нём открытым текстом.
- С state должен работать один процесс одновременно. Два параллельных
applyспособны повредить его.
Remote backend с блокировкой
Локальный state подходит только для экспериментов. Для команды нужен remote backend: общее хранилище, к которому есть доступ у всех и у CI.
Что должен давать хороший backend:
| Требование | Зачем |
|---|---|
| Блокировка (locking) | Не даёт двум запускам менять state одновременно |
| Шифрование | Защищает секреты внутри state |
| Версионирование | Позволяет откатиться к предыдущей версии state |
| Контроль доступа | Ограничивает, кто может читать и менять state |
Пример для AWS S3:
terraform {
backend "s3" {
bucket = "company-terraform-state"
key = "prod/network/terraform.tfstate"
region = "eu-central-1"
encrypt = true
use_lockfile = true
}
}
Механизм блокировки зависит от backend и версии Terraform: в старых конфигурациях для S3 использовалась таблица DynamoDB. Сверяйтесь с документацией вашей версии. Альтернативы — GCS, Azure Blob, Terraform Cloud/HCP, GitLab-managed state.
Сам бакет для state лучше создать отдельно (вручную или отдельной конфигурацией) и включить в нём версионирование.
Разделение state по окружениям и компонентам
Один огромный state для всего — источник проблем: долгие plan, большой радиус поражения ошибки, конфликты блокировок.
Два основных подхода:
- Отдельные каталоги на окружение (
envs/dev,envs/prod) с разнымиkeyв backend. Окружения изолированы явно, можно иметь разные права доступа. - Workspaces — несколько state в одной конфигурации, переключение через
terraform workspace select. Удобно для однотипных копий, но легко случайно применить изменения не к тому окружению.
Для продакшена чаще выбирают отдельные каталоги или отдельные backend-конфигурации, а workspaces оставляют для временных и однотипных стендов. Внутри окружения полезно делить state по слоям: сеть, данные, приложения. Связь между ними — через terraform_remote_state или передачу outputs.
Импорт существующих ресурсов
Если ресурс создан вручную, его можно взять под управление без пересоздания:
import {
to = aws_s3_bucket.assets
id = "company-assets"
}
Порядок: описать ресурс в коде (или сгенерировать конфигурацию через terraform plan -generate-config-out=...), выполнить plan, убедиться, что изменений нет или они ожидаемы, затем apply. Для старых версий есть команда terraform import.
Drift: когда реальность разошлась с кодом
Drift — изменения, сделанные мимо Terraform: кто-то поправил правило firewall в консоли.
- Запустите
terraform plan -refresh-only— он покажет, чем реальность отличается от state. - Решите, что правильно: код или ручное изменение.
- Если правильно ручное — перенесите его в код. Если код — выполните обычный
apply. - Регулярно запускайте
planв CI по расписанию, чтобы замечать drift рано.
Для переименования ресурсов используйте блок moved или terraform state mv, для удаления из-под управления без удаления объекта — блок removed или terraform state rm.
Частые ошибки
- Хранить
terraform.tfstateв Git. - Править state вручную в текстовом редакторе.
- Снимать блокировку (
force-unlock), не убедившись, что другой процесс действительно завершился. - Давать всем разработчикам права на запись в продакшен-state.