Перейти к основному содержимому

Справочник по Terraform


CLI, конфигурация и типовые сценарии Terraform (DevOps, CI/CD, инфраструктура). Учебный курс: раздел.

Terraform — инструмент для декларативного управления инфраструктурой как кодом (Infrastructure as Code, IaC). Он позволяет описывать целевую инфраструктуру в текстовых файлах, применять изменения безопасно и воспроизводимо, а также отслеживать состояние ресурсов через файл состояния (state file).


Справочные таблицы​

Содержание справочника​


Общие сведения​

Terraform — инструмент для декларативного управления инфраструктурой как кодом (Infrastructure as Code, IaC). Он позволяет описывать целевую инфраструктуру в текстовых файлах, применять изменения безопасно и воспроизводимо, а также отслеживать состояние ресурсов через файл состояния (state file).

Terraform использует язык конфигурации HCL (HashiCorp Configuration Language), который поддерживает читаемый человеком синтаксис и мощные конструкции программирования.


Структура конфигурационного файла Terraform​

Файлы Terraform имеют расширение .tf. Основной файл обычно называется main.tf, но допустимо разделение логики по нескольким файлам:

  • main.tf — основная логика развертывания
  • variables.tf — объявление входных переменных
  • outputs.tf — определение выходных значений
  • versions.tf — указание версий провайдеров и самого Terraform
  • locals.tf — локальные значения
  • backend.tf — конфигурация бэкенда состояния

Все файлы в одной директории рассматриваются как единый модуль.


Блоки конфигурации​

terraform​

Блок terraform задает настройки самого Terraform и его взаимодействия с внешними системами.


Пример​

Код ITЗагрузка примера кода…


Поддерживаемые атрибуты​
  • required_version — минимальная или точная версия Terraform, необходимая для выполнения конфигурации.
  • backend — определяет место хранения файла состояния (local, s3, azurerm, gcs и другие).
  • required_providers — явное указание провайдеров с их источниками и версиями.
  • Эксперименты — включение экспериментальных функций (например, module_variable_optional_attrs).

provider​

Блок provider настраивает конкретный облачный или API-провайдер.


Пример​
provider "aws" {
region = "us-east-1"
profile = "default"
}

Общие параметры (зависят от провайдера)​
  • region, zone, project, subscription_id — географические или проектные идентификаторы.
  • credentials, access_key, secret_key — данные аутентификации.
  • alias — позволяет использовать несколько экземпляров одного провайдера.

Провайдеры загружаются автоматически при первом terraform init (см. "Быстрый старт").


resource​

Блок resource описывает управляемый объект инфраструктуры — виртуальную машину, базу данных, сеть и так далее.


Синтаксис​
resource "тип_ресурса" "локальное_имя" {
атрибут1 = значение1
атрибут2 = значение2
}

Пример​
resource "aws_instance" "web" {
ami = "ami-0c02fb55956c7d316"
instance_type = "t3.micro"
tags = {
Name = "WebServer"
}
}

Особенности​
  • Тип ресурса — комбинация имени провайдера и типа (например, aws_instance, google_compute_instance).
  • Локальное имя — используется внутри модуля для ссылок.
  • Атрибуты зависят от типа ресурса и документируются в спецификации провайдера.
  • Ресурсы могут содержать вложенные блоки (например, ebs_block_device внутри aws_instance).

Данные​

Блок Данные извлекает информацию о существующих объектах инфраструктуры без их изменения.


Пример​
Данные "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
}

Результат доступен как data.aws_ami.ubuntu.id.


variable​

Блок variable объявляет входной параметр модуля.


Пример​
variable "region" {
description = "AWS регион для развертывания"
type = string
default = "us-east-1"
}

Поддерживаемые атрибуты​
  • description — пояснение назначения переменной.
  • type — тип данных — string, number, bool, list(...), map(...), object({...}), tuple([...]).
  • default — значение по умолчанию.
  • validation — пользовательские правила проверки (начиная с Terraform 0.13).

Пример валидации​
variable "instance_type" {
type = string
validation {
condition = contains(["t3.micro", "t3.small", "t3.medium"], var.instance_type)
error_message = "Допустимые типы: t3.micro, t3.small, t3.medium."
}
}

output​

Блок output определяет значения, которые будут показаны после применения конфигурации.


