· 18 мин чтения

Terraform для малого и среднего бизнеса: практический гайд по IaC

Меня зовут Семёнов Евгений Сергеевич, директор АйТи Фреш. 15+ лет я видел, как компании теряют недели на восстановление «упавшей» облачной инфраструктуры или пересобирают стенд тестирования по памяти коллеги в отпуске. Infrastructure as Code решает это одним подходом: вся конфигурация — в Git, применение — командой, ревью — через Pull Request. Terraform (и его форк OpenTofu) в этой парадигме — рабочая лошадка. Расскажу, как внедрить без лишней мифологии.

Зачем IaC малому бизнесу

Есть миф, что Terraform — для гигантов с тысячами серверов. Неправда. Даже для офиса с 5 виртуалками и одним облачным тестовым стендом IaC даёт три главных эффекта: документированность, воспроизводимость, version control. Когда через полгода в проект приходит новый админ — он поднимает полную копию среды за час вместо двух дней «реверс-инжиниринга».

Terraform или OpenTofu

После смены лицензии HashiCorp в 2023 году появился OpenTofu под эгидой Linux Foundation. Синтаксис совместим до версии 1.5. Для нового проекта я советую OpenTofu. Для существующих — продолжать на Terraform, пока не упрётесь в лицензионные ограничения.

Структура проекта

infrastructure/
├── modules/
│   ├── network/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── compute/
├── envs/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── backend.tf
│   │   └── terraform.tfvars
│   ├── staging/
│   └── prod/
└── README.md

Удалённый state в S3

Никогда не коммитьте terraform.tfstate в Git. Это антипаттерн с точки зрения безопасности (там могут быть пароли) и неудобен для команды.

# envs/prod/backend.tf
terraform {
  required_version = ">= 1.5"
  backend "s3" {
    bucket         = "itfresh-tfstate"
    key            = "prod/terraform.tfstate"
    region         = "ru-central1"
    endpoint       = "https://storage.yandexcloud.net"
    skip_credentials_validation = true
    skip_region_validation      = true
    dynamodb_table = "tf-lock"
    encrypt        = true
  }
}

Пример: инфраструктура в Yandex Cloud

# envs/prod/main.tf
terraform {
  required_providers {
    yandex = { source = "yandex-cloud/yandex", version = "0.104.0" }
  }
}

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

module "network" {
  source = "../../modules/network"
  name   = "prod-net"
  cidr   = "10.10.0.0/16"
}

module "web" {
  source        = "../../modules/compute"
  name_prefix   = "web"
  count         = 3
  subnet_id     = module.network.public_subnet_id
  image         = "ubuntu-2204-lts"
  platform      = "standard-v3"
  cpu           = 2
  ram           = 4
  disk_size     = 40
  user_data     = file("cloud-init.yaml")
}

Модуль compute

# modules/compute/main.tf
variable "count"        { type = number }
variable "name_prefix"  { type = string }
variable "subnet_id"    { type = string }
variable "image"        { type = string }
variable "platform"     { type = string }
variable "cpu"          { type = number }
variable "ram"          { type = number }
variable "disk_size"    { type = number }
variable "user_data"    { type = string }

data "yandex_compute_image" "os" {
  family = var.image
}

resource "yandex_compute_instance" "vm" {
  count       = var.count
  name        = "${var.name_prefix}-${count.index + 1}"
  platform_id = var.platform

  resources {
    cores  = var.cpu
    memory = var.ram
  }

  boot_disk {
    initialize_params {
      image_id = data.yandex_compute_image.os.id
      size     = var.disk_size
      type     = "network-ssd"
    }
  }

  network_interface {
    subnet_id = var.subnet_id
    nat       = true
  }

  metadata = { user-data = var.user_data }
}

output "ips" {
  value = yandex_compute_instance.vm[*].network_interface[0].nat_ip_address
}

Workspaces для окружений

Workspaces удобны, когда один код-база обслуживает dev/stage/prod. Переключение — terraform workspace select prod.

terraform workspace new dev
terraform workspace new prod
terraform workspace list
terraform workspace show

Импорт существующих ресурсов

Реальный мир — это когда у вас уже есть 30 ВМ, созданных руками. Terraform import аккуратно затягивает их в state.

# Современный способ с import блоком (1.5+)
import {
  to = yandex_compute_instance.legacy["web-1"]
  id = "ef3abc123..."
}

resource "yandex_compute_instance" "legacy" {
  for_each = toset(["web-1","web-2","db-1"])
  # ... заполняется после terraform plan -generate-config-out=legacy.tf
}

terraform plan -generate-config-out=legacy.tf

CI/CD с GitLab

# .gitlab-ci.yml
stages: [validate, plan, apply]

image: hashicorp/terraform:1.7

variables:
  TF_ROOT: envs/prod

before_script:
  - cd $TF_ROOT
  - terraform init

validate:
  stage: validate
  script: terraform validate && terraform fmt -check

plan:
  stage: plan
  script: terraform plan -out tfplan
  artifacts:
    paths: [envs/prod/tfplan]

apply:
  stage: apply
  script: terraform apply tfplan
  when: manual
  only: [main]

Мини-кейс: миграция клиента в облако

Зимой 2025 года к нам пришёл клиент — дистрибьютор промышленного оборудования, офис 70 РМ. Задача: перенести 14 ВМ с физического Dell Xeon Platinum 8280 (дата-центр МТС, 40G Mellanox) в Yandex Cloud для резервирования. Ручная копия клонов заняла бы неделю. За 3 рабочих дня мы написали Terraform-модули: network (VPC+4 подсети+security groups), compute (виртуалки с cloud-init), dns (PTR и A-записи), backup-policy. Первая среда (staging) развернулась за 14 минут с нуля, вторая (prod) — за 11. Rollback-скрипт документирован: `terraform destroy`. Стоимость миграции 220 000 руб., экономия 5 рабочих дней каждый раз, когда нужно поднять тестовую копию.

Безопасность state и secrets

Типичные ошибки

Внедрим Terraform в вашу инфраструктуру

Проектирование модулей, миграция существующего парка, CI/CD, ревью процесса. От 120 000 руб. за первую площадку и 3 окружения.

Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш

FAQ — частые вопросы о Terraform

Зачем малому офису Terraform?
Воспроизводимость инфраструктуры, версионирование изменений в Git и ревью через Pull Request.
Где хранить state-файл?
Только в удалённом backend: S3, Yandex Object Storage, GitLab HTTP backend или Terraform Cloud.
Что такое модуль?
Переиспользуемый набор ресурсов с входными и выходными параметрами.
Можно ли импортировать существующую инфраструктуру?
Да, команда terraform import или блок import для массового импорта.
OpenTofu вместо Terraform?
Форк после смены лицензии HashiCorp, совместим до версии 1.5. Для новых проектов подходит.

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.