diff --git a/docs/curated/pipeline/vdc_edge_ip_snat.md b/docs/curated/pipeline/vdc_edge_ip_snat.md new file mode 100644 index 0000000..9f6807c --- /dev/null +++ b/docs/curated/pipeline/vdc_edge_ip_snat.md @@ -0,0 +1,112 @@ +# Пайплайн: vDC → Edge → внешние IP → SNAT + +> Проверено на dev-стенде 2026-09-24 (провайдер `2.0.20`): один `apply` собирает всю цепочку, +> повторный `plan` не показывает изменений, `destroy` проходит в обратном порядке. + +## Что делает пайплайн + +Собирает сетевую основу под нагрузку: виртуальный датацентр, периметровый шлюз, внешние IP +на организации и SNAT на шлюзе — **без ручных операций в ЛК после создания организации**. + +**Кластер Штурвал в этот пайплайн не входит** — он разворачивается очень долго, это отдельный шаг. + +## Что вне Terraform (создаётся один раз вручную) + +**Организация в Cloud Director** — одна на ресурсный realm, создать вторую нельзя. В конфиге она +адресуется по UUID (`org_uid`), а её внешние IP выделяются уже Terraform-ресурсом. + +## Порядок и почему он такой + +| # | Ресурс | Что создаёт | +|---|---|---| +| 1 | `nubes_vc_vdc` | виртуальный датацентр | +| 2 | `nubes_vc_nsxt` | сетевой шлюз периметра (Edge), ALB/AVI | +| 3 | `nubes_vc_org_ip_allocation` | внешние IP на организации (`vIPConfigure`) | +| 4 | `nubes_vc_nsxt_snat` | SNAT на шлюзе (`ipSpaceName`) | + +Порядок обязателен: шаги 3 и 4 — операции `modify`, а платформа строит список доступных `ipSpace` +из состояния `job.vcd.networkProvider` / `job.vcd.providerGateway`, то есть **требует уже созданные +vDC и Edge**. В инструкции к операции это записано прямо: «предварительно необходимо создать +Виртуальный датацентр (VDC), потом Сетевой шлюз периметра (Edge Gateway)». Если открыть `modify` +на организации без vDC/Edge, список значений падает с ошибкой `Can't cast Complex Object Type +Struct to String`. + +## Пример конфигурации + +```hcl +resource "nubes_vc_vdc" "vdc" { + resource_name = "fullpipe-vdc" + organization_uid = var.organization # имя или UUID существующей организации + network_provider = "snb1" # из ЛК + provider_vdc = "Intel Broadwell 2.4" + storage_config = jsonencode([{ name = "SATA", size = "200" }]) + suspend_on_destroy = true +} + +resource "nubes_vc_nsxt" "edge" { + resource_name = "fullpipe-edge" + vdc_type = "vdc" + vdc_uid = nubes_vc_vdc.vdc.id # Edge создаётся только после vDC + + need_enable_avi = true + virtual_services_count = 3 # Штурвалу нужно ≥ 3 + routed_net_configuration = { + ip_addr_pool = "10.10.102.0/24" + main_dns = "81.22.46.22" + second_dns = "185.247.187.77" + } +} + +# Внешние IP на организации — только после создания Edge +resource "nubes_vc_org_ip_allocation" "org_ip" { + org_uid = var.org_uid # UUID организации + + vip_configure = jsonencode([ + { name = "internet-ipv4-v1", count = "3" } + ]) + + depends_on = [nubes_vc_nsxt.edge] +} + +# SNAT на шлюзе этим ipSpace +resource "nubes_vc_nsxt_snat" "snat" { + nsxt_uid = nubes_vc_nsxt.edge.id + ip_space_name = "internet-ipv4-v1" + + depends_on = [nubes_vc_org_ip_allocation.org_ip] +} +``` + +Порядок ключей в `vip_configure` и его форматирование значения не имеют — сравнение смысловое. + +## Значения, которые берутся из ЛК + +| Параметр | Где смотреть | +|---|---| +| `organization_uid` / `org_uid` | карточка услуги «Организация в Cloud Director» | +| `network_provider`, `provider_vdc` | страница vDC | +| `storage_config` (имена политик) | дисковые политики ресурсного пула (`SATA`, `SSD`) | +| `ip_space_name` | список ipSpace организации (доступен после создания vDC и Edge) | + +## Удаление + +`terraform destroy` идёт в обратном порядке и сам приводит систему в исходное состояние: + +| # | Ресурс | Обратная операция | +|---|---|---| +| 1 | `nubes_vc_nsxt_snat` | `modify` с `ipSpaceName = "no-needed"` (SNAT выключается) | +| 2 | `nubes_vc_org_ip_allocation` | `modify` с `count = "0"` (квота IP обнуляется) | +| 3 | `nubes_vc_nsxt` | удаление шлюза | +| 4 | `nubes_vc_vdc` | удаление vDC | + +Организацию удаление не затрагивает. Если снимать SNAT или квоту не нужно — у ресурсов есть +`keep_on_destroy = true`. + +## Что подтверждено живым прогоном (dev, 2026-09-24) + +- вся цепочка поднимается **одним `apply`**; +- повторный `plan` не требует изменений; +- после apply в API: у организации `vIPConfigure: [{"name":"internet-ipv4-v1","count":"3"}]`, + у шлюза `ipSpaceName: "internet-ipv4-v1"`, при этом `needEnableAVI` и `virtualServicesCount` + не затираются (SNAT-модификация отправляет только своё поле); +- `destroy` выключает SNAT и обнуляет квоту, орг остаётся живой. diff --git a/mkdocs.yml b/mkdocs.yml index 949a88a..e6894ba 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -60,4 +60,5 @@ nav: - Глоссарий: 30_registry/guides/glossary.md - Проверенные примеры: - PostgreSQL: curated/postgres/pg_user_db.md + - Пайплайн vDC → Edge → IP → SNAT: curated/pipeline/vdc_edge_ip_snat.md - Ресурсы-модификаторы (IP организации, SNAT): curated/modifiers/org_ip_and_snat.md