From f7d6eb46883c9960936f03b0922473e5a1a369aa Mon Sep 17 00:00:00 2001 From: Repinoid Date: Thu, 1 Oct 2026 08:21:08 +0300 Subject: [PATCH] =?UTF-8?q?feat(test-stand):=20TEST=5FSTAND/FPipeGmail=20?= =?UTF-8?q?=E2=80=94=20=D0=BA=D0=BE=D0=BF=D0=B8=D1=8F=20dev-=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BC=D0=B5=D1=80=D0=B0=20=D0=BF=D0=BE=D0=B4=20test-?= =?UTF-8?q?=D1=81=D1=82=D0=B5=D0=BD=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Создана папка (без .terraform/state/lock — это состояние dev). Изменены параметры: - versions.tf: nubes-dev/nubes 2.0.1 -> nubes-test/nubes 3.0.0; - variables.tf: api_endpoint -> lk-api-gateway-test.ngcloud.ru; - terraform.tfvars: organization=NaeelOrg (найдена через API, svc 19), ip_count=10 (в test на орге уже выделено 10 IP), storage SSD (в test vDC строят на SSD); - shturval.tf: shturval-test1 / shturval-test-01 / workers-shturval-test. Коллизии проверены: в test заняты naeel-vdc, 'VDC для кластера iot-naeel', naeel_vc_nsxt, 'Edge для кластера IOT naeel', 'Кластер Kubernetes [iot-naeel]' — наши имена (fullpipe-vdc/-edge/-vapp-02, web02, shturval-test1) свободны. Проверено: terraform init (3.0.0), fmt -check OK, validate Success, plan = 7 to add / 0 change / 0 destroy. apply НЕ запускался. Документация: HISTORY/2026-10-01_test_stand_fpipegmail.md --- HISTORY/2026-10-01_test_stand_fpipegmail.md | 79 ++++++++ TEST_STAND/FPipeGmail/edge.tf | 28 +++ TEST_STAND/FPipeGmail/modifiers.tf | 60 ++++++ TEST_STAND/FPipeGmail/outputs.tf | 29 +++ TEST_STAND/FPipeGmail/provider.tf | 4 + TEST_STAND/FPipeGmail/shturval.tf | 161 +++++++++++++++ .../FPipeGmail/terraform.tfvars.example | 24 +++ TEST_STAND/FPipeGmail/variables.tf | 116 +++++++++++ TEST_STAND/FPipeGmail/vdc.tf | 20 ++ TEST_STAND/FPipeGmail/versions.tf | 10 + TEST_STAND/FPipeGmail/vm.tf | 189 ++++++++++++++++++ 11 files changed, 720 insertions(+) create mode 100644 HISTORY/2026-10-01_test_stand_fpipegmail.md create mode 100644 TEST_STAND/FPipeGmail/edge.tf create mode 100644 TEST_STAND/FPipeGmail/modifiers.tf create mode 100644 TEST_STAND/FPipeGmail/outputs.tf create mode 100644 TEST_STAND/FPipeGmail/provider.tf create mode 100644 TEST_STAND/FPipeGmail/shturval.tf create mode 100644 TEST_STAND/FPipeGmail/terraform.tfvars.example create mode 100644 TEST_STAND/FPipeGmail/variables.tf create mode 100644 TEST_STAND/FPipeGmail/vdc.tf create mode 100644 TEST_STAND/FPipeGmail/versions.tf create mode 100644 TEST_STAND/FPipeGmail/vm.tf diff --git a/HISTORY/2026-10-01_test_stand_fpipegmail.md b/HISTORY/2026-10-01_test_stand_fpipegmail.md new file mode 100644 index 0000000..a666f65 --- /dev/null +++ b/HISTORY/2026-10-01_test_stand_fpipegmail.md @@ -0,0 +1,79 @@ +# 2026-10-01 — Стенд `TEST_STAND/FPipeGmail`: копия dev-примера, адаптированная под test + +> Команда владельца: «`DEV_STAND/FPipeGmail` — это в дев. Надо — сделать такую же папку +> в `TEST_STAND` и соответственно изменить параметры в tf-конфигах, и посмотри чтобы +> не было коллизий — там в стенде есть и эдж и вдц. Найди имя огра». + +## Что сделано + +Создана `TEST_STAND/FPipeGmail/` — копия `DEV_STAND/FPipeGmail` **без** `.terraform/`, +`terraform.tfstate*`, `.terraform.lock.hcl` (это состояние dev, к test оно не относится). +Состав: `vdc.tf`, `edge.tf`, `modifiers.tf`, `vm.tf`, `shturval.tf`, `variables.tf`, +`outputs.tf`, `provider.tf`, `versions.tf`, `terraform.tfvars` (+ `.example`). + +## Найденные данные test-стенда (из API, не из догадок) + +| Что | Значение | Откуда | +|---|---|---| +| Организация (vcOrg) | **`NaeelOrg`**, uuid `3f0850f2-3506-4efd-b84b-7270b5027ab5`, `running`, `iaas` | `GET /instances?serviceId=19` | +| ipSpace на организации | `internet-ipv4-v1`, уже выделено **10** IP | `GET /instances/3f0850f2-…` → `vIPConfigure` | +| networkProvider | `snb1` | `GET /instances/e3c9e4f1-…` (существующий vDC `naeel-vdc`) | +| providerVdc | `Intel Broadwell 2.4` | там же | +| storage | `SSD` | там же (`storageConfig`) | +| realm | `sandbox.nubes.ru` | `GET /instances/3f0850f2-…` | + +## Изменённые параметры (dev → test) + +| Файл | Было (dev) | Стало (test) | +|---|---|---| +| `versions.tf` | `…/nubes-dev/nubes`, `2.0.1` | **`…/nubes-test/nubes`, `3.0.0`** | +| `variables.tf` → `api_endpoint` | `lk-api-gateway-dev…` | **`lk-api-gateway-test…`** | +| `terraform.tfvars` → `organization` | `kontra` | **`NaeelOrg`** | +| `terraform.tfvars` → `api_token` | dev-токен | **test-токен** (`secrets/test.token`) | +| `terraform.tfvars` → `ip_count` | `4` | **`10`** (не уменьшать уже выделенное) | +| `terraform.tfvars` → `vdc_storage_config` | `SATA / 200` | **`SSD / 200`** (в test vDC строят на SSD) | +| `shturval.tf` → `shturval_resource_name` | `shturval-dev1` | **`shturval-test1`** | +| `shturval.tf` → `shturval_cluster_name` | `shturval-dev-01` | **`shturval-test-01`** | +| `shturval.tf` → `shturval_worker_group_name` | `workers-shturval-dev` | **`workers-shturval-test`** | + +Не менялись (совпадают с test): `vdc_network_provider=snb1`, `vdc_provider_vdc="Intel Broadwell 2.4"`, +`ip_space_name=internet-ipv4-v1`, DNS/пул Edge, имена `fullpipe-vdc` / `fullpipe-edge` / `fullpipe-vapp-02`. + +## Проверка коллизий (в test уже есть эдж и vDC) + +Занято в test сейчас: + +| Услуга | Имена | Статус | +|---|---|---| +| vDC (21) | `naeel-vdc`, `VDC для кластера iot-naeel` | running | +| Edge (22) | `naeel_vc_nsxt`, `Edge для кластера IOT naeel` | running | +| vApp (26) | `vapp-222`, `vm-sless-vapp`, `vm-sless-demo-vapp` | deleted | +| ВМ (28) | `vm-sless`, `vm-sless-1`, `vm-sless-demo` | deleted | +| Штурвал (150) | `naeel-wheel` (deleted), `Кластер Kubernetes [iot-naeel]` | running | + +Наши имена (`fullpipe-vdc`, `fullpipe-edge`, `fullpipe-vapp-02`, `web02`, `shturval-test1`) +**свободны** — пересечений нет. + +## Проверки конфигурации + +```bash +terraform init # установлен nubes-test/nubes 3.0.0 (подпись CB3A0DF161ECC416) +terraform fmt -check -recursive # OK +terraform validate # Success! The configuration is valid. +terraform plan # Plan: 7 to add, 0 to change, 0 to destroy +``` + +⚠️ `terraform apply` **не выполнялся** — по правилам запускает только владелец. + +## Риск, который надо помнить + +- `nubes_vc_org_ip_allocation` (модификатор `vIPConfigure`) **перезаписывает массив внешних IP целиком**. + В test на `NaeelOrg` уже выделено 10 адресов (их использует кластер `iot-naeel`), поэтому + `ip_count="10"` — уменьшение сломает чужой стенд. +- В `.gitignore` уже закрыты `terraform.tfvars`, `.terraform/`, `.terraform.lock.hcl`, + `terraform.tfstate*` — в репозиторий попадут только `.tf` и `terraform.tfvars.example`. + +## Связанные документы + +- `HISTORY/2026-09-25_fullpipe_example_shturval_and_docs.md` — исходный пример FPipeGmail (dev). +- `HISTORY/2026-10-01_release_x_0_0_all_stands.md` — актуальные версии провайдеров стендов. diff --git a/TEST_STAND/FPipeGmail/edge.tf b/TEST_STAND/FPipeGmail/edge.tf new file mode 100644 index 0000000..ec8f962 --- /dev/null +++ b/TEST_STAND/FPipeGmail/edge.tf @@ -0,0 +1,28 @@ +resource "nubes_vc_nsxt" "edge" { + resource_name = var.nsxt_resource_name + + # Тип родительской услуги: "vdc" (нужен vdc_uid) или "vdcGroup" (нужен vdc_group_uid) + vdc_type = var.nsxt_vdc_type + + # refSvc-поле: принимает UUID или имя. Здесь берём UID созданного VDC, + # чтобы Edge гарантированно создавался после vDC. + vdc_uid = nubes_vc_vdc.vdc.id + + need_enable_avi = var.nsxt_need_enable_avi + virtual_services_count = var.nsxt_virtual_services_count + + # routed-сеть, которую разворачивает Edge (SingleNestedAttribute -> объект) + routed_net_configuration = { + ip_addr_pool = var.nsxt_ip_addr_pool + main_dns = var.nsxt_main_dns + second_dns = var.nsxt_second_dns + } + + # «Заморозка»: destroy НЕ удаляет эдж (у платформы для эджа нет операции suspend), + # а только убирает его из состояния. Для полного удаления — keep_on_destroy = false. + keep_on_destroy = true + + # Повторный apply усыновляет уже работающий эдж, а не падает с + # «РЕСУРС С ТАКИМ ИМЕНЕМ УЖЕ СУЩЕСТВУЕТ (RUNNING)». + adopt_existing_on_create = true +} diff --git a/TEST_STAND/FPipeGmail/modifiers.tf b/TEST_STAND/FPipeGmail/modifiers.tf new file mode 100644 index 0000000..a148873 --- /dev/null +++ b/TEST_STAND/FPipeGmail/modifiers.tf @@ -0,0 +1,60 @@ +# ============================================================================= +# Ресурсы-модификаторы (операции modify, которых нет в create-схеме ресурсов) +# +# Порядок строго такой: +# орга (создана вручную в ЛК) +# -> nubes_vc_vdc.vdc +# -> nubes_vc_nsxt.edge +# -> nubes_vc_org_ip_allocation (выделение внешних IP на орге) +# -> nubes_vc_nsxt_snat (SNAT на эдже этим ipSpace) +# +# Почему аллокация ПОСЛЕ эджа: платформа строит список ipSpace из состояния +# `job.vcd.networkProvider` / `job.vcd.providerGateway`, то есть требует уже +# созданный vDC и Edge. Иначе modify на орге падает +# («Can't cast Complex Object Type Struct to String»). +# ============================================================================= + +# 1. Внешние IP на организации (modify: vIPConfigure, массив перезаписывается целиком) +resource "nubes_vc_org_ip_allocation" "org_ip" { + organization = var.organization + + vip_configure = jsonencode([ + { + name = var.ip_space_name + count = var.ip_count + } + ]) + + # true = «заморозка»: destroy не трогает квоту внешних IP (кластер Штурвала держит + # адреса, опустить count ниже занятых платформа не даёт). Для полного удаления — false + # (и только после удаления кластера). + keep_on_destroy = true + + depends_on = [nubes_vc_nsxt.edge] +} + +# 2. SNAT на эдже (modify: ipSpaceName) +resource "nubes_vc_nsxt_snat" "snat" { + nsxt_uid = nubes_vc_nsxt.edge.id + ip_space_name = var.ip_space_name + + # true = «заморозка»: destroy не выключает SNAT на эдже. Для полного удаления — false. + keep_on_destroy = true + + # ipSpace должен быть уже выделен на организации + depends_on = [nubes_vc_org_ip_allocation.org_ip] +} + +output "allocated_org_ip" { + description = "Выделено внешних IP на организации" + value = { + organization = var.organization + ip_space_name = var.ip_space_name + ip_count = var.ip_count + } +} + +output "snat_ip_space" { + description = "ipSpace, включённый как SNAT на эдже" + value = nubes_vc_nsxt_snat.snat.ip_space_name +} diff --git a/TEST_STAND/FPipeGmail/outputs.tf b/TEST_STAND/FPipeGmail/outputs.tf new file mode 100644 index 0000000..13ee3e0 --- /dev/null +++ b/TEST_STAND/FPipeGmail/outputs.tf @@ -0,0 +1,29 @@ +output "vdc_id" { + description = "UID созданного VDC" + value = nubes_vc_vdc.vdc.id +} + +output "vdc_name" { + description = "Имя VDC" + value = nubes_vc_vdc.vdc.resource_name +} + +output "vdc_state_params" { + description = "Параметры состояния VDC из API" + value = nubes_vc_vdc.vdc.state_params +} + +output "nsxt_id" { + description = "UID созданного Edge (vc_nsxt)" + value = nubes_vc_nsxt.edge.id +} + +output "nsxt_name" { + description = "Имя Edge (vc_nsxt)" + value = nubes_vc_nsxt.edge.resource_name +} + +output "nsxt_state_params" { + description = "Параметры состояния Edge (vc_nsxt) из API" + value = nubes_vc_nsxt.edge.state_params +} diff --git a/TEST_STAND/FPipeGmail/provider.tf b/TEST_STAND/FPipeGmail/provider.tf new file mode 100644 index 0000000..9d91910 --- /dev/null +++ b/TEST_STAND/FPipeGmail/provider.tf @@ -0,0 +1,4 @@ +provider "nubes" { + api_token = var.api_token + api_endpoint = var.api_endpoint +} diff --git a/TEST_STAND/FPipeGmail/shturval.tf b/TEST_STAND/FPipeGmail/shturval.tf new file mode 100644 index 0000000..0b9a1f1 --- /dev/null +++ b/TEST_STAND/FPipeGmail/shturval.tf @@ -0,0 +1,161 @@ +# ============================================================================= +# Kubernetes кластер Штурвал — сервис 150, ресурс nubes_k8s_sthutrval_cluster +# (НЕ 148 «Менеджмент Kubernetes кластер Штурвал» — это другой сервис) +# +# Всё, что относится к Штурвалу, лежит ТОЛЬКО в этом файле: переменные, их +# значения по умолчанию и сам ресурс. Чтобы выключить Штурвал — удалить файл +# или закомментировать ресурс. +# +# Порядок (чек-лист из инструкции на услугу в ЛК): +# 1) Организация в Cloud Director — создана вручную в ЛК +# 2) nubes_vc_vdc.vdc — есть +# 3) nubes_vc_nsxt.edge — есть, обязательно ALB + AVI VS >= 3 +# 4) внешние адреса в организации — суммарно >= 3 (nubes_vc_org_ip_allocation) +# 5) SNAT на Edge — nubes_vc_nsxt_snat +# 6) Kubernetes кластер Штурвал — этот ресурс +# +# Минимальные требования к кластеру: мастер-нод >= 1, воркер-нод >= 1, +# 4 vCPU / 8 GB RAM / 50 GB диска на ноду. +# ============================================================================= + +# --- Переменные Штурвала --- + +variable "shturval_resource_name" { + type = string + default = "shturval-test1" + description = "Имя услуги «Kubernetes кластер Штурвал» в ЛК" +} + +variable "shturval_cluster_name" { + type = string + default = "shturval-test-01" + description = "Имя кластера внутри Штурвала" +} + +variable "shturval_app_version" { + type = string + default = "2.14.0" + description = "Версия Штурвала (значение по умолчанию платформы — 2.14.0)" +} + +variable "shturval_cp_sizing_policy" { + type = string + default = "TKG 4CPU 8RAM" + description = "Политика размера control plane: 4 vCPU / 8 GB (минимум по инструкции). Должна существовать в ресурсной платформе vDC — список политик берётся из услуги «Виртуальный датацентр»" +} + +variable "shturval_cp_sizing_disk" { + type = number + default = 50 + description = "Диск control plane, ГБ (минимум 50)" +} + +variable "shturval_cp_count" { + type = number + default = 1 + description = "Количество мастер-нод: 1, 3 или 5" +} + +variable "shturval_worker_group_name" { + type = string + default = "workers-shturval-test" + description = "Имя группы воркеров (уникальное в кластере; допустимы строчные латинские буквы, цифры и дефис)" +} + +variable "shturval_worker_sizing_policy" { + type = string + default = "TKG 4CPU 8RAM" + description = "Политика размера воркеров: 4 vCPU / 8 GB (минимум по инструкции)" +} + +variable "shturval_worker_sizing_disk" { + type = number + default = 50 + description = "Диск воркеров, ГБ (минимум 50)" +} + +variable "shturval_worker_count" { + type = number + default = 1 + description = "Количество воркер-нод (минимум 1)" +} + +# --- Значения, которые собираются из переменных --- + +locals { + # Группы воркеров передаются JSON-строкой ВНУТРЬ услуги как есть, поэтому ключи + # должны быть ровно такими, как в манифесте услуги 150: groupName, sizingPolicy, + # sizingDisk, count, autoscale, labelDeck. + # ВНИМАНИЕ: в сгенерированном примере провайдера (docs → Example) ключи показаны + # в snake_case — это ошибка генератора, платформа на них падает с + # «Cannot invoke method split() on null object» (не находит groupName → null). + shturval_worker_config = jsonencode([ + { + groupName = var.shturval_worker_group_name + sizingPolicy = var.shturval_worker_sizing_policy + sizingDisk = var.shturval_worker_sizing_disk + count = var.shturval_worker_count + autoscale = false # автоскейл выключен + labelDeck = true # разрешить разворачивать услуги из ЛК на этих нодах + } + ]) +} + +# --- Ресурс Штурвала --- + +resource "nubes_k8s_sthutrval_cluster" "shturval" { + resource_name = var.shturval_resource_name + + # Кластер Штурвала уже существует (инстанс «shturval-dev») и в проде не + # удаляется неделями, поэтому ресурс должен УСЫНОВИТЬ существующий инстанс, + # а не падать с «РЕСУРС С ТАКИМ ИМЕНЕМ УЖЕ СУЩЕСТВУЕТ (SUSPEND)». + # Проверка/adopt выполняются в Create на apply (в plan будет «will be created»). + adopt_existing_on_create = true + + # «Заморозка»: destroy приостанавливает кластер (suspend), а не удаляет. + # Следующий apply усыновит его и разморозит (resume). + suspend_on_destroy = true + + # Штурвал создаётся долго (десятки минут) — поднимаем таймаут ожидания, + # иначе провайдер сдаётся на дефолтных 600 с. + operation_timeout = "60m" + + startup_configuration = { + # vDC и Edge из этого же конфига (обязательные поля) + vdc_uid = nubes_vc_vdc.vdc.id + nsxt_uid = nubes_vc_nsxt.edge.id + + cluster_name = var.shturval_cluster_name + + # Дополнительные возможности кластера (в ЛК — галочки при создании) + ex_logging = true # логи в Loki (без него логи услуг не видны в ЛК) + ex_monitoring = true # метрики в VictoriaMetrics (без него метрик в ЛК нет) + ex_local_csi = true + ex_vip = true + ex_update = true + ex_ingress = true + ex_named_csi = true + } + + cluster_configuration = { + app_version = var.shturval_app_version + } + + control_plane_configuration = { + sizing_policy = var.shturval_cp_sizing_policy + sizing_disk = var.shturval_cp_sizing_disk + count = var.shturval_cp_count + } + + worker_configuration = local.shturval_worker_config + + access_configuration = { + need_external_address_api = true # внешний адрес для Kubernetes API (false недопустим) + access_ip_list_api = jsonencode([]) # пусто = доступ всем + need_external_address_ingress = true # внешний адрес для Ingress + access_ip_list_ingress = jsonencode([]) # пусто = доступ всем + } + + # Кластер поднимается только после готовой сети: vDC -> Edge -> внешние IP -> SNAT + depends_on = [nubes_vc_nsxt_snat.snat] +} diff --git a/TEST_STAND/FPipeGmail/terraform.tfvars.example b/TEST_STAND/FPipeGmail/terraform.tfvars.example new file mode 100644 index 0000000..6e1eba5 --- /dev/null +++ b/TEST_STAND/FPipeGmail/terraform.tfvars.example @@ -0,0 +1,24 @@ +api_token = "ВАШ_ТОКЕН_ИЗ_ЛК (test)" + +# Имя или UUID организации (test-стенд: NaeelOrg, uuid 3f0850f2-3506-4efd-b84b-7270b5027ab5) +organization = "NaeelOrg" + +# Внешние IP на организации (modify vIPConfigure). ВНИМАНИЕ: массив +# перезаписывается целиком — значение не должно быть меньше уже занятого +# (в test на NaeelOrg уже выделено 10 → count="10"). +ip_space_name = "internet-ipv4-v1" +ip_count = "10" + +vdc_resource_name = "fullpipe-vdc" +vdc_network_provider = "snb1" +vdc_provider_vdc = "Intel Broadwell 2.4" +vdc_cpu_allocated = 12 +vdc_cpu_guaranteed = 0 +vdc_mem_allocated = 32 + +# Политика хранилища должна существовать в ресурсном пуле. +# В test существующий vDC (naeel-vdc) создан с политикой SSD. +vdc_storage_config = "[{\"name\":\"SSD\",\"size\":\"200\"}]" + +# Всё про ВМ (включая публичный SSH-ключ) лежит внутри vm.tf — +# здесь для ВМ задавать ничего не нужно. diff --git a/TEST_STAND/FPipeGmail/variables.tf b/TEST_STAND/FPipeGmail/variables.tf new file mode 100644 index 0000000..11a4db9 --- /dev/null +++ b/TEST_STAND/FPipeGmail/variables.tf @@ -0,0 +1,116 @@ +variable "api_token" { + type = string + sensitive = true + description = "API-токен Nubes" +} + +variable "api_endpoint" { + type = string + default = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" + description = "API Gateway URL" +} + +# Имя (display_name, напр. "kontora") ИЛИ UUID организации из ЛК +variable "organization" { + type = string + description = "Имя или UUID организации (vc_org)" +} + +# --- Модификаторы (IP на орге + SNAT на эдже) --- + +variable "ip_space_name" { + type = string + description = "Имя ipSpace, доступное организации (смотреть в ЛК, напр. internet-ipv4-v1)" +} + +variable "ip_count" { + type = string + default = "3" + description = "Сколько внешних IP выделить на организации (count — строка)" +} + +variable "vdc_resource_name" { + type = string + default = "fullpipe-vdc" + description = "Имя VDC" +} + +variable "vdc_network_provider" { + type = string + default = null + description = "Сетевой провайдер. Заполнить значением из текущей страницы ЛК" +} + +variable "vdc_provider_vdc" { + type = string + default = null + description = "Provider VDC. Заполнить значением из текущей страницы ЛК" +} + +variable "vdc_cpu_allocated" { + type = number + default = 8 + description = "vCPU (шт.)" +} + +variable "vdc_cpu_guaranteed" { + type = number + default = 0 + description = "Резервирование vCPU (%, допустимо: 0, 50, 80)" +} + +variable "vdc_mem_allocated" { + type = number + default = 32 + description = "RAM (GB)" +} + +variable "vdc_storage_config" { + type = string + default = "[{\"name\":\"SATA\",\"size\":\"200\"}]" + description = "Дисковое хранилище (JSON-массив, size в GB). Имя политики должно существовать в ресурсном пуле (например, SATA, SSD)" +} + +# --- vc_nsxt (Сетевой шлюз периметра / Edge) --- + +variable "nsxt_resource_name" { + type = string + default = "fullpipe-edge" + description = "Имя Edge (vc_nsxt)" +} + +variable "nsxt_vdc_type" { + type = string + default = "vdc" + description = "Тип родительской услуги: vdc или vdcGroup" +} + +variable "nsxt_need_enable_avi" { + type = bool + default = true + description = "Включить AVI Load Balancer (ALB)" +} + +variable "nsxt_virtual_services_count" { + type = number + default = 3 + description = "Кол-во виртуальных сервисов на AVI (1..4; Штурвал: ≥ 3)" +} + +variable "nsxt_ip_addr_pool" { + type = string + default = "10.10.102.0/24" + description = "Адресный пул routed-сети (маска /24 обязательна)" +} + +variable "nsxt_main_dns" { + type = string + default = "81.22.46.22" + description = "Основной DNS" +} + +variable "nsxt_second_dns" { + type = string + default = "185.247.187.77" + description = "Второй DNS" +} diff --git a/TEST_STAND/FPipeGmail/vdc.tf b/TEST_STAND/FPipeGmail/vdc.tf new file mode 100644 index 0000000..f69039e --- /dev/null +++ b/TEST_STAND/FPipeGmail/vdc.tf @@ -0,0 +1,20 @@ +resource "nubes_vc_vdc" "vdc" { + resource_name = var.vdc_resource_name + + # Организация: имя из ЛК ("kontora") или точный UUID + organization_uid = var.organization + + network_provider = var.vdc_network_provider + provider_vdc = var.vdc_provider_vdc + + cpu_allocated = var.vdc_cpu_allocated + cpu_guaranteed = var.vdc_cpu_guaranteed + mem_allocated = var.vdc_mem_allocated + + # JSON-массив дисковых политик (size в GB) + storage_config = var.vdc_storage_config + + suspend_on_destroy = true + + adopt_existing_on_create = true +} diff --git a/TEST_STAND/FPipeGmail/versions.tf b/TEST_STAND/FPipeGmail/versions.tf new file mode 100644 index 0000000..31f46cd --- /dev/null +++ b/TEST_STAND/FPipeGmail/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + nubes = { + source = "tf-registry.containerk8s.services.ngcloud.ru/nubes-test/nubes" + version = "3.0.0" + } + } +} diff --git a/TEST_STAND/FPipeGmail/vm.tf b/TEST_STAND/FPipeGmail/vm.tf new file mode 100644 index 0000000..b7789fc --- /dev/null +++ b/TEST_STAND/FPipeGmail/vm.tf @@ -0,0 +1,189 @@ +# ============================================================================= +# Виртуальная машина внутри vApp — услуги 26 (vApp) и 28 (ВМ) +# +# Всё, что относится к ВМ, лежит ТОЛЬКО в этом файле: переменные, их значения +# по умолчанию, оба ресурса и выводы. Чтобы выключить ВМ — удалить или +# закомментировать этот файл (по аналогии с shturval.tf). +# +# Место в цепочке: +# орга (вручную в ЛК) → vDC (21) → Edge (22) → внешние IP → SNAT +# → [ vApp (26) → ВМ (28) ] → Штурвал (150) +# +# Зависимости (из манифестов услуг, сгенерированные ресурсы): +# vApp (26) — nubes_vapp: требует vdc_uid (21) и nsxt_uid (22) +# ВМ (28) — nubes_vc_vm_v3: требует vapp_uid (26) +# +# Внешний доступ: ВМ публикуется за общим SNAT эджа (same_snat = false), для +# этого ipSpace должен быть выделен на организации и включён как SNAT +# (см. modifiers.tf). Нужен ВЫДЕЛЕННЫЙ внешний адрес — same_snat = true. +# ipSpace для ВМ берём тот же, что у SNAT (var.ip_space_name). +# +# Режим destroy: у обеих услуг операция delete требует предварительного +# suspend, поэтому по умолчанию suspend_on_destroy = true («заморозка»). +# Полное удаление vApp возможно только через 14 дней после suspend. +# ============================================================================= + +# --- Переменные vApp --- + +variable "vapp_resource_name" { + type = string + default = "fullpipe-vapp-02" + description = "Имя услуги «Виртуальный каталог ВМ (vApp)» в ЛК" +} + +variable "vapp_name" { + type = string + default = "fullpipe-vapp-02" + description = "Имя vApp. Маска ^[a-z0-9][a-z0-9.-]{3,61}[a-z0-9]$, уникально в организации; участвует в DNS-имени ВМ. НЕ оставлять дефолтом платформы." +} + +# --- Переменные ВМ --- + +variable "vm_resource_name" { + type = string + default = "fullpipe-vm-02" + description = "Имя услуги «Виртуальная машина» в ЛК" +} + +variable "vm_name" { + type = string + default = "web02" + description = "Имя ВМ. Маска ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$. Определяет имя NSX-T IP Set: {vapp_name}-{vm_name}" +} + +variable "vm_image" { + type = string + default = "Ubuntu_22-20G" + description = "Образ ОС. Доступные значения: RockyLinux_9-16G-cloudinit, Ubuntu_22-20G, Debian_13-20G. Не изменяется после создания" +} + +variable "vm_cpu" { + type = number + default = 2 + description = "vCPU (1..64), шт" +} + +variable "vm_ram" { + type = number + default = 2 + description = "RAM (1..256), GB" +} + +variable "vm_disk" { + type = number + default = 20 + description = "Дополнительный диск, GB (основной диск зависит от образа)" +} + +variable "vm_user_login" { + type = string + default = "ubuntu" + description = "Учётка SSH. Не изменяется после создания" +} + +variable "vm_user_public_key" { + type = string + # ВСЕ параметры ВМ живут в этом файле — включая ключ. Удалил файл — ВМ исключена + # из конфига полностью, в terraform.tfvars ничего про ВМ не остаётся. + # Здесь публичный ключ (не секрет), тот же, что в secrets/id_ed25519.pub. + # Переопределить можно в terraform.tfvars — но тогда при исключении ВМ + # надо удалить и эту строку (иного способа у Terraform нет). + default = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPR8S07Mnku1VlVR/lq6hCKPo9fNzJ+7E0DoE7bkvy4p tazet@narod.ru" + description = "Публичная часть SSH-ключа в формате OpenSSH. Не изменяется после создания. По умолчанию — ключ tazet@narod.ru" +} + +variable "vm_access_port_list" { + type = list(object({ + port = string + type = string + })) + default = [ + { port = "22", type = "tcp" } + ] + description = "Белый список портов для доступа извне; type: tcp | udp | all" +} + +variable "vm_access_ip_list" { + type = list(string) + default = ["0.0.0.0/0"] + description = "Белый список адресов, которым разрешён доступ к ВМ. Требует выделенного внешнего IP" +} + +variable "vm_same_snat" { + type = bool + default = false + description = "false — публикация за общим SNAT эджа; true — за выделенным внешним IP услуги" +} + +# --- vApp (услуга 26) --- + +resource "nubes_vapp" "vapp" { + resource_name = var.vapp_resource_name + vapp_name = var.vapp_name + + vdc_uid = nubes_vc_vdc.vdc.id # ref 21 — вычислительная инфраструктура + nsxt_uid = nubes_vc_nsxt.edge.id # ref 22 — сеть/маршрутизация + + # «Заморозка»: destroy переводит vApp в suspend (delete требует suspend). + suspend_on_destroy = true + + # Повторный apply усыновляет существующий vApp, а не падает с + # «РЕСУРС С ТАКИМ ИМЕНЕМ УЖЕ СУЩЕСТВУЕТ». + adopt_existing_on_create = true + + # vApp требует готовую сеть (ipSpace на организации + SNAT на эдже). + depends_on = [nubes_vc_nsxt_snat.snat] +} + +# --- ВМ (услуга 28) --- + +resource "nubes_vc_vm_v3" "vm" { + resource_name = var.vm_resource_name + vm_name = var.vm_name + + vapp_uid = nubes_vapp.vapp.id # ref 26 — ВМ размещается в vApp + image_vm = var.vm_image + + vm_cpu = var.vm_cpu + vm_ram = var.vm_ram + vm_disk = var.vm_disk + + user_login = var.vm_user_login + user_public_key = var.vm_user_public_key + + # Внешний доступ + ip_space_name = var.ip_space_name # тот же ipSpace, что у SNAT эджа + same_snat = var.vm_same_snat + access_port_list = jsonencode(var.vm_access_port_list) + access_ip_list = jsonencode(var.vm_access_ip_list) + + # «Заморозка»: destroy переводит ВМ в suspend. + suspend_on_destroy = true + + adopt_existing_on_create = true + + # ВМ создаётся платформой долго — поднимаем таймаут ожидания. + operation_timeout = "15m" +} + +# --- Выводы --- + +output "vapp_id" { + description = "UID созданного vApp (услуга 26)" + value = nubes_vapp.vapp.id +} + +output "vapp_name" { + description = "Имя vApp" + value = nubes_vapp.vapp.vapp_name +} + +output "vm_id" { + description = "UID созданной ВМ (услуга 28)" + value = nubes_vc_vm_v3.vm.id +} + +output "vm_state_flat" { + description = "Плоский state ВМ — IP-адреса, статус и т.д." + value = nubes_vc_vm_v3.vm.state_out_flat +}