Представь: у тебя есть сервер на AWS, база данных, балансировщик, два окружения — staging и production. Всё это настраивалось вручную: зашёл в консоль, покликал, создал ресурс, прописал настройки. Месяц спустя нужно поднять ещё одно окружение — и ты снова кликаешь, пытаясь вспомнить, что именно делал тогда. Один параметр не тот — и всё сломалось.

Инфраструктура как код (IaC, Infrastructure as Code) решает именно эту проблему. Ты описываешь всю инфраструктуру в файлах — как обычный код — и применяешь её одной командой. Reproducibility, версионирование, никаких «снежинок» среди серверов.

Terraform от HashiCorp — самый популярный инструмент в этой нише. По данным Stack Overflow Developer Survey 2024, его используют больше 30% DevOps-инженеров. Конкуренты есть, но Terraform держит позиции за счёт зрелости экосистемы и поддержки почти любого облака.

Как это работает

Terraform читает .tf файлы, в которых ты описываешь желаемое состояние инфраструктуры. Потом сравнивает это с реальным состоянием — хранит его в state-файле — и делает только нужные изменения.

Три команды, которых хватает на 90% работы:

  • terraform init — инициализирует проект, скачивает провайдеры
  • terraform plan — показывает, что изменится (ничего не трогает)
  • terraform apply — применяет изменения

Провайдеры — это плагины, которые умеют общаться с конкретными API. Есть провайдеры для AWS, Google Cloud, Azure, Yandex Cloud, Digital Ocean, Cloudflare, GitHub, Kubernetes и ещё нескольких сотен сервисов. Реестр живёт на registry.terraform.io.

Базовый пример: поднимаем VPS на Yandex Cloud

Вот минимальный конфиг для создания виртуальной машины:

terraform {
  required_providers {
    yandex = {
      source  = "yandex-cloud/yandex"
      version = "~> 0.90"
    }
  }
}

provider "yandex" {
  token     = var.yc_token
  cloud_id  = var.cloud_id
  folder_id = var.folder_id
  zone      = "ru-central1-a"
}

resource "yandex_compute_instance" "web" {
  name        = "web-server"
  platform_id = "standard-v3"

  resources {
    cores  = 2
    memory = 4
  }

  boot_disk {
    initialize_params {
      image_id = "fd8abc123"  # Ubuntu 22.04
      size     = 20
    }
  }

  network_interface {
    subnet_id = yandex_vpc_subnet.main.id
    nat       = true
  }
}

resource "yandex_vpc_network" "main" {
  name = "main-network"
}

resource "yandex_vpc_subnet" "main" {
  name           = "main-subnet"
  zone           = "ru-central1-a"
  network_id     = yandex_vpc_network.main.id
  v4_cidr_blocks = ["10.0.1.0/24"]
}

Запускаешь terraform apply — через 2–3 минуты сервер с сетью готов. Хочешь второй такой же — меняешь имя ресурса и снова apply. Хочешь удалить — terraform destroy.

State-файл: самое важное, что нужно понять

State-файл (terraform.tfstate) — это снимок текущего состояния инфраструктуры с точки зрения Terraform. По нему он понимает, что уже создано, а что нужно изменить или удалить.

Если работаешь один и state лежит локально — пока терпимо. Как только появляется второй человек в команде, всё ломается: у каждого своя версия state, конфликты неизбежны.

Решение — remote state. Популярные варианты:

  • Terraform Cloud — есть бесплатный tier до 5 пользователей
  • S3 + DynamoDB на AWS — классика, надёжно
  • Yandex Object Storage + YDB — для тех, кто работает в российских облаках
  • GitLab Managed Terraform State — если GitLab уже используется

Пример backend для S3:

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Главное правило: никогда не коммить terraform.tfstate в git. Там могут быть секреты в открытом виде — пароли, токены, ключи доступа.

Переменные и модули

Повторяющийся код — признак плохой архитектуры. В Terraform с этим борются через переменные и модули.

Переменные:

variable "instance_count" {
  type        = number
  default     = 2
  description = "Количество серверов"
}

Значения передаются через файл terraform.tfvars, переменные окружения (TF_VAR_instance_count=3) или флаги при запуске. Для чувствительных данных используй sensitive = true — Terraform скроет их вывод в логах.

Модули — это папки с набором .tf файлов. Описываешь типичную конфигурацию сервера один раз и переиспользуешь:

module "web_server" {
  source = "./modules/web-server"

  name   = "prod-web"
  cores  = 4
  memory = 8
}

Публичные модули есть на registry.terraform.io — тысячи готовых решений для AWS, GCP, Azure. Модуль для EKS-кластера, RDS-инстанса, VPC — всё есть, настраивай под себя.