Пример​
output "public_ip" {
value = aws_instance.web.public_ip
description = "Публичный IP-адрес веб-сервера"
sensitive = false
}

Атрибуты​
  • value — выражение или ссылка на ресурс/переменную.
  • description — пояснение.
  • sensitive — скрывает значение в выводе при true.

locals​

Блок locals определяет локальные значения, вычисляемые один раз и переиспользуемые в конфигурации.


Пример​
locals {
common_tags = {
Environment = "production"
Owner = "team-infra"
}
instance_name = "web-${var.environment}"
}

Используется как local.common_tags или local.instance_name.


module​

Блок module вызывает другой модуль Terraform.


Пример​
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
}

Атрибуты​
  • source — путь к модулю: локальный (./path), Git (git::https://...), реестр Terraform (terraform-aws-modules/vpc/aws).
  • Параметры передаются как аргументы с именами, соответствующими variable в модуле.

Выражения и функции​

Типы выражений​

  • Литералы — "строка", 42, true, [1,2,3], {key = "value"}
  • Ссылки: var.name, local.value, aws_instance.web.id, module.vpc.vpc_id
  • Арифметика — +, -, *, /, %
  • Логика — &&, ||, !, ==, !=, <, <=, >, >=
  • Условные операторы: condition ? true_val : false_val
  • Циклы: for-выражения

Встроенные функции​

Terraform предоставляет сотни встроенных функций. Ниже — наиболее часто используемые категории.


Строковые функции​
  • upper("hello") → "HELLO"
  • lower("HELLO") → "hello"
  • replace("foo-bar", "-", "_") → "foo_bar"
  • format("IP: %s", var.ip) → "IP: 192.168.1.1"
  • join(",", ["a", "b", "c"]) → "a,b,c"
  • split(".", "192.168.1.1") → ["192", "168", "1", "1"]
  • substr("terraform", 0, 5) → "terra"

Числовые функции​
  • abs(-5) → 5
  • ceil(3.2) → 4
  • floor(3.9) → 3
  • log(100, 10) → 2
  • pow(2, 3) → 8

Коллекции и структуры​
  • length([1,2,3]) → 3
  • keys({a = 1, b = 2}) → ["a", "b"]
  • values({a = 1, b = 2}) → [1, 2]
  • → {a = 1, b = 2}
merge({a = 1}, {b = 2})
  • lookup(map, key, default) — получение значения из map с fallback

Преобразования​
  • jsonencode({...}) — сериализация в JSON
  • yamlencode({...}) — сериализация в YAML (начиная с Terraform 1.2)
  • tomlencode({...}) — сериализация в TOML (начиная с Terraform 1.3)
  • base64encode("text") → "dGV4dA=="

Файловые операции​
  • file("path.txt") — читает содержимое файла как строку
  • templatefile("template.tftpl", {vars}) — рендерит шаблон
  • fileexists("config.yaml") → true/false

Дата и время​
  • timestamp() → "2026-02-24T12:34:56Z"
  • timeadd(timestamp(), "24h") — добавляет интервал
  • formatdate("YYYY-MM-DD", timestamp()) → "2026-02-24"

Криптография и хеширование​
  • sha256("input") → хеш в hex
  • bcrypt("password", 10) — хеширование пароля
  • uuid() — генерация UUID v4
  • random_password (через ресурс) — безопасная генерация паролей

Управляющие конструкции​

Условные выражения​

count = var.create_instance ? 1 : 0

Циклы с for_each​

resource "aws_iam_user" "users" {
for_each = toset(var.user_names)
name = each.value
}

Доступ к текущему элементу: each.key, each.value.


Циклы с count​

resource "aws_instance" "server" {
count = var.instance_count
ami = var.ami
tags = {
Name = "server-${count.index}"
}
}

Индексы начинаются с 0.


Динамические блоки​

Для повторяющихся вложенных блоков:

dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}

Типы данных в Terraform​

Terraform поддерживает богатую систему типов, позволяющую точно описывать структуру входных данных и результатов.


Примитивные типы​

  • string — текстовая строка: "example", var.name
  • number — целое или дробное число: 42, 3.14, -10
  • bool — логическое значение: true, false

