Короткий ответ
Нужно описать новый backend в конфигурации, выполнить terraform init -migrate-state, которая скопирует существующий state в новое хранилище и подтвердит это, а также немедленно удалить terraform.tfstate из git и добавить файл в .gitignore; просто скопировать файл в S3 вручную недостаточно, потому что Terraform должен сам обновить метаданные backend и включить locking, а ручное копирование не гарантирует согласованность и не настраивает блокировки.
Как это работает подробнее
блок backend в конфигурации описывает, где Terraform хранит state и как блокирует его; при смене backend Terraform сравнивает текущий (locally known) state с целевым хранилищем и при -migrate-state переносит содержимое, сохраняя serial-номер версии state, чтобы не создать рассинхронизацию между старым и новым источником истины.
Пример кода
terraform {
backend "s3" {
bucket = "acme-tfstate-prod"
key = "env/prod/terraform.tfstate"
region = "eu-central-1"
dynamodb_table = "acme-tf-locks"
encrypt = true
}
}
$ terraform init -migrate-state
Terraform detected that the backend type changed from "local" to "s3"...
Do you want to copy existing state to the new backend? yesЧто использовать на практике
- Практика. перед миграцией стоит сделать резервную копию текущего state (
terraform state pull > backup.tfstate), выполнить миграцию на некритичном окне, когда никто не запускает apply, и сразу после миграции проверитьterraform plan— он должен показать отсутствие изменений (no-op), что подтверждает успешный перенос; также нужно включить versioning на S3-бакете и таблицу DynamoDB для locking, чтобы получить защиту от конкурентной записи.
Подводные камни
- Ошибка. частая ошибка — вручную загрузить файл state в S3 через CLI/консоль без
terraform init -migrate-state, из-за чего локальный backend продолжает считаться активным и следующий apply создаёт ресурсы заново или теряет связь с реальными; ещё одна ошибка — не включить versioning на бакете, из-за чего при случайной порче state нет возможности откатиться к предыдущей версии.