Якщо ви працюєте з хмарою у OpenStack CLI та регулярно розгортаєте середовища з однаковими конфігураціями — краще автоматизувати цей процес за допомогою Terraform, щоб не виконувати кожен раз одні й ті самі кроки.

Terraform — це інструмент автоматизації OpenStack, який дозволяє описати параметри інфраструктури (серверів, мережі, дисків, тощо) у конфігураційному файлі, щоби потім все це діло розгортати однією командою. У цій статті розглянемо, як це працює.

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

1. Встановіть Terraform за інструкцією.

2. Перевірте версію та коректність встановлення:

terraform -version

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

У Terraform вся логіка розбита на декілька файлів. Це не обов’язково, але така структура — стандарт де-факто: вона дозволяє не змішувати ресурси, змінні та результати в одному місці.

Створіть такі чотири файли у каталозі, де плануєте розгортати середовища. Вони мають називатися так само як і у прикладі. Шаблони вмісту для кожного з файлів надаємо далі в статті.

my-project/
├── variables.tf # змінні (що можна налаштувати)
├── terraform.tfvars # значення змінних (конкретні значення)
├── main.tf # основні ресурси (що саме створюємо)
└── outputs.tf # вивід (що отримаємо на виході)

Аутентифікація

Відбувається за допомогою файлу clouds.yaml. Про те, як його налаштувати, ми розповідали в окремій статті про роботу з хмарою OpenStack через API. Служба Terraform OpenStack також використовує цей файл у своїй роботі.

Як керувати хмарою OpenStack через API

Конфігурація

Як ми вже казали, стандартна логіка роботи Terraform передбачає використання таких чотирьох файлів: variables.tf, terraform.tfvars, main.tf та outputs.tf. У цьому розділі — що має бути в кожному з них.

variables.tf

Це файл, де ви оголошуєте всі змінні, які будете використовувати. Без нього Terraform не зрозуміє, звідки брати значення.

Ось приклад вмісту файлу, в якому:

  • description — просто підказка для вас;
  • default — значення за замовчуванням (можна не задавати).

Якщо default немає — значення обов’язково треба передати через файл terraform.tfvars.

variable "cloud_name" {
description = "Профіль з clouds.yaml"
default = "openstack-ua"
}

variable "server_name" {
description = "Ім'я сервера"
default = "my-server"
}

variable "image_id" {
description = "ID образу ОС"
}

variable "flavor_id" {
description = "ID конфігурації сервера"
}

variable "network_id" {
description = "ID мережі (Public)"
}

variable "volume_size" {
description = "Розмір завантажувального диска в ГБ"
default = 50
}

variable "key_name" {
description = "Ім'я SSH-ключа"
}

variable "security_group_id" {
description = "ID існуючої security group (опціонально — якщо не задано, буде створена нова)"
default = ""

 terraform.tfvars

Тут ви вже не описуєте, а підставляєте реальні дані. Це як файл .env у звичайних проектах. Саме цей файл Terraform автоматично підхоплює при запуску. Підставте у нього реальні значення з панелі (Project → API Access) або з результатів команд:

openstack --os-cloud=openstack-nl image list
openstack --os-cloud=openstack-nl flavor list
openstack --os-cloud=openstack-nl network list
openstack --os-cloud=openstack-nl security group list
openstack --os-cloud=openstack-nl keypair list 
cloud_name        = "openstack-nl"
server_name = "my-server"
image_id = "PASTE_IMAGE_ID"
flavor_id = "PASTE_FLAVOR_ID"
network_id = "PASTE_PUBLIC_NETWORK_ID"
volume_size = 50
key_name = "PASTE_KEY_NAME"
security_group_id = "PASTE_SG_ID" 

⚠️ Нюанс: Цей файл часто містить чутливі або прив’язані до середовища дані — тому його не комітять у git. Додайте його у .gitignore.

main.tf

Це головний файл. У ньому описано ресурси, які Terraform має створити. В ньому нічого змінювати не треба, просто скопіюйте вміст як є.

terraform {
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 1.54"
}
}
}

# Провайдер — читає credentials з clouds.yaml
provider "openstack" {
cloud = var.cloud_name
}

