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.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
| Критерій | Terraform | Ansible |
|---|---|---|
| Модель | Декларативна, зі станом (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 за розкладом, щоб такий дрейф не накопичувався непомітно.