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-04-large-scale-state

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

Large-scale state, разбиение монолита

Один большой state с 1000 ресурсами, это lock-contention, медленный refresh, риск catastrophic-failure. Решение, split на иерархию: network, apps, и т.д. Между ними terraform_remote_state. На этом уроке: создашь монолит, поделишь его на network и apps, увидишь как они общаются.

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

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

запустить sandbox →

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

Шаги

  1. 01

    Базовый монолит

    bash
    cd /home/student/scale/monolith
    cat > main.tf <<'EOF'
    resource "aws_vpc" "main" {
      cidr_block = "10.0.0.0/16"
      tags = { Name = "scale-vpc" }
    }
    resource "aws_subnet" "private" {
      count             = 2
      vpc_id            = aws_vpc.main.id
      cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
      availability_zone = "us-east-1${["a", "b"][count.index]}"
      tags = { Name = "private-${count.index}" }
    }
    resource "aws_s3_bucket" "app_logs" {
      bucket = "scale-app-logs"
    }
    resource "aws_s3_bucket" "app_data" {
      bucket = "scale-app-data"
    }
    EOF
    terraform init -no-color > /dev/null
    terraform apply -auto-approve -no-color > /dev/null
    terraform state list

    Видишь VPC, 2 subnets, 2 buckets, всё в одном state'е.

    ✓ Монолит создан. Сейчас разделим.

  2. 02

    Извлеки VPC + subnets в network-state

    Стратегия, создать новый state, перенести в него ресурсы:

    bash
    cd /home/student/scale/network
    cat > main.tf <<'EOF'
    resource "aws_vpc" "main" {
      cidr_block = "10.0.0.0/16"
      tags = { Name = "scale-vpc" }
    }
    resource "aws_subnet" "private" {
      count             = 2
      vpc_id            = aws_vpc.main.id
      cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
      availability_zone = "us-east-1${["a", "b"][count.index]}"
      tags = { Name = "private-${count.index}" }
    }
    output "vpc_id" {
      value = aws_vpc.main.id
    }
    output "private_subnet_ids" {
      value = aws_subnet.private[*].id
    }
    EOF
    terraform init -no-color > /dev/null

    Теперь перенесём ресурсы, state pull из монолита, state push сюда:

    bash
    # из монолита достаём только network ресурсы
    cd ../monolith
    terraform state pull > /tmp/full.tfstate
    terraform state mv -state-out=/tmp/network.tfstate aws_vpc.main aws_vpc.main
    terraform state mv -state-out=/tmp/network.tfstate 'aws_subnet.private[0]' 'aws_subnet.private[0]'
    terraform state mv -state-out=/tmp/network.tfstate 'aws_subnet.private[1]' 'aws_subnet.private[1]'
    terraform state list
    # импортируем в network-state
    cd ../network
    terraform state push -force /tmp/network.tfstate
    terraform state list

    Network-state теперь содержит VPC + 2 subnet'а. Монолит, только bucket'ы.

    ✓ Network вынесен. State'ов теперь два.

  3. 03

    Apps-state с terraform_remote_state

    bash
    cd /home/student/scale/apps
    cat > main.tf <<'EOF'
    data "terraform_remote_state" "network" {
      backend = "local"
      config = {
        path = "../network/terraform.tfstate"
      }
    }
    resource "aws_s3_bucket" "app_logs" {
      bucket = "scale-app-logs"
      tags = {
        VPC = data.terraform_remote_state.network.outputs.vpc_id
      }
    }
    resource "aws_s3_bucket" "app_data" {
      bucket = "scale-app-data"
      tags = {
        SubnetCount = length(data.terraform_remote_state.network.outputs.private_subnet_ids)
      }
    }
    EOF
    terraform init -no-color > /dev/null

    Перенесём buckets из монолита:

    bash
    cd ../monolith
    terraform state mv -state-out=/tmp/apps.tfstate aws_s3_bucket.app_logs aws_s3_bucket.app_logs
    terraform state mv -state-out=/tmp/apps.tfstate aws_s3_bucket.app_data aws_s3_bucket.app_data
    terraform state list
    cd ../apps
    terraform state push -force /tmp/apps.tfstate
    terraform state list

    Apps-state, 2 bucket'а. Monolith, пустой.

    ✓ Apps читает network через remote_state. Монолит разобран.

  4. 04

    Проверь cross-state-ссылку

    bash
    cd /home/student/scale/apps
    terraform plan -no-color 2>&1 | tail -10

    Apps plan показывает что bucket'ы хотят добавить тег с VPC = <vpc-id>, взятый из network-state.

    Применяем:

    bash
    terraform apply -auto-approve -no-color > /dev/null
    terraform state show aws_s3_bucket.app_logs | grep -E "VPC|tags"

    Тег есть, vpc-id настоящий, apps реально прочитал output из network-state.

    ✓ Cross-state ссылка работает. Outputs network доступны в apps.

  5. 05

    Apps и network теперь меняются независимо

    Сценарий: добавляем ещё один bucket в apps. Network не трогается.

    bash
    cd /home/student/scale/apps
    cat >> main.tf <<'EOF'
    resource "aws_s3_bucket" "metrics" {
      bucket = "scale-metrics"
    }
    EOF
    terraform plan -no-color 2>&1 | tail -10
    terraform apply -auto-approve -no-color > /dev/null
    # network-state не тронули
    cd ../network
    terraform plan -no-color 2>&1 | tail -5

    Apps-plan показывает +1 ресурс. Network-plan, No changes. Изоляция работает.

    На большом проекте это значит: PR в apps не блокирует network-PR'ы, lock на разных state'ах разные, blast-radius ограничен.

    ✓ Изоляция доказана. Apps меняется без касания network.

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

    OpenTofu держит CLI и state совместимыми с Terraform по командам этого шага: миграция обычно проходит через mv .terraform .terraform.bak; tofu init -upgrade. Но при первом переходе сделай backup state и прогон на feature-branch - расхождения концентрируются в новых фичах (variables в backend, state-encryption, OCI registry-backed модули). См. tf-opentofu-parity для полной матрицы.

    • → OpenTofu parity
  6. 06

    «Blast-radius», сломай apps, network уцелеет

    Симулируем разрушение apps-state'а (не делай так в prod без бэкапа):

    bash
    cd /home/student/scale/apps
    cp terraform.tfstate /tmp/apps-backup.tfstate
    echo '{"corrupt": true}' > terraform.tfstate
    set +e
    terraform plan -no-color 2>&1 | tail -5
    code=$?
    set -e
    echo "apps plan exit: $code"
    # восстанавливаем
    cp /tmp/apps-backup.tfstate terraform.tfstate

    Apps state corrupt, plan падает. Но network-state цел:

    bash
    cd ../network
    terraform plan -no-color 2>&1 | tail -5
    echo "network plan ok"

    VPC и subnets продолжают работать. Это и есть изолированный blast-radius, один stack может сгореть, остальное живёт.

    ✓ Network защищён от поломок apps. Это и есть blast-radius isolation.

    Когда не разделять

    Разделение, не всегда win. Накладные расходы:

    1. Orchestration. Apply'ить нужно в правильном порядке. Terragrunt или shell-script нужны.
    2. Cross-state coupling. Output deletes ломают reader'ов.
    3. Сложность для новичков. «Где живёт VPC-id?», теперь ответ длиннее.
    4. Replicated provider-config. Каждый stack нуждается в провайдере. На 10 stack'ов, 10 provider-блоков.

    Не разделять если:

    • Меньше 200 ресурсов в state.
    • Один env, одна команда.
    • Plan < 30s, apply разумный.

    Делать раздел осознанно, когда симптомы (медленный plan, lock-contention, страх перед apply) появились. Не «на будущее».

    См. tf-large-scale-state.

    • → Large-scale state
    • → state mv детально

Что ты узнал

terraform_remote_state, data-source, читает outputs из другого state-файла. Только outputs видны cross-state, внутренние ресурсы и locals нет. Каждый stack, свой backend-key, свой lock.

команды

  • terraform_remote_state.network.outputs.Xссылка на output из другого state'а.
  • terraform state listчто в текущем state. Один state ≠ всё.
  • terraform state pull > backup.jsonбекап перед split-операцией.

концепции

  • · Один state per layer = изоляция blast-radius
  • · Cross-state через outputs, versionируй, не переименовывай легко
  • · DynamoDB-lock-table одна на org, partition-key per state

← предыдущий

Нативные тесты, .tftest.hcl и assert

следующий →

State: что внутри файла terraform.tfstate

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