🏗️ Advanced Patterns & Import
Dynamic blocks, moved block, import, lifecycle hooks, refactoring
🔄 Dynamic Blocks
Динамическое создание повторяющихся вложенных блоков. `dynamic "ingress"` и блок `content`. Комбинируется с `for_each`. Например: список правил security group. Очень полезно для сложных ресурсов (ALB listener rules, IAM policy statements).
📦 moved Block (Terraform 1.1+)
Решает проблему со state при переименовании ресурса или перемещении в модуль. Декларативная альтернатива `terraform state mv`. `moved { from = aws_instance.old to = aws_instance.new }`. Отображается в plan, без destroy+recreate. Необходим при реструктуризации модулей.
📥 import Block (Terraform 1.5+)
Передача существующего ресурса под управление Terraform — декларативно. `import { to = aws_s3_bucket.main id = "my-bucket-name" }`. `terraform plan -generate-config-out=generated.tf` — также генерирует .tf-файл. Старый способ: команда `terraform import` (по-прежнему работает).
🔧 Lifecycle Hooks
Внутри блока `lifecycle`: create_before_destroy — сначала создаётся новый ресурс, затем удаляется старый (zero downtime). prevent_destroy — защита от удаления. ignore_changes — Terraform игнорирует изменения указанных атрибутов (например, ami). replace_triggered_by — пересоздание при изменении другого ресурса.
💡 Ключевые моменты
- dynamic block: повторяющиеся вложенные блоки с for_each
- moved block: rename/refactor без destroy
- import block (1.5+): декларативный import
- create_before_destroy: замена без простоя (zero downtime)
- ignore_changes: принятие дрейфа конфигурации
- prevent_destroy: защита production-ресурсов
📋 Пример кода
# Dynamic blocks: security group rules
variable "ingress_rules" {
default = [
{ port = 80, cidr = "0.0.0.0/0" },
{ port = 443, cidr = "0.0.0.0/0" },
{ port = 22, cidr = "10.0.0.0/8" }
]
}
resource "aws_security_group" "web" {
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = "tcp"
cidr_blocks = [ingress.value.cidr]
}
}
}
# moved block: aws_instance.web -> module.compute.aws_instance.web
moved {
from = aws_instance.web
to = module.compute.aws_instance.web
}
# import block (Terraform 1.5+)
import {
to = aws_s3_bucket.existing
id = "my-existing-bucket"
}
# lifecycle
resource "aws_instance" "web" {
ami = data.aws_ami.latest.id
instance_type = "t3.micro"
lifecycle {
create_before_destroy = true
prevent_destroy = true
ignore_changes = [ami]
}
}
🎯 Советы для экзамена
- dynamic block — только для вложенных блоков ресурса (не для top-level ресурсов)
- moved block vs terraform state mv: moved = декларативно (код можно ревьюить), state mv = императивно
- import block (1.5+) + generate-config-out → .tf-файл создаётся автоматически
- ignore_changes = ["ami"] — Terraform игнорирует изменения ami у instance (паттерн ASG launch template)
- replace_triggered_by — триггер перебилда в цепочке зависимостей
⚠️ Частые ошибки
- Путаница между dynamic block и мета-аргументом for_each — dynamic=итератор вложенных блоков, for_each=итератор ресурсов
- Ошибочное предположение, что moved block выполняет destroy+recreate — moved лишь изменяет маппинг в state
- Ошибочное предположение, что import block всегда создаёт .tf-файл — только при использовании -generate-config-out
🧠 Для запоминания: "DMIL" = Dynamic (blocks), Moved (refactor), Import (existing), Lifecycle (hooks) — 4 продвинутых паттерна Terraform
Проверьте себя по теме «Advanced Patterns & Import»
Бесплатные интерактивные тесты, пробный экзамен и полные уроки — на платформе CertMaster.
Начать бесплатно →