Коллекционные типы​

  • list(type) — упорядоченный список элементов одного типа
    Пример — ["a", "b", "c"], [1, 2, 3]
  • set(type) — неупорядоченная коллекция уникальных элементов
    Пример: toset(["x", "y"])
  • map(type) — ассоциативный массив (ключ → значение)
    Пример: {name = "web", port = 80}

Структурные типы​

  • object({ ... }) — именованная структура с фиксированными полями
    Пример:
variable "server" {
type = object({
name = string
cpu_cores = number
public_ip = bool
})
}
  • tuple([type, ...]) — упорядоченная последовательность значений разных типов
    Пример — ["web", 2, true]

Специальные типы​

  • any — принимает любой тип (используется редко, только для совместимости)
  • dynamic — ключевое слово для динамических блоков

Преобразования типов​

Terraform автоматически приводит типы в большинстве случаев, но явное преобразование повышает надёжность:

  • tostring(42) → "42"
  • tonumber("100") → 100
  • tobool("true") → true
  • tolist(map) → список значений
  • tomap(list_of_pairs) → карта из пар ключ-значение

Модули​

Модуль — это переиспользуемый пакет конфигурации Terraform. Любой набор .tf-файлов в директории является модулем.


Структура модуля​

/modules/
└── vpc/
├── main.tf
├── variables.tf
├── outputs.tf
└── README.md

Входные переменные (variables.tf)​

Объявляются через блок variable. Все параметры вызова модуля должны соответствовать этим объявлениям.


Выходные значения (outputs.tf)​

Определяют, какие данные модуль предоставляет внешнему миру:

output "vpc_id" {
value = aws_vpc.main.id
}

Вызов модуля​

module "prod_vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
enable_nat = true
}

Результат доступен как module.prod_vpc.vpc_id.


Источники модулей​

  • Локальный путь: "./modules/web"
  • Git-репозиторий: "git::https://github.com/user/repo.git//path?ref=v1.2.0"
  • Terraform Registry: "terraform-aws-modules/vpc/aws"
  • HTTP-архив: "https://example.com/module.zip"

Версионирование​

Для модулей из реестра или Git можно указать версию:

module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
}

Операторы сравнения:

  • ~> 5.0 — любая версия >= 5.0, но < 6.0
  • >= 4.0, < 5.0 — диапазон
  • = 3.2.1 — точное совпадение

Файл состояния (State)​

Файл состояния (terraform.tfstate) хранит соответствие между описанием в коде и реальными ресурсами в облаке.


Содержимое state-файла​

  • version — версия формата
  • terraform_version — версия Terraform
  • serial — порядковый номер изменения
  • lineage — уникальный идентификатор окружения
  • resources — список управляемых ресурсов с их атрибутами и зависимостями

Пример записи ресурса:

Код ITЗагрузка примера кода…


Управление состоянием​

См. блок "Работа с состоянием" в разделе CLI; удаление из state без удаления ресурса:

terraform state rm aws_instance.web

Блокировки состояния​

При использовании удалённого бэкенда (например, S3 + DynamoDB) Terraform автоматически блокирует файл состояния во время операций plan/apply, предотвращая одновременные изменения.


Бэкенды (Backends)​

Бэкенд определяет, где хранится файл состояния и как выполняются операции.


Локальный бэкенд (local)​

По умолчанию. Хранит terraform.tfstate в текущей директории.


Удалённые бэкенды​

s3 (AWS)​
backend "s3" {
bucket = "my-terraform-states"
key = "prod/web.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}

Требует:

  • S3-бакет с включённой версионностью
  • DynamoDB-таблица для блокировок (опционально, но рекомендуется)

Bootstrap backend S3 и DynamoDB​

Backend S3 нельзя "создать из того же state, который в нём хранится". Один раз поднимают отдельный минимальный стек (или руками в консоли), затем мигрируют рабочие проекты.

Код ITЗагрузка примера кода…

Разбор:

  • prevent_destroy на bucket — защита от случайного terraform destroy bootstrap-стека.
  • Versioning S3 — откат state при повреждении или ошибочном apply.
  • DynamoDB LockID — блокировка параллельных apply (параметр dynamodb_table в backend).
  • После bootstrap в рабочих модулях указывают backend "s3" { bucket = "my-company-terraform-state" ... } и выполняют terraform init -migrate-state.

Флаг -lock-timeout=10m задаёт, сколько ждать снятия блокировки, если другой процесс уже выполняет apply.


azurerm (Azure)​
backend "azurerm" {
resource_group_name = "tfstate-rg"
storage_account_name = "tfstatestorage"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}

gcs (Google Cloud)​
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod"
}

