Что такое state и зачем он нужен
State (состояние) — это карта, связывающая ваш код с реальными ресурсами в облаке. Без неё Terraform не знал бы, какой сервер в коде соответствует какому серверу в AWS.
State — самый важный и самый опасный артефакт Terraform. Потеряете его — Terraform «забудет» всю инфраструктуру и попробует создать её заново. Сломаете — устроите хаос. Относитесь к нему как к проду.
Terraform управляет тремя мирами: код (что вы хотите, желаемое состояние), реальность (что есть в облаке) и state (что Terraform думает о реальности). State — это связующее звено: он хранит соответствие aws_instance.web → i-0abc123. Без него Terraform не отличит свой сервер от чужого.
Что внутри tfstate
Файл terraform.tfstate — это JSON. В нём для каждого ресурса записан его адрес, тип, провайдер и снимок всех атрибутов:
{
"version": 4,
"resources": [
{
"type": "aws_instance",
"name": "web",
"instances": [
{
"attributes": {
"id": "i-0abc123",
"instance_type": "t2.micro",
"public_ip": "54.1.2.3"
}
}
]
}
]
}
КОД (.tf) STATE (карта) РЕАЛЬНОСТЬ (облако) желаемое что знает TF что есть на самом деле ----------- -------------- -------------------- aws_instance.web -> i-0abc123 -> [сервер i-0abc123] aws_s3.data -> bucket-xyz -> [бакет bucket-xyz] plan = сравнить КОД и STATE+РЕАЛЬНОСТЬ, выдать diff
Как работает под капотом
На plan Terraform делает три шага: читает желаемое (код), читает запомненное (state), опрашивает реальность (refresh) и сравнивает. State нужен в том числе чтобы понять, какие ресурсы удалить — их нет в коде, но они есть в state. Смоделируем роль state как «памяти»:
desired = {"web", "db", "cache"} # в коде
state = {"web", "db", "old_lb"} # TF помнит это
to_create = desired - state # есть в коде, нет в памяти
to_delete = state - desired # есть в памяти, нет в коде
to_keep = desired & state # есть в обоих
print("создать:", to_create)
print("удалить:", to_delete, "<- без state TF бы это НЕ нашёл!")
print("оставить:", to_keep)
«Попробуй сам ▶» — обратите внимание: old_lb попадает в «удалить» только потому, что Terraform помнит его в state. Без state он бы остался брошенным навсегда.
Частые ошибки
- Коммитить tfstate в git. В нём лежат секреты открытым текстом (пароли, ключи) — прямая утечка.
- Удалить или потерять state. Terraform забудет инфраструктуру и попытается создать дубли.
- Редактировать tfstate руками. Один неверный символ — и весь файл невалиден.
Best practices
- Никогда не храните state в git. Только удалённый бэкенд (об этом — следующий урок).
- Делайте бэкапы state и включайте версионирование хранилища.
- Не правьте state текстовым редактором — для этого есть команды
terraform state.
Разбор глубже
Возникает резонный вопрос: зачем вообще нужен state, почему Terraform не может каждый раз заново опрашивать облако и сравнивать с кодом? Причин несколько. Во-первых, производительность: полный обход всех ресурсов через API на большом проекте занимал бы минуты и упирался в лимиты. State служит кешем. Во-вторых, сопоставление: облако не знает, что инстанс i-0abc — это именно ваш aws_instance.web; эту привязку хранит только state. В-третьих, удаление: чтобы понять, что ресурс надо снести, Terraform должен помнить, что когда-то его создавал, — без state удалённый из кода ресурс просто остался бы брошенным навсегда.
В state хранятся и метаданные, невидимые в коде: версия формата (version), серийный номер (увеличивается с каждым изменением и помогает обнаружить устаревшую копию), и зависимости между ресурсами на момент последнего apply. Поэтому редактировать state руками крайне опасно — легко рассогласовать эти служебные поля. Для любых правок существуют специальные команды terraform state, которые меняют файл корректно и согласованно. А золотое правило безопасности простое: state — это прод, относитесь к нему так же бережно, как к боевой базе данных.
Наконец, важно осознавать, что state — это единая точка истины и одновременно единая точка отказа. Вся команда и весь CI читают и пишут один и тот же файл, поэтому его доступность и целостность критичны. Отсюда вытекают три обязательных меры, которые мы детально разберём дальше: хранить state в надёжном удалённом бэкенде, защищать его блокировкой от одновременной записи и обязательно держать версионирование хранилища, чтобы любую испорченную версию можно было откатить. Потерянный или повреждённый state — одна из немногих по-настоящему болезненных аварий в мире Terraform, и вся гигиена работы с ним направлена на то, чтобы такая ситуация просто не могла возникнуть.
Итог: state — карта между кодом и реальностью, без которой Terraform слеп. Это JSON с секретами, поэтому его берегут и не кладут в git. Дальше — где его правильно хранить.