Операции над state: import, move, rm
Иногда нужно поправить саму карту-state, не трогая реальные ресурсы: импортировать существующий сервер, переименовать ресурс или убрать его из-под управления Terraform. Для этого есть отдельные команды.
Эти команды правят память Terraform, а не облако.
state rmне удаляет сервер — он лишь заставляет Terraform о нём забыть. Понимание этой грани спасает от катастроф.
Бывают ситуации, когда код и реальность нужно «подружить» через state. Сервер создан вручную до Terraform — его надо импортировать. Ресурс переименовали в коде — нужно переместить его в state, чтобы избежать пересоздания. Ресурс передают другой команде — его убирают из state без удаления.
Три операции
# IMPORT: взять существующий ресурс под управление
terraform import aws_instance.web i-0abc123
# в новых версиях -- декларативно через import-блок:
# import { to = aws_instance.web; id = "i-0abc123" }
# MOVE: переименовать без пересоздания (адрес в state)
terraform state mv aws_instance.old aws_instance.new
# или декларативно: moved { from = ...; to = ... }
# RM: забыть ресурс, НЕ удаляя его в облаке
terraform state rm aws_instance.legacy
import создаёт запись в state для уже существующего объекта (но HCL-код для него надо написать самому). state mv и декларативный moved-блок переименовывают ресурс в state, спасая от связки «удали-создай». state rm убирает ресурс из state, оставляя его живым в облаке.
Как работает под капотом
Все три команды — это операции над словарём state, а не над облаком. Смоделируем их, держа в голове, что реальные ресурсы не трогаются:
state = {"aws_instance.web": "i-001", "aws_s3.data": "bucket-x"}
cloud = {"i-001", "bucket-x", "i-999"} # i-999 создан вручную, не в state
# IMPORT: ресурс i-999 уже в облаке, добавляем в state
state["aws_instance.legacy"] = "i-999"
print("после import:", state)
# MOVE: переименование ключа, реальный i-001 не трогаем
state["aws_instance.app"] = state.pop("aws_instance.web")
print("после move: ", state)
# RM: убрать из state, но cloud НЕ меняется
removed = state.pop("aws_s3.data")
print("после rm: ", state)
print("bucket-x всё ещё в облаке:", "bucket-x" in cloud)
«Попробуй сам ▶» — заметьте: после rm бакет bucket-x по-прежнему существует в облаке. Менялась только карта-state.
Частые ошибки
- Думать, что
state rmудаляет ресурс. Нет — он лишь забывает его; ресурс остаётся (и продолжает стоить денег). - Import без HCL-кода. Импортировали в state, но блок
resourceне написали — следующий plan захочет всё снести. - Переименование без
moved. Просто сменив имя в коде, вы получите destroy+create вместо переименования.
Best practices
- Предпочитайте декларативные
import- иmoved-блоки командам CLI — они версионируются в git и видны в plan. - После
importсразу прогонитеplan: он должен показать «no changes», если код точен. state rmиспользуйте осознанно — например, перед передачей ресурса в другой state.
Разбор глубже
Импорт ресурсов прошёл большую эволюцию. Старый способ — императивная команда terraform import адрес ID — добавлял ресурс в state, но HCL-код для него вы должны были написать руками, угадывая все аргументы; малейшее несовпадение, и следующий план хотел что-то менять. Современный декларативный import-блок решает это изящнее: вы пишете import { to = ...; id = ... } прямо в коде, а Terraform на плане показывает, что будет импортировано, и даже умеет сгенерировать заготовку HCL флагом -generate-config-out. Это превращает рискованную ручную операцию в обычный, ревьюируемый через git процесс.
Команды семейства terraform state — это, по сути, набор скальпелей для операций на state. state list показывает все ресурсы в state, state show адрес — детали конкретного, state mv — переименовывает или переносит между state, state rm — забывает ресурс. Все они работают только с картой-state и никогда не трогают реальные ресурсы в облаке. Это и сила, и опасность: ошибка в state mv не сломает прод напрямую, но рассогласует карту, после чего следующий apply может натворить дел. Поэтому перед такими операциями всегда делают резервную копию state.
Общее правило безопасности для всех операций со state — делать резервную копию перед вмешательством. Команда terraform state pull > backup.tfstate сохраняет текущее состояние локально, и если state mv или rm пошли не так, можно вернуться к снимку через state push. Удалённые бэкенды с версионированием дают эту защиту автоматически, но привычка делать явный бэкап перед ручной операцией над state остаётся признаком аккуратного инженера. Эти команды правят карту, по которой Terraform ориентируется в реальности, и цена ошибки в карте — рассогласование, которое всплывёт уже на следующем apply.
Итог: import, mv/moved и rm правят карту-state, а не облако; особенно помните, что rm не удаляет ресурс. Дальше — как переиспользовать код через модули.