Особенности бэкендов​

  • После изменения бэкенда — terraform init -reconfigure (см. блок CLI)
  • Нельзя менять бэкенд без миграции состояния
  • Некоторые бэкенды поддерживают workspace'ы — изолированные состояния в одном бэкенде

CLI-команды Terraform​

Основные команды​

terraform init
terraform init -reconfigure
terraform validate
terraform fmt -check
terraform plan -out=tfplan
terraform apply tfplan
terraform destroy

Работа с состоянием​

terraform state list
terraform state show aws_instance.web
terraform state pull > state.json
terraform import aws_instance.web i-0123456789abcdef0
terraform taint aws_instance.web
terraform untaint aws_instance.web

Переменные в CLI​

  • -var="key=value" — передача одной переменной
  • -var-file="prod.tfvars" — загрузка из файла
  • TF_VAR_name=value terraform apply — через переменную окружения

Формат .tfvars:

region = "eu-west-1"
instance_count = 3
tags = {
env = "production"
}

Workspace'ы и окружения​

Workspace в Terraform — механизм изоляции состояний в рамках одного бэкенда. Он позволяет использовать одну и ту же конфигурацию для нескольких окружений — dev, stage, prod.


Создание и переключение​

terraform workspace new dev
terraform workspace select prod
terraform workspace list

Каждый workspace хранит отдельный файл состояния на бэкенде (например, env:/prod/terraform.tfstate в S3).


Использование в коде​

Текущее имя workspace доступно через встроенную переменную:

locals {
tags = {
Environment = terraform.workspace
ManagedBy = "Terraform"
}
}

Ограничения​

  • Workspace не заменяет модульность: он не подходит для фундаментально разных архитектур.
  • Не рекомендуется использовать workspace для управления разными регионами или облачными провайдерами.
  • Все workspace'ы используют один и тот же набор .tf-файлов — логика должна быть параметризована.

Альтернатива — каталоги окружений​

Более прозрачный подход — хранить каждое окружение в отдельной директории:

environments/
├── dev/
│ └── main.tf
├── stage/
│ └── main.tf
└── prod/
└── main.tf

Каждая директория вызывает общий модуль с разными входами. Такой подход лучше подходит для командной работы и ревью.


Управление секретами​

Чувствительные данные (пароли, ключи API, сертификаты) не должны храниться в коде Terraform.


Рекомендуемые практики​

  • Использовать внешние хранилища — HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager.
  • Передавать секреты через переменные окружения только в CI/CD, не вручную.
  • Помечать чувствительные выходы как sensitive = true.
  • Избегать записи секретов в логи: Terraform автоматически скрывает значения, помеченные как sensitive.

Пример с AWS Secrets Manager​

Данные "aws_secretsmanager_secret_version" "db_password" {
secret_id = "prod/db-password"
}

resource "aws_rds_cluster" "main" {
master_password = jsondecode(data.aws_secretsmanager_secret_version.db_password.secret_string)["password"]
}

Запрещено​

  • Хранение секретов в .tf или .tfvars файлах.
  • Коммит секретов в Git, даже в зашифрованном виде без строгого контроля доступа.
  • Использование random_password без сохранения результата во внешнем хранилище.

Policy as Code​

Terraform Enterprise/Cloud и Sentinel (HashiCorp) или Open Policy Agent (OPA) позволяют применять правила к планам и состояниям.


Пример политики Sentinel (запрет определённых типов инстансов)​


import "tfplan"

main = rule {
all tfplan.resources as _, instances {
all instances as r {
not r.applied.instance_type in ["t2.micro", "t3.nano"]
}
}
}

Интеграция с OPA​

Через conftest можно проверять планы:

terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > tfplan.json
conftest test tfplan.json --policy policies/

Политики могут запрещать:

  • Публичные IP-адреса без обоснования
  • Отсутствие тегов
  • Использование устаревших AMI
  • Несоответствие стандартам безопасности

Продвинутые паттерны​

Условное создание ресурсов​

