369 lines
15 KiB
Markdown
369 lines
15 KiB
Markdown
# Начало работы с Nubes Terraform
|
||
|
||
Это руководство поможет вам установить инструменты, настроить доступ и развернуть вашу первую инфраструктуру в облаке Nubes, используя Terraform.
|
||
|
||
## 0. Установка Terraform
|
||
|
||
Для работы с инфраструктурой как кодом (IaC) потребуется утилита Terraform (версии 1.0 или выше).
|
||
|
||
1. **Скачивание**:
|
||
* Официальный сайт: [hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install)
|
||
* *Для пользователей из РФ (без VPN):* [Yandex Cloud Mirror](https://hashicorp-releases.yandexcloud.net/terraform/)
|
||
2. **Установка**:
|
||
* Распакуйте скачанный архив.
|
||
* Поместите исполняемый файл (`terraform` или `terraform.exe`) в папку, доступную в переменной окружения `PATH`.
|
||
3. **Проверка**:
|
||
* Откройте терминал (PowerShell, CMD, Bash или Terminal в macOS).
|
||
* Введите команду `terraform -version`. Вы должны увидеть номер версии.
|
||
|
||
## 1. Подготовка конфигурации
|
||
|
||
Создайте рабочую директорию для вашего проекта и создайте основной файл конфигурации `main.tf`.
|
||
|
||
```hcl title="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 стенду.
|
||
|
||
- Личный кабинет: https://deck-test.ngcloud.ru/dashboard/
|
||
- API endpoint: https://deck-api-test.ngcloud.ru/api/v1
|
||
|
||
!!! tip "Безопасность"
|
||
Никогда не храните токен прямо в файле `main.tf`, если планируете загружать код в систему контроля версий (git). Используйте `variables.tf` или файл `terraform.tfvars`.
|
||
|
||
## 2. Получение API токена
|
||
|
||
Токен (Access Token) необходим провайдеру для авторизации ваших действий в облаке.
|
||
|
||
Если нет ТОКЕНА доступа или хотите создать новый -
|
||
В Личном Кабинете - на странице Профиля пользователя https://deck.ngcloud.ru/authorization/profile
|
||
во вкладке Токены - нажать "Выпустить тех-токен"
|
||
Значение токена показывается только при его создании, надо его сохранить
|
||
|
||
Создайте файл `terraform.tfvars` и сохраните токен там:
|
||
|
||
```hcl title="terraform.tfvars"
|
||
api_token = "eyJhbGciOiJ..." # Ваш длинный токен
|
||
```
|
||
|
||
## 3. Описание ресурсов
|
||
|
||
Добавьте ресурсы, которые вы хотите создать, в файл `main.tf` или `resources.tf`.
|
||
|
||
Пример создания S3 бакета:
|
||
|
||
```hcl
|
||
resource "nubes_s3bucket" "my_files" {
|
||
resource_name = "bucket_0"
|
||
bucket_name = "my-unique-bucket-name"
|
||
s3_user_uid = "235e0546-..." # UID Корневой услуги S3
|
||
}
|
||
```
|
||
|
||
Или Postgres кластера:
|
||
|
||
```hcl
|
||
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`.
|
||
|
||
- найден `running` → `adopt`;
|
||
- найден `suspended` + обязательные параметры совпадают → `resume + adopt`.
|
||
|
||
### Важно
|
||
|
||
Один инстанс должен быть только в одном state.
|
||
|
||
Если подключить один инстанс
|
||
к двум манифестам,
|
||
получится конфликт управления:
|
||
|
||
- первый `apply` меняет ресурс;
|
||
- второй `apply` откатывает
|
||
или перезаписывает изменения.
|
||
|
||
---
|
||
|
||
Следующий шаг: изучите [Справочник по командам Terraform](terraform-basics.md) для уверенной работы.
|
||
|
||
## Примеры
|
||
|
||
### Lucee & Postgress
|
||
|
||
Lucee и NodeJS — это два отдельных UI для CRUD‑операций, оба работают с одной и той же таблицей в Postgres.
|
||
|
||
```hcl title="resources.tf"
|
||
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
|
||
|
||
```hcl title="resources.tf"
|
||
# 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"
|
||
}
|
||
```
|
||
|
||
```hcl title="variables.tf"
|
||
// 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>
|
||
}
|
||
```
|
||
|
||
```hcl title="terraform.tfvars"
|
||
# Инструкция по получению токена: раздел "Получение API токена"
|
||
api_token = "eyJhbGciOiJ..."
|
||
```
|