Вся прошлая часть курса была про то, как писать terraform так, чтобы он работал. Этот урок - про то, как сделать так, чтобы инфраструктура как код жила в команде и не превращалась в минное поле. Стиль, ревью, автоматизация прогона и policy as code - это не бюрократия, а ремни безопасности. Поехали.
Стиль и структура: чтобы код читался, а не расшифровывался
Начнём с дешёвого и обязательного. terraform fmt (или tofu fmt в OpenTofu) переформатирует все .tf файлы по канону: отступы, выравнивание знаков "=", переносы. Спорить о стиле скобок - пустая трата нервов, инструмент решает это за тебя. В CI добавляй проверочный режим, который не правит, а падает, если форматирование съехало:
Код: Выделить всё
terraform fmt -check -recursive
terraform validate
- ресурсы и переменные - в snake_case, без транслита и сокращений типа srv1;
- имя ресурса не дублирует тип. Пиши resource "yandex_compute_instance" "web", а не "web_instance" - тип уже в первом аргументе;
- main.tf - основные ресурсы, variables.tf - входы, outputs.tf - выходы, versions.tf - блок required_providers и backend, locals.tf - вычисляемые значения;
- один логический компонент - один модуль, а не сто ресурсов в плоском main.tf на тысячу строк.
[/code был тут лишним, продолжаем списком]
Код: Выделить всё
terraform-docs markdown table . > README.md
Код: Выделить всё
variable "zone" {
description = "Зона доступности YC"
type = string
default = "ru-central1-a"
}
resource "yandex_compute_instance" "web" {
name = "web-app"
zone = var.zone
resources {
cores = 2
memory = 2
}
boot_disk {
initialize_params {
image_id = var.image_id
}
}
network_interface {
subnet_id = var.subnet_id
nat = true
}
}

Ревью инфра-PR: читаем не код, а plan
Главная мысль урока: на ревью инфраструктуры ты смотришь не столько на .tf, сколько на вывод terraform plan apply-цикла - то есть на сам plan. Код может выглядеть невинно, а план - показывать destroy боевого ресурса. План это правда о том, что реально произойдёт.
В выводе plan есть три значка, и ты обязан читать их как сапёр:
- "+" create - создаётся ресурс. Обычно безопасно, но проверь, не плодим ли дубль;
- "~" update in-place - меняется на месте, downtime маловероятен;
- "-" destroy и особенно "-/+" replace - ресурс будет удалён и пересоздан. Для базы данных, диска или статического IP это потенциальная катастрофа. Тут останавливаемся и думаем, почему terraform хочет это сделать.
Автоматизация: Atlantis, TACOS и policy as code
Гонять plan и apply с локальной машины - путь к беде. У всех разные версии CLI, у кого-то лежат прод-ключи в открытом виде, а кто-то забыл, что у него незакоммиченные правки. Решение - вынести весь цикл в pull request.
Atlantis - это open-source сервис, который ты хостишь сам. Он слушает вебхуки от GitHub/GitLab и работает прямо в комментариях PR. Открыл PR - Atlantis сам пишет результат terraform plan в комментарий. Посмотрел, ревьюер апрувнул - пишешь atlantis apply, и инфраструктура применяется. Никто не запускает apply со своего ноута, всё проходит через PR и аудируется. Atlantis активно развивается - на 2026 год это версия из ветки 0.4x. Для России и self-hosted это основной вариант: ставишь в свой контур, ключи Yandex Cloud живут на сервере Atlantis, наружу ничего не утекает. Минимальный atlantis.yaml в корне репозитория:
Код: Выделить всё
version: 3
projects:
- name: prod
dir: environments/prod
workflow: default
apply_requirements:
- approved
- mergeable
TACOS (TerraForm/OpenTofu Automation and Collaboration Software) - это управляемые платформы того же назначения, но с UI, RBAC, очередями и хранением state из коробки: Terraform Cloud (HCP Terraform), Spacelift, env0, Scalr. Удобно, но это SaaS, и для многих российских команд это стоп-фактор по доступности, оплате и тому, где физически лежит state. Поэтому в РФ типовой стек - self-hosted Atlantis либо просто пайплайн в GitLab CI, который сам по шагам гоняет fmt, validate, plan на MR и apply на main. Логика та же, просто без отдельного сервиса.
Policy as code - последний рубеж. Договорённости "мы не открываем порт 22 наружу" нельзя держать только в головах. Их кодируют политиками на OPA (язык Rego) и проверяют утилитой Conftest на машиночитаемом плане. Schema простая: превращаем план в JSON и прогоняем через политики, и если правило нарушено - merge блокируется автоматически, без участия живого ревьюера:
Код: Выделить всё
terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > tfplan.json
conftest test tfplan.json
Дрейф-детект и типичные грабли
Дрейф (drift) - это расхождение между тем, что записано в state, и тем, что реально в облаке. Кто-то поправил security group через веб-консоль Yandex Cloud - и terraform об этом не знает. Ловится регулярным прогоном plan по расписанию (например, ночной job в CI): если plan не пустой, хотя кода никто не менял, - кто-то лазил руками. Atlantis и TACOS-платформы умеют такой drift detection из коробки и присылают алерт.
Грабли, на которых спотыкаются все:
- apply с локальной машины в обход PR. Один такой apply - и state в репозитории разъехался с тем, что реально применили коллеги через Atlantis;
- ревью только по диффу кода без чтения plan. Самое опасное - destroy/replace - в коде выглядит безобидно;
- auto-apply на merge без апрува. Заманчиво, но один кривой PR улетит в прод без единого человеческого взгляда;
- policy-проверки не как блокирующие, а "для информации". Если они не блокируют merge, их просто перестают читать;
- секреты в открытом state. State хранит значения в открытом виде. В OpenTofu есть нативное шифрование state (начиная с 1.7, ключи через PBKDF2, а также AWS/GCP KMS) - в чувствительных проектах это must have.
Возьми любой свой модуль под Yandex Cloud и руками прогони полный конвейер:
- terraform fmt -check -recursive и terraform validate - убедись, что код чистый;
- сгенерируй README через terraform-docs и сравни таблицу входов с реальными переменными;
- сделай plan, сохрани его в JSON через terraform show -json и глазами найди значки "+", "~", "-/+";
- напиши на Rego одну простую политику (например, "у любого yandex_compute_instance memory не больше 8") и прогони Conftest - сначала на проходящем плане, потом нарушь правило и убедись, что проверка падает.
- Почему на ревью инфра-PR главное - читать plan, а не только дифф .tf файлов?
- Чем "-/+" (replace) в плане опаснее обычного "~" (update in-place) и для каких ресурсов это критично?
- Почему для российских и self-hosted команд Atlantis или GitLab CI обычно предпочтительнее SaaS-TACOS вроде Spacelift или env0?
- Что такое дрейф инфраструктуры и как его поймать автоматически?
terraform fmt и terraform-docs - бесплатная гигиена, ставь в CI и забудь о спорах про стиль. На ревью читай plan и охоться за destroy и replace - именно там прячется боль. Apply гоняй только через PR: self-hosted Atlantis для РФ, GitLab CI как простая альтернатива, TACOS - если доступен SaaS. Policy as code на OPA/Conftest делай блокирующим на merge, иначе он бесполезен. И раз в сутки проверяй дрейф - руками в облаке всегда кто-нибудь да полазит. Так инфраструктура как код перестаёт быть лотереей и становится инженерной дисциплиной.