resource "aws_s3_bucket" "logs" {
count = var.enable_logging ? 1 : 0
bucket = "${var.project}-logs"
}

Динамические провайдеры​

Можно использовать несколько провайдеров с разными учетными данными:

Код ITЗагрузка примера кода…


Циклы вложенных блоков​

Для повторяющихся секций (например, ingress-правила в Безопасность group):

Код ITЗагрузка примера кода…


Модуль с опциональными блоками​

Использование try() и can() для безопасного доступа к атрибутам:

locals {
db_name = try(var.database.name, "default")
}

Отладка и профилирование​

Логирование​

Установка переменной окружения:

export TF_LOG=DEBUG
export TF_LOG_PATH=terraform.log

Уровни — TRACE, DEBUG, INFO, WARN, ERROR.


Интерактивная консоль​

terraform console
> var.region
"eu-west-1"
> length(["a", "b", "c"])
3

Граф зависимостей​

terraform graph | dot -Tpng > graph.png

Граф показывает порядок создания ресурсов и зависимости между ними.


Проверка плана вручную​

terraform show tfplan.binary

Позволяет увидеть точные изменения до применения.


Интеграция с CI/CD​

Общая схема​

Типичная цепочка в пайплайне (см. также "Быстрый старт" выше):

terraform init
terraform validate
terraform fmt -check
terraform plan -out=tfplan
# conftest test — опционально, проверка политик
terraform apply tfplan # только в защищённой ветке

Безопасность в CI​

  • Использовать отдельные IAM-роли с минимальными правами.
  • Хранить состояние только в удалённом бэкенде с включённой версионностью.
  • Блокировать прямые коммиты в main/prod.
  • Использовать pull request с обязательным ревью и автоматическим комментарием от terraform plan.

Пример GitHub Actions​

- name: Terraform Plan
run: |
terraform init
terraform validate
terraform plan -out=tfplan
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Встроенные функции Terraform​

Terraform предоставляет более 130 встроенных функций. Ниже — систематизированный список по категориям.


Строковые функции​

  • chomp("text\n") — удаляет завершающий символ перевода строки
  • format("Hello, %s!", "Alice") → "Hello, Alice!"
  • formatlist("ID — %s", ["a", "b"]) → ["ID: a", "ID: b"]
  • indent(4, "line1\nline2") — добавляет отступ ко всем строкам
  • join(",", ["a", "b"]) → "a,b"
  • lower("HELLO") → "hello"
  • upper("hello") → "HELLO"
  • replace("foo-bar", "-", "_") → "foo_bar"
  • split(".", "192.168.1.1") → ["192", "168", "1", "1"]
  • strrev("abc") → "cba"
  • substr("terraform", 0, 5) → "terra"
  • title("hello world") → "Hello World"
  • trim(" abc ", " ") → "abc"
  • trimprefix("v1.2.0", "v") → "1.2.0"
  • trimsuffix("file.txt", ".txt") → "file"

Числовые функции​

  • abs(-5) → 5
  • ceil(3.2) → 4
  • floor(3.9) → 3
  • log(100, 10) → 2
  • max(1, 5, 3) → 5
  • min(1, 5, 3) → 1
  • pow(2, 3) → 8
  • signum(-3) → -1
  • sqrt(16) → 4

Коллекции и структуры​

  • chunklist(["a", "b", "c", "d"], 2) → [["a", "b"], ["c", "d"]]
  • coalesce("a", "", "b") → "a" (первое непустое значение)
  • coalescelist(["x"], [], ["y"]) → ["x"]
  • compact(["a", "", "b", null]) → ["a", "b"]
  • concat([1], [2, 3]) → [1, 2, 3]
  • distinct([1, 2, 2, 3]) → [1, 2, 3]
  • flatten([[1, 2], [3]]) → [1, 2, 3]
  • keys({a = 1, b = 2}) → ["a", "b"]
  • length([1, 2, 3]) → 3
  • lookup({a = 1}, "a", 0) → 1
  • → {a = 1, b = 2}
merge({a = 1}, {b = 2})
  • reverse([1, 2, 3]) → [3, 2, 1]
  • setintersection(["a", "b"], ["b", "c"]) → ["b"]
  • setsubtract(["a", "b"], ["b"]) → ["a"]
  • setunion(["a"], ["b"]) → ["a", "b"]
  • sort(["c", "a", "b"]) → ["a", "b", "c"]
  • transpose({a = ["x"], b = ["y"]}) → {x = ["a"], y = ["b"]}
  • values({a = 1, b = 2}) → [1, 2]

