До основного вмісту

Terraform: інфраструктура як код для VPS і хмари

Хмара та DevOps · 19.04.2026 · 4 хв читання
Ілюстрація до статті «Terraform: інфраструктура як код для VPS і хмари»

Terraform: інфраструктура як код

Terraform (HashiCorp) дає змогу описувати серверну інфраструктуру у вигляді конфігураційних файлів .tf і керувати нею через CLI. Замість ручного створення серверів через вебконсоль — увесь стек у репозиторії Git.

Встановлення Terraform

wget https://releases.hashicorp.com/terraform/1.7.0/terraform_1.7.0_linux_amd64.zip
unzip terraform_1.7.0_linux_amd64.zip
mv terraform /usr/local/bin/
terraform --version

Приклад: Hetzner Cloud

# main.tf
terraform {
  required_providers {
    hcloud = {
      source  = "hetznercloud/hcloud"
      version = "~> 1.44"
    }
  }
}

provider "hcloud" {
  token = var.hcloud_token
}

# SSH-ключ
resource "hcloud_ssh_key" "default" {
  name       = "my-key"
  public_key = file("~/.ssh/id_rsa.pub")
}

# Сервер
resource "hcloud_server" "web" {
  name        = "web-01"
  image       = "ubuntu-24.04"
  server_type = "cx22"
  location    = "nbg1"
  ssh_keys    = [hcloud_ssh_key.default.id]

  user_data = <<-EOF
    #!/bin/bash
    apt update && apt install -y nginx
    systemctl enable nginx
  EOF
}

# Firewall
resource "hcloud_firewall" "web_fw" {
  name = "web-firewall"

  rule {
    direction  = "in"
    protocol   = "tcp"
    port       = "80"
    source_ips = ["0.0.0.0/0", "::/0"]
  }

  rule {
    direction  = "in"
    protocol   = "tcp"
    port       = "443"
    source_ips = ["0.0.0.0/0", "::/0"]
  }
}

resource "hcloud_firewall_attachment" "web" {
  firewall_id = hcloud_firewall.web_fw.id
  server_ids  = [hcloud_server.web.id]
}

output "server_ip" {
  value = hcloud_server.web.ipv4_address
}
# variables.tf
variable "hcloud_token" {
  sensitive = true
}
# terraform.tfvars (у .gitignore!)
hcloud_token = "your-hetzner-api-token"

Основні команди

# Ініціалізація (завантажити провайдери)
terraform init

# Перегляд плану змін
terraform plan

# Застосувати зміни
terraform apply

# Переглянути стан
terraform show
terraform state list

# Знищити інфраструктуру
terraform destroy

Кілька серверів через count

resource "hcloud_server" "app" {
  count       = 3
  name        = "app-${count.index + 1}"
  image       = "ubuntu-24.04"
  server_type = "cx22"
  location    = "nbg1"
  ssh_keys    = [hcloud_ssh_key.default.id]
}

output "app_ips" {
  value = hcloud_server.app[*].ipv4_address
}
Безпека: Ніколи не комітьте terraform.tfvars та *.tfstate до репозиторію — вони містять токени й секрети. Додайте їх до .gitignore.
Remote State: Для командної роботи зберігайте terraform.tfstate у Terraform Cloud, S3 або Hetzner Object Storage — це дає змогу кільком людям керувати однією інфраструктурою.

Розбір реальних помилок Terraform

Дві помилки майже гарантовано трапляться під час командної роботи з Terraform, і обидві пов'язані не із синтаксисом HCL, а зі станом.

Error acquiring the state lock

Error: Error acquiring the state lock

Lock Info:
  ID:        7a3f1c2e-...
  Path:      terraform.tfstate
  Operation: OperationTypeApply
  Who:       ci-runner@build-42

Хтось вже виконує apply, або попередній процес впав і не зняв блокування. Перш ніж розблоковувати, переконайтеся, що паралельного запуску справді немає — інакше ризикуєте пошкодити state. Тільки після цього: terraform force-unlock 7a3f1c2e-....

Inconsistent dependency lock file

Error: Inconsistent dependency lock file

The following dependency selections recorded in the lock file are inconsistent with the current configuration.

To update the locked dependency selections to match a change in the configuration, run: terraform init -upgrade

Версія провайдера в .terraform.lock.hcl не збігається з тією, що вказана в блоці required_providers — зазвичай після оновлення версії вручну в коді без перезбирання лока. Рішення прямо в тексті помилки: terraform init -upgrade, потім закомітити оновлений lock-файл.

Terraform проти Ansible

КритерійTerraformAnsible
МодельДекларативна, зі станом (state)Процедурна, без стану за замовчуванням
Основна задачаСтворення інфраструктури (сервери, мережі, DNS)Налаштування ОС всередині вже наявного сервера
ІдемпотентністьГарантована через порівняння зі stateЗалежить від якості написаних модулів і задач

Коли Terraform не підходить

  • Разова зміна одного сервера — повноцінний цикл plan/apply надлишковий, швидше й зрозуміліше прямий виклик API чи CLI провайдера.
  • Налаштування ПЗ всередині сервера — встановлення пакетів, шаблони конфігів, systemd-юніти. Для цього потрібен Ansible, Terraform лише створює залізо і запускає cloud-init.
  • Потрібна складна імперативна логіка з циклами і умовною обробкою помилок — декларативний HCL для цього погано пристосований.
  • Один сервер, одна команда з двох людей, інфраструктура майже ніколи не змінюється — оверхед на remote state і HCL не окупається.
  • Потрібен миттєвий відкат інфраструктури без перерахунку плану — terraform apply і destroy не транзакційні і потребують часу на виконання кожного ресурсу.

Перевірка результату

# План має бути порожнім після успішного apply — ознака ідемпотентності
terraform plan -detailed-exitcode
# exit code 0 = змін немає, 2 = є розбіжності, 1 = помилка

# Синтаксис і форматування в порядку
terraform validate
terraform fmt -check -recursive

# Звірити стан із реальністю у провайдера
terraform state list
hcloud server list

Якщо terraform plan -detailed-exitcode повертає 2 одразу після apply — десь є дрейф: або ресурс змінили вручну через вебконсоль, або провайдер сам змінив атрибут (наприклад, призначив іншу IP). Регулярно проганяйте terraform plan за розкладом, щоб такий дрейф не накопичувався непомітно.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці