Заметка о том, почему инфраструктуру описывают кодом, а не настраивают руками в панелях, как устроен Terraform и чем его заменяют. Примеры опираются на записи DNS из заметки «Как сайт попадает в интернет».
- Зачем описывать инфраструктуру кодом
- Декларативный подход
- Terraform: провайдеры, ресурсы, состояние
- Цикл работы
- Пример: запись DNS в Cloudflare
- Где хранить состояние
- Лицензия Terraform и OpenTofu
- Создать или настроить: альтернативы
Серверы, базы, записи DNS и сертификаты можно завести руками — в веб-панели поставщика. Пока их пять, это работает. Потом начинаются проблемы:
- Никто не помнит, почему настроено именно так: в панели нет истории изменений и нет объяснений.
- Окружения расходятся: предпродакшен настраивали в марте, продакшен — в мае, и они уже не одинаковые.
- Повторить нельзя: поднять копию системы в другом регионе — это неделя кликов и надежда ничего не забыть.
- Ревью нет: опасное изменение делается одним нажатием без второго взгляда.
Инфраструктурой как код (англ. infrastructure as code, IaC) называют подход, при котором инфраструктура описывается файлами в репозитории. Тогда у неё появляется всё, что есть у кода: история, ревью, откат и повторяемость.
Описывать можно двумя способами.
Императивно: «создай сервер, потом добавь диск, потом открой порт». Это сценарий, и его результат зависит от того, что было до запуска.
Декларативно: «должен существовать сервер с таким диском и таким открытым портом». Инструмент сам сравнивает желаемое с тем, что есть, и вычисляет, что изменить.
Большинство инструментов этого класса декларативны. Так себя и описывает Terraform: инструмент, который превращает API поставщиков в декларативные конфигурационные файлы, которые можно хранить, ревьюить и версионировать (репозиторий Terraform).
Тот же принцип — «опиши желаемое состояние» — лежит в основе Kubernetes.
Terraform — инструмент инфраструктуры как кода, который позволяет описывать и облачные, и собственные ресурсы в понятных человеку конфигурационных файлах (документация HashiCorp).
Три понятия, на которых он держится:
- Провайдер (англ.
provider) — плагин, который умеет говорить с API конкретного поставщика. По документации, провайдеры позволяют Terraform работать практически с любой платформой или сервисом, у которых есть доступный API. - Ресурс (англ.
resource) — одна управляемая сущность: сервер, запись DNS, бакет хранилища. - Состояние (англ.
state) — файл, в котором Terraform помнит, какими ресурсами он управляет и как они связаны с реальными объектами (документация HashiCorp).
Состояние — ключ ко всей схеме. Без него Terraform не знал бы, какая запись в Cloudflare «его», а какую завели руками, и не смог бы вычислить разницу.
Базовый цикл — три шага (документация HashiCorp):
- Написать — описать желаемую инфраструктуру в файлах.
- Спланировать — посмотреть, что Terraform собирается изменить.
- Применить — выполнить изменения.
terraform init # скачать провайдеров и подготовить каталог
terraform plan # показать разницу между желаемым и текущим
terraform apply # применить измененияВторой шаг — главное отличие от ручной работы. План показывает ровно то, что будет создано, изменено и удалено, — до того, как это случится. Его и отправляют на ревью.
Та же запись www, что в примере с GitHub Pages, но описанная кодом. Имя ресурса и поля — по документации провайдера Cloudflare: на 27 сентября 2026 года последняя версия — 5.26.0 (реестр Terraform).
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 5.0"
}
}
}
variable "cloudflare_api_token" {
type = string
sensitive = true
}
variable "zone_id" {
type = string
}
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
resource "cloudflare_dns_record" "www" {
zone_id = var.zone_id
name = "www.example.com"
type = "CNAME"
content = "max-starling.github.io"
ttl = 3600
proxied = true
}Токен в код не пишут: он приходит переменной, а провайдер умеет брать его и из переменной окружения CLOUDFLARE_API_TOKEN (документация провайдера). Это то самое разделение кода и конфигурации из общих понятий.
Имена ресурсов меняются между старшими версиями провайдеров: в старых примерах эта же запись может называться иначе. Поэтому версию фиксируют — строка version выше — и сверяются с документацией своей версии, а не с первым попавшимся примером.
Здесь ловушка, в которую попадают все. Файл состояния хранится как обычный текст — и в нём оказываются все секреты, которые были в конфигурации (документация HashiCorp). Поэтому:
- Не класть состояние в git. Иначе секреты окажутся в истории репозитория навсегда.
- Хранить удалённо, в хранилище с ограниченным доступом, — а не на ноутбуке одного разработчика.
- Пользоваться блокировкой. Если хранилище её поддерживает, Terraform блокирует состояние на все операции, которые могут его изменить (документация HashiCorp). Иначе два одновременных
applyиспортят его.
Terraform долго был открытым проектом, а потом компания HashiCorp перевела его на лицензию Business Source License — доступный исходный код, но не открытый в строгом смысле. В ответ несколько компаний, в их числе Gruntwork, Spacelift, Harness, Env0 и Scalr, сделали ответвление — OpenTofu (FAQ OpenTofu).
OpenTofu развивается под эгидой Linux Foundation (opentofu.org) и распространяется под открытой лицензией MPL-2.0 (репозиторий OpenTofu). Для пользователя это почти тот же инструмент: тот же язык конфигурации, тот же цикл plan / apply.
Выбор между ними — вопрос лицензии и политики компании, а не технических возможностей.
Инструменты этого класса делятся по задаче.
Создание инфраструктуры (англ. provisioning) — завести сервер, базу, запись DNS. Это делают Terraform, OpenTofu и Pulumi, который описывает инфраструктуру на обычных языках программирования (репозиторий Pulumi) — на Python, TypeScript, Go вместо отдельного языка конфигурации.
Настройка того, что уже создано (англ. configuration management) — установить пакеты, разложить файлы, перезапустить службы. Это ниша Ansible: платформа автоматизации, которая работает через SSH и не требует ставить агентов на управляемые машины (репозиторий Ansible).
| Инструмент | Задача | Как описывается | Лицензия |
|---|---|---|---|
| Terraform | создание | свой декларативный язык | BUSL |
| OpenTofu | создание | тот же язык, что у Terraform | MPL-2.0 |
| Pulumi | создание | обычные языки программирования | Apache-2.0 |
| Ansible | настройка | сценарии на YAML | GPL-3.0 |
На практике их часто сочетают: Terraform создаёт серверы, Ansible их настраивает. А если приложение живёт в контейнерах, вторую половину работы берёт на себя Kubernetes.