Workspaces: несколько окружений из одного кода

Terraform Workspaces позволяют держать staging и production в одной кодовой базе, но с раздельными state-файлами:

terraform workspace new staging
terraform workspace new production
terraform workspace select staging

Внутри конфига можно ссылаться на имя окружения:

locals {
  env = terraform.workspace

  instance_size = {
    staging    = 2
    production = 4
  }
}

resource "yandex_compute_instance" "web" {
  resources {
    cores = local.instance_size[local.env]
  }
}

Альтернативный подход — отдельные папки для каждого окружения (environments/staging/, environments/prod/) с общими модулями. Он более явный и удобен для крупных проектов.

Terraform против конкурентов

AWS CloudFormation — работает только с AWS, синтаксис JSON/YAML неудобен, трудно отлаживать. Если ты намертво привязан к AWS — можно, но Terraform гибче.

Pulumi — позволяет писать инфраструктуру на TypeScript, Python, Go. Удобен для команд, где инженеры хотят привычный язык программирования. Экосистема слабее, провайдеров меньше.

Ansible — скорее конфигурационный менеджмент, чем IaC. Хорош для настройки уже существующих серверов, но не для их создания. Часто используют вместе с Terraform: Terraform поднимает инфраструктуру, Ansible её настраивает.

OpenTofu — форк Terraform с открытой лицензией, появился после того, как HashiCorp в 2023 году сменила лицензию с open-source на Business Source License. Полностью совместим с Terraform, активно развивается. Если корпоративная политика против BSL — OpenTofu твой вариант.

Рабочий процесс в команде

Лучший паттерн — GitOps для инфраструктуры:

  1. Все изменения через pull request
  2. В CI запускается terraform plan, результат публикуется в PR комментарием
  3. После approve — автоматический terraform apply при мёрже в main

Это даёт ревью инфраструктурных изменений, историю в git и возможность откатиться.

Инструменты: Atlantis (self-hosted, бесплатный), Terraform Cloud с VCS-интеграцией, Spacelift для сложных сценариев.

Для качества кода добавь в CI:

  • terraform fmt — форматирует по стандарту
  • terraform validate — проверяет синтаксис
  • tflint — статический анализ, ловит типичные ошибки
  • checkov или tfsec — проверка безопасности конфигов

Типичные ошибки, которые дорого стоят

Секреты в .tf файлах. Никогда не пиши пароли и токены прямо в конфигах. Используй переменные окружения, HashiCorp Vault, AWS Secrets Manager или хотя бы terraform.tfvars с .gitignore.

Один гигантский state. Если prod, staging и все сервисы живут в одном state-файле — любое изменение затрагивает всё, terraform plan работает минутами. Дели по окружениям и сервисам.

Пропустить plan перед apply. Всегда смотри, что изменится. Terraform может пересоздать ресурс (удалить и создать заново) там, где ты ожидал просто update. В выводе это обозначается как -/+ вместо ~. Для базы данных это катастрофа.

Ручные изменения в консоли. Поменял что-то в AWS-консоли, не обновив Terraform — при следующем apply это изменение откатится. Либо всё через Terraform, либо ничего.

Нет защиты критичных ресурсов. lifecycle блок с prevent_destroy спасёт от случайного удаления баз данных и других важных ресурсов:

resource "aws_db_instance" "main" {
  # ...

  lifecycle {
    prevent_destroy       = true
    ignore_changes        = [password]
  }
}

С чего начать прямо сейчас

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

  1. Поставь Terraform — tfenv удобен для управления версиями
  2. Возьми бесплатный аккаунт в Yandex Cloud или Digital Ocean
  3. Создай простой ресурс — VPS или S3 bucket
  4. Добавь remote state
  5. Попробуй сломать через destroy и восстановить через apply

Официальная документация на developer.hashicorp.com/terraform реально хорошая — с туториалами и интерактивными примерами. Сертификат HashiCorp Certified: Terraform Associate стоит $70 и хорошо структурирует знания.

Терраform имеет смысл вводить, когда у тебя больше одного окружения или больше одного человека в команде. До этого порога часто достаточно bash-скрипта и ручного управления. Не надо тащить тяжёлые инструменты туда, где они не нужны.

В REEXY при работе над корпоративными сайтами (от 15 000 ₽) и интернет-магазинами (от 10 000 ₽) мы регулярно обсуждаем с клиентами вопросы инфраструктуры: где хостить, как масштабироваться под нагрузку, нужен ли Kubernetes. Terraform в таких проектах — не модная игрушка, а способ сэкономить часы работы при каждом деплое и не зависеть от памяти конкретного инженера.