# SSH-ключ — використовуємо наявний
data "openstack_compute_keypair_v2" "keypair" {
name = var.key_name
}

# Сервер — використовуємо існуючу security group з панелі
resource "openstack_compute_instance_v2" "server" {
name = var.server_name
flavor_id = var.flavor_id
key_pair = data.openstack_compute_keypair_v2.keypair.name

security_groups = [var.security_group_id]

# Boot from volume — обов'язково для нашої хмари
block_device {
uuid = var.image_id
source_type = "image"
destination_type = "volume"
volume_size = var.volume_size
boot_index = 0
delete_on_termination = true
}

network {
uuid = var.network_id
}

outputs.tf

Після команди terraform apply ви зазвичай хотітимете отримати не просто «успішно», а корисні дані — наприклад IP сервера. Що конкретно треба вивести — описують у цьому файлі. У нашому прикладі файлу буде виводитися ID сервера, його ім’я, публічний IP та команда для підключення за SSH.

output "server_id" {
value = openstack_compute_instance_v2.server.id
}

output "server_name" {
value = openstack_compute_instance_v2.server.name
}

output "public_ip" {
description = "Публічна IP-адреса сервера"
value = openstack_compute_instance_v2.server.access_ip_v4
}

output "ssh_command" {
description = "Команда для підключення по SSH"
value = "ssh clouduser@${openstack_compute_instance_v2.server.access_ip_v4}"
}

Базовий воркфлоу

Ось приклад типової взаємодії з Terraform після налаштування всіх необхідних файлів.

Ініціалізація (один раз)

Заходимо у каталог, де буде створюватися сервер та запускаємо Terraform:

cd my-server
terraform init 

Переглянути, що буде створено

Дивимося список ресурсів які будуть створені — без реальних змін.

terraform plan 

Розгорнути

terraform apply 

Розгортаємо конфігурацію. Terraform знову покаже план і запитає підтвердження. Після введення yes створить всі ресурси і виведе outputs:

Outputs:

public_ip = "185.91.72.xxx"
server_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
server_name = "my-server"
ssh_command = "ssh clouduser@185.91.72.xxx"

Як підключитися до хмарного VPS

Видалити все

Видалити всі ресурси які створив цей шаблон — сервер, диск, security group, тощо.

terraform destroy

Поширені питання

Ось декілька ситуацій, з якими часто стикаються користувачі Terraform.

Попередження про loadbalancer/neutron-lbaas при plan/apply — що робити? 

Ігнорувати. Це попередження стосується балансувальника навантаження, який ми не використовуємо у себе на хостингу.

 Як дізнатись IP сервера після розгортання?

Виконати команду для виведення IP:

terraform output public_ip

Або команду для підключення:

terraform output ssh_command

Як змінити розмір сервера після створення? 

Змінити flavor_id у terraform.tfvars і запустити terraform apply. У результаті Terraform видалить старий сервер та створить інший вже з новими параметрами. 

Якщо хочете змінити розмір диска без втрати даних та перестворення всього сервера, можете спробувати зробити це в панелі керування хмарою.

Як змінити характеристики хмарного VPS

Як подивитись поточний стан інфраструктури?

terraform show

Як розгорнути такий самий сервер в Україні?

Змінити у terraform.tfvars:

cloud_name = "openstack-ua"

І підставити відповідні ID ресурсів для UA регіону — image, flavor, network, security group, keypair в UA інші, ніж в NL. Отримайте їх командами:

openstack --os-cloud=openstack-ua image list
openstack --os-cloud=openstack-ua flavor list
openstack --os-cloud=openstack-ua network list
openstack --os-cloud=openstack-ua security group list
openstack --os-cloud=openstack-ua keypair list

При перемиканні між регіонами (NL → UA або навпаки) Terraform видає помилку про endpoint?

Провайдер закешував стан попереднього регіону. Треба очистити його та ініціалізувати повторно:

rm -rf .terraform .terraform.lock.hcl terraform.tfstate terraform.tfstate.backup
terraform init
terraform plan

Корисні посилання

OpenStack Terraform провайдер

Документація Terraform

Compute ресурси

Networking ресурси