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-garden-01-cycle-error

lesson ── terraform-garden ── ~18 мин ── 3 шагов

Troubleshooting Garden: распутай Cycle Error

В ~/tf-garden лежит готовый HCL. terraform init пройдёт, plan, нет: Cycle Error. Один ресурс ссылается на другой, тот на третий, третий обратно на первый. Без распутывания граф не строится, plan не запустится.

Твоя задача, найти цикл, понять зачем он там, разорвать его так, чтобы смысл остался, и доказать plan'ом что граф стал DAG.

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

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

запустить sandbox →

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

Шаги

  1. 01

    Запусти init и plan, поймай Cycle Error

    Войди в директорию, проинициализируй и попробуй сделать plan.

    bash
    cd /home/student/tf-garden
    terraform init
    terraform plan 2>&1 | tee /tmp/cycle.log

    В cycle.log будет блок вида:

    Error: Cycle: random_id.suffix, aws_s3_bucket.demo, aws_s3_bucket_policy.demo

    Запиши себе три имени ресурсов. Это твой цикл.

    ✓ Цикл подтверждён. Теперь, почему он там.

    Откуда циклы берутся

    Самый частый сценарий: keepers или triggers в utility-ресурсе ссылается на ресурс, который сам зависит от utility-ресурса. Тут random_id.keepers.bucket_arn = aws_s3_bucket.demo.arn, а aws_s3_bucket.demo.bucket, garden-cycle-${random_id.suffix.hex}. Получили зависимость в обе стороны.

    Второй частый сценарий: depends_on руками поверх implicit-deps. Terraform строит граф автоматически, если ты пишешь depends_on туда же, можно получить «А зависит от B, B зависит от A через ручной depends_on».

  2. 02

    Перепиши HCL так, чтобы цикл исчез

    Решение: убери обратную зависимость random_id.keepers (она бесполезна, потому что random_id и так пересоздаётся через -replace), и вынеси условие из политики в locals:

    hcl
    locals {
      suffix_hex = random_id.suffix.hex
    }
    resource "random_id" "suffix" {
      byte_length = 4
    }
    resource "aws_s3_bucket" "demo" {
      bucket = "garden-cycle-${local.suffix_hex}"
    }
    resource "aws_s3_bucket_policy" "demo" {
      bucket = aws_s3_bucket.demo.id
      policy = jsonencode({
        Version = "2012-10-17"
        Statement = [{
          Effect    = "Allow"
          Principal = "*"
          Action    = "s3:GetObject"
          Resource  = "${aws_s3_bucket.demo.arn}/*"
          Condition = {
            StringEquals = {
              "aws:RequestTag/SuffixHex" = local.suffix_hex
            }
          }
        }]
      })
    }

    Положи это в ~/tf-garden/main.tf поверх старого. После, проверь что блока keepers нет.

    подсказка

    В новом main.tf не должно быть слова `keepers`. Не пытайся «починить» политику добавлением depends_on, это не туда.

    ✓ HCL переписан. Проверим граф.

  3. 03

    Plan должен пройти и показать diff

    bash
    cd /home/student/tf-garden
    terraform plan -out=plan.tfplan

    Теперь plan должен пройти: «Plan: 3 to add, 0 to change, 0 to destroy». Apply в этом уроке не обязателен, главное что граф собрался.

    Если plan всё ещё ругается, посмотри terraform graph -draw-cycles, может остался ещё один цикл, который ты не заметил.

    ✓ Plan собрался, граф стал DAG. Цикл распутан.

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

    OpenTofu повторяет ту же логику Cycle-проверки 1:1, те же сообщения, тот же graph-командой. Это часть наследия HCL, не отличие реализаций. Полная статья про различия и совместимость, tf-opentofu-parity.

    • → OpenTofu parity
    • → Типичные ошибки
    • → terraform graph

Что ты узнал

Cycle, это всегда дизайн-ошибка, не баг tf. Видишь цикл? Кто-то написал зависимости в две стороны. random_id.keepers ссылающийся на ресурс, который зависит от того же random_id, классика. Решение: убрать обратную ссылку и переложить логику в data-block или local, или признать что зависимость в одну сторону.

команды

  • terraform graph -draw-cycles | dot -Tsvg > /tmp/g.svgграфическая подсветка цикла; если dot не доступен, читай ASCII-вывод
  • terraform graph -type=plan-destroyещё одна оптика на тот же граф; иногда видно лучше

концепции

  • · Cycle Error всегда конкретен: цикл из 2-3 узлов, не «весь граф плохой»
  • · random_id.keepers, мощный инструмент, но триггерит зависимости в обе стороны
  • · Conditions в политиках можно вычислять локалями, а не attribute-references

← предыдущий

Hello, S3: первый ресурс в Terraform

следующий →

Свой первый модуль: выноси S3 в reusable

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