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
  • Собеседование
Cluster

← все кластеры

Troubleshooting и отладка

Что делать когда `plan` падает с невнятной ошибкой. Чтение TF_LOG, распространённые ошибки (cycle, inconsistent dependency lock, provider auth). terraform console для отладки выражений, чтение plan diff, terraform graph - когда он реально нужен.

6 вопросов · ~22 мин чтения

Questions

На этой странице

  1. 01Что такое TF_LOG и какие уровни осмысленно использовать?
  2. 02Получаешь `Error: Cycle: A → B → A`. Что делать?
  3. 03`Error: Inconsistent dependency lock file`. Что случилось?
  4. 04Что делает `terraform console` и когда его использовать?
  5. 05Какие символы в plan-выводе и что они значат?
  6. 06Когда `terraform graph` реально полезен, а когда overkill?

#tf-log-levels-and-usage

juniorиногда

Что такое TF_LOG и какие уровни осмысленно использовать?

Что отвечать

`TF_LOG` - env-переменная для вывода диагностики Terraform во время команды. Уровни: TRACE > DEBUG > INFO > WARN > ERROR. TRACE сыпет каждую HTTP-операцию провайдера, миллионы строк. DEBUG - чуть тише, обычно достаточно для понимания «что Terraform хотел сделать». INFO - стандартный production-уровень. Для long-running команд - `TF_LOG_PATH=tf.log` чтобы писать в файл, не засорять терминал. Полезный трюк: `TF_LOG_PROVIDER=DEBUG` отдельно от core - видишь только provider-логи без graph-internals.

Что хотят услышать

Senior должен: - различить TF_LOG (всё) и TF_LOG_PROVIDER (только провайдер) - часто нужен только второй - назвать `TF_LOG_PATH` для file-output - terminal лог теряет scrollback на больших стейтах - сказать что TRACE даёт raw HTTP requests/responses к провайдеру, бесценно для диагностики auth или timeout - упомянуть что в логах могут оседать secrets (Bearer-токены в Authorization-headers) - не делиться файлами без чистки

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

  • ✗ Запустить `TF_LOG=TRACE plan` без `TF_LOG_PATH` - терминал забивается, скроллить вверх до полезного - вечность
  • ✗ Поделиться tf.log в Slack без редактирования - там Authorization headers и иногда state-выдержки
  • ✗ Использовать TF_LOG=INFO когда DEBUG нужнее - INFO почти ничего не показывает, лишний раз поднимать не страшно

Follow-up

  • ? Чем `TF_LOG_PROVIDER` отличается от просто `TF_LOG`?
  • ? Какие уровни логирования имеет смысл смешивать?
  • ? Что можно вычистить из TF_LOG-файла перед расшариванием?

Глубина в базе знаний

  • TF_LOG: диагностические логи Terraform
  • terraform plan: посмотреть, что Terraform собирается сделать
  • [[tf-common-errors]]
tags: debug, logs

#common-cycle-error

intermediateиногда

Получаешь `Error: Cycle: A → B → A`. Что делать?

Что отвечать

Cycle - circular dependency в графе ресурсов. Сначала: `terraform graph | dot -Tsvg > g.svg` - визуально видно где замкнулось. Чаще всего причина: лишний `depends_on` там где Terraform уже видит implicit dep через атрибут, или `replace_triggered_by` который ссылается обратно. Лечение: убрать дублирующий depends_on, разорвать через local-переменную (`local.shared = aws_x.y.attr`, оба ресурса ссылаются на local), вынести в data source если ресурс «чужой».

Что хотят услышать

Senior должен: - назвать `terraform graph | dot` как первый инструмент диагностики - дать конкретные источники cycle: лишний depends_on (самый частый), replace_triggered_by, цикл через child-модуль (`module.A` зависит от `module.B` который зависит от `module.A`) - объяснить разрыв через local: если оба ресурса ссылаются на одно значение через locals, граф разрывается - упомянуть что cycle ловится только на `plan`, не статически

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

  • ✗ Удалить explicit depends_on и не проверить, что implicit действительно есть - apply упадёт на runtime
  • ✗ Сделать `terraform graph` без `dot` (одна графовая утилита) - сырой output читать невозможно
  • ✗ Пытаться разрулить cycle через `-target` - симптом, не лечение

