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-beginner-09-lifecycle

lesson ── terraform-beginner ── ~12 мин ── 4 шагов

lifecycle: запреты, игнор и пересоздание

По умолчанию Terraform работает так: «если в HCL стало по-другому, изменить ресурс. Если убрал из HCL, удалить». Но иногда поведение надо подкрутить. Для этого есть блок lifecycle внутри ресурса.

В этом уроке ты попробуешь три опции: prevent_destroy (защита от удаления), ignore_changes (игнор drift'а по атрибутам), create_before_destroy (zero-downtime пересоздание). См. tf-resource-lifecycle.

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

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

запустить sandbox →

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

Шаги

  1. 01

    Создай бакет с тегом, который потом будем игнорировать

    Создай main.tf:

    hcl
    resource "aws_s3_bucket" "demo" {
      bucket = "linuxlab-lifecycle-${random_id.suffix.hex}"
      tags = {
        Owner       = "student"
        LastTouched = "2026-01-01"   # это поле часто меняется снаружи
      }
    }
    resource "random_id" "suffix" {
      byte_length = 4
    }
    bash
    cd /home/student/tf-lifecycle
    terraform init -input=false
    terraform apply -auto-approve -input=false
    подсказка

    Это базовый setup: следующие шаги будут только добавлять lifecycle опции.

    ✓ Бакет создан с двумя тегами. Дальше: защита от destroy.

  2. 02

    Защити бакет от удаления

    Добавь блок lifecycle в ресурс:

    hcl
    resource "aws_s3_bucket" "demo" {
      bucket = "linuxlab-lifecycle-${random_id.suffix.hex}"
      tags = {
        Owner       = "student"
        LastTouched = "2026-01-01"
      }
      lifecycle {
        prevent_destroy = true
      }
    }

    Применить:

    bash
    terraform apply -auto-approve

    Теперь попробуй удалить:

    bash
    terraform destroy -auto-approve

    Получишь:

    Error: Instance cannot be destroyed
    Resource aws_s3_bucket.demo has lifecycle.prevent_destroy set...

    Защита работает: чтобы реально снести, нужно сначала убрать prevent_destroy, сделать apply, и только тогда destroy. Это двухшаговая защита от случайностей.

    подсказка

    Если destroy прошёл без ошибки: значит, apply не успел записать lifecycle в state. Повтори apply и destroy.

    ✓ prevent_destroy блокирует destroy. В проде это спасает от опечаток.

  3. 03

    Игнорируй изменения LastTouched

    Представь: внешний скрипт обновляет тег LastTouched каждую ночь. Terraform будет видеть это как drift и каждый plan показывать изменение. Раздражает и опасно.

    Решение, ignore_changes. Добавь в lifecycle:

    hcl
    lifecycle {
      prevent_destroy = true
      ignore_changes  = [
        tags["LastTouched"],
      ]
    }

    Применить:

    bash
    terraform apply -auto-approve

    Теперь имитируем drift, поменяй тег через AWS CLI (точнее, его эмуляцию в LocalStack эмулирует aws-сlient внутри). Но в нашем sandbox мы можем сделать иначе: поменять значение в HCL.

    Открой main.tf, поменяй:

    hcl
    LastTouched = "2026-06-15"   # новая дата

    И запусти plan:

    bash
    terraform plan

    Вывод: No changes. Terraform увидел разницу в tags["LastTouched"], но ignore_changes сказал «не считай это изменением». State и реальность считаются совпавшими.

    подсказка

    Если plan показывает изменение: проверь синтаксис ignore_changes: список квадратных скобок, имена в [].

    ✓ ignore_changes работает: drift по конкретному атрибуту игнорируется.

    create_before_destroy для zero-downtime

    Третья частая опция, create_before_destroy = true. Она меняет порядок при пересоздании ресурса (когда атрибут требует replacement): по умолчанию Terraform сначала сносит старый, потом создаёт новый, между ними даунтайм. С create_before_destroy наоборот: сначала создать новый, переключить зависимости, потом снести старый. Это даёт zero-downtime, но требует уникальности имён (нельзя два ресурса с одинаковым identifier одновременно).

    • → lifecycle блок целиком
  4. 04

    Сними prevent_destroy и удали

    Чтобы оставить sandbox чистым (хотя он и так умрёт по TTL), убери lifecycle и снеси бакет:

    hcl
    resource "aws_s3_bucket" "demo" {
      bucket = "linuxlab-lifecycle-${random_id.suffix.hex}"
      tags = {
        Owner = "student"
      }
      # никакого lifecycle
    }
    bash
    terraform apply -auto-approve
    terraform destroy -auto-approve

    Бакет снесён. Это и есть правильный workflow:

    1. Понадобилось удалить защищённый ресурс.
    2. Шаг 1: убрать prevent_destroy через apply.
    3. Шаг 2: сделать destroy.

    Двухшаговая последовательность, не лишняя бюрократия, это защита от случайностей.

    подсказка

    Если apply ругается на удаление lifecycle: это значит prevent_destroy всё ещё в state. Сделай apply сначала, потом destroy.

    ✓ Всё снесено. Lifecycle ты теперь умеешь использовать осмысленно.

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

Что ты узнал

Ты увидел три типичных применения lifecycle: блокировка destroy через prevent_destroy, игнор тегов через ignore_changes, и понимание того, как create_before_destroy меняет порядок операций при пересоздании.

команды

  • terraform planlifecycle покажет ошибку если защита нарушена
  • terraform state show <addr>увидеть какие lifecycle активны на ресурсе

концепции

  • · prevent_destroy: защита от случайного удаления (двухшаговая)
  • · ignore_changes. Terraform не считает drift по этим атрибутам
  • · create_before_destroy: создать новый, потом снести старый

← предыдущий

GitHub Actions, полный pipeline через act

следующий →

moved блок: рефакторинг без пересоздания

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