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/lessons/tf-intermediate-07-state-manipulation

lesson ── terraform-intermediate ── ~15 мин ── 6 шагов

state mv, state rm: операции над state

State, это файл с записями «адрес ресурса в HCL → конкретный объект в облаке». Иногда адрес нужно поменять (переименование, перенос в модуль): но облачный ресурс не трогать. CLI terraform state mv/rm это делают.

В этом уроке: создашь бакет, переименуешь его в state'е, проверишь что бакет не пересоздавался, потом удалишь ресурс из state без destroy.

С TF 1.1+ для большинства кейсов лучше декларативный moved блок, он будет в следующем уроке. Сейчас, про CLI, потому что иногда только она работает.

▶ интерактивный sandbox

Поднимется пара контейнеров: terraform 1.9 и localstack 3.8 в одной сети. В браузере откроется терминал, можно сразу terraform init. Каждый шаг проверяется автоматически. TTL 45 минут, без регистрации.

запустить sandbox →

stack ── terraform · localstack · 1 GB RAM · самоуничтожается через 45 мин простоя

Шаги

  1. 01

    Создай бакет под управление

    bash
    cd /home/student/tf-state-ops
    cat > main.tf <<'EOF'
    resource "random_id" "suffix" {
      byte_length = 4
    }
    resource "aws_s3_bucket" "logs" {
      bucket = "linuxlab-state-ops-${random_id.suffix.hex}"
    }
    EOF
    terraform init
    terraform apply -auto-approve
    terraform state list

    Должно вывести:

    aws_s3_bucket.logs
    random_id.suffix

    ✓ Бакет создан под адресом aws_s3_bucket.logs.

  2. 02

    Бэкап state перед операциями

    bash
    terraform state pull > /tmp/state-backup.json
    ls -la /tmp/state-backup.json
    jq '.serial, .lineage' /tmp/state-backup.json

    Это твой safety-net. Если что-то пойдёт не так, terraform state push /tmp/state-backup.json вернёт всё на место.

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

    ✓ Бэкап сделан. Теперь: state mv.

  3. 03

    Переименуй ресурс в state

    Хотим переименовать aws_s3_bucket.logs → aws_s3_bucket.log_storage.

    bash
    terraform state mv aws_s3_bucket.logs aws_s3_bucket.log_storage

    Вывод:

    Move "aws_s3_bucket.logs" to "aws_s3_bucket.log_storage"
    Successfully moved 1 object(s).

    Теперь обязательно поправь HCL, иначе plan покажет destroy на log_storage и create на logs:

    bash
    sed -i 's/"aws_s3_bucket" "logs"/"aws_s3_bucket" "log_storage"/' main.tf

    Проверь:

    bash
    grep -n "aws_s3_bucket" main.tf
    terraform state list
    terraform plan

    State и HCL согласованы. Plan: No changes.

    ✓ Адрес переименован, бакет в облаке не пересоздавался.

  4. 04

    Попробуй state rm в режиме dry-run

    Хотим убрать ресурс из управления, но не удалять бакет в облаке.

    Сначала dry-run:

    bash
    terraform state rm -dry-run aws_s3_bucket.log_storage

    Покажет:

    Would remove:
      aws_s3_bucket.log_storage

    Без изменений. Это твой sanity check. Всегда dry-run перед настоящим rm. См. tf-state-manipulation.

    ✓ Dry-run отработал. Теперь: настоящий rm.

  5. 05

    Убери ресурс из state

    bash
    terraform state rm aws_s3_bucket.log_storage

    Вывод:

    Removed aws_s3_bucket.log_storage
    Successfully removed 1 resource instance(s).

    Проверь:

    bash
    terraform state list

    aws_s3_bucket.log_storage исчез. В облаке, посмотри:

    bash
    aws --endpoint-url=http://localstack:4566 s3 ls

    Бакет всё ещё там! State его «забыл», но реально он живёт. Теперь этот бакет, ничейный с точки зрения terraform.

    Если ты сейчас сделаешь terraform apply без правки HCL. Terraform увидит «log_storage есть в HCL, нет в state» и попробует создать его в облаке. Упадёт на «bucket already exists».

    Это нормальное состояние при подготовке к import (следующий урок). Чтобы сейчас починить, удали ресурс из HCL:

    bash
    # удаляем resource блок aws_s3_bucket.log_storage
    cat > main.tf <<'EOF'
    resource "random_id" "suffix" {
      byte_length = 4
    }
    EOF

    ✓ State освободил ресурс, бакет в облаке остался. Это и есть state rm.

    То же самое на OpenTofu

    OpenTofu держит CLI и state совместимыми с Terraform по командам этого шага: миграция обычно проходит через mv .terraform .terraform.bak; tofu init -upgrade. Но при первом переходе сделай backup state и прогон на feature-branch - расхождения концентрируются в новых фичах (variables в backend, state-encryption, OCI registry-backed модули). См. tf-opentofu-parity для полной матрицы.

    • → OpenTofu parity
  6. 06

    Восстанови из бэкапа

    Если хотел вернуть как было:

    bash
    terraform state push /tmp/state-backup.json

    Terraform проверит lineage и serial:

    • Lineage в бэкапе == текущий → OK.
    • Serial в бэкапе < текущего → попросит подтверждения (это потенциальный rollback).
    • Lineage отличается → откажется. Защита от случайной подмены.

    -force обходит проверки, но обычно не нужен.

    bash
    terraform state list

    Видны все ресурсы из бэкапа. Это твой safety-net.

    В реальной работе с S3-backend бэкап делается автоматически (versioning). Восстановление, через aws s3 cp s3://.../tfstate?versionId=....

    ✓ Восстановление возможно. Бэкап перед операциями: не паранойя, а гигиена.

    Когда CLI state mv/rm, а когда moved/removed блок

    Главное правило: декларативно лучше императивно.

    КейсЧто использовать
    Переименование (один человек, в текущем спринте)state mv быстрее, но moved лучше для PR
    Переименование (в команде, в репо)moved блок, повторится у всех
    Удалить из state без destroyremoved блок (TF 1.7+): видно в diff
    Аварийный «уберите этот ресурс пока я разбираюсь»state rm
    Слияние state'ов разных root'овstate mv с -state-out
    Починка битого state из дампаstate push (только так)

    Правило: в production-репо CLI, last resort. Сначала пробуй декларативные блоки. CLI оставляет операцию без следа в git, полгода спустя никто не вспомнит почему bucket.logs стал bucket.log_storage.

    • → moved block
    • → removed block

Что ты узнал

terraform state mv <SRC> <DST> меняет адрес в state без trogания облака. terraform state rm <ADDR> убирает запись из state, ресурс в облаке остаётся. Перед обоими, terraform state pull > backup.json.

команды

  • terraform state listчто в state: точка входа
  • terraform state pull > backup.jsonбэкап перед опасной операцией
  • terraform state mv SRC DSTпереименовать адрес
  • terraform state rm -dry-run ADDRчто бы сделал rm: без изменений
  • terraform state push backup.jsonвосстановить state из дампа

концепции

  • · state mv меняет state, не HCL: синхронизация HCL твоя ручная работа
  • · state rm не удаляет ресурс в облаке: это только разрыв связи
  • · Бэкап state перед любой опасной операцией обязателен

← предыдущий

Data sources: читаем существующее

следующий →

Plan как артефакт, между PR и apply

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки