Представь ситуацию. Ты написал конфиг, сделал terraform apply, поднял виртуалку в Yandex Cloud. Через неделю ты поменял у этой виртуалки объём памяти и снова запустил apply. И тут возникает вопрос на миллион: откуда Terraform знает, что виртуалку нужно ИЗМЕНИТЬ, а не создать ещё одну рядом? В твоём облаке уже крутится десяток ресурсов, в коде описано то же самое - как инструмент сопоставляет одно с другим?
Ответ - файл состояния, он же state, он же terraform.tfstate. Это память Terraform. Без него инструмент - амнезиак, который каждый раз видит мир впервые. И именно поэтому state - одна из тех тем, которую новички проскакивают, а потом неделями огребают на проде. Давай разберёмся раз и навсегда, что это за зверь и почему держать его локально в команде - билет в один конец.

Что такое state и что у него внутри
Terraform работает по принципу инфраструктура как код (IaC, она же infrastructure as code). Ты декларативно описываешь желаемое состояние, а инструмент приводит реальность к нему. Но чтобы понять, что делать, ему нужно знать три вещи: что ты хочешь (это твой .tf код), что есть на самом деле (это реальные ресурсы в облаке) и что было создано в прошлый раз (а вот это и есть state).
State выполняет несколько работ сразу:
- Маппинг код - реальность. Связывает твой ресурс yandex_compute_instance.web с конкретным id виртуалки в облаке, например fhm9abc.... Без этой связки Terraform не знает, какой реальный объект соответствует какому блоку кода.
- Метаданные. Хранит все атрибуты ресурсов, которые вернуло облако после создания - ip-адреса, autogenerated id, статусы. Это позволяет на следующем плане сравнить желаемое с фактическим.
- Граф зависимостей. Terraform помнит, в каком порядке ресурсы связаны, чтобы корректно их удалять и пересоздавать. При destroy он идёт в обратном порядке - сначала виртуалку, потом сеть.
- Производительность. На больших инфраструктурах Terraform кеширует атрибуты в state, чтобы не дёргать API облака по каждому ресурсу на каждый terraform plan.
Код: Выделить всё
{
"version": 4,
"terraform_version": "1.7.0",
"serial": 8,
"lineage": "a1b2c3d4-...",
"resources": [
{
"mode": "managed",
"type": "yandex_compute_instance",
"name": "web",
"provider": "provider[\"registry.terraform.io/yandex-cloud/yandex\"]",
"instances": [
{
"attributes": {
"id": "fhm9abcde12345",
"name": "web-1",
"zone": "ru-central1-a",
"fqdn": "web-1.ru-central1.internal"
}
}
]
}
]
}
Почему локальный файл - это бомба замедленного действия
Пока ты один и проект учебный, terraform.tfstate спокойно лежит рядом с кодом, и всё работает. Проблемы начинаются, как только появляется второй человек или второй компьютер. Разберём по пунктам, чем опасен локальный terraform state.
1. Нет шеринга. State лежит у тебя на ноуте. Коллега клонирует репозиторий - а state там нет (и быть не должно, об этом ниже). Он делает apply со своей машины, Terraform не видит твоих ресурсов в своём пустом state и пытается создать всё заново. Получаем дубли инфраструктуры и счёт от облака в подарок.
2. Конфликты и гонки. Допустим, вы решили класть state в git, чтобы шерить. Звучит логично, но это ловушка. Двое одновременно делают apply, каждый коммитит свой обновлённый state - и вы получаете merge-конфликт в гигантском JSON, который руками не разрулить. А если apply идут параллельно, два процесса пишут в один файл без блокировки и затирают изменения друг друга. Это и есть гонка состояний (race condition), после которой state перестаёт отражать реальность.
3. Секреты в открытом виде. Вот это больно. State хранит ВСЕ атрибуты ресурсов, включая чувствительные. Пароль от управляемой базы данных, приватный ключ, токен - всё это ложится в tfstate открытым текстом. Положил такой файл в публичный (да и в приватный) git - считай, слил секреты. Никакой sensitive = true в коде это не лечит, в state значение всё равно настоящее.
4. Легко потерять. Снёс папку, переустановил систему, не закоммитил, ноут утонул в кофе - и всё, маппинг потерян. Ресурсы в облаке живут, но Terraform о них больше не знает. Теперь либо мучительный terraform import каждого ресурса вручную, либо удаление и пересоздание всего с нуля.
Вывод простой: в любой командной работе state должен жить в удалённом бэкенде - например, в Yandex Object Storage с блокировкой через YDB или в Terraform Cloud. Удалённый бэкенд решает сразу все четыре боли: один общий источник правды, блокировка от гонок, шифрование секретов at rest, бэкапы. Настройку бэкенда мы детально разберём в следующем уроке, а пока главное - усвоить, ПОЧЕМУ локальный файл не вариант. Кстати, если ты используешь OpenTofu (открытый форк Terraform после смены лицензии), всё сказанное про state работает абсолютно так же - формат файла и логика идентичны.
Команды для работы с state
Лезть в JSON руками - табу, но Terraform даёт безопасный CLI-инструментарий, чтобы с состоянием работать цивилизованно. Вот рабочий минимум.
terraform state list - показывает список всех ресурсов в state. Первое, что стоит запустить, когда непонятно, что вообще под управлением Terraform.
Код: Выделить всё
terraform state list
# yandex_compute_instance.web
# yandex_vpc_network.main
# yandex_vpc_subnet.main
Код: Выделить всё
terraform state show yandex_compute_instance.web
Код: Выделить всё
terraform state rm yandex_compute_instance.web
Код: Выделить всё
terraform state mv yandex_compute_instance.web yandex_compute_instance.app
Мини-лаба
Руки помнят лучше глаз. Сделай это сам:
- Подними любой простой ресурс через apply (хватит yandex_vpc_network).
- Открой terraform.tfstate в редакторе и найди поля version, serial, lineage и блок resources. Не меняй ничего, просто посмотри.
- Запусти terraform state list, потом terraform state show на свою сеть. Сравни вывод с тем, что в JSON.
- Сделай state rm своей сети, затем terraform plan. Обрати внимание: Terraform теперь хочет создать её заново, потому что забыл про неё. Сеть в облаке при этом цела.
- Верни управление через terraform import (синтаксис: terraform import адрес id_ресурса) и убедись, что plan снова чистый.
- Зачем Terraform нужен state, если он и так может опросить API облака?
- Назови минимум две причины, почему хранить tfstate локально в команде опасно.
- Чем terraform state rm отличается от terraform destroy с точки зрения реальных ресурсов?
- Почему нельзя редактировать файл состояния руками и что использовать вместо этого?
State - это память Terraform, JSON-файл с маппингом кода на реальные ресурсы, метаданными и зависимостями. Локальный terraform.tfstate годится только для соло-эксперимента: в команде он не шерится, ловит гонки и конфликты, светит секретами и легко теряется. Лечение - удалённый бэкенд (Yandex Object Storage и подобные). Для разбора и переноса ресурсов есть безопасные команды state list/show/rm/mv, а лезть в JSON руками - запрещено. Усвоишь это сейчас - сэкономишь себе пару бессонных ночей на проде потом.