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-advanced-07-opentofu-matrix

lesson ── terraform-advanced ── ~12 мин ── 6 шагов

OpenTofu, matrix-CI рядом с Terraform

OpenTofu, fork Terraform под MPL-2.0. Бинарь tofu уже лежит в образе рядом с terraform. На уроке прогоним один HCL обоими, сравним результат и соберём matrix-pipeline для CI. Это страховка от lock-in HashiCorp-лицензии.

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

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

запустить sandbox →

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

Шаги

  1. 01

    OpenTofu в образе

    bash
    which terraform
    terraform --version
    echo ---
    which tofu
    tofu --version

    Оба бинаря лежат в /usr/local/bin. Версии могут не совпадать это норма, fork ветки развиваются параллельно.

    ✓ Tofu и terraform в одном sandbox'е.

  2. 02

    Тот же HCL, оба инструмента

    bash
    cd /home/student/parity
    cat > main.tf <<'EOF'
    resource "aws_s3_bucket" "parity_demo" {
      bucket = "linuxlab-parity-demo"
      tags = {
        ManagedBy = "either"
      }
    }
    output "name" {
      value = aws_s3_bucket.parity_demo.bucket
    }
    EOF

    Сначала Terraform:

    bash
    terraform init -no-color > /dev/null
    terraform plan -no-color -out=plan.terraform > /dev/null
    terraform show -no-color plan.terraform > plan-terraform.txt
    head -20 plan-terraform.txt

    Теперь OpenTofu (в новом каталоге чтобы не путать state):

    bash
    mkdir -p tofu-test
    cp main.tf provider.tf tofu-test/
    cd tofu-test
    tofu init -no-color > /dev/null
    tofu plan -no-color -out=plan.tofu > /dev/null
    tofu show -no-color plan.tofu > ../plan-tofu.txt
    cd ..
    head -20 plan-tofu.txt

    Оба показали тот же ресурс к созданию.

    ✓ Оба инструмента видят одно и то же. Parity подтверждена.

  3. 03

    Diff между plan'ами

    bash
    diff plan-terraform.txt plan-tofu.txt | head -20 || echo "outputs identical (or minor diff)"

    Должно быть либо нет вывода (identical), либо minor stylistic diff (например, заголовок «Terraform used the selected providers» vs «OpenTofu used...»). Семантически, то же самое.

    В CI этот diff (минус headers) проверяется регулярно. Если внезапно large diff, фича расходится, время решить какой выбираем.

    ✓ Plan'ы сравнены. Расхождения видны явно.

  4. 04

    Matrix-CI: workflow для двух

    bash
    mkdir -p .github/workflows
    cat > .github/workflows/parity.yml <<'EOF'
    name: Parity CI
    on:
      push:
        branches: [main]
      pull_request:
    jobs:
      terraform-plan:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: hashicorp/setup-terraform@v3
            with:
              terraform_version: 1.9.8
          - run: terraform init -input=false
          - run: terraform plan -input=false -no-color
      opentofu-plan:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: opentofu/setup-opentofu@v1
            with:
              tofu_version: 1.8.5
          - run: tofu init -input=false
          - run: tofu plan -input=false -no-color
    EOF
    cat .github/workflows/parity.yml

    Два независимых job'а. Если один зелёный, другой красный сразу видно расхождение. На critical-расхождения PR блокируется.

    ✓ Matrix-workflow написан. В реальном GitHub оба job'а гоняются параллельно.

  5. 05

    State от Terraform, читается OpenTofu

    Самое важное свойство, state совместим.

    bash
    # apply через Terraform
    cd /home/student/parity
    terraform apply -auto-approve plan.terraform > /dev/null
    ls terraform.tfstate
    # OpenTofu теперь сможет работать с этим state'ом
    tofu show terraform.tfstate 2>&1 | head -15

    OpenTofu корректно прочитал state, созданный Terraform'ом. Это и есть основа miracle-миграции: переключаешь CI с terraform на tofu, ничего больше не меняешь.

    Обратное тоже работает: state от tofu apply читается terraform.

    ✓ State полностью совместим. Миграция в обе стороны без conversion.

  6. 06

    Когда terraform, когда tofu

    Решение:

    bash
    cat > /tmp/decision.md <<'EOF'
    | Сигнал | Выбор |
    |---|---|
    | Текущая команда на HashiCorp Terraform / HCP | Terraform |
    | Новый проект, нет lock-in'а | OpenTofu (MPL-license) |
    | Нужны Stacks (HCP) | Terraform |
    | Нужно state encryption at rest | OpenTofu (нативно) |
    | Нужен exclude в for_each | OpenTofu 1.8+ |
    | Команда на Atlantis / Spacelift | Проверь поддержку обоих в твоём tool'е |
    | Air-gapped / regulated | OpenTofu (Linux Foundation, MPL) |
    Для большинства команд: matrix-CI = страховка, выбор default'а
    определяется текущей инфраструктурой и risk-tolerance.
    EOF
    cat /tmp/decision.md

    В реальной команде это часть архитектурного решения; ADR это фиксирует.

    ✓ Знаешь когда что. Дальше, capstone-проект.

    Migration scenario

    Реальная миграция Terraform → OpenTofu для команды:

    1. Pin'нуть текущий Terraform (1.5.7, последний MPL). Можно работать дальше без хитростей.

    2. Параллельно ставить OpenTofu на dev-machines. Прогнать tofu plan на текущих stack'ах, расхождений быть не должно.

    3. Matrix-CI добавить, tofu plan рядом с terraform plan. Зелёный, ок продолжаем.

    4. Переключение в CI. В одном feature-branch меняем setup-terraform → setup-opentofu. Тестируем неделю.

    5. Свич main'а. После confidence, переключаем всех. State не трогается.

    6. Удаляем terraform job'у через месяц-два после stable-state'а.

    Что-то ломается, terraform job всё ещё там, fallback готов.

    Подробнее, tf-opentofu-parity.

    • → OpenTofu целиком

Что ты узнал

OpenTofu (tofu), drop-in replacement Terraform. В образе уже стоит рядом с terraform. tofu init/plan/apply работает с тем же HCL и тем же state'ом. CI с двумя jobs (terraform + tofu) ловит расхождения сразу.

команды

  • tofu --versionOpenTofu предустановлен в sandbox-образе.
  • tofu init && tofu planобычные команды, но через tofu.
  • diff plan.terraform plan.tofuсравнить вывод plan'ов на расхождения.

концепции

  • · OpenTofu = MPL fork последнего MPL-Terraform
  • · State совместим, миграция без conversion'а
  • · Расхождения растут с версиями; matrix-CI ловит сразу

← предыдущий

OPA + Rego, гейтим plan.json

следующий →

Data sources: читаем существующее

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