Преобразования и кодировки​

  • base64decode("dGVzdA==") → "test"
  • base64encode("test") → "dGVzdA=="
  • base64gzip("text") → закодированная и сжатая строка
  • csvdecode("a,b\n1,2") → [[{a = "1", b = "2"}]]
  • jsondecode("{\"a\":1}") → {a = 1}
  • jsonencode({a = 1}) → "{\"a\":1}"
  • urlencode("hello world") → "hello+world"
  • yamldecode("a: 1\nb: 2") → {a = 1, b = 2}
  • yamlencode({a = 1}) → "a: 1\n"
  • tomlencode({a = 1}) → "a = 1\n"

Файловые операции​

  • abspath("./file") → абсолютный путь
  • dirname("/path/to/file") → "/path/to"
  • basename("/path/to/file.txt") → "file.txt"
  • file("config.txt") — читает содержимое файла
  • fileexists("config.txt") → true/false
  • fileset("/dir", "*.tf") → список файлов
  • templatefile("template.tftpl", {name = "web"}) — рендерит шаблон

Дата и время​

  • formatdate("YYYY-MM-DD", timestamp()) → "2026-02-24"
  • timeadd("2026-01-01T00:00:00Z", "72h") → "2026-01-04T00:00:00Z"
  • timestamp() → "2026-02-24T12:34:56Z"

Криптография и безопасность​

  • bcrypt("password", 10) — хеширование с cost=10
  • md5("input") → hex-хеш
  • sha1("input") → hex-хеш
  • sha256("input") → hex-хеш
  • uuid() → "f47ac10b-58cc-4372-a567-0e02b2c3d479"
  • uuidv5("ns", "name") — детерминированный UUID

Работа с IP-адресами​

  • cidrhost("10.0.0.0/24", 5) → "10.0.0.5"
  • cidrnetmask("10.0.0.0/24") → "255.255.255.0"
  • cidrsubnet("10.0.0.0/8", 8, 1) → "10.1.0.0/16"
  • cidrsubnets("10.0.0.0/24", 4, 4) → ["10.0.0.0/28", "10.0.0.16/28"]

Ключевые атрибуты ресурсов​

AWS EC2 (aws_instance)​

  • ami — идентификатор образа
  • instance_type — тип инстанса (t3.micro, m5.large)
  • key_name — имя SSH-ключа
  • user_data — скрипт инициализации
  • tags — метаданные
  • vpc_security_group_ids — список Безопасность group
  • subnet_id — подсеть
  • root_block_device — настройки корневого диска
  • ebs_block_device — дополнительные EBS-тома

AWS S3 (aws_s3_bucket)​

  • bucket — имя бакета
  • acl — уровень доступа (private, public-read)
  • versioning — включение версионирования
  • server_side_encryption_configuration — шифрование
  • lifecycle_rule — правила удаления объектов
  • cors_rule — CORS-политики

AWS RDS (aws_db_instance)​

  • engine — PostgreSQL, MySQL, Aurora
  • engine_version — версия СУБД
  • instance_class — класс инстанса
  • username, password — учётные данные
  • allocated_storage — размер хранилища
  • backup_retention_period — срок хранения бэкапов
  • multi_az — отказоустойчивость
  • vpc_security_group_ids — группы безопасности

Azure VM (azurerm_linux_virtual_machine)​

  • name — имя ВМ
  • resource_group_name — группа ресурсов
  • location — регион
  • size — размер (Standard_B1s)
  • admin_username — имя администратора
  • network_interface_ids — сетевые интерфейсы
  • os_disk — конфигурация диска
  • source_image_reference — образ ОС

GCP Compute (google_compute_instance)​

  • name — имя инстанса
  • machine_type — тип машины (e2-micro)
  • zone — зона
  • boot_disk — загрузочный диск
  • network_interface — сеть и внешний IP
  • metadata — пользовательские метаданные
  • service_account — учётная запись сервиса

Настройка провайдеров​