Follow-up

  • ? Как `terraform graph` помогает увидеть source of cycle?
  • ? Чем разрыв через local отличается от data source?
  • ? Какие конструкции HCL чаще создают cycle?

Глубина в базе знаний

  • [[tf-common-errors]]
  • terraform graph: граф зависимостей ресурсов
  • DAG в Terraform, как строится граф зависимостей
  • Зависимости ресурсов: явные и неявные
tags: debug, cycle, graph

#inconsistent-dependency-lock

intermediateчасто

`Error: Inconsistent dependency lock file`. Что случилось?

Что отвечать

`.terraform.lock.hcl` фиксирует версии провайдеров и их checksums. Ошибка значит: то, что в lockfile - не совпадает с тем что Terraform нашёл в `terraform init`. Сценарии: (1) кто-то обновил version constraint в HCL, но не обновил lockfile (надо `init -upgrade`); (2) lockfile содержит checksum для одной платформы (linux_amd64), ты на другой (darwin_arm64) - надо `providers lock -platform=darwin_arm64`; (3) провайдер опубликовал новый artifact на ту же версию - тогда надо вручную обновить checksum.

Что хотят услышать

Senior должен: - объяснить роль lockfile: воспроизводимость провайдер-версий между runs и машинами, защита от tampered artifacts через checksum - назвать `terraform providers lock -platform=X -platform=Y` для многоплатформенного CI (macOS dev + linux CI) - сказать что коммит lockfile обязателен; репо без `.terraform.lock.hcl` даёт «у меня всё работает, у тебя нет» - упомянуть что `init -upgrade` пересчитывает lockfile - использовать осознанно, не по умолчанию

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

  • ✗ Не коммитить lockfile - воспроизводимости нет, дрейф провайдер-версий через год
  • ✗ Запускать `init -upgrade` в pipeline по умолчанию - получаешь неожиданное поведение на minor-bump провайдера
  • ✗ Собирать lockfile только под linux_amd64 - dev'ы на маках падают на init

Follow-up

  • ? Зачем `terraform providers lock -platform=darwin_arm64`?
  • ? Что произойдёт если коммитить lockfile только с linux-чексами?
  • ? Чем `init -upgrade` отличается от обычного init?

Глубина в базе знаний

  • .terraform.lock.hcl: фиксация версий провайдеров
  • terraform init: первая команда в любом проекте
  • [[tf-common-errors]]
tags: debug, lockfile, ci

#terraform-console-debug

juniorиногда

Что делает `terraform console` и когда его использовать?

Что отвечать

`terraform console` - REPL для интерактивной проверки выражений против текущего state. Полезен когда в HCL что-то странное и не понимаешь как функция отрабатывает. Запускаешь `terraform console`, пишешь `{ for k, v in aws_subnet.public : k => v.cidr_block }` - видишь результат немедленно, без apply. Также: `length(var.list)`, `try(local.maybe_missing, "default")`, проверка type coercion. Работает только с уже инициализированным root, читает state.

Что хотят услышать

Кандидат должен: - назвать console как способ быстро проверить выражение без правки HCL и `terraform plan` - сказать что console читает реальный state - значения computed атрибутов уже там - упомянуть multi-line ввод через скобки или heredoc для сложных выражений - назвать что без `terraform init` console не запустится; нужны провайдеры, чтобы знать схему ресурсов

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

  • ✗ Думать что console может вычислить выражение со ссылкой на ресурс, которого ещё нет в state - не может
  • ✗ Пытаться сделать `aws_instance.demo = ...` в console - это REPL для выражений, не для апдейта
  • ✗ Не выйти из console и потерять lock - console не держит lock, но в долгой сессии state может протухнуть

