linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • База знаний
  • Шпаргалка
  • Capstone
  • Собеседование
home/terraform/kb/State/tf-state-manipulation

kb/state ── State ── intermediate

state mv, state rm, state pull/push: ручные операции

`terraform state mv` переименовывает адрес ресурса в state (без destroy/recreate). `terraform state rm` убирает ресурс из state (но не из облака). `terraform state pull/push`, скачать/залить state как файл. Все четыре, резкие операции, делать через backup и понимая зачем. Для декларативных альтернатив есть [[tf-moved-block]] и [[tf-removed-block]].

view as markdownaka: terraform-state-mv, terraform-state-cli

Когда лезть в state руками

В идеале, никогда. Terraform любит declarative-подход: меняешь HCL, делаешь plan, видишь что будет, применяешь. Прямые операции над state, для случаев когда declarative не работает:

  • Переименование ресурса без destroy и create (исторически, через state mv; с TF 1.1+, через moved блок, см. tf-moved-block).
  • Удаление из управления terraform без удаления в облаке (с TF 1.7+ , через removed блок, см. tf-removed-block).
  • Аварийное починить битый state, state pull, поправить JSON руками, state push. Редко, страшно, обычно через support.
  • Слияние двух state'ов в один, state mv с межgolang-state'овой нотацией.

Декларативные блоки (moved, removed, import): предпочтительны. Они оставляют след в HCL и git, повторяются между членами команды автоматически. CLI-операции, invisible, только тот кто запустил знает что произошло.

terraform state list

Точка входа: что в state'е?

bash
terraform state list
# aws_s3_bucket.demo
# module.logs.aws_s3_bucket.this
# random_id.suffix

Фильтр по адресу:

bash
terraform state list 'module.logs.*'
# module.logs.aws_s3_bucket.this

Полезно перед любой state mv/rm, проверь что трогаешь именно то.

terraform state show

Атрибуты конкретного ресурса:

bash
terraform state show aws_s3_bucket.demo

Печатает HCL-подобную форму со всеми attributes. Включая sensitive (в отличие от terraform plan/apply, который маскирует). Это причина почему state защищается так же строго как секреты.

terraform state mv

Самая частая «руками» операция. Меняет адрес ресурса в state без destroy.

Кейс 1: переименовать ресурс

Был:

hcl
resource "aws_s3_bucket" "logs" { ... }

Хочешь:

hcl
resource "aws_s3_bucket" "log_storage" { ... }

Без state mv. Terraform увидит «logs больше нет в HCL, log_storage появился» и сделает destroy+create. Бакет уничтожится с данными.

С state mv:

bash
terraform state mv aws_s3_bucket.logs aws_s3_bucket.log_storage

Теперь в state ресурс называется log_storage. HCL поправь параллельно. terraform plan → No changes.

Кейс 2: переместить в модуль

Был ресурс в root, хочешь вынести в модуль ./modules/buckets.

bash
# сначала добавь в HCL:
# module "buckets" { source = "./modules/buckets" }
# внутри модуля: resource "aws_s3_bucket" "logs" { ... }
terraform state mv aws_s3_bucket.logs module.buckets.aws_s3_bucket.logs

plan → No changes. Это типичный refactoring-сценарий, см. tf-refactor-patterns.

Кейс 3: между разными state'ами

Один root отделяешь на два root'а. Часть ресурсов мигрирует:

bash
# в исходном root:
terraform state mv -state-out=../other/terraform.tfstate \
                   aws_s3_bucket.logs aws_s3_bucket.logs

Это редкая операция, обычно, при разделении монолита на сервисы.

terraform state rm

Убирает ресурс из state. Облачный ресурс остаётся.

bash
terraform state rm aws_s3_bucket.demo

Теперь Terraform «забывает» про бакет. Следующий apply (если ресурс в HCL остался) увидит «нет в state, есть в HCL», попытается создать заново, упадёт на «bucket already exists». Чтобы захватить, import, см. tf-state-import.

Кейсы:

  • Ресурс случайно попал в этот state, должен жить в другом. После state rm делаешь import в правильном state.
  • Переход на другую конструкцию: был count = 1, делаем for_each. Адреса разные, без помощи Terraform делает destroy+create. state rm старого адреса + import нового, без пересоздания. С TF 1.1+ это лучше через moved.

-dry-run

bash
terraform state rm -dry-run aws_s3_bucket.demo

Покажет что бы сделал, без изменений. Всегда используй -dry-run перед настоящим rm.

