From 5511546534bd97782c58e757e1af4df65ac3a869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Wed, 22 Jul 2026 10:19:24 +0400 Subject: [PATCH] =?UTF-8?q?IoT=20Demo:=20Terraform-=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=84=D0=B8=D0=B3=20=D0=B4=D0=BB=D1=8F=206=20=D1=81=D0=B5?= =?UTF-8?q?=D1=80=D0=B2=D0=B8=D1=81=D0=BE=D0=B2=20Nubes=20Cloud?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Producer -> RabbitMQ -> Consumer -> Redis+MongoDB -> Dashboard Подробная инструкция в README.md: - Что заменить в locals.tf (домены, git_path, ресурсы) - Как заполнить terraform.tfvars - Как форкнуть репо приложений --- iot-rmq-demo/README.md | 127 ++++++++++++++++++++++++++ iot-rmq-demo/consumer.tf | 65 +++++++++++++ iot-rmq-demo/dashboard.tf | 47 ++++++++++ iot-rmq-demo/infra.tf | 84 +++++++++++++++++ iot-rmq-demo/locals.tf | 61 +++++++++++++ iot-rmq-demo/main.tf | 52 +++++++++++ iot-rmq-demo/producer.tf | 52 +++++++++++ iot-rmq-demo/terraform.tfvars.example | 18 ++++ 8 files changed, 506 insertions(+) create mode 100644 iot-rmq-demo/README.md create mode 100644 iot-rmq-demo/consumer.tf create mode 100644 iot-rmq-demo/dashboard.tf create mode 100644 iot-rmq-demo/infra.tf create mode 100644 iot-rmq-demo/locals.tf create mode 100644 iot-rmq-demo/main.tf create mode 100644 iot-rmq-demo/producer.tf create mode 100644 iot-rmq-demo/terraform.tfvars.example diff --git a/iot-rmq-demo/README.md b/iot-rmq-demo/README.md new file mode 100644 index 0000000..06b6895 --- /dev/null +++ b/iot-rmq-demo/README.md @@ -0,0 +1,127 @@ +# IoT Demo — Nubes Cloud + +Разворачивание демо-стенда «Умный дом» из 6 сервисов Nubes Cloud через Terraform. + +## Архитектура + +``` +Producer (Node.js) → RabbitMQ → Consumer (Node.js) → Redis + MongoDB → Dashboard (Node.js + Chart.js) +``` + +| Сервис | Тип Nubes | Роль | +|---|---|---| +| `iot-rmq` | RabbitMQ | Очередь сообщений | +| `iot-rds` | Redis | Кэш дашборда | +| `iot-mgo` | MongoDB | Постоянный архив | +| `iot-prod` | Node.js (22) | Генератор IoT-событий | +| `iot-cons` | Node.js (22) | Обработчик очереди | +| `iot-dash` | Node.js (22) | Веб-дашборд | + +## Быстрый старт + +### 1. Подготовка + +```bash +# Склонируйте репозиторий +git clone <этот-репо> / cd tf_examples/iot-rmq-demo + +# Скопируйте и заполните переменные +cp terraform.tfvars.example terraform.tfvars +``` + +### 2. Что обязательно ЗАМЕНИТЬ в `locals.tf` + +Файл `locals.tf` — центральное место всех настроек. Откройте и измените: + +| Параметр | Где | Что писать | Пример | +|---|---|---|---| +| `prod_git_path` | locals.tf | URL **вашего** форка producer в Gitea | `https://gitea.../МОЙ_ЛОГИН/tf-iot-producer.git` | +| `cons_git_path` | locals.tf | URL **вашего** форка consumer | `https://gitea.../МОЙ_ЛОГИН/tf-iot-consumer.git` | +| `dash_git_path` | locals.tf | URL **вашего** форка dashboard | `https://gitea.../МОЙ_ЛОГИН/tf-iot-dashboard.git` | +| `prod_domain` | locals.tf | **Уникальный** поддомен для producer | `my-iot-prod` | +| `cons_domain` | locals.tf | **Уникальный** поддомен для consumer | `my-iot-cons` | +| `dash_domain` | locals.tf | **Уникальный** поддомен для dashboard | `my-iot-dash` | +| `prod_resource_name` | locals.tf | Имя инстанса в кабинете Nubes | `my-iot-prod` | +| `cons_resource_name` | locals.tf | Имя инстанса | `my-iot-cons` | +| `dash_resource_name` | locals.tf | Имя инстанса | `my-iot-dash` | + +> **⚠️ ВАЖНО про домены:** домены (поддомены `.nodejsk8s.dev.nubes.ru`) должны быть **уникальными** в рамках кластера. Если домен уже занят — деплой упадёт с ошибкой. Придумайте свои: `myproject-prod`, `demo-iot-cons`, etc. + +### 3. Что заполнить в `terraform.tfvars` + +```hcl +api_token = "xxx" # API-токен из ЛК Nubes +realm = "k8s-4-sandbox-nubes-ru" # Ваш K8s-кластер +api_endpoint = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" # test или prod +``` + +### 4. Форкнуть репозитории приложений + +Код приложений лежит в [`apps/`](../../apps/). Каждое приложение — отдельный Git-репо. + +**Порядок действий для каждого из трёх приложений (producer, consumer, dashboard):** + +```bash +cd apps/iot-producer # (или iot-consumer, iot-dashboard) + +# Создать репо в своём Gitea +# https://gitea.services.ngcloud.ru → Новый репозиторий → tf-iot-producer + +git remote add my https://gitea.services.ngcloud.ru/МОЙ_ЛОГИН/tf-iot-producer.git +git push my main + +# Скопировать хеш последнего коммита: +git rev-parse HEAD +``` + +Полученный хеш вставить в `locals.tf` → `prod_git_revision` (и аналогично для consumer/dashboard). Или просто указать `"main"` — тогда Nubes будет деплоить последний коммит ветки. + +### 5. Деплой + +```bash +terraform init +terraform plan # проверить что всё ok +terraform apply # развернуть (≈3–5 минут) +``` + +### 6. Проверка + +```bash +# Producer — отправил ли события? +curl https://.nodejsk8s.dev.nubes.ru +# → {"events_sent": 150, "errors": 0} + +# Consumer — обработал ли? +curl https://.nodejsk8s.dev.nubes.ru +# → {"consumed": 150, "errors": 0} + +# Dashboard — открыть в браузере: +# https://.nodejsk8s.dev.nubes.ru +``` + +## Файлы + +| Файл | Назначение | +|---|---| +| `main.tf` | Провайдер, переменные | +| `locals.tf` | **Все настройки** — менять здесь | +| `infra.tf` | RabbitMQ + Redis + MongoDB | +| `producer.tf` | Node.js producer | +| `consumer.tf` | Node.js consumer | +| `dashboard.tf` | Node.js dashboard | +| `terraform.tfvars.example` | Шаблон секретов | + +## Примечания + +- **MongoDB без пароля** — для демо-стенда. В продакшене настроить аутентификацию. +- **`adopt_existing_on_create = true`** — позволяет повторный `apply` без удаления старых инстансов. +- **`suspend_on_destroy = true`** — при `destroy` инстансы не удаляются, а засыпают (suspend). +- Все внутренние соединения — через K8s Service (`.svc.cluster.local`), трафик не выходит наружу. + +## Репозитории приложений + +| Приложение | Репо (шаблон) | Описание | +|---|---|---| +| Producer | [`apps/iot-producer`](../../apps/iot-producer) | Node.js + amqplib | +| Consumer | [`apps/iot-consumer`](../../apps/iot-consumer) | Node.js + amqplib + redis + mongodb | +| Dashboard | [`apps/iot-dashboard`](../../apps/iot-dashboard) | Node.js + express + redis + Chart.js | diff --git a/iot-rmq-demo/consumer.tf b/iot-rmq-demo/consumer.tf new file mode 100644 index 0000000..63c3250 --- /dev/null +++ b/iot-rmq-demo/consumer.tf @@ -0,0 +1,65 @@ +# ============================================================================= +# Consumer (Node.js) — читает RabbitMQ, сохраняет в Redis + MongoDB +# Использует amqplib для AMQP-подключения к RabbitMQ +# ============================================================================= + +locals { + # Подключение к RabbitMQ (AMQP, порт 5672) + cons_rmq_host = nubes_rabbitmq.main.state_out_flat["internalConnect"] # K8s-хост + cons_rmq_user = nonsensitive(nubes_rabbitmq.main.vault_secrets["adminUser"]) # логин + cons_rmq_pass = nonsensitive(nubes_rabbitmq.main.vault_secrets["adminPass"]) # пароль + + # Подключение к Redis (порт 6379) + cons_rds_host = nubes_redis.main.state_out_flat["internalConnect.master"] # K8s-хост + cons_rds_pass = nonsensitive(nubes_redis.main.vault_secrets["adminPass"]) # пароль + + # Подключение к MongoDB (порт 27017) — без аутентификации (vault пустой) + cons_mgo_host = nubes_mongodb.main.state_out_flat["internalConnect"] # K8s-хост + cons_mgo_user = "admin" # дефолтный пользователь + cons_mgo_pass = "" # без пароля +} + +resource "nubes_nodejs" "consumer" { + resource_name = local.cons_resource_name # имя в личном кабинете + + startup_configuration = { + resource_realm = var.realm # K8s-кластер + } + + cluster_configuration = { + cpu = local.cons_cpu # CPU millicores + memory = local.cons_memory # память MB + replicas = local.cons_replicas # количество подов + } + + access_configuration = { + domain = local.cons_domain # поддомен для HTTP + } + + app_configuration = { + version = "22" # версия Node.js + git_path = local.cons_git_path # Git-репо с кодом + health_path = "/" # health-check эндпоинт + } + + git_revision = local.cons_git_revision # коммит для деплоя + operation_timeout = local.cons_timeout # таймаут + adopt_existing_on_create = true # подхватить suspended инстанс при повторном apply + + # Переменные окружения для K8s пода + json_env = jsonencode({ + RMQ_HOST = local.cons_rmq_host # хост RabbitMQ + RMQ_PORT = "5672" # порт AMQP + RMQ_USER = local.cons_rmq_user # логин RabbitMQ + RMQ_PASS = local.cons_rmq_pass # пароль RabbitMQ + RMQ_QUEUE = local.rmq_queue # имя очереди + REDIS_HOST = local.cons_rds_host # хост Redis + REDIS_PORT = "6379" # порт Redis + REDIS_PASS = local.cons_rds_pass # пароль Redis + MONGO_URI = "mongodb://${local.cons_mgo_user}:${local.cons_mgo_pass}@${local.cons_mgo_host}:27017/iot?authSource=admin" + MONGO_DB = "iot" # имя базы MongoDB + }) + + # Ждать создания всех трёх сервисов + depends_on = [nubes_rabbitmq.main, nubes_redis.main, nubes_mongodb.main] +} diff --git a/iot-rmq-demo/dashboard.tf b/iot-rmq-demo/dashboard.tf new file mode 100644 index 0000000..c5457ce --- /dev/null +++ b/iot-rmq-demo/dashboard.tf @@ -0,0 +1,47 @@ +# ============================================================================= +# Dashboard (Node.js + Chart.js) — читает Redis, показывает графики +# API: /api/latest, /api/counters, /api/recent +# ============================================================================= + +locals { + # Подключение к Redis (только чтение) + dash_rds_host = nubes_redis.main.state_out_flat["internalConnect.master"] # K8s-хост Redis + dash_rds_pass = nonsensitive(nubes_redis.main.vault_secrets["adminPass"]) # пароль Redis +} + +resource "nubes_nodejs" "dashboard" { + resource_name = local.dash_resource_name # имя в личном кабинете + + startup_configuration = { + resource_realm = var.realm # K8s-кластер + } + + cluster_configuration = { + cpu = local.dash_cpu # CPU millicores + memory = local.dash_memory # память MB + replicas = local.dash_replicas # количество подов + } + + access_configuration = { + domain = local.dash_domain # поддомен -> iotdash22.nodejsk8s.dev.nubes.ru + } + + app_configuration = { + version = "22" # версия Node.js + git_path = local.dash_git_path # Git-репо с кодом + health_path = "/" # health-check + } + + git_revision = local.dash_git_revision # коммит для деплоя + operation_timeout = local.dash_timeout # таймаут + adopt_existing_on_create = true # подхватить suspended инстанс при повторном apply + + # Переменные окружения + json_env = jsonencode({ + REDIS_HOST = local.dash_rds_host # хост Redis + REDIS_PORT = "6379" # порт Redis + REDIS_PASS = local.dash_rds_pass # пароль Redis + }) + + depends_on = [nubes_redis.main] # ждать создания Redis +} diff --git a/iot-rmq-demo/infra.tf b/iot-rmq-demo/infra.tf new file mode 100644 index 0000000..8966b62 --- /dev/null +++ b/iot-rmq-demo/infra.tf @@ -0,0 +1,84 @@ +# ============================================================================= +# Инфраструктурные сервисы (создаются первым прогоном apply) +# RabbitMQ (очередь) + Redis (кэш) + MongoDB (архив) +# ============================================================================= + +# --- RabbitMQ: очередь сообщений (сервис 93) --- +# state_out_flat["internalConnect"] = K8s-хост (service.cluster.local) +# vault_secrets["adminUser"] / ["adminPass"] = логин/пароль (прямые строки, не JSON) +resource "nubes_rabbitmq" "main" { + resource_name = local.rmq_resource_name # имя в личном кабинете + + startup_configuration = { # на каком K8s-кластере развернуть + resource_realm = var.realm + } + + cluster_configuration = { # ресурсы пода + cpu = local.rmq_cpu # CPU millicores + memory = local.rmq_memory # память MB + disk = local.rmq_disk # диск GB + replicas = local.rmq_replicas # количество нод + } + + access_configuration = { # сетевой доступ + master_ip_space = "no-needed" # не резервировать внешний IP + master_access_list = jsonencode(["10.0.0.0/8"]) # внутренняя сеть K8s + } + + operation_timeout = local.rmq_timeout # макс. время ожидания + adopt_existing_on_create = true # подхватить suspended инстанс при повторном apply +} + +# --- Redis: кэш дашборда (сервис 91) --- +# state_out_flat["internalConnect.master"] = хост +# vault_secrets["adminPass"] = пароль (прямая строка, не JSON) +resource "nubes_redis" "main" { + resource_name = local.rds_resource_name # имя в личном кабинете (rds = ReDiS) + + startup_configuration = { # на каком K8s-кластере + resource_realm = var.realm + } + + cluster_configuration = { # ресурсы пода + cpu = local.rds_cpu # CPU millicores + memory = local.rds_memory # память MB + disk = local.rds_disk # диск GB + replicas = local.rds_replicas # количество нод + } + + access_configuration = { # сетевой доступ + master_ip_space = "no-needed" # не резервировать внешний IP + master_access_list = jsonencode(["10.0.0.0/8"]) # разрешить всю внутреннюю сеть K8s + slave_ip_space = "no-needed" # slave-нода не нужна + slave_access_list = jsonencode([]) # slave-нода не нужна + } + + operation_timeout = local.rds_timeout # макс. время ожидания операций + adopt_existing_on_create = true # подхватить suspended инстанс при повторном apply +} + +# --- MongoDB: архив событий (сервис 92) --- +# state_out_flat["internalConnect"] = хост +# vault_secrets — пустой (нет дефолтных пользователей), подключаемся без пароля +resource "nubes_mongodb" "main" { + resource_name = local.mgo_resource_name # имя в личном кабинете (mgo = MonGO) + + startup_configuration = { # на каком K8s-кластере + resource_realm = var.realm + } + + cluster_configuration = { # ресурсы пода + cpu = local.mgo_cpu # CPU millicores + memory = local.mgo_memory # память MB + disk = local.mgo_disk # диск GB + replicas = local.mgo_replicas # количество нод + } + + access_configuration = { # сетевой доступ + master_ip_space = "no-needed" # не резервировать внешний IP + master_access_list = jsonencode(["10.0.0.0/8"]) # разрешить всю внутреннюю сеть K8s + } + + operation_timeout = local.mgo_timeout # макс. время ожидания + adopt_existing_on_create = true # подхватить suspended инстанс при повторном apply +} diff --git a/iot-rmq-demo/locals.tf b/iot-rmq-demo/locals.tf new file mode 100644 index 0000000..186f786 --- /dev/null +++ b/iot-rmq-demo/locals.tf @@ -0,0 +1,61 @@ +# ============================================================================= +# Общие переменные для всех ресурсов демо-стенда IoT +# Пайплайн: Producer -> RabbitMQ -> Consumer -> Redis+MongoDB -> Dashboard +# Все значения вынесены сюда — в ресурсах хардкода нет +# ============================================================================= +locals { + # --- RabbitMQ: очередь сообщений (сервис 93) --- + rmq_resource_name = "iot-rmq" # имя инстанса в личном кабинете Nubes + rmq_cpu = 300 # CPU в millicores (1000 = 1 ядро) + rmq_memory = 512 # память в MB + rmq_disk = 5 # диск в GB + rmq_replicas = 1 # количество реплик (нод) + rmq_timeout = "11m" # таймаут ожидания операций create/modify + rmq_queue = "iot-events" # имя очереди: producer кладёт, consumer забирает + + # --- Redis: кэш дашборда (сервис 91) --- + rds_resource_name = "iot-rds" # имя инстанса (rds = ReDiS) + rds_cpu = 300 # CPU millicores + rds_memory = 512 # память MB + rds_disk = 5 # диск GB + rds_replicas = 1 # реплик (нод) + rds_timeout = "11m" # таймаут операций + + # --- MongoDB: архив всех событий (сервис 92) --- + mgo_resource_name = "iot-mgo" # имя инстанса (mgo = MonGO) + mgo_cpu = 300 # CPU millicores + mgo_memory = 512 # память MB + mgo_disk = 5 # диск GB + mgo_replicas = 1 # реплик (нод) + mgo_timeout = "11m" # таймаут операций + + # --- Producer (Node.js): генерирует IoT-события -> RabbitMQ --- + prod_resource_name = "iot-prod" # имя инстанса в личном кабинете + prod_domain = "iot-prod" # поддомен (станет .nodejsk8s.dev.nubes.ru) + prod_git_path = "https://gitea.services.ngcloud.ru/ВАШ_ЛОГИН/tf-iot-producer.git" # ⚠️ замените на свой форк + prod_git_revision = "main" # ветка или хеш коммита для деплоя + prod_cpu = 300 # CPU millicores + prod_memory = 256 # память MB + prod_replicas = 1 # количество подов + prod_timeout = "11m" # таймаут операций + + # --- Consumer (Node.js): RabbitMQ -> Redis + MongoDB --- + cons_resource_name = "iot-cons" # имя инстанса в личном кабинете + cons_domain = "iot-cons" # поддомен (станет .nodejsk8s.dev.nubes.ru) + cons_git_path = "https://gitea.services.ngcloud.ru/ВАШ_ЛОГИН/tf-iot-consumer.git" # ⚠️ замените на свой форк + cons_git_revision = "main" # ветка или хеш коммита для деплоя + cons_cpu = 300 # CPU millicores + cons_memory = 256 # память MB + cons_replicas = 1 # количество подов + cons_timeout = "11m" # таймаут операций + + # --- Dashboard (Node.js + Chart.js): Redis -> графики --- + dash_resource_name = "iot-dash" # имя инстанса в личном кабинете + dash_domain = "iot-dash" # поддомен (станет .nodejsk8s.dev.nubes.ru) + dash_git_path = "https://gitea.services.ngcloud.ru/ВАШ_ЛОГИН/tf-iot-dashboard.git" # ⚠️ замените на свой форк + dash_git_revision = "main" # ветка или хеш коммита для деплоя + dash_cpu = 300 # CPU millicores + dash_memory = 256 # память MB + dash_replicas = 1 # количество подов + dash_timeout = "11m" # таймаут операций +} diff --git a/iot-rmq-demo/main.tf b/iot-rmq-demo/main.tf new file mode 100644 index 0000000..7caf437 --- /dev/null +++ b/iot-rmq-demo/main.tf @@ -0,0 +1,52 @@ +# ============================================================================= +# Terraform-конфиг: IoT Demo на Nubes Cloud +# ============================================================================= +# 6 сервисов: RabbitMQ, Redis, MongoDB, 3× Node.js +# Пайплайн: Producer → RabbitMQ → Consumer → Redis + MongoDB → Dashboard +# +# Требования: +# - Nubes Cloud CLI (провайдер registry.kube5s.ru) +# - API-токен из личного кабинета +# - Заполненный terraform.tfvars (см. terraform.tfvars.example) +# +# Быстрый старт: +# 1. Скопировать terraform.tfvars.example → terraform.tfvars +# 2. Заполнить api_token, realm, api_endpoint +# 3. Форкнуть репозитории приложений в свой Gitea (см. README.md) +# 4. Обновить git_path и git_revision в locals.tf +# 5. terraform init && terraform apply +# ============================================================================= + +terraform { + required_providers { + nubes = { + source = "registry.kube5s.ru/nubes-test/nubes" # реестр провайдера Nubes + version = "5.1.16" # версия провайдера + } + } +} + +# API-токен для доступа к Nubes Cloud (из личного кабинета) +variable "api_token" { + type = string + sensitive = true # не показывать в логах/плане +} + +# K8s-кластер (realm) для развёртывания (например: k8s-4-sandbox-nubes-ru) +variable "realm" { + type = string +} + +# API-эндпоинт Nubes Cloud: +# Тестовый: https://lk-api-gateway-test.ngcloud.ru/api/v1/svc +# Боевой: https://lk-api-gateway.ngcloud.ru/api/v1/svc +variable "api_endpoint" { + type = string + default = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" +} + +# Конфигурация провайдера Nubes +provider "nubes" { + api_token = var.api_token + api_endpoint = var.api_endpoint +} diff --git a/iot-rmq-demo/producer.tf b/iot-rmq-demo/producer.tf new file mode 100644 index 0000000..97ec455 --- /dev/null +++ b/iot-rmq-demo/producer.tf @@ -0,0 +1,52 @@ +# ============================================================================= +# Producer (Node.js) — генерирует IoT-события и шлёт в RabbitMQ +# Каждые 3 сек создаёт случайное событие от одного из 8 датчиков +# Переменные окружения попадают в K8s под через json_env +# ============================================================================= + +locals { + # Достаём реальные значения из созданного RabbitMQ (state_out_flat + vault_secrets) + prod_rmq_host = nubes_rabbitmq.main.state_out_flat["internalConnect"] # K8s-хост RabbitMQ + prod_rmq_user = nonsensitive(nubes_rabbitmq.main.vault_secrets["adminUser"]) # логин RabbitMQ + prod_rmq_pass = nonsensitive(nubes_rabbitmq.main.vault_secrets["adminPass"]) # пароль RabbitMQ +} + +resource "nubes_nodejs" "producer" { + resource_name = local.prod_resource_name # имя в личном кабинете + + startup_configuration = { + resource_realm = var.realm # K8s-кластер + } + + cluster_configuration = { + cpu = local.prod_cpu # CPU millicores + memory = local.prod_memory # память MB + replicas = local.prod_replicas # количество подов + } + + access_configuration = { + domain = local.prod_domain # поддомен для HTTP-доступа + } + + app_configuration = { + version = "22" # версия Node.js + git_path = local.prod_git_path # Git-репо с кодом + health_path = "/" # эндпоинт для health-check'а + } + + git_revision = local.prod_git_revision # коммит для деплоя + operation_timeout = local.prod_timeout # таймаут + adopt_existing_on_create = true # подхватить suspended инстанс при повторном apply + + # Переменные окружения в K8s поде (доступны через process.env) + json_env = jsonencode({ + RABBIT_HOST = local.prod_rmq_host # хост RabbitMQ + RABBIT_PORT = "5672" # порт AMQP + RABBIT_USER = local.prod_rmq_user # логин + RABBIT_PASS = local.prod_rmq_pass # пароль + RABBIT_QUEUE = local.rmq_queue # имя очереди + PRODUCE_INTERVAL = "3" # интервал между событиями (сек) + }) + + depends_on = [nubes_rabbitmq.main] # ждать создания RabbitMQ +} diff --git a/iot-rmq-demo/terraform.tfvars.example b/iot-rmq-demo/terraform.tfvars.example new file mode 100644 index 0000000..831d762 --- /dev/null +++ b/iot-rmq-demo/terraform.tfvars.example @@ -0,0 +1,18 @@ +# ============================================================================= +# terraform.tfvars — переменные для IoT Demo +# Скопируйте этот файл: cp terraform.tfvars.example terraform.tfvars +# и заполните значения ниже. +# ============================================================================= + +# API-токен из личного кабинета Nubes Cloud +# (Настройки → API-ключи → Создать) +api_token = "ВАШ_API_ТОКЕН" + +# K8s-кластер для развёртывания +# (например: k8s-4-sandbox-nubes-ru — тестовый кластер) +realm = "ВАШ_REALM" + +# API-эндпоинт (раскомментируйте нужный): +# Тест: https://lk-api-gateway-test.ngcloud.ru/api/v1/svc +# Прод: https://lk-api-gateway.ngcloud.ru/api/v1/svc +# api_endpoint = "https://lk-api-gateway.ngcloud.ru/api/v1/svc"