В небольших проектах инфраструктуру можно создать вручную через веб-интерфейс облачного провайдера. Но если серверов десятки, а окружений несколько (Development, Testing, Staging и Production), ручное управление становится медленным и приводит к ошибкам.
Поэтому часто в современной DevOps-практике используется Infrastructure as Code (IaC) — подход, при котором инфраструктура описывается в виде кода и может быть создана или изменена одной командой. Одним из самых популярных инструментов для этого является Terraform.
В этой статье разберём, что такое Terraform, как он работает, из каких компонентов состоит и почему знание Terraform стало одним из базовых требований к DevOps-инженерам.
Что такое Infrastructure as Code?
Infrastructure as Code (IaC) — это подход, при котором инфраструктура описывается в текстовых файлах вместо ручной настройки через веб-интерфейс. Например, вместо того чтобы вручную:
-
создать виртуальную машину;
-
выбрать её размер;
-
настроить сеть;
-
добавить правила брандмауэра;
-
создать диск;
-
назначить публичный IP,
инженер один раз описывает всё это в конфигурационном файле. После этого Terraform автоматически создает инфраструктуру. Именно поэтому инфраструктуру называют «кодом».
Что такое Terraform?
Terraform — это инструмент для создания, изменения и удаления инфраструктуры с помощью декларативных конфигурационных файлов. Terraform поддерживает сотни платформ, включая:
-
AWS;
-
Microsoft Azure;
-
Google Cloud Platform;
-
Oracle Cloud;
-
DigitalOcean;
-
VMware;
-
Kubernetes;
-
Cloudflare;
-
GitHub.
Это означает, что один инструмент позволяет управлять инфраструктурой самых разных сервисов.
Декларативный подход
Terraform использует декларативный стиль описания. Инженер не пишет последовательность действий. Вместо этого он описывает желаемое состояние инфраструктуры. Для примера:
Нужна виртуальная машина с двумя ядрами, 4 ГБ оперативной памяти и публичным IP-адресом.
Упрощенно в виде кода это выглядит так
resource "cloud_virtual_machine" "web_server" { name = "web-server" cpu = 2 memory = 4 # GB public_ip = true}
Terraform самостоятельно определяет, какие действия необходимо выполнить, чтобы получить такой результат.
Как работает Terraform?
Процесс работы можно представить следующим образом:
Конфигурация Terraform ▼terraform plan ▼План изменений ▼terraform apply ▼Облачный провайдер ▼Созданная инфраструктура
Сначала Terraform анализирует конфигурацию и показывает, что именно будет создано или изменено. Только после подтверждения изменения применяются. Это значительно снижает риск случайных ошибок.
Основные компоненты Terraform
Providers
Terraform не взаимодействует с облаками напрямую. Для этого используются Providers — специальные плагины. Именно Provider знает, как работать с API конкретной платформы.
Resources
Практически всё, чем управляет Terraform, является ресурсом (resource). Это могут быть виртуальные машины, сети, базы данных, Kubernetes Namespace или DNS-записи. Именно из описания ресурсов состоит большая часть Terraform-конфигурации.
Также Terraform автоматически строит граф зависимостей (Dependency Graph) между ресурсами и определяет порядок их создания, изменения и удаления.
Variables
Чтобы не изменять конфигурацию вручную, используют переменные. К примеру, можно менять:
-
регион;
-
имя проекта;
-
размер виртуальной машины;
-
количество серверов.
Один и тот же код можно использовать для разных окружений.
Outputs
После создания инфраструктуры Terraform может вывести полезную информацию:
-
IP-адрес сервера;
-
DNS-имя;
-
идентификатор Kubernetes-кластера;
-
URL балансировщика нагрузки.
Эти данные можно использовать в других инструментах автоматизации.
Terraform State
Одна из самых важных особенностей Terraform — файл State. После каждого применения конфигурации Terraform сохраняет информацию о созданных ресурсах.
Именно благодаря этому он понимает:
-
что уже существует;
-
что изменилось;
-
что необходимо удалить;
-
что нужно создать заново.
Без файла состояния Terraform не сможет корректно управлять инфраструктурой. Далее мы подробнее разберем State.
Drift
Если кто-то изменит инфраструктуру вручную вне Terraform, при выполнении terraform plan Terraform обнаружит расхождение между конфигурацией и фактическим состоянием инфраструктуры, такое событие называется Drift.
Основные команды Terraform
|
Команда |
Что делает |
Когда используется |
|---|---|---|
|
|
Инициализирует проект |
Для создания проекта или изменения провайдеров |
|
|
Форматирует конфигурацию |
Перед коммитом |
|
|
Проверяет конфигурацию |
Перед созданием плана |
|
|
Показывает изменения |
Перед применением |
|
|
Применяет изменения |
После проверки изменений |
|
|
Удаляет инфраструктуру |
При завершении работы или очистке стенда |
Даже опытные инженеры почти всегда выполняют terraform plan перед terraform apply, чтобы убедиться, что изменения соответствуют ожиданиям.
Почему Terraform популярен?
Основные преимущества:
-
инфраструктура хранится в Git;
-
конфигурацию можно повторно использовать;
-
можно быстро восстановить инфраструктуру;
-
поддерживаются десятки облачных платформ.
Именно поэтому Terraform широко используется как небольшими компаниями, так и крупными организациями.
Установка Terraform
Terraform доступен для Linux, Windows и macOS. На Linux его можно установить из официального репозитория или скачать готовый архив с официального сайта. После установки убедитесь, что всё работает:
terraform version
Если команда выводит установленную версию, Terraform готов к работе.
Структура проекта Terraform
В отличие от обычных программ, проект Terraform состоит из текстовых файлов с расширением .tf. Минимальная структура выглядит так:
terraform-demo/├── main.tf├── variables.tf├── outputs.tf└── terraform.tfvars
Названия файлов не являются обязательными — Terraform автоматически загружает все файлы с расширением .tf в текущем каталоге. Однако такое разделение считается хорошей практикой и делает проект более понятным.
Что такое HCL?
Все конфигурации Terraform пишутся на языке HCL (HashiCorp Configuration Language). HCL создан специально для описания инфраструктуры. По синтаксису он напоминает JSON, но легче читается человеком и поддерживает переменные, выражения и ссылки между объектами.
Простейший пример:
terraform { required_version = ">= 1.6"}
Terraform считывает этот блок и проверяет, соответствует ли установленная версия Terraform указанным требованиям.
Providers
Terraform сам по себе не умеет создавать виртуальные машины, контейнеры или облачные ресурсы. Для взаимодействия с различными платформами используются Providers — специальные плагины. В нашем примере подключим Docker Provider:
terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "~> 3.0" } }}provider "docker" { host = "unix:///var/run/docker.sock"}
При первом запуске Terraform автоматически скачает необходимый провайдер.
Инициализация проекта
Перед началом работы необходимо выполнить:
terraform init
Эта команда:
-
загружает провайдеры;
-
создаёт каталог
.terraform; -
подготавливает проект к работе.
Команда terraform init выполняется один раз при создании проекта или после изменения списка провайдеров.
Resources
Resource — основной строительный блок Terraform. Каждый ресурс описывает объект инфраструктуры: контейнер, виртуальную машину, сеть, базу данных и т.д. Создадим контейнер Nginx:
resource "docker_image" "nginx" { name = "nginx:latest"}resource "docker_container" "web" { name = "my-nginx" image = docker_image.nginx.image_idports { internal = 80 external = 8080 }}
Здесь описаны два ресурса:
-
образ Docker;
-
контейнер, использующий этот образ.
Terraform автоматически понимает, что контейнер зависит от образа, и создаст их в правильном порядке.
Variables
Переменные позволяют не изменять конфигурацию при каждом запуске. Файл variables.tf:
variable "container_name" { type = string default = "my-nginx"}
Использование:
name = var.container_name
При необходимости значение можно переопределить в файле terraform.tfvars:
container_name = "web-server"
Такой подход делает конфигурацию более гибкой и удобной для повторного использования.
Outputs
После создания инфраструктуры Terraform может вывести полезную информацию. Для примера:
output "container_name" {value = docker_container.web.name}
После выполнения terraform apply Terraform покажет имя созданного контейнера. В облачных проектах через Outputs часто выводят IP-адреса, DNS-имена и другие параметры созданной инфраструктуры.
Проверка конфигурации
Перед созданием инфраструктуры рекомендуется проверить конфигурацию. Отформатировать файлы:
terraform fmt
Проверить синтаксис:
terraform validate
Эти команды помогают обнаружить ошибки ещё до применения изменений.
План изменений
Следующий шаг — посмотреть, что именно собирается сделать Terraform.
terraform plan
Terraform сравнит конфигурацию с текущим состоянием инфраструктуры и покажет список операций:
-
что будет создано;
-
что изменится;
-
что будет удалено.
Просмотр плана перед применением изменений считается обязательной практикой.
Создание инфраструктуры
Если план выглядит корректно, можно применить изменения:
terraform apply
Terraform ещё раз покажет план и попросит подтвердить выполнение. После подтверждения будут созданы описанные ресурсы.
Удаление инфраструктуры
Одно из главных преимуществ Terraform — возможность полностью удалить созданную инфраструктуру той же конфигурацией. Для этого используется команда:
terraform destroy
Terraform покажет список ресурсов, которые будут удалены, и запросит подтверждение.
Terraform State
При работе с реальными проектами быстро возникают новые вопросы:
-
Как Terraform понимает, какие ресурсы уже существуют?
-
Почему не стоит изменять инфраструктуру вручную?
-
Как повторно использовать один и тот же код?
-
Нужно ли каждый раз писать конфигурацию с нуля?
Ответы на эти вопросы дают два ключевых механизма Terraform: State, Modules. Именно они делают Terraform удобным инструментом для сопровождения инфраструктуры в долгосрочной перспективе.
Что такое Terraform State?
После выполнения команды terraform apply Terraform создаёт файл terraform.tfstate. Именно в нём хранится информация обо всех ресурсах, которыми управляет Terraform.
Например:
-
идентификаторы виртуальных машин;
-
IP-адреса;
-
идентификаторы сетей;
-
параметры созданных ресурсов;
-
связи между ними.
Можно представить State как базу данных Terraform.
main.tf ▼terraform apply ▼terraform.tfstate ▼Информация о созданной инфраструктуре
Без этого файла Terraform не сможет определить, что уже создано и какие изменения необходимо выполнить.
Почему State настолько важен?
Представим ситуацию. Вы создали сервер:
terraform apply
Через неделю увеличили объём оперативной памяти. Terraform сравнит:
-
текущую конфигурацию;
-
содержимое State;
-
реальную инфраструктуру.
После этого он покажет изменения, которые необходимо выполнить. Если бы State не существовал, Terraform пришлось бы создавать инфраструктуру заново.
Почему нельзя редактировать State вручную?
Файл состояния содержит внутреннюю информацию Terraform. Любые случайные изменения могут привести к тому, что Terraform:
-
перестанет видеть существующие ресурсы;
-
попытается создать их повторно;
-
удалит работающую инфраструктуру;
-
потеряет связь между объектами.
Поэтому напрямую изменять terraform.tfstate практически никогда не рекомендуется. Если требуется изменить инфраструктуру, следует менять HCL-конфигурацию, а не файл состояния.
Local State и Remote State
По умолчанию файл состояния хранится локально.
terraform.tfstate
Такой вариант подходит для обучения и небольших проектов. Однако при командной работе возникают проблемы.
Например:
-
несколько инженеров одновременно изменяют инфраструктуру;
-
у каждого хранится собственная копия State;
-
изменения начинают конфликтовать.
Для решения этой задачи используется Remote State.
Remote State
Remote State хранится в удалённом хранилище, доступном всей команде. К примеру:
-
Amazon S3;
-
Azure Storage;
-
Google Cloud Storage;
-
HashiCorp Terraform Cloud.
Все инженеры используют один источник состояния, что снижает риск конфликтов. Во многих компаниях использование Remote State является обязательной практикой.
Что такое модуль?
Представьте, что вам необходимо создать одинаковую инфраструктуру для трёх проектов. Можно трижды скопировать один и тот же код. Но это неудобно.
Terraform предлагает более элегантное решение — Modules. Модуль представляет собой повторно используемый набор Terraform-конфигураций. Иными словами, модуль — это шаблон инфраструктуры.
Почему используют модули?
Предположим, каждая команда компании использует одинаковую инфраструктуру:
-
виртуальная машина;
-
сеть;
-
группа безопасности;
-
балансировщик нагрузки.
Вместо копирования сотен строк кода достаточно создать один модуль и использовать его в разных проектах. Получается следующая схема:
Module│ ├── Project A ├── Project B├── Project C
Изменения в модуле автоматически становятся доступны всем проектам после обновления версии.
Структура модуля
Обычно модуль имеет такую структуру:
network-module/main.tfvariables.tfoutputs.tfREADME.md
Она очень похожа на структуру обычного Terraform-проекта. Главное отличие заключается в том, что модуль предназначен для повторного использования.
Подключение модуля
Использовать модуль очень просто:
module "network" { source = "./network-module"}
После этого Terraform загрузит модуль и создаст все описанные в нём ресурсы. При необходимости модулю можно передавать переменные.
Например:
module "network" { source = "./network-module" network_name = "production"}
Так один и тот же модуль можно использовать для разных окружений.
Terraform Registry
Необязательно создавать все модули самостоятельно. Существует Terraform Registry — официальный каталог провайдеров и модулей Terraform. В нём опубликованы тысячи модулей от разработчиков и крупных компаний.
Например, можно найти готовые модули для:
-
Kubernetes;
-
GitHub;
-
Cloudflare;
-
VMware;
-
PostgreSQL;
-
MongoDB.
Во многих случаях достаточно подключить готовый модуль вместо написания конфигурации с нуля.
Как работает Terraform Registry?
Последовательность выглядит следующим образом:
Terraform Registry ▼Готовый Module ▼terraform init ▼Ваш проект
Terraform автоматически загрузит модуль и подключит его к проекту. Это значительно ускоряет разработку инфраструктуры.
Когда использовать готовые модули?
Хорошей практикой считается использование проверенных модулей для типовых задач:
-
создание VPC;
-
Kubernetes-кластера;
-
виртуальных машин;
-
баз данных;
-
сетевых правил.
Однако перед использованием стороннего модуля важно изучить его документацию, поддерживаемые версии Terraform и историю обновлений.
Практический проект:
Чтобы освоить Terraform, необязательно сразу регистрироваться в AWS, Azure или Google Cloud. Начать можно локально с помощью Docker Provider. Это позволит изучить основные возможности Terraform без риска и лишних трудностей.
В этом разделе мы:
-
создадим первый проект;
-
развернём контейнер Nginx;
-
импортируем существующий ресурс в Terraform;
-
познакомимся с современными способами пересоздания ресурсов;
-
научимся использовать собственные модули.
Подготовка
Перед началом необходимо установить:
-
Docker Desktop (Windows/macOS) или Docker Engine (Linux);
-
Terraform.
Проверяем установку:
docker versionterraform version
Если обе команды выводят информацию о версии, можно приступать.
Структура проекта
Создадим каталог:
terraform-docker/main.tfvariables.tfoutputs.tfterraform.tfvars
Шаг 1. Подключаем Docker Provider
Файл main.tf
terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "~> 3.0" } }}provider "docker" { host = "unix:///var/run/docker.sock"}
Инициализируем проект:
terraform init
Terraform автоматически скачает Docker Provider из Terraform Registry.
Шаг 2. Создаём первый ресурс
Добавим Docker-образ.
resource "docker_image" "nginx" { name = "nginx:latest"}
Теперь создадим контейнер.
resource "docker_container" "web" { name = "terraform-nginx" image = docker_image.nginx.image_id ports { internal = 80 external = 8080 }}
Шаг 3. Проверяем изменения
Перед созданием инфраструктуры всегда рекомендуется выполнить:
terraform plan
Terraform покажет примерно следующее:
Plan:+ docker_image.nginx+ docker_container.web2 to add
Это означает, что будут созданы два ресурса.
Шаг 4. Создаём инфраструктуру
terraform apply
После подтверждения Terraform:
-
скачает образ Nginx;
-
создаст контейнер;
-
подключит порт 8080.
Проверяем:
docker ps
Открываем браузер:
http://localhost:8080
Появится стандартная страница Nginx Это первая инфраструктура, полностью созданная Terraform.
Используем Variables
Создадим файл variables.tf
variable "container_name" { default = "terraform-nginx"}
Используем переменную:
name = var.container_name
Теперь можно менять имя контейнера без изменения конфигурации.
Файл terraform.tfvars
container_name = "production-nginx"
Используем Outputs
Создадим outputs.tf
output "container_name" { value = docker_container.web.name}
После применения Terraform покажет:
Outputs:container_name = production-nginx
Импорт существующих ресурсов
На практике инфраструктура не всегда создаётся Terraform с нуля. Например, виртуальная машина или контейнер уже существуют, но вы хотите начать управлять ими через Terraform.
Для этого используется команда:
terraform import
Предположим, контейнер existing-nginx уже создан вручную.
Сначала необходимо описать ресурс в конфигурации:
resource "docker_container" "existing" {}
Затем выполнить импорт:
terraform import docker_container.existing existing-nginx
После этого Terraform начнёт отслеживать этот контейнер через файл terraform.tfstate.
Важно понимать, что terraform import не создаёт HCL-конфигурацию автоматически. Он лишь добавляет существующий объект в состояние Terraform. После импорта конфигурацию нужно привести в соответствие с реальными параметрами ресурса. Хотя в современных версиях Terraform существует экспериментальная возможность генерации конфигурации с помощью блока import и команды terraform plan -generate-config-out, однако на практике большинство инженеров по-прежнему описывают ресурсы вручную.
Пересоздание ресурсов
Раньше для принудительного пересоздания ресурса часто использовали команду taint. Например:
terraform taint docker_container.web
После этого Terraform помечал ресурс как повреждённый и пересоздавал его при следующем terraform apply. Команда terraform taint считается устаревшим способом пометки ресурса для пересоздания и сохранена главным образом для обратной совместимости. В современных версиях Terraform предпочтительно использовать команду:
terraform apply -replace="docker_container.web"
или
terraform plan -replace="docker_container.web"
Такой подход делает намерение более явным и не изменяет состояние заранее.
Практический пример с модулями
Предположим, компания запускает несколько одинаковых веб-приложений. Вместо копирования конфигурации создадим модуль. Структура проекта:
terraform-demo/main.tfmodules/nginx/main.tfvariables.tfoutputs.tf
modules/nginx/main.tf
resource "docker_image" "nginx" { name = "nginx:latest"}resource "docker_container" "web" { name = var.name image = docker_image.nginx.image_id ports { internal = 80 external = var.port }}
modules/nginx/variables.tf
variable "name" {}variable "port" {}
Корневой main.tf
Теперь можно создать сразу несколько контейнеров.
module "frontend" { source = "./modules/nginx" name = "frontend" port = 8080}module "backend" { source = "./modules/nginx" name = "backend" port = 8081}module "admin" { source = "./modules/nginx" name = "admin" port = 8082}
Terraform создаст три независимых контейнера, используя один и тот же модуль.
modules/ nginx ▲ ▲ ▲frontend backend admin
Такой подход избавляет от дублирования кода и значительно упрощает сопровождение инфраструктуры. Если потребуется изменить конфигурацию всех контейнеров, достаточно обновить модуль один раз — изменения можно затем применить ко всем экземплярам.
Ресурсы для обучения
1. Terraform Documentation (официальная документация)
Официальная документация Terraform с подробным описанием языка HCL, команд, провайдеров, модулей и лучших практик. Это основной источник информации, который стоит использовать в первую очередь.
2. HashiCorp Learn
Бесплатные пошаговые руководства и практические лабораторные работы по Terraform — от базовых примеров до построения инфраструктуры в облаке.
3. Terraform Language Documentation
Подробное описание языка HCL, переменных, функций, циклов, условий, модулей и других возможностей Terraform.
4. Terraform Best Practices
Рекомендации по организации Terraform-проектов, структуре каталогов, работе с модулями, состоянием (State) и совместной разработке.
5. LabEx
Интерактивные лабораторные работы по Terraform и Infrastructure as Code. Позволяют выполнять задания непосредственно в браузере без предварительной настройки окружения.
6. Awesome Terraform
Подборка полезных инструментов, модулей, статей, книг и материалов по Terraform, поддерживаемая сообществом.
7. OpenTofu Documentation
OpenTofu — открытая альтернатива Terraform, совместимая с большинством существующих конфигураций. Полезно познакомиться с проектом, чтобы понимать современное развитие экосистемы Infrastructure as Code.
Заключение
Terraform давно стал стандартом де-факто для управления инфраструктурой как кодом. Даже если в будущем вы будете работать с IaC-инструментами, понимание принципов Terraform — декларативного подхода, состояния инфраструктуры, модулей и провайдеров — станет прочной основой для дальнейшего изучения DevOps и облачных технологий.
В следующей части мы рассмотрим взаимодействие Terraform с облачными провайдерами.
ссылка на оригинал статьи https://habr.com/ru/articles/1063234/