Что такое backend
Backend, это адрес, где terraform хранит state-файл и где берёт
блокировку (lock) на время apply. По умолчанию backend, local:
terraform.tfstate лежит в той же папке, что и HCL, никаких lock'ов
кроме файлового флажка.
Backend конфигурируется в блоке terraform:
terraform { backend "local" {path = "terraform.tfstate"
}
}
Локальный backend, дефолт, явно прописывать его не обязательно.
Зачем уходить от local
Local backend работает, пока:
- проект один человек;
- state не критичный;
- нет CI/CD, который тоже хочет применить.
Как только в проект приходит второй человек или CI, нужны:
- общее хранилище, чтобы все видели один state, а не каждый свою локальную копию;
- блокировка, чтобы два параллельных
applyне покалечили state-файл (один пишет, второй пишет поверх, получается мусор); - версионирование/бекап, на случай, если кто-то случайно повредил state.
Эти требования закрывают remote backends.
Какие remote backends есть
Курс не настраивает их (это интермедиат-материал), но знать про
существование полезно. Все они объявляются в блоке backend с
соответствующим именем.
S3 (самый частый в AWS-проектах)
terraform { backend "s3" {bucket = "myorg-tfstate"
key = "projects/web/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "tf-locks" # для блокировок
}
}
Бакет хранит state, DynamoDB-таблица, lock. С Terraform 1.10+ блокировки можно держать прямо в S3 (через S3 conditional writes), тогда DynamoDB не нужна.
Google Cloud Storage
terraform { backend "gcs" {bucket = "myorg-tfstate"
prefix = "projects/web/"
}
}
Lock тоже в GCS (через generation-based если-conditions).
HTTP (универсальный)
terraform { backend "http" {address = "https://example.com/state/web"
lock_address = "https://example.com/state/web/lock"
unlock_address = "https://example.com/state/web/lock"
}
}
Любой сервис, который реализует ожидаемый REST-контракт (GET/POST state, LOCK/UNLOCK). На этом построен Atlantis, GitLab managed state и большинство кастомных решений.
Terraform Cloud / Enterprise
Не совсем backend, отдельный блок cloud {} с workspaces и run
history. Это управляющая платформа, в которой state, только одна
из деталей.
Как backend меняется
Поменял backend в HCL, следующий init спросит:
Initial configuration of the requested backend "s3"
Do you want to copy existing state to the new backend?
Pre-existing state was found while migrating the previous "local"
backend to the newly configured "s3" backend. No existing state
was found in the newly configured "s3" backend. Do you want to
copy this state to the new "s3" backend?
Enter "yes" or "no":
yes, terraform перенесёт state со старого места на новое.no, оставит как есть; новый backend начнёт с пустого state.
Чтобы пропустить вопрос, есть флаги:
terraform init -migrate-state, явно сказать «мигрируй».terraform init -reconfigure, переинициализировать новый backend без переноса. Старый state остаётся как есть, новый, пустой.
Без понимания, какой флаг ты дёргаешь, лучше не торопиться: можно затереть рабочий state.
State locking, что это и зачем
Lock, это «занят, идёт apply, никому не вмешиваться». Без него:
- два инженера одновременно
apply, два разных state. Кто последний сохранил, того и state. - apply упал на середине, без lock другой может стартовать поверх и добить.
Local backend lock делает через файловый advisory lock (.tfstate.lock.info).
Этого хватает для одного процесса, но не для команды.
S3 backend. DynamoDB-таблица или S3 conditional writes.
Terraform Cloud, встроенный механизм. HTTP, через lock_address.
Если другой процесс держит lock и упал, есть terraform force-unlock <id>.
Этот рычаг страшный, использовать осторожно: можно сломать живущий
apply, который просто медленный.
Подводные камни
backendнельзя параметризовать через переменные. В блокеbackend "s3"нельзяbucket = var.bucket. Это потому, что backend читается до того, как HCL загружен полностью. Решение,-backend-configфлаги при init, либо отдельныйbackend.tfв разных директориях.- State в local backend, открытый текст. Любые
password,token,secret_keyлежат в нём как есть. На прод-окружениях это решается remote-backend'ом с шифрованием. - Init без backend, ловушка. Если убрал блок
backendиз HCL, terraform решит, что переехал на local, и спросит про миграцию. Не путай «нет backend в коде» (== local) с «есть пустойbackend "local" {}». force-unlock, оружие массового поражения. Если lock держит реально работающий apply, и ты снимешь его силой, второй apply запишет состояние поверх. State можно сломать на несколько часов.