Словарь терминов
1. Базовые свойства и модель выполнения
Terraform — декларативный инструмент: в коде описывается желаемое конечное состояние инфраструктуры, а не последовательность шагов для его достижения. Порядок операций Terraform строит сам, из графа зависимостей между ресурсами (см. раздел 5).
Idempotency (Идемпотентность) — свойство: повторный terraform apply с тем же кодом и тем же state не приводит к новым изменениям. Если реальная инфраструктура уже соответствует описанному состоянию — plan пустой.
Determinism (Детерминированность) — свойство: одинаковый код и одинаковое окружение дают одинаковый план и результат. Нет случайных выборов и скрытых внешних зависимостей, влияющих на исход apply.
Важно не путать эти два свойства: идемпотентность — про повторный запуск с уже применённым состоянием, детерминированность — про воспроизводимость плана в принципе, независимо от того, применялся он раньше или нет.
Immutable infrastructure (Иммутабельная инфраструктура) — подход, при котором ресурсы не изменяются на месте, а заменяются целиком. В Terraform это проявляется как forces replacement: изменение определённых атрибутов не обновляет ресурс, а вызывает destroy + create (в плане отображается как -/+).
Drift — расхождение между реальным состоянием инфраструктуры и Terraform state. Возникает, когда ресурс изменён вручную через консоль или CLI облака, в обход Terraform.
Blast radius — масштаб возможного ущерба при ошибке apply. Аргумент в пользу изоляции стеков и multi-account структуры: сломанный apply в dev-аккаунте физически не может задеть prod.
DRY (Don't Repeat Yourself) — принцип неповторения кода. В контексте Terraform — проблема, которую решает Terragrunt (раздел 10): backend и provider описываются один раз вместо копирования в каждый стек.
2. State
State / terraform.tfstate — файл состояния, mapping между ресурсами в коде и реальными ресурсами в облаке. Хранит resource ID, ARN, атрибуты, зависимости и outputs. Без state Terraform не может определить, что уже существует и что нужно менять.
Remote backend — хранение state в удалённом хранилище (S3, GCS, Azure Blob) вместо локального файла. Обязательно для production: даёт shared access, versioning и locking.
Locking — механизм, предотвращающий одновременный apply двумя инженерами или двумя pipeline'ами. Для S3-backend реализуется через DynamoDB (запись с LockID); с Terraform 1.10+ доступна нативная блокировка через use_lockfile = true прямо в S3, без отдельной таблицы DynamoDB.
force-unlock — принудительное снятие lock по его ID. Используется, когда предыдущий apply упал (CI crashed, network issue) и lock завис. Операция опасная: нужно быть уверенным, что другой apply действительно не выполняется — иначе можно получить два параллельных apply над одним state.
Sensitive — атрибут переменной или output (sensitive = true). Скрывает значение в CLI-выводе. Не защищает данные в самом state-файле — значение там хранится в plaintext, поэтому шифрование backend'а обязательно.
Refresh — чтение реального состояния инфраструктуры из API провайдера и сверка с сохранённым state. Происходит автоматически перед terraform plan. terraform plan -refresh-only — обновить state без изменения инфраструктуры.
terraform_remote_state — data source для чтения outputs другого Terraform-стека. Используется для передачи данных между независимыми стеками (например, VPC → EKS).
3. Providers
Provider — бинарный плагин, через который Terraform взаимодействует с конкретным облаком или сервисом (AWS, GCP, Kubernetes). Запускается как отдельный процесс и общается с Terraform-ядром по gRPC; провайдер стартует один раз на весь apply, а не на каждый ресурс.
required_providers — блок конфигурации, где фиксируется источник и версия каждого провайдера. Обязательная практика для production: предотвращает неожиданное подтягивание breaking changes при следующем terraform init.
.terraform.lock.hcl — lock-файл, создаётся при terraform init. Фиксирует точные версии провайдеров и их checksums. Должен коммититься в git — иначе разные машины могут получить разные версии провайдера при одном и том же коде.
alias — параметр provider-блока, позволяющий использовать несколько конфигураций одного провайдера в одном коде: например, два региона или два AWS-аккаунта одновременно.
assume_role — блок конфигурации AWS provider. CI/CD runner делает AssumeRole в целевую IAM-роль вместо использования долгоживущих статических ключей.
Eventual consistency — свойство облачных API: только что созданный ресурс может быть недоступен для немедленного чтения. Провайдеры компенсируют это retry с backoff; иногда всё равно требуется явный depends_on, если зависимость не выводится автоматически из атрибутов.
4. Аутентификация и безопасность
| Механизм | Что делает | Где используется |
|---|---|---|
| STS (Security Token Service) | Выдаёт временные AWS-credentials | Базовый сервис для AssumeRole и OIDC |
| AssumeRole | Получение временных credentials через принятие IAM-роли | Межаккаунтный доступ |
| AssumeRoleWithWebIdentity | Обмен OIDC-токена на временные credentials | CI/CD (GitHub Actions, GitLab CI) |
| OIDC (OpenID Connect) | Протокол аутентификации поверх OAuth 2.0 | Платформа CI/CD выдаёт JWT, AWS обменивает его на credentials — без хранения статических ключей в секретах |
| IRSA (IAM Roles for Service Accounts) | Привязка IAM-роли к Kubernetes Service Account через OIDC | Pod получает AWS credentials без ключей внутри кластера |
| SCPs (Service Control Policies) | Guardrails на уровне AWS Organizations | Ограничивают всех IAM users и roles в аккаунте, включая root; управляются Terraform'ом из management-аккаунта |
Общий принцип для всех строк таблицы: ни один механизм не заменяет статические ключи копированием их в другое место — все они построены на выдаче временных credentials через STS.
5. Граф зависимостей и порядок выполнения
DAG (Directed Acyclic Graph) — ориентированный ациклический граф, который Terraform строит из ресурсов и связей между ними. Определяет порядок создания: ресурс создаётся только после того, как созданы все его зависимости. Циклов в графе быть не может — если код описывает циклическую зависимость, terraform plan завершится ошибкой ещё до применения.
Implicit dependency (Неявная зависимость) — зависимость, которую Terraform выводит автоматически из ссылок между ресурсами: subnet_ids = aws_subnet.private[*].id — и граф уже знает, что subnet должен существовать раньше.
Explicit dependency / depends_on — зависимость, указанная вручную. Нужна, когда зависимость реально существует, но не отражена ни в одном атрибуте ресурса. Блокирует параллелизм для связанных ресурсов, поэтому злоупотреблять depends_on не стоит — сначала нужно проверить, не выводится ли зависимость implicit-путём.
Parallelism — количество ресурсов, создаваемых одновременно. По умолчанию — 10. Меняется флагом -parallelism=N. Параллельно выполняются только ресурсы без зависимостей друг от друга — parallelism не отменяет порядок, заданный графом.
-target — флаг terraform apply -target=<resource> для применения изменений только к одному ресурсу. Нарушает целостность обычного цикла plan/apply (Terraform не учитывает остальной граф) — используется только в экстренных ситуациях, не как рабочий паттерн.
6. Lifecycle-блок
| Опция | Что делает | Типичный кейс |
|---|---|---|
create_before_destroy |
Создать новый ресурс до удаления старого, вместо стандартного destroy → create | Zero-downtime пересоздание Load Balancer, ASG, ACM-сертификата |
prevent_destroy |
Запрещает удаление ресурса через Terraform; попытка destroy — ошибка plan | RDS, S3 с данными, VPC |
ignore_changes |
Terraform игнорирует изменения указанных атрибутов | desired_capacity в ASG, которым управляет Auto Scaling снаружи Terraform |
precondition |
Валидация внутри ресурса, проверяется до его создания | Понятная ошибка на этапе plan вместо непонятной ошибки API на apply |
forces replacement — не отдельная lifecycle-опция, а маркер в документации провайдера: изменение конкретного атрибута ресурса вызывает destroy + create целиком (см. раздел 1, Immutable infrastructure).
7. Модули
Root module — директория, из которой запускается terraform plan/apply. Точка входа в конфигурацию.
Child module — любой модуль, вызванный через блок module {} из root или из другого модуля.
versions.tf — файл с блоками required_version и required_providers. Фиксирует минимальную версию Terraform CLI и версии провайдеров для конкретного модуля.
~> (pessimistic constraint) — оператор версионирования: ~> 5.0 разрешает 5.x, но не 6.x; ~> 5.0.0 разрешает только 5.0.x. Позволяет получать патчи, блокируя минорные и мажорные breaking changes.
8. Рефакторинг state
| Способ | Декларативный / императивный | Что делает |
|---|---|---|
moved block |
Декларативный (Terraform 1.1+) | Переименование/перемещение ресурса внутри state без пересоздания; описывается в коде, проходит code review, виден в git-истории |
terraform state mv |
Императивный | То же самое действие, но CLI-командой — без code review и истории изменений |
terraform state rm |
Императивный | Удаляет запись из state, не трогая реальный ресурс в облаке; Terraform перестаёт им управлять |
import block |
Декларативный (Terraform 1.5+) | Импорт существующего ресурса в state, применяется обычным terraform apply |
terraform import |
Императивный | CLI-команда привязки существующего ресурса к адресу в state; код ресурса нужно писать отдельно, вручную |
Общая закономерность: у каждой императивной команды (state mv, terraform import) есть декларативный аналог (moved, import block), появившийся позже. Декларативный вариант предпочтителен там, где нужна ревьюируемость и история в git; императивный остаётся инструментом для разовых и экстренных операций.
9. CI/CD и статический анализ
Plan artifact — сохранённый результат terraform plan -out=tfplan. Гарантирует, что terraform apply tfplan применит именно тот план, который прошёл review — а не пересчитанный заново (и потенциально другой) план.
Atlantis — open-source инструмент автоматизации Terraform через Pull Request. Слушает webhooks GitHub/GitLab, запускает plan/apply, комментирует результат прямо в PR.
| Инструмент | Что проверяет |
|---|---|
| tflint | Проблемы, которые terraform validate не видит: неверные значения instance_type, deprecated-аргументы, нарушения naming conventions |
| checkov | Безопасность и compliance: встроенные правила CIS Benchmark, SOC2, PCI-DSS; поддерживает кастомные правила |
| tfsec / trivy | Security misconfiguration: S3 без encryption, RDS без deletion_protection, открытый 0.0.0.0/0 |
| OPA (Open Policy Agent) | Политики как код на языке Rego; для Terraform применяется через conftest к JSON-представлению плана |
| Sentinel | Встроенный policy engine именно Terraform Cloud / HCP Terraform (не community CLI) — plan не проходит, если политика не выполнена |
Terratest — Go-библиотека для интеграционного тестирования модулей: создаёт реальную инфраструктуру, тестирует, уничтожает. Дорогой процесс по времени и деньгам — обычно не запускается на каждый PR.
TF_LOG — переменная окружения для уровня логирования Terraform: ERROR, WARN, INFO, DEBUG, TRACE. DEBUG показывает API-запросы провайдера, TRACE — полные HTTP-запросы к облачному API.
10. Terragrunt
Terragrunt — тонкий wrapper над Terraform от компании Gruntwork, устраняющий дублирование backend- и provider-конфигурации при большом числе стеков (см. DRY, раздел 1).
find_in_parent_folders() — встроенная функция: ищет terragrunt.hcl вверх по дереву директорий и подключает его через include.
path_relative_to_include() — встроенная функция: возвращает путь текущей директории относительно root terragrunt.hcl. Типично используется для автогенерации уникального S3-ключа под каждый стек.
run-all — команда, которая находит все стеки в поддиректориях, строит граф зависимостей между ними (через dependency block) и применяет их в правильном порядке. Пример: terragrunt run-all apply.
dependency block — объявляет зависимость одного стека от другого и позволяет читать его outputs; именно эти блоки run-all использует для построения порядка применения.
11. AWS и multi-account
AWS Organizations — сервис централизованного управления несколькими AWS-аккаунтами. Management account управляет billing, SCP (раздел 4) и структурой аккаунтов.
Transit Gateway — сервис для подключения VPC из разных аккаунтов между собой; в Terraform управляется через два provider alias (раздел 3) — по одному на каждый аккаунт.
RAM (Resource Access Manager) — сервис для шаринга ресурсов между аккаунтами; типичный кейс — передача Transit Gateway из network-аккаунта в workload-аккаунты.
12. Kubernetes-интеграция
Helm provider — Terraform-провайдер для установки Helm-чартов; используется для bootstrap инфраструктурных компонентов кластера (ingress-nginx, cert-manager, cluster-autoscaler).
GitOps — практика управления инфраструктурой и приложениями через git как единственный source of truth.
ArgoCD — Kubernetes-native инструмент GitOps. Типичное разделение ответственности: Terraform один раз bootstrap-ит ArgoCD через Helm provider, после чего дальнейшее управление application workloads переходит к ArgoCD, а не к Terraform.
13. Повторим основные вопросы
"Terraform выполняет ресурсы в том порядке, в котором они написаны в файле?"
Нет. Порядок задаёт DAG (раздел 5), построенный из implicit- и explicit-зависимостей. Порядок в файле на это не влияет.
"Идемпотентность и детерминированность — это одно и то же?"
Нет. Идемпотентность — про повторный apply без изменений в уже применённом состоянии. Детерминированность — про воспроизводимость плана вообще, при любом первом запуске.
"Если удалить lock через force-unlock, это безопасно?"
Не всегда. Безопасно только если точно известно, что другой apply/pipeline не выполняется прямо сейчас — иначе возможен параллельный apply над одним state.
"`moved` block и `terraform state mv` делают разные вещи?"
Нет, одно и то же действие — перемещение ресурса в state. Разница в форме: moved декларативный и проходит review, state mv — императивная команда без истории в git.
"Sentinel можно использовать с обычным Terraform CLI (open-source)?"
Нет. Sentinel — policy engine именно Terraform Cloud / HCP Terraform. Для open-source CLI аналогичную роль играет OPA + conftest.
"`-target` — это нормальный рабочий инструмент?"
Нет. Это аварийный флаг: он обходит часть графа зависимостей и может привести к рассинхронизации state. Использовать только в экстренных случаях.
"Versioning в контексте Terraform относится к S3-объектам или к самому Terraform?"
Отдельно нужно различать: versioning S3-bucket'а (защита state-файла от перезаписи) и required_version/~> (версионирование самого Terraform CLI и провайдеров). Это два независимых механизма с похожими именами.
| Вопрос | Ответ |
|---|---|
| Локальная блокировка state по умолчанию (S3 backend) | DynamoDB, либо use_lockfile с Terraform 1.10+ |
| Parallelism по умолчанию | 10 |
С какой версии появился moved block |
Terraform 1.1 |
С какой версии появился import block |
Terraform 1.5 |
| Кто выдаёт временные credentials в AssumeRole/OIDC | AWS STS |
Файл, который нужно коммитить в git после terraform init |
.terraform.lock.hcl |
Чем depends_on отличается от implicit dependency |
Указывается вручную, когда связь не видна из атрибутов ресурса |
| Policy engine для Terraform Cloud / HCP | Sentinel |
| Policy engine для open-source CLI | OPA + conftest |
| Компания-автор Terragrunt | Gruntwork |
Что физически создаёт run-all перед применением |
Граф зависимостей между стеками (dependency block) |
Комментарии