lesson ── terraform-beginner ── ~12 мин ── 5 шагов
Сейчас ты пройдёшь главный цикл Terraform за 10 минут: напишешь HCL для одного S3-бакета, проинициализируешь рабочую директорию, посмотришь план, применишь его, и проверишь что state знает про созданный ресурс.
Облако. LocalStack (см. localstack-provider). Никакого настоящего AWS, никаких счетов. Можно ломать, сносить, начинать заново.
интерактивный sandbox
Поднимется пара контейнеров: terraform 1.9 и localstack 3.8 в одной сети. В браузере откроется терминал, можно сразу terraform init. Каждый шаг проверяется автоматически. TTL 45 минут, без регистрации.
stack ── terraform · localstack · 1 GB RAM · самоуничтожается через 45 мин простоя
В рабочей директории ~/tf-hello уже лежит файл provider.tf,
настройки провайдера AWS, нацеленные на LocalStack (endpoints { ... }).
Сейчас твоя задача, создать рядом файл main.tf с описанием одного
S3-бакета.
Создай файл ~/tf-hello/main.tf со следующим содержимым:
resource "aws_s3_bucket" "demo" { bucket = "linuxlab-hello-${random_id.suffix.hex}" tags = {Owner = "student"
Project = "terraform-hello"
}
}
resource "random_id" "suffix" {byte_length = 4
}
Зачем random_id? S3-bucket-имена должны быть глобально уникальными.
Даже в LocalStack мы соблюдаем эту дисциплину, чтобы не вырабатывать
дурную привычку.
О формате блоков resource "..." "..." { ... }, см. tf-resource-block
и hcl-syntax.
Можешь использовать `cat > main.tf <<EOF ... EOF` или редактор `nano main.tf`.
✓ HCL написан. Теперь Terraform нужно инициализировать.
Команда init читает provider.tf и скачивает AWS-плагин из реестра
Terraform. После неё появятся:
.terraform/, с плагином внутри..terraform.lock.hcl, с зафиксированной версией плагина.Без init другие команды не запустятся.
Запусти:
cd /home/student/tf-hello
terraform init
Подробнее про init и lockfile, tf-init и tf-lockfile.
Не забудь `cd /home/student/tf-hello` перед `terraform init`.
✓ Провайдер AWS скачан, lockfile создан.
Lockfile, гарантия воспроизводимости. Он фиксирует точную версию
провайдера и его SHA-хеши. Если ты или коллега запустите init
снова, Terraform скачает ровно эту версию. Если хеш не сошёлся,
упадёт с ошибкой (защита от подмены пакета).
plan сравнивает HCL и state. Сейчас state пустой, значит plan покажет
«+ 2 to add»: один aws_s3_bucket и один random_id.
Запусти:
terraform plan
Обрати внимание на строки с + resource, это создаваемые ресурсы.
В конце, сводка вида Plan: 2 to add, 0 to change, 0 to destroy.
Plan ничего не меняет в облаке. Можешь запустить сколько угодно раз. См. tf-plan.
Если plan ругается «provider not initialized»: вернись и проверь что `init` прошёл.
✓ Plan показал план: 2 ресурса к созданию. Теперь применим.
apply запускает план в реальном облаке. Сейчас «облако», это
LocalStack: контейнер рядом, который притворяется AWS.
Запусти с -auto-approve (без интерактивного «yes», это учебная
задача):
terraform apply -auto-approve
После apply должны появиться строчки:
random_id.suffix: Creation complete after Xs
aws_s3_bucket.demo: Creation complete after Xs
Apply complete! Resources: 2 added
Если что-то упало, проверь, что LocalStack отвечает (init-скрипт
wait-for-localstack.sh должен был дождаться его при старте сессии).
См. tf-apply и localstack-provider.
Если получаешь TLS-ошибку: это значит провайдер пытается ходить в настоящий AWS. Проверь что `provider.tf` содержит блок endpoints.
✓ Бакет создан в LocalStack. State обновился. Открой его и посмотри.
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: после apply повторный plan должен показывать «No changes». Это инвариант. Если показывает изменения, значит, в state и в HCL расхождение, или drift.
Запусти ещё раз:
terraform plan -detailed-exitcode
Флаг -detailed-exitcode важен: exit 0 = нет изменений, exit 2 = есть.
Эта проверка пройдёт только если plan чистый.
Если plan показывает изменения: посмотри `terraform show -json | jq` и сравни с HCL.
✓ Plan чистый: state и HCL совпадают. Terraform-инвариант соблюдён.
Drift, это когда состояние в облаке отличается от того что Terraform записал в state. Бывает: кто-то руками удалил бакет через AWS console, auto-scaling сам подкрутил мощность. Terraform увидит drift при следующем plan/refresh. Стратегии работы с ним, в lifecycle.ignore_changes.
Ты увидел декларативный подход Terraform: описал желаемое состояние, и Terraform сам разобрался что создать. Узнал три обязательных команды (init, plan, apply) и понял что они делают.
команды
terraform initскачать провайдеры и создать lockfileterraform planпоказать diff между HCL и stateterraform apply -auto-approveприменить планterraform showраспечатать содержимое stateконцепции