Infrastructure as Code (IaC): инфраструктура описывается файлами в git, а инструмент создаёт и меняет её по описанию. Плюсы: воспроизводимость, ревью изменений, история, одинаковые окружения. Terraform самый популярный инструмент для облачной инфраструктуры. С 2023 года он распространяется под лицензией BSL, и сообщество сделало открытый форк OpenTofu с почти тем же синтаксисом и командами.
Основные понятия
terraform {
required_version = ">= 1.6"
required_providers {
yandex = {
source = "yandex-cloud/yandex"
version = "~> 0.130"
}
}
backend "s3" { ... } # где хранить state
}
variable "env" { type = string }
locals {
name = "api-${var.env}"
}
resource "yandex_compute_instance" "api" { ... } # что создать
data "yandex_compute_image" "ubuntu" { # что прочитать
family = "ubuntu-2404-lts"
}
output "ip" { value = yandex_compute_instance.api.network_interface[0].nat_ip_address }
- Provider: плагин для API облака или сервиса (AWS, Yandex Cloud, Kubernetes, GitHub).
- Resource: объект, которым Terraform управляет.
- Data source: объект, который Terraform только читает.
- Variable, local, output: входы, внутренние вычисления, выходы.
Версии провайдеров фиксируются в .terraform.lock.hcl, его коммитят в git.
Цикл работы
terraform init: скачать провайдеры и модули, подключить backend.terraform fmtиterraform validate: форматирование и проверка синтаксиса.terraform plan -out=tfplan: показать, что изменится, и сохранить план.terraform apply tfplan: применить ровно сохранённый план.
В плане значки: + создать, ~ изменить на месте, - удалить, -/+ пересоздать (удалить и создать, «must be replaced»). Пересоздание базы данных из-за смены неизменяемого поля это классический способ потерять прод, поэтому план читают внимательно.
State
Terraform хранит в state соответствие «ресурс в коде, объект в облаке» и последние известные атрибуты. Без state он не знает, что уже создал.
- Хранить state удалённо (S3-совместимое хранилище, Terraform Cloud, Postgres), а не в локальном файле.
- Включить блокировку, чтобы два
applyне шли одновременно. Классика AWS: S3 плюс DynamoDB; в новых версиях S3-бэкенд умеет блокировку файлом в бакете (use_lockfile). В Yandex Cloud: Object Storage и YDB. - Включить версионирование бакета: испорченный state можно вернуть.
- State содержит секреты в открытом виде (пароли, ключи), даже если переменная помечена
sensitive. Доступ к нему ограничивают и шифруют.
Команды работы со state: terraform state list, state show, state mv (переименовать адрес без пересоздания), state rm (забыть ресурс, не удаляя в облаке). Вместо state mv теперь удобнее блок moved, вместо ручного terraform import блок import: оба проходят через план и ревью.
Drift
Дрейф: кто-то поменял ресурс руками в консоли облака. terraform plan покажет разницу и предложит вернуть как в коде. terraform plan -refresh-only показывает только изменения в облаке и позволяет принять их в state. Дрейф ловят регулярным plan по расписанию в CI.
Модули
Модуль это каталог с .tf файлами, который вызывают с параметрами:
module "vpc" {
source = "./modules/vpc"
cidr = "10.10.0.0/16"
}
Модули дают переиспользование (одна сеть для dev и prod с разными параметрами). Версию внешнего модуля фиксируют (?ref=v1.2.0 или version).
count и for_each
count = 3 создаёт ресурсы с адресами [0], [1], [2]. Если удалить элемент из середины списка, индексы сдвинутся, и Terraform пересоздаст соседей. for_each по множеству или мапе адресует ресурсы ключами (["api"], ["web"]), удаление одного не задевает остальные.
lifecycle
prevent_destroy = true: план с удалением ресурса упадёт. Для баз и бакетов с данными.create_before_destroy = true: при пересоздании сначала новый, потом удаление старого.ignore_changes = [tags]: не трогать поле, которое меняет кто-то другой.
Окружения
Варианты: отдельные каталоги или state на каждое окружение (envs/dev, envs/prod) с общими модулями, либо workspaces. Для сильно различающихся окружений и разных прав доступа чаще выбирают отдельные каталоги и state: ошибка в dev не заденет prod.
Terraform в команде
- Plan в merge request, apply только после ревью и из CI (Atlantis, GitLab, Terraform Cloud).
- Никаких ручных изменений в консоли.
- Небольшие state: один огромный state медленный и опасный.
- В России registry.terraform.io доступен не всегда; используют зеркала провайдеров (у Yandex Cloud есть своё) через
~/.terraformrc.
Частые ошибки
- Локальный state на ноутбуке и два человека с разными версиями.
applyбез сохранённого плана: применится не то, что смотрели на ревью.countпо списку, который меняется.- Пароли в
.tfи в git. - Игнорировать
-/+в плане.
Что спросят на собесе
- Что такое state, где его хранить и зачем блокировка.
- Как импортировать существующий ресурс и как переименовать ресурс без пересоздания.
- Что такое drift и как его обнаружить.
- Разница
countиfor_each. - Как организовать Terraform для нескольких окружений и команды.