Follow-up

  • ? Может ли console обращаться к provider API?
  • ? Как протестировать `try()` или `coalesce()` через console?
  • ? Зачем нужен `terraform init` перед console?

Глубина в базе знаний

  • terraform console. REPL для выражений HCL
  • Ссылки в HCL: как читать aws_s3_bucket.demo.bucket
  • Функции коллекций HCL: length, lookup, merge, concat, flatten
tags: debug, console

#plan-diff-symbols

intermediateчасто

Какие символы в plan-выводе и что они значат?

Что отвечать

`+` - create. `-` - destroy. `~` - update in-place (атрибут меняется, ресурс остаётся). `-/+` - destroy then create (replace, нужен полный пересоздание, обычно immutable attribute). `+/-` - create then destroy (то же, но с `create_before_destroy`). `<=` - read (data source). `# (will be unchanged)` - no-op. Самое важное при ревью - различать `~` (in-place, безопасно) и `-/+` (replace, может быть downtime). Replace через `-target` всегда подозрителен.

Что хотят услышать

Senior должен: - различить in-place update (`~`) и replace (`-/+`); replace = destroy старого + create нового, часто означает downtime - сказать что `+/-` - replace через `create_before_destroy`, новый создаётся до уничтожения старого - упомянуть что Terraform даёт detail почему ресурс replace'ится: «(forces replacement)» рядом с атрибутом - назвать `terraform show -json plan.tfplan | jq` для автоматизированной проверки plan'а в CI без visual review

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

  • ✗ Не заметить `-/+` в plan и аплайнуть - downtime в проде
  • ✗ Считать что `~` всегда безопасен - на некоторых ресурсах in-place update тоже даёт downtime (RDS engine_version)
  • ✗ Парсить plan-output regex'ом вместо JSON - формат меняется между версиями

Follow-up

  • ? Чем `-/+` принципиально отличается от `+/-`?
  • ? Как найти «forces replacement» причину в plan-output JSON?
  • ? Когда `~` всё-таки даёт downtime?

Глубина в базе знаний

  • [[tf-plan-diff]]
  • terraform plan: посмотреть, что Terraform собирается сделать
  • lifecycle: управляем поведением resource
tags: debug, plan, diff

#terraform-graph-when-useful

seniorредко

Когда `terraform graph` реально полезен, а когда overkill?

Что отвечать

Graph выводит DAG ресурсов в формате DOT. Полезен в трёх случаях: (1) cycle - визуально видно где замкнулось; (2) понимание плотности графа после рефакторинга - не плодишь ли лишних рёбер через depends_on; (3) ревью большой инфры - кто на кого ссылается. В повседневной работе - не нужен; план и diff показывают всё что нужно для apply'а. Утилита Rover (`im2ag/rover`) делает интерактивный web-визуализатор поверх graph - удобнее для разговора с command'ой «вот наша инфра».

Что хотят услышать

Senior должен: - назвать конкретные сценарии где graph даёт ценность (cycle, refactor review, knowledge transfer) - сказать что raw DOT нечитаем; всегда через `dot -Tsvg` или Rover - упомянуть что graph не показывает provider-атрибуты, только dependencies между ресурсами и data source'ами - назвать что для большой инфры graph становится monstre - 5000 нодов в svg, ничего не разглядеть; rover с фильтрами эффективнее

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

  • ✗ Делать `terraform graph` без `dot` или Rover - читать невозможно
  • ✗ Использовать graph для CI-проверок («не появилось ли cycle») - lifecycle сам ловит cycle на plan
  • ✗ Считать что graph показывает реальную топологию инфры - он показывает граф управления Terraform'ом, не сеть

Follow-up

  • ? Чем Rover лучше чем плоский dot-вывод?
  • ? Что показывает graph для модулей?
  • ? Какие edges в graph можно безопасно игнорировать?

Глубина в базе знаний

  • terraform graph: граф зависимостей ресурсов
  • [[tf-rover-visualization]]
  • DAG в Terraform, как строится граф зависимостей
tags: debug, graph, visualization
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки