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-05-blue-green-migration

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

Blue-green миграция legacy в Terraform

Legacy-инфра, созданная руками или CloudFormation'ом. Захватить её через terraform import, недели работы и риск destroy. Альтернатива blue-green: создать параллельную копию через Terraform, переключить traffic, снести legacy. На уроке сэмулируешь это на S3-bucket'ах «legacy» и «tf», с символическим traffic-switch'ем.

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

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

запустить sandbox →

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

Шаги

  1. 01

    «Legacy»-bucket, созданный вручную

    Эмуляция legacy, создаём через aws-cli, не через Terraform:

    bash
    cd /home/student/blue-green
    aws --endpoint-url=http://localstack:4566 \
      s3api create-bucket --bucket legacy-app-data --region us-east-1
    aws --endpoint-url=http://localstack:4566 \
      s3api put-bucket-tagging --bucket legacy-app-data \
      --tagging 'TagSet=[
        {Key=ManagedBy,Value=clickops},
        {Key=Owner,Value=unknown}
      ]'
    # положим что-то "пользовательское"
    echo "important data v1" > /tmp/data-1.txt
    echo "important data v2" > /tmp/data-2.txt
    aws --endpoint-url=http://localstack:4566 s3 cp /tmp/data-1.txt s3://legacy-app-data/
    aws --endpoint-url=http://localstack:4566 s3 cp /tmp/data-2.txt s3://legacy-app-data/
    aws --endpoint-url=http://localstack:4566 s3 ls s3://legacy-app-data/

    Legacy bucket в облаке, под управлением Terraform его нет.

    ✓ Legacy на месте. Terraform его не знает.

  2. 02

    Создай tf-bucket (green) рядом

    bash
    cat > main.tf <<'EOF'
    resource "aws_s3_bucket" "tf_app_data" {
      bucket = "tf-app-data"
      tags = {
        ManagedBy = "terraform"
        MigratedFrom = "legacy-app-data"
      }
    }
    resource "aws_s3_bucket_versioning" "tf_app_data" {
      bucket = aws_s3_bucket.tf_app_data.id
      versioning_configuration {
        status = "Enabled"
      }
    }
    output "tf_bucket" {
      value = aws_s3_bucket.tf_app_data.bucket
    }
    EOF
    terraform init -no-color > /dev/null
    terraform apply -auto-approve -no-color > /dev/null
    aws --endpoint-url=http://localstack:4566 s3 ls

    Видишь два bucket'а: legacy-app-data и tf-app-data. Green пустой, пока.

    ✓ Green создан, рядом с legacy. Tracker, Terraform.

  3. 03

    Синкай данные blue → green

    bash
    aws --endpoint-url=http://localstack:4566 \
      s3 sync s3://legacy-app-data s3://tf-app-data --exact-timestamps
    aws --endpoint-url=http://localstack:4566 s3 ls s3://tf-app-data/

    Данные в green. Это самая дорогая часть в реальной миграции (terabytes данных = часы).

    В production: либо это short-window cutover, либо logical-replication (RDS, MongoDB).

    ✓ Данные синхронизированы. Green готов принимать traffic.

  4. 04

    Эмулируй traffic-switch

    В реальной системе switch, это DNS/Route53/ALB. На LocalStack возьмём proxy «который application bucket?»:

    bash
    # Symlink-эмуляция конфига приложения
    cat > current-target.txt <<EOF
    target: legacy-app-data
    EOF
    cat current-target.txt
    # smoke-test «приложения», читает указанный bucket
    cat > smoke.sh <<'EOF'
    #!/bin/bash
    TARGET=$(grep '^target' current-target.txt | cut -d' ' -f2)
    echo "Reading from $TARGET..."
    aws --endpoint-url=http://localstack:4566 s3 ls s3://$TARGET/ | head -2
    EOF
    chmod +x smoke.sh
    ./smoke.sh

    Сейчас приложение читает legacy. Переключим:

    bash
    sed -i 's/legacy-app-data/tf-app-data/' current-target.txt
    ./smoke.sh

    Реальный switch через Route53 weighted-records (вес 100 → tf-, 0 → legacy-) или ALB target-group. См. KB tf-blue-green-migration.

    ✓ Traffic переключён на green. Старый bucket в standby.

  5. 05

    Monitoring-окно перед сносом

    В реальном production, несколько дней с включёнными метриками. Symbolically:

    bash
    cat > /tmp/monitoring.log <<EOF
    day-1: requests=10000 errors=0  | green ok
    day-2: requests=15000 errors=2  | green ok (within tolerance)
    day-3: requests=12000 errors=0  | green ok
    EOF
    cat /tmp/monitoring.log

    Если бы green показывал нестабильность, sed -i 's/tf-app-data/legacy-app-data/' current-target.txt и rollback готов. Blue ещё цел.

    Это и есть преимущество blue-green: rollback дешёвый, decision reversible до момента сноса blue.

    ✓ Monitoring-окно прошло без incident'ов. Готовы сносить legacy.

    То же самое на 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

    Сноси legacy

    bash
    # очистка содержимого (s3 rb требует пустой bucket если без --force)
    aws --endpoint-url=http://localstack:4566 \
      s3 rm s3://legacy-app-data --recursive
    aws --endpoint-url=http://localstack:4566 \
      s3 rb s3://legacy-app-data
    aws --endpoint-url=http://localstack:4566 s3 ls

    Legacy snесён. Терраформ-state'у он не нужен, tf_app_data всегда был под управлением Terraform.

    Финальная проверка, приложение всё ещё работает:

    bash
    ./smoke.sh

    Видит данные в tf-app-data. Миграция завершена.

    Никакого terraform import, никаких ужасных state-операций. Только создание новой инфры рядом и постепенный switch.

    ✓ Legacy ушёл. Green работает. Blue-green миграция завершена.

    Когда blue-green не подходит

    Blue-green не серебряная пуля. Случаи когда стоит делать import или другой путь:

    1. Уникальный ARN/ID в external-системах. IAM-role с хардкоднутым ARN'ом в стороннем сервисе, blue-green не поможет, ARN другой будет.

    2. Stateful с большими данными. 100 TB в RDS, sync дорого, простой большой. import плюс careful refactor могут быть cheaper.

    3. Hard-dependencies к specific IP'шкам. Internal-ALB с прибитым IP. Blue-green создаст другой IP, внешние клиенты не догадаются.

    4. Cross-account / cross-team coupling. Если другие команды ссылаются на твой ресурс по имени, и переименование требует coordination, import понятнее (имя не меняется).

    Решение делается case-by-case. Blue-green, default-выбор для большинства stateless ресурсов и small statefuls. import когда blue-green физически дорого или невозможно.

    • → Blue-green целиком
    • → Когда import оправдан

Что ты узнал

Сценарий: legacy bucket существует, создан вне Terraform. Не import'им его, создаём параллельный tf-bucket, синкаем данные через aws s3 sync, переключаем DNS (или alias), снимаем legacy. На каждом шаге легко откатиться.

команды

  • aws s3 sync s3://legacy s3://tf-managedкопируем данные.
  • terraform applyразвёртываем green.
  • aws s3 rb s3://legacy --forceфинальный sneeze legacy.

концепции

  • · Blue (legacy) и green (Terraform) живут параллельно дни-недели
  • · Switch, DNS / alias / traffic weight, не «import + apply»
  • · Rollback, переключить обратно, blue ещё жив

← предыдущий

Mock-провайдеры, тесты без облака

следующий →

Update: меняем атрибут, видим diff

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