Аутентификация​

  • AWS — IAM-роли, shared credentials file, environment variables (AWS_ACCESS_KEY_ID)
  • Azure — Service Principal, Managed Identity, CLI credentials
  • GCP: Service Account key file, Application Default Credentials

Retry-логика​

Провайдеры автоматически повторяют запросы при временных ошибках. Поведение можно настроить через переменные окружения:

  • AWS_MAX_ATTEMPTS=10
  • AZURE_RETRY_COUNT=5

Custom endpoints​

Для частных облаков или mock-серверов:

provider "aws" {
region = "custom"
endpoints {
ec2 = "https://ec2.custom-cloud.local"
s3 = "https://s3.custom-cloud.local"
}
}

Шаблонизация через templatefile​

Файл nginx.conf.tftpl:

server {
listen ${port};
server_name ${hostname};
root /var/www/${app_name};
}

Использование:

locals {
nginx_config = templatefile("${path.module}/nginx.conf.tftpl", {
port = var.nginx_port
hostname = var.domain
app_name = var.app_name
})
}

resource "aws_instance" "web" {
user_data = base64encode(local.nginx_config)
}

Поддерживаемые конструкции в шаблонах:

  • ${variable} — подстановка
  • %{ for item in list }%...%{ endfor }% — циклы
  • %{ if condition }%...%{ endif }% — условия

Миграция между версиями​

Terraform​

  • При переходе с 0.12 → 1.x: требуется обновление синтаксиса (например, list → list(string))
  • При переходе с 1.0 → 1.5+: проверка совместимости провайдеров
  • Использовать terraform 0.13upgrade для автоматической миграции старых конфигураций

Провайдеры​

  • Всегда указывать required_providers с версиями
  • Избегать ~> 4.0 без тестирования — breaking changes возможны даже в патч-версиях
  • Перед обновлением провайдера: выполнить terraform plan в staging-окружении

Работа с большими состояниями​

Partitioning​

Разделение инфраструктуры на модули:

  • Сеть/ — VPC, подсети, маршруты
  • compute/ — ВМ, autoscaling
  • database/ — RDS, кластеры

Каждый модуль имеет своё состояние.


Remote state как Данные source​

Данные "terraform_remote_state" "Сеть" {
backend = "s3"
config = {
bucket = "my-states"
key = "Сеть/terraform.tfstate"
region = "us-east-1"
}
}

resource "aws_instance" "web" {
subnet_id = data.terraform_remote_state.Сеть.outputs.public_subnet_id
}

Это позволяет связывать модули без жёсткой зависимости.


CLI-флаги Terraform​

Terraform предоставляет широкий набор флагов для тонкой настройки поведения команд.


Общие флаги​

  • -chdir=DIR — изменяет рабочую директорию перед выполнением
  • -help — вывод справки по команде
  • -version — показывает версию Terraform и провайдеров

Флаги для init​

  • -backend=true|false — инициализировать бэкенд (по умолчанию true)
  • -backend-config=path — указывает файл конфигурации бэкенда (можно несколько раз)
  • -reconfigure — игнорирует существующую конфигурацию бэкенда и перезаписывает её
  • -upgrade — обновляет все провайдеры до последней совместимой версии

Флаги для plan​

  • -out=path — сохраняет план в бинарный файл для последующего apply
  • -var="key=value" — задаёт значение переменной
  • -var-file=path — загружает переменные из файла
  • -destroy — генерирует план полного удаления инфраструктуры
  • -refresh-only — обновляет состояние без изменения ресурсов
  • -target=resource — ограничивает план только указанным ресурсом (и его зависимостями)

Флаги для apply​

  • -auto-approve — пропускает интерактивное подтверждение
  • -lock=true|false — блокирует состояние во время операции (по умолчанию true)
  • -lock-timeout=0s — максимальное время ожидания блокировки (например, 10m)
  • -parallelism=n — ограничивает количество одновременных операций (по умолчанию 10)

Флаги для destroy​

  • Все флаги apply, плюс:
  • -refresh=true|false — обновлять ли состояние перед удалением (по умолчанию true)

Флаги для state​

  • -state=path — указывает путь к файлу состояния (для локального бэкенда)
  • -state-out=path — путь для записи изменённого состояния

Флаги для validate​

  • -json — выводит результат в формате JSON (полезно для CI)