terraform state pull / push

Аварийный механизм. Скачать state как файл:

bash
terraform state pull > terraform.tfstate.dump

Работает с любым backend, local, S3, remote. Сохраняет в текущую папку.

Залить обратно:

bash
terraform state push terraform.tfstate.dump

Terraform проверит lineage и serial. Если serial меньше текущего, спросит подтверждение (это потенциальный rollback). Если lineage отличается, откажется, защита от подмены state'а другого проекта.

Используется когда:

  • Нужно править JSON руками (например, после провайдер-апгрейда формат state поломался). Это последняя надежда, обычно лучше terraform refresh или поговорить с автором провайдера.
  • Перенос state между backends руками (вместо init -migrate-state).
  • Резервный бекап перед опасной операцией: state pull > backup-$(date).json.

Backup перед любой операцией

Любая state mv/rm/push, сделай дамп до:

bash
terraform state pull > backup-pre-refactor-$(date +%s).json

S3-backend с версионированием это делает автоматически, но дублировать не повредит. С local backend, обязательно вручную.

Подводные камни

  • state mv не правит HCL. Поменял имя в state, поменяй и в HCL. Иначе следующий plan снова покажет destroy+create.

  • state rm не возвращает. Реально нет «undo». Если облачный ресурс важен, сначала state pull > backup.json, потом rm. При проблеме, state push backup.json.

  • С remote backend lock работает только если ты ходишь через terraform CLI. state pull берёт lock, state push тоже. Но если ты руками aws s3 cp tfstate ./, никакого lock нет, можешь конфликтовать с apply'ем другого человека.

  • state mv для count/for_each ресурсов требует точного адреса. aws_iam_user.user[0] или aws_iam_user.user["alice"], не aws_iam_user.user. Если ошибся индекс, переместишь не тот.

  • Между state'ами с разным lineage, push не пройдёт. Это защита. Если действительно нужно (например, ты делаешь bootstrap нового state'а с импортом из старого): добавь -force к push. Но сначала ответь себе зачем.

  • moved и removed блоки лучше, когда применимы. Они декларативны, видны в diff, выполняются автоматически у всех. state mv/rm, один раз, у того кто запустил, остальные узнают по конфликтам.

§ команды

bash
terraform state list

Все ресурсы под управлением. Точка входа для любых state-операций.

bash
terraform state show <ADDRESS>

Атрибуты ресурса включая sensitive. Чтоб видно что мы трогаем.

bash
terraform state mv <SRC> <DST>

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

bash
terraform state rm -dry-run <ADDRESS>

Что бы сделал rm. Всегда так сначала, потом без -dry-run.

bash
terraform state pull > backup-$(date +%s).json

Бекап state перед опасной операцией.

bash
terraform state push <FILE>

Залить state из файла. Проверяет lineage/serial. Аварийный механизм.

§ см. также

  • tf-stateState: память Terraform о созданномState. JSON-файл terraform.tfstate, где Terraform записывает, что он создал в облаке. Без него Terraform не знал бы, какой бакет «его», а какой чужой. Содержит ID ресурсов, все атрибуты, и часто секреты. Самая чувствительная часть проекта.
  • tf-moved-blockmoved блок: переименование без destroy`moved { from = ..., to = ... }` в HCL декларативно говорит Terraform: «этот ресурс раньше был по одному адресу, теперь по другому, в облаке тот же». Plan покажет «move», не «destroy + create». Появился в TF 1.1. Замена ручному `terraform state mv`, оставляет след в git, повторяется у всех в команде, видно в diff.
  • tf-remote-backend-s3Remote state в S3: бакет, DynamoDB lock, encryptionS3-backend хранит `terraform.tfstate` в бакете, DynamoDB-таблица даёт блокировку одного-apply-за-раз. Конфигурация, в блоке `backend "s3"` внутри `terraform { ... }`. State в S3. Это единственный source of truth, локального файла больше нет. Переезд с local на S3, через `terraform init -migrate-state`.
  • tf-refactor-patternsПаттерны рефакторинга: count→for_each, split files, extract moduleБольшие конфиги превращаются в спагетти. Базовые рефакторинги: count→for_each (стабильные ключи), разделение на файлы по доменам (network/compute/storage), вынос повторяющегося блока в модуль, объединение мелких ресурсов в составной, удаление мёртвых импортов. Каждый, пошагово, с проверкой `plan` на каждом шагу.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки