Files
tf_provider/docs/30_registry/guides/getting-started.md
T
2026-06-30 15:45:24 +04:00

15 KiB
Raw Blame History

Начало работы с Nubes Terraform

Это руководство поможет вам установить инструменты, настроить доступ и развернуть вашу первую инфраструктуру в облаке Nubes, используя Terraform.

0. Установка Terraform

Для работы с инфраструктурой как кодом (IaC) потребуется утилита Terraform (версии 1.0 или выше).

  1. Скачивание:
  2. Установка:
    • Распакуйте скачанный архив.
    • Поместите исполняемый файл (terraform или terraform.exe) в папку, доступную в переменной окружения PATH.
  3. Проверка:
    • Откройте терминал (PowerShell, CMD, Bash или Terminal в macOS).
    • Введите команду terraform -version. Вы должны увидеть номер версии.

1. Подготовка конфигурации

Создайте рабочую директорию для вашего проекта и создайте основной файл конфигурации main.tf.

terraform {
  required_providers {
    nubes = {
      source  = "terra.k8c.ru/nubes/nubes"
      version = "2.1.23"  # Поставьте нужную вам версию провайдера
    }
  }
}

provider "nubes" {
  api_endpoint = "https://deck-api.ngcloud.ru/api/v1/index.cfm"
  api_token = var.api_token
}

variable "api_token" {
  type      = string
  sensitive = true
}

!!! info "TEST стенд (обязательные адреса)" Эта документация относится к TEST стенду.

!!! 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. Запуск

Теперь вы готовы применить конфигурацию:

  1. Инициализация: terraform init (загружает плагин провайдера).
  2. План: terraform plan (показывает, что будет сделано).
  3. Применение: terraform apply (создает инфраструктуру).

5. Почему провайдер использует Suspend/Adopt

Для этой логики используются два флага.

  • suspend_on_destroy
  • adopt_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.

  • найден runningadopt;
  • найден 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://terra.k8c.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..."