lesson ── terraform-intermediate ── ~15 мин ── 5 шагов
Сообщество написало модули на все случаи: VPC, EKS, ALB, S3 с audit-конфигурацией. Прежде чем писать свой, посмотри Registry. Часто готовый модуль закрывает 90% потребности и сэкономит неделю.
Здесь подключишь terraform-aws-modules/s3-bucket/aws из Registry, это
публичный модуль, поддерживается активным сообществом. Покажешь как
читать version constraints, как искать input/output в документации,
как версию заморозить.
интерактивный sandbox
Поднимется пара контейнеров: terraform 1.9 и localstack 3.8 в одной сети. В браузере откроется терминал, можно сразу terraform init. Каждый шаг проверяется автоматически. TTL 45 минут, без регистрации.
stack ── terraform · localstack · 1 GB RAM · самоуничтожается через 45 мин простоя
Подключим terraform-aws-modules/s3-bucket/aws. Это самый популярный
community-модуль для S3.
Документация: https://registry.terraform.io/modules/terraform-aws-modules/s3-bucket/aws/latest
В реальной работе тебе нужно прочитать секции:
Это первое что ты делаешь перед использованием любого community-модуля. Не пишешь HCL → не дебажишь ошибки → читаешь.
Пока ничего не делаем, просто понимаем процесс.
✓ Готово к подключению.
Создай main.tf:
resource "random_id" "suffix" {byte_length = 4
}
module "logs_bucket" {source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 4.0"
bucket = "linuxlab-registry-logs-${random_id.suffix.hex}" versioning = {enabled = true
}
tags = {Owner = "student"
Project = "registry-lesson"
}
}
output "registry_bucket_arn" {value = module.logs_bucket.s3_bucket_arn
}
Ключевое:
source, три сегмента namespace/name/provider, без https://.version = "~> 4.0", pessimistic constraint, см.
tf-module-versioning. Берёт любую 4.x, но не 5.x.bucket, versioning, tags, input'ы модуля. Их имена и формат
, из его документации, не выдуманы.module.logs_bucket.s3_bucket_arn, output модуля. Опять же, имя
не выдумано, берётся из секции Outputs модуля.✓ Подключение описано. Теперь init.
cd /home/student/tf-registry
terraform init
Internet-доступ нужен только Terraform Registry, сам HCL модуля будет ходить на LocalStack endpoints, не на real AWS.
В выводе должно быть:
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/s3-bucket/aws ...
Проверь что скачалось:
cat .terraform/modules/modules.json | jq '.Modules[] | {Key, Source, Version}'Увидишь основной модуль и его подмодули (большие community-модули
внутри используют другие модули). Это нормально, что вызывал ты
один, а в .terraform/modules/ может оказаться 5 директорий.
Если init падает с network error: проверь internet: `curl -I https://registry.terraform.io`. В нашем sandbox это должно работать (links.internal: false).
✓ Модуль скачан. Теперь plan и apply.
terraform apply -auto-approve
Плагины модуля видят AWS-endpoints, настроенные в provider.tf (мы
их унаследовали от aws-localstack-provider.tf). Внутри модуля никакой
специальной настройки, просто aws_s3_bucket. Поэтому он работает
и на LocalStack, и на real AWS.
После apply посмотри state:
terraform state list | grep module
Адресы внутри модуля могут выглядеть так:
module.logs_bucket.aws_s3_bucket.this[0]
module.logs_bucket.aws_s3_bucket_versioning.this[0]
Заметь [0], community-модуль использует count = local.create ? 1 : 0
внутри (опциональное создание). Это типичный паттерн в больших модулях.
✓ Registry-модуль создал бакет внутри своей вложенности.
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 для полной матрицы.
terraform output registry_bucket_arn
Должен вывестись ARN бакета (arn:aws:s3:::linuxlab-registry-logs-...).
Это значение прошло через два контракта:
output "s3_bucket_arn" { value = ... }.output "registry_bucket_arn" { value = module.logs_bucket.s3_bucket_arn }.Без явного output на уровне root, наружу из root наглядно ничего не
видно. Output модуля доступен только через адрес module.X.<имя>,
но terraform output показывает только root-level outputs.
✓ Контракт замкнулся: модуль → root → CLI.
Готовый модуль, экономия времени, но не всегда удачный выбор:
90% input'ов тебе не нужны. terraform-aws-modules/vpc/aws
имеет 200+ переменных. Если ты используешь 5, твой HCL выглядит
обманчиво простым, но в depend-tree куча кода которого ты не
знаешь. Дебаг падает.
Поведение «магии». Хороший community-модуль документирует поведение, но не всегда, встречаются модули с неочевидными зависимостями (например, автоматически создают IAM-роль).
Версии и upgrade-боль. Major-апгрейд (4.x → 5.x) обычно ломает контракт. Если у тебя 50 root'ов используют модуль, апгрейд это спринт работы.
Свой модуль на 100 строк vs Registry на 5000 строк. Если твои нужды простые, свой модуль лучше. Полный контроль, ясный граф зависимостей.
Правило: community-модуль, когда экосистема за тобой. Большая AWS-инфра, ALB+EKS+RDS, берёшь community. Маленький проект, часто проще написать свой.
Registry-модуль = source формата <namespace>/<name>/<provider> плюс
обязательный version. Без version Terraform возьмёт max, в проде это
бомба. Документация модуля живёт на странице Registry, секции Inputs и
Outputs, это его контракт.
команды
terraform initкачает модуль и его подмодули в .terraform/modules/terraform init -upgradeперечитать version constraints, скачать новые в их рамкахterraform providersдерево provider'ов по модулям: видно какие подмодули подтянулиськонцепции