15 KiB
Начало работы с Nubes Terraform
Это руководство поможет вам установить инструменты, настроить доступ и развернуть вашу первую инфраструктуру в облаке Nubes, используя Terraform.
0. Установка Terraform
Для работы с инфраструктурой как кодом (IaC) потребуется утилита Terraform (версии 1.0 или выше).
- Скачивание:
- Официальный сайт: hashicorp.com/terraform/install
- Для пользователей из РФ (без VPN): Yandex Cloud Mirror
- Установка:
- Распакуйте скачанный архив.
- Поместите исполняемый файл (
terraformилиterraform.exe) в папку, доступную в переменной окруженияPATH.
- Проверка:
- Откройте терминал (PowerShell, CMD, Bash или Terminal в macOS).
- Введите команду
terraform -version. Вы должны увидеть номер версии.
1. Подготовка конфигурации
Создайте рабочую директорию для вашего проекта и создайте основной файл конфигурации main.tf.
terraform {
required_providers {
nubes = {
source = "tf-registry.containerk8s.services.ngcloud.ru/nubes/nubes"
version = "5.0.5" # Поставьте нужную вам версию провайдера
}
}
}
provider "nubes" {
api_endpoint = "https://lk-api-gateway.ngcloud.ru/api/v1/svc"
api_token = var.api_token
}
variable "api_token" {
type = string
sensitive = true
}
!!! info "TEST стенд (обязательные адреса)" Эта документация относится к TEST стенду.
- Личный кабинет: https://deck-test.ngcloud.ru/dashboard/
- API endpoint: https://lk-api-gateway-test.ngcloud.ru/api/v1/svc
!!! tip "Безопасность"
Никогда не храните токен прямо в файле main.tf, если планируете загружать код в систему контроля версий (git). Используйте variables.tf или файл terraform.tfvars.
2. Получение API токена
Токен (Access Token) необходим провайдеру для авторизации ваших действий в облаке.
Если нет ТОКЕНА доступа или хотите создать новый - В Личном Кабинете - на странице Профиля пользователя https://deck.ngcloud.ru/authorization/profile во вкладке Токены - нажать "Выпустить тех-токен" Значение токена показывается только при его создании, надо его сохранить
Создайте файл terraform.tfvars и сохраните токен там:
api_token = "eyJhbGciOiJ..." # Ваш длинный токен
3. Описание ресурсов
Добавьте ресурсы, которые вы хотите создать, в файл main.tf или resources.tf.
Пример создания S3 бакета:
resource "nubes_s3bucket" "my_files" {
resource_name = "bucket_0"
bucket_name = "my-unique-bucket-name"
s3_user_uid = "235e0546-..." # UID Корневой услуги S3
}
Или Postgres кластера:
resource "nubes_postgres" "db" {
resource_name = "pg-tst0"
resource_realm = "k8s-3.ext.nubes.ru" # Платформа развертывания
s3_uid = "235e0546-..." # UUID услуги S3 для бэкапов
resource_c_p_u = 2000 # 2 vCPU (в милликорах)
resource_memory = 4096 # 4 GB (в МБ)
resource_disk = "20" # 20 GB
resource_instances = 1
}
Подробные примеры конфигураций смотрите в разделе Resources документации.
4. Запуск
Теперь вы готовы применить конфигурацию:
- Инициализация:
terraform init(загружает плагин провайдера). - План:
terraform plan(показывает, что будет сделано). - Применение:
terraform apply(создает инфраструктуру).
5. Почему провайдер использует Suspend/Adopt
Для этой логики используются два флага.
suspend_on_destroyadopt_existing_on_create
suspend_on_destroy
true(по умолчанию)- при
terraform destroyинстанс уходит вSuspend; - при удалении ресурса из манифеста — тоже
Suspend.
- при
false- Terraform удаляет ресурс только из state;
- в облаке инстанс не меняется.
adopt_existing_on_create
false(по умолчанию)- если инстанс уже существует, Terraform вернёт ошибку.
true- Terraform может взять существующий инстанс под управление.
Как это связано с terraform import
Это похоже на terraform import,
но срабатывает в обычном apply.
- найден
running→adopt; - найден
suspended+ обязательные параметры совпадают →resume + adopt.
Важно
Один инстанс должен быть только в одном state.
Если подключить один инстанс к двум манифестам, получится конфликт управления:
- первый
applyменяет ресурс; - второй
applyоткатывает или перезаписывает изменения.
Следующий шаг: изучите Справочник по командам Terraform для уверенной работы.
Примеры
Lucee & Postgress
Lucee и NodeJS — это два отдельных UI для CRUD‑операций, оба работают с одной и той же таблицей в Postgres.
resource "nubes_postgres" "db2" {
# Основной Postgres-кластер для демо.
resource_name = "pg-tst0"
s3_uid = "235e0546-..."
resource_realm = "k8s-3.ext.nubes.ru" # Платформа развертывания
resource_instances = 1
resource_memory = 512
resource_c_p_u = 500
resource_disk = "1"
app_version = "17"
json_parameters = jsonencode({
# Выключаем подробные логи подключений в демо.
log_connections = "off"
log_disconnections = "off"
})
enable_pg_pooler_master = false
enable_pg_pooler_slave = false
allow_no_s_s_l = false
auto_scale = false
auto_scale_percentage = 10
auto_scale_tech_window = 0
auto_scale_quota_gb = "1"
need_external_address_master = false
}
resource "nubes_lucee" "app1" {
# Lucee UI, который читает/пишет в Postgres.
resource_name = "lucy1"
resource_realm = nubes_postgres.db2.resource_realm
domain = "web03" # Пример домена приложения
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/testlucee.git"
json_env = jsonencode({
# JDBC datasource для Lucee.
testds_class = "org.postgresql.Driver"
testds_bundleName = "org.postgresql.jdbc"
testds_bundleVersion = "42.6.0"
testds_connectionString = "jdbc:postgresql://${nubes_postgres.db2.state_out_flat["internalConnect.master"]}:5432/postgres"
testds_username = nubes_postgres.db2.vault_secrets["adminUser"]
testds_password = nubes_postgres.db2.vault_secrets["adminPass"]
testds_connectionLimit = "5"
testds_liveTimeout = "15"
testds_validate = "false"
})
resource_c_p_u = 300
resource_memory = 512
resource_instances = 1
app_version = "5.4"
depends_on = [nubes_postgres.db2]
}
resource "nubes_nodejs" "app3" {
# NodeJS демо, работающий с тем же Postgres.
resource_name = "node_0"
resource_realm = nubes_postgres.db2.resource_realm
domain = "node"
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/testnode.git"
health_path = "/healthz"
app_version = "23"
json_env = jsonencode({
# Переменные подключения к Postgres.
PGHOST = nubes_postgres.db2.state_out_flat["internalConnect.master"]
PGPORT = "5432"
PGUSER = nubes_postgres.db2.vault_secrets["adminUser"]
PGPASSWORD = nubes_postgres.db2.vault_secrets["adminPass"]
PGSSLMODE = "require"
DATABASE_URL = format(
"postgresql://%s:%s@%s:5432/postgres",
nubes_postgres.db2.vault_secrets["adminUser"],
nubes_postgres.db2.vault_secrets["adminPass"],
nubes_postgres.db2.state_out_flat["internalConnect.master"]
)
})
resource_c_p_u = 300
resource_memory = 256
resource_instances = 1
depends_on = [nubes_postgres.db2]
}
Пример (PROD_STAND/RABBIT)
Ниже полный пример resources.tf для RabbitMQ + Lucee UI + NodeJS воркера.
Комментарий: UI Lucee отправляет CRUD‑запросы в RabbitMQ, а применение изменений в Postgres выполняет отдельный воркер на NodeJS. Сервис Postgres должен быть запущен заранее. В данном примере используется Postgres из раздела https://tf-registry.containerk8s.services.ngcloud.ru/docs/nubes/nubes/2.1.7/30_registry/guides/getting-started/#lucee-postgress
# RabbitMQ кластер для демо.
resource "nubes_rabbitmq" "rb1" {
resource_name = "rabbit_0"
resource_realm = "k8s-3.ext.nubes.ru"
resource_instances = 1
resource_memory = 512
resource_c_p_u = 500
resource_disk = 5
need_external_address_master = false
need_external_address_slave = false
}
# Lucee UI, который пишет в Rabbit и читает из Postgres.
resource "nubes_lucee" "rabbit_ui" {
resource_name = "rb-lucee-ui"
resource_realm = "k8s-3.ext.nubes.ru"
domain = "rb-ui"
app_version = "5.4"
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/rabbit-lsd"
resource_c_p_u = 300
resource_memory = 512
resource_instances = 1
# Переменные окружения для datasource, Rabbit и UI.
json_env = jsonencode({
testds_bundleName = "org.postgresql.jdbc"
testds_bundleVersion = "42.6.0"
testds_class = "org.postgresql.Driver"
testds_connectionLimit = "5"
testds_connectionString = "jdbc:postgresql://${var.PGHOST}:5432/postgres"
testds_liveTimeout = "15"
testds_username = var.PGUSER
testds_password = var.PGPASSWORD
testds_validate = "false"
PG_TABLE = "rabbit_messages"
UI_LOG_TABLE = "rabbit_ui_log"
RABBIT_HOST = try(nubes_rabbitmq.rb1.state_out_flat["internalConnect.master"], nubes_rabbitmq.rb1.state_out_flat["inernalConnect.master"])
RABBIT_PORT = "5672"
RABBIT_USER = nubes_rabbitmq.rb1.vault_secrets["adminUser"]
RABBIT_PASSWORD = nubes_rabbitmq.rb1.vault_secrets["adminPass"]
RABBIT_VHOST = "/"
RABBIT_QUEUES = "crud_queue"
RABBIT_DURABLE = "true"
RABBIT_ADMIN_URL = "https://${nubes_rabbitmq.rb1.state_out_flat["externalConnect.admin.fqdn"]}/#/"
NODEWORKER_URL = "https://nodeworker.nodejsk8s.services.ngcloud.ru/"
})
depends_on = [nubes_rabbitmq.rb1]
}
# NodeJS воркер, который переносит CRUD из очереди в Postgres.
resource "nubes_nodejs" "rabbit_nodeworker" {
resource_name = "nodeworker"
resource_realm = "k8s-3.ext.nubes.ru"
domain = "nodeworker"
app_version = "23"
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/rabbit-nodeworker.git"
health_path = "/healthz"
resource_c_p_u = 100
resource_memory = 256
resource_instances = 1
# Параметры подключения к Rabbit и Postgres.
json_env = jsonencode({
RABBIT_HOST = try(nubes_rabbitmq.rb1.state_out_flat["internalConnect.master"], nubes_rabbitmq.rb1.state_out_flat["inernalConnect.master"])
RABBIT_PORT = "5672"
RABBIT_USER = nubes_rabbitmq.rb1.vault_secrets["adminUser"]
RABBIT_PASSWORD = nubes_rabbitmq.rb1.vault_secrets["adminPass"]
RABBIT_VHOST = "/"
RABBIT_QUEUES = "crud_queue"
RABBIT_DURABLE = "true"
RABBIT_PREFETCH = "1"
REQUEUE_ON_ERROR = "true"
PGHOST = var.PGHOST
PGPORT = "5432"
PGUSER = var.PGUSER
PGPASSWORD = var.PGPASSWORD
PGDATABASE = "postgres"
PGSSLMODE = "require"
PG_TABLE = "rabbit_messages"
})
depends_on = [nubes_rabbitmq.rb1]
}
# Ручной триггер redeploy для воркера.
resource "nubes_nodejs_redeploy" "rabbit_nodeworker_redeploy" {
nodejs_id = nubes_nodejs.rabbit_nodeworker.id
resource_realm = "k8s-3.ext.nubes.ru"
run_id = "redeploy-2026-02-23-011"
}
// Postgres уже запущен, значения берутся из UI Личного кабинета.
variable "PGUSER" {
type = string
default = "postgres"
}
variable "PGPASSWORD" {
type = string
default = "" # пароль укажите вручную, в примере не публикуем
}
variable "PGHOST" {
type = string
default = "postgresqlk8s-master.<id>.svc.k8s-3.ext.nubes.ru" # оставьте префикс и суффикс, меняется только <id>
}
# Инструкция по получению токена: раздел "Получение API токена"
api_token = "eyJhbGciOiJ..."