Флаги для fmt​

  • -check — проверяет форматирование без изменения файлов
  • -diff — показывает различия
  • -write=false — не записывает изменения на диск

.terraform.lock.hcl​

Файл .terraform.lock.hcl фиксирует точные версии провайдеров и их хеши. Он гарантирует воспроизводимость: все участники проекта используют одинаковые двоичные файлы провайдеров.


Структура файла​

provider "registry.terraform.io/hashicorp/aws" {
version = "5.34.0"
constraints = "~> 5.0"
hashes = [
"h1:abc123...",
"h1:def456..."
]
}

Поведение​

  • Файл создаётся при первом terraform init
  • Обновляется при terraform init -upgrade
  • Должен быть закоммичен в Git
  • Terraform проверяет хеш при загрузке провайдера — несоответствие вызывает ошибку

Управление​

  • Чтобы обновить только один провайдер:
    terraform providers lock -platform=linux_amd64 -fs-mirror=./mirror hashicorp/aws
  • Для работы в offline-режиме: используйте -plugin-dir или filesystem mirror

Блок moved​

Блок moved позволяет безопасно переименовывать или перемещать ресурсы без потери состояния.


Пример​

moved {
from = aws_instance.old_name
to = aws_instance.new_name
}

После terraform apply Terraform переносит состояние из старого адреса в новый, не удаляя и не создавая ресурс.


Использование​

  • При рефакторинге модулей
  • При изменении for_each или count с сохранением существующих ресурсов
  • При миграции между модулями

Ограничения​

  • Нельзя использовать moved для ресурсов с разными типами
  • Нельзя указывать один и тот же адрес в нескольких from или to

Блок check​

Начиная с Terraform 1.7, доступен блок check для валидации после применения.


Пример​

check "database_reachable" {
Данные "http" "db_health" {
url = "http://${aws_db_instance.main.address}:8080/health"
}

assert {
condition = data.http.db_health.status_code == 200
error_message = "Database health check failed"
}
}

Особенности​

  • Выполняется после apply, но до завершения операции
  • При провале проверки применение откатывается (если поддерживается провайдером)
  • Может содержать Данные-блоки и assert-утверждения

Примеры модулей​

Модуль VPC (AWS)​

resource "aws_vpc" "main" {
cidr_block = var.cidr_block
tags = merge(var.tags, { Name = var.name })
}

resource "aws_subnet" "public" {
for_each = toset(var.public_subnets)
vpc_id = aws_vpc.main.id
cidr_block = each.value
availability_zone = each.key
}

Модуль Kubernetes Cluster (EKS)​

Код ITЗагрузка примера кода…


Модуль CI Pipeline (GitHub Actions + AWS)​

resource "github_repository_file" ".github/workflows/deploy.yml" {
repository = var.repo_name
file = ".github/workflows/deploy.yml"
content = templatefile("${path.module}/deploy.yml.tftpl", {
tf_version = var.terraform_version
env = var.environment
})
}

Интеграция с Terragrunt​

Terragrunt — тонкая надстройка над Terraform для управления DRY-конфигурацией.


Основные возможности​

  • Наследование конфигурации через include
  • Автоматическое создание бэкендов
  • Зависимости между модулями через dependency
  • CLI-аргументы через generate

Пример terragrunt.hcl​

include "root" {
path = find_in_parent_folders()
}

terraform {
source = "../modules/vpc"
}

inputs = {
cidr_block = "10.0.0.0/16"
region = "eu-west-1"
}

Когда использовать​

  • При управлении десятками окружений с минимальными отличиями
  • При необходимости строгого порядка применения (например, сначала сеть, потом базы)
  • При централизованном управлении бэкендами и провайдерами

Ошибки​

СитуацияЧто проверить
Команда не найденаPATH, установка пакета, alias
Permission deniedпользователь, группа, sudo, ACL
Неверная версиясм. "Совместимость", --version

Совместимость​

ОбластьПримечание
Версииактуальные LTS/стабильные релизы Terraform
Платформыофициальная матрица поддержки вендора
СтандартыRFC, ISO, спецификация API — см. таблицы выше

Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.


В подборках​

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

Справочники — Справочник по нотации BPMN 2.0, Справочник по Ansible, Справочник по языку С, Справочник по Nginx, Справочник по ассемблеру, Справочник по GitHub Actions.