From 0464a306422fdfa0c7a19ba820acc936375c6efd Mon Sep 17 00:00:00 2001 From: Repinoid Date: Fri, 18 Sep 2026 18:44:36 +0300 Subject: [PATCH] =?UTF-8?q?docs(strategy):=20=D0=BE=D1=80=D0=BA=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B2=D0=B7=D0=B0?= =?UTF-8?q?=D0=B8=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC?= =?UTF-8?q?=D1=8B=D1=85=20=D1=80=D0=B5=D1=81=D1=83=D1=80=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B8=20=D0=BF=D0=B0=D1=82=D1=82=D0=B5=D1=80=D0=BD=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D0=B2=D1=8F=D0=B7=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - complex_provisioning_workflow.md — цепочка vcOrg -> vcVdc -> vcNsxt -> Штурвал, включая modify-шаги и пошаговые модификации - shturval_dev_provisioning_spec.md — точные параметры и ID операций DEV-стенда для цепочки развёртывания k8s_sthutrval_cluster - terraform_association_pattern_and_pipeline.md — Resource Association Pattern (разделение сущности и ресурсов-привязок/модификаций) --- .../complex_provisioning_workflow.md | 138 ++++++++++++++++++ .../shturval_dev_provisioning_spec.md | 86 +++++++++++ ...raform_association_pattern_and_pipeline.md | 105 +++++++++++++ 3 files changed, 329 insertions(+) create mode 100644 docs/60_strategy/complex_provisioning_workflow.md create mode 100644 docs/60_strategy/shturval_dev_provisioning_spec.md create mode 100644 docs/60_strategy/terraform_association_pattern_and_pipeline.md diff --git a/docs/60_strategy/complex_provisioning_workflow.md b/docs/60_strategy/complex_provisioning_workflow.md new file mode 100644 index 0000000..8a1970c --- /dev/null +++ b/docs/60_strategy/complex_provisioning_workflow.md @@ -0,0 +1,138 @@ +# Оркестрация взаимозависимых ресурсов и пошаговых модификаций (на примере Штурвал) + +## 1. Контекст и проблематика + +### Исходная последовательность развертывания +Для развертывания инстанса сервиса **Штурвал** требуется подготовить сетевую и виртуальную инфраструктуру, состоящую из трёх взаимозависимых компонентов: +1. `vcOrg/create` — создание виртуальной организации (vCD Org). +2. `vcVdc/create` — создание виртуального дата-центра (vDC) внутри организации. +3. `vcNsxt/create` — создание сетевого шлюза NSX-T (включение AVI, выделение 4 Service Engine). +4. `vcOrg/modify` — модификация организации (добавление 3 внешних IP-адресов). +5. `vcNsxt/modify` — повторная модификация NSX-T (включение SNAT, привязка выделенного `ipSpace` из `vcOrg`). +6. `Штурвал/create` — создание кластера сервиса «Штурвал». + +### В чём архитектурная сложность для Terraform +В стандартной декларативной модели Terraform каждый ресурс управляется монолитно: один блок `resource` соответствует полному жизненному циклу одной сущности (Create -> Read -> Update -> Delete). + +В описанном сценарии возникает **чередующаяся (interleaved) зависимость**: +* `vcOrg` должен существовать до `vcVdc` и `vcNsxt`. +* Но добавление IP-адресов в `vcOrg` (шаг 4) и настройка SNAT в `vcNsxt` (шаг 5) должны выполняться **после** создания базового `vcNsxt` (шаг 3). +* Штурвал (шаг 6) требует, чтобы и IP-адреса, и SNAT уже были применены. + +Если пытаться упаковать шаги 1 и 4 в один ресурс `cloud_vc_org`, а шаги 3 и 5 — в один `cloud_vc_nsxt`, возникает тупик в графе зависимостей Terraform (Directed Acyclic Graph, DAG), либо API вернет ошибку из-за несвоевременного вызова параметров. + +--- + +## 2. Архитектурное решение: Паттерн отдельных ресурсов модификации (Subresource / Action Pattern) + +Канонический подход в экосистеме Terraform (аналогично `aws_security_group` + `aws_security_group_rule`, `aws_vpc` + `aws_route`) — **декомпозиция отложенных действий и привязок в отдельные управляемые ресурсы провайдера**. + +### Структура ресурсов +1. **Базовые ресурсы жизненного цикла (Core Instances):** + * `cloud_vc_org` — создает и держит базу организации. + * `cloud_vc_vdc` — создает VDC внутри Org. + * `cloud_vc_nsxt` — создает NSX-T шлюз (AVI, 4 SE). +2. **Ресурсы отложенной конфигурации / модификаций (Action / Subresources):** + * `cloud_vc_org_ip_allocation` (или `cloud_vc_org_modify_ip`) — управляет пулом выделенных IP-адресов организации. + * `cloud_vc_nsxt_snat` (или `cloud_vc_nsxt_modify_snat`) — управляет правилом SNAT и связкой с `ip_space`. +3. **Целевой сервис:** + * `cloud_shturval` — разворачивает кластер Штурвал. + +### Пример манифеста HCL + +```hcl +# 1. Создание организации +resource "cloud_vc_org" "org" { + name = "demo-org" +} + +# 2. Создание VDC +resource "cloud_vc_vdc" "vdc" { + name = "demo-vdc" + org_id = cloud_vc_org.org.id +} + +# 3. Создание NSX-T (включение AVI и 4 Service Engine) +resource "cloud_vc_nsxt" "nsxt" { + name = "demo-nsxt" + vdc_id = cloud_vc_vdc.vdc.id + enable_avi = true + service_engines = 4 +} + +# 4. Модификация vcOrg: добавление 3 IP после готовности NSX-T +resource "cloud_vc_org_ip_allocation" "org_ips" { + org_id = cloud_vc_org.org.id + ip_count = 3 + + # Явная зависимость гарантирует выполнение после создания NSX-T + depends_on = [cloud_vc_nsxt.nsxt] +} + +# 5. Модификация vcNsxt: включение SNAT с ipSpace из vcOrg +resource "cloud_vc_nsxt_snat" "snat" { + nsxt_id = cloud_vc_nsxt.nsxt.id + ip_space = cloud_vc_org_ip_allocation.org_ips.ip_space_id + enabled = true +} + +# 6. Создание сервиса Штурвал +resource "cloud_shturval" "cluster" { + name = "demo-shturval" + vdc_id = cloud_vc_vdc.vdc.id + + # Зависит от полной готовности сетевой связки + depends_on = [ + cloud_vc_nsxt_snat.snat, + cloud_vc_org_ip_allocation.org_ips + ] +} +``` + +Terraform самостоятельно строит идеальный граф исполнения: +```mermaid +graph TD + A[cloud_vc_org] --> B[cloud_vc_vdc] + B --> C[cloud_vc_nsxt] + C --> D[cloud_vc_org_ip_allocation] + D --> E[cloud_vc_nsxt_snat] + E --> F[cloud_shturval] +``` + +--- + +## 3. Интеграция в провайдер + +### Реализация через генератор провайдера +Согласно политике репозитория (Immutability Policy), код конкретных ресурсов не правится вручную, а генерируется: +1. В схему генератора добавляются описания новых сущностей: + * Тип `action` или `subresource` для вызова эндпоинтов модификации. + * Контракты входных/выходных атрибутов (`org_id`, `ip_count`, `ip_space_id`, `nsxt_id`, `enabled`). +2. Кодогенератор генерирует стандартные CRUD-структуры Terraform Plugin Framework / SDK. + +### Жизненный цикл ресурсов модификации +* **Create**: + - Вызывает соответствующий API-метод (`POST /api/v1/vcOrg/{id}/modify` или `/api/v1/vcNsxt/{id}/modify`). + - Дожидается применения задачи (task tracking / polling). + - Сохраняет идентификатор операции или полученный `ip_space_id` в Terraform State. +* **Read**: + - Запрашивает текущее состояние родительского ресурса через GET API. + - Проверяет, выделены ли IP / активен ли SNAT. +* **Update**: + - Если меняется количество IP или настройки SNAT — отправляет повторный запрос на модификацию. +* **Delete (terraform destroy)**: + - При уничтожении инфраструктуры порядок разворачивается в обратную сторону. + - Сначала удаляется `cloud_shturval`. + - Затем `cloud_vc_nsxt_snat` отключает SNAT. + - Затем `cloud_vc_org_ip_allocation` освобождает выделенные IP. + - И только затем удаляются базовые `vcNsxt`, `vcVdc` и `vcOrg`. + +--- + +## 4. Альтернативные подходы + +1. **Smart Provider (комбинированный Create)**: + - Если API позволяет вызывать шаги последовательно внутри одного HTTP-сеанса бэкенда, провайдер мог бы скрыть это внутри `Create` ресурса `cloud_shturval`. + - *Минус*: теряется гибкость и прозрачность статусов; сбой на промежуточном этапе оставляет "зависшие" ресурсы в облаке без записи в tfstate. +2. **Модули Terraform (Module Wrapper)**: + - Описанная выше структура ресурсов упаковывается в официальный Terraform-модуль `terraform-nubes-shturval`, скрывая сложность связей от конечного пользователя и предоставляя простой интерфейс ввода параметров. diff --git a/docs/60_strategy/shturval_dev_provisioning_spec.md b/docs/60_strategy/shturval_dev_provisioning_spec.md new file mode 100644 index 0000000..cc2c2e0 --- /dev/null +++ b/docs/60_strategy/shturval_dev_provisioning_spec.md @@ -0,0 +1,86 @@ +# Спецификация цепочки развертывания: vcOrg -> vcVdc -> vcNsxt -> k8sSthutrvalCluster (DEV Stand) + +Документ описывает точные параметры и операции сервисов DEV-стенда из `generated/dev/resources_yaml/`, необходимые для оркестрации цепочки развертывания кластера Штурвал (`k8s_sthutrval_cluster`, ID 150). + +--- + +## 1. Сводная таблица шагов + +| Шаг | Действие | Сервис (ID) | Операция | Ключевые параметры | +|---|---|---|---|---| +| 1 | `vcOrg/create` | `vc_org` (19) | `create` (136) | `resourceRealm`, `organizationType = "iaas"`, `orgSuffix` | +| 2 | `vcVdc/create` | `vc_vdc` (21) | `create` (9) | `organizationUid` (ссылка на Org), `providerVdc`, `networkProvider`, `storageConfig`, `cpuAllocated`, `memAllocated` | +| 3 | `vcNsxt/create` | `vc_nsxt` (22) | `create` (10) | `vdcType = "vdc"`, `vdcUid` (ссылка на VDC), `needEnableAVI = true`, `virtualServicesCount = 4`, `routedNetConfiguration` | +| 4 | `vcOrg/modify` | `vc_org` (19) | `modify` (207) | `vIPConfigure`: `name` (ipSpace), `count = 3` | +| 5 | `vcNsxt/modify` | `vc_nsxt` (22) | `modify` (111) | `ipSpaceName` (имя из шага 4), `needEnableAVI = true`, `virtualServicesCount = 4`, `routedNetConfiguration` | +| 6 | `k8sSthutrvalCluster/create` | `k8s_sthutrval_cluster` (150) | `create` (108) | `startupConfiguration`: `vdcUid`, `nsxtUid`, `clusterName`; `controlPlaneConfiguration`; `workerConfiguration` | + +--- + +## 2. Детальная спецификация параметров из YAML DEV + +### Шаг 1: `vc_org` (ID 19) — `create` (id: 136) +*Источник: `generated/dev/resources_yaml/19_vc_org.yaml`* +* `resourceRealm` (`string`, required, default: `sandbox.nubes.ru`) — целевое облако. +* `organizationType` (`string`, required, default: `iaas`, values: `iaas`, `saas`) — тип тенанта (`iaas` для доступа в Keycloak). +* `orgSuffix` (`string`, optional, regex: `^[0-9a-z]+$`, 3–10 символов) — суффикс организации. + +### Шаг 2: `vc_vdc` (ID 21) — `create` (id: 9) +*Источник: `generated/dev/resources_yaml/21_vc_vdc.yaml`* +* `organizationUid` (`uuid`, required, ref: 19) — UUID созданной организации `vc_org`. +* `networkProvider` (`string`, required) — сетевой провайдер платформы. +* `providerVdc` (`string`, required) — пул ресурсов Cloud Director. +* `storageConfig` (`array-map-fixed`, required): + * `name` (`string`, required) — имя storage-политики. + * `size` (`integer > 0`, required, default: `2000`) — размер хранилища в ГБ. +* `cpuGuaranteed` (`integer >= 0`, required, values: `0`, `50`, `80`, default: `0`). +* `cpuAllocated` (`integer > 0`, required, default: `80`). +* `memAllocated` (`integer > 0`, required, default: `200`). + +### Шаг 3: `vc_nsxt` (ID 22) — `create` (id: 10) +*Источник: `generated/dev/resources_yaml/22_vc_nsxt.yaml`* +* `vdcType` (`string`, required, default: `vdc`, values: `vdc`, `vdcGroup`). +* `vdcUid` (`string`, required при `vdcType == "vdc"`, ref: 21) — UUID инстанса `vc_vdc`. +* `needEnableAVI` (`boolean`, required, default: `false`) — **значение: `true`** (активация AVI Load Balancer). +* `virtualServicesCount` (`integer > 0`, 1..4, default: `1`) — **значение: `4`** (Service Engine / резерв VS). +* `routedNetConfiguration` (`map-fixed`, required): + * `ipAddrPool` (`string`, default: `10.10.102.0/24`) — CIDR routed-сети. + * `mainDns` (`string`, default: `8.8.8.8`). + * `secondDns` (`string`, default: `8.8.4.4`). + +### Шаг 4: `vc_org` (ID 19) — `modify` (id: 207) +*Источник: `generated/dev/resources_yaml/19_vc_org.yaml`* +* `vIPConfigure` (`array-map-fixed`, required) — добавление внешних IP: + * `name` (`string`, required) — имя пула / ipSpace. + * `count` (`integer > 0`, required) — **значение: `3`**. +* *Условие API*: выполняется строго после создания VDC и Edge Gateway. + +### Шаг 5: `vc_nsxt` (ID 22) — `modify` (id: 111) +*Источник: `generated/dev/resources_yaml/22_vc_nsxt.yaml`* +* `ipSpaceName` (`string`, optional) — **имя ipSpace**, заданное на шаге 4 (`vIPConfigure[].name`). Включает SNAT. +* `needEnableAVI` (`boolean`, optional) — `true`. +* `virtualServicesCount` (`integer > 0`, 1..4, optional) — `4`. +* `routedNetConfiguration` (`map-fixed`, required): + * `ipAddrPool`, `mainDns`, `secondDns`. +* *Условие API*: создание правила SNAT требует наличия свободных IP в организации. + +### Шаг 6: `k8s_sthutrval_cluster` (ID 150) — `create` (id: 108) +*Источник: `generated/dev/resources_yaml/150_k8s_sthutrval_cluster.yaml`* +* `startupConfiguration` (`map-fixed`, required): + * `vdcUid` (`string`, required) — UUID инстанса `vc_vdc`. + * `nsxtUid` (`string`, required) — UUID инстанса `vc_nsxt` (после настройки SNAT). + * `clusterName` (`string`, required, regex: `(?=^.{1,63}$)^[a-z0-9]([a-z0-9-]*[a-z0-9])?$`). + * Флаги расширений (`boolean`, defaults: `true`): `exIngress`, `exLogging`, `exMonitoring`, `exVip`, `exNamedCsi`, `exLocalCsi`, `exUpdate`. +* `controlPlaneConfiguration` (`map-fixed`, required): + * `count` (`integer > 0`, values: `1`, `3`, `5`, default: `1`). + * `sizingPolicy` (`string`, required). + * `sizingDisk` (`integer > 0`, required, default: `50`). +* `workerConfiguration` (`array-map-fixed`, required): + * `count` (`integer > 0`, required, default: `2`). + * `sizingPolicy` (`string`, required). + * `sizingDisk` (`integer > 0`, required, default: `50`). + * `labelDeck` (`boolean`, required, default: `true`). + * `autoscale` (`boolean`, optional, default: `false`). + * `autoscaleMin` (`integer > 0`, optional, default: `2`). + * `autoscaleMax` (`integer > 0`, optional, default: `3`). +* *Условие API*: перед разворачиванием кластера в пуле должно быть не менее 2 свободных невыделенных IP. diff --git a/docs/60_strategy/terraform_association_pattern_and_pipeline.md b/docs/60_strategy/terraform_association_pattern_and_pipeline.md new file mode 100644 index 0000000..273a7d1 --- /dev/null +++ b/docs/60_strategy/terraform_association_pattern_and_pipeline.md @@ -0,0 +1,105 @@ +# Архитектурный паттерн Terraform: Ресурсы привязок и модификаций (Resource Association Pattern) + +## 1. Канонический стандарт Terraform + +Разделение базовой сущности и её отложенных настроек/модификаций на самостоятельные ресурсы в Terraform является индустриальным стандартом (**Resource Association / Separate Resource Pattern**), рекомендованным HashiCorp и повсеместно используемым в провайдерах первого эшелона (AWS, Google Cloud, Azure, OpenStack). + +### Примеры из мировой практики: +* **AWS Security Groups**: + * Базовый ресурс: `aws_security_group` (создание пустой группы). + * Ресурс настройки: `aws_security_group_rule` (отдельное правило ingress/egress). + * *Причина*: разрыв взаимных и циклических зависимостей, когда правила одной группы ссылаются на другую. +* **AWS VPC & Routing**: + * Базовые ресурсы: `aws_vpc`, `aws_route_table`, `aws_subnet`. + * Ресурсы привязок: `aws_route_table_association`, `aws_vpn_gateway_attachment`. +* **IAM (GCP / AWS)**: + * Базовые сущности: `aws_iam_user`, `aws_iam_role`. + * Ресурсы привязок прав: `aws_iam_user_policy_attachment`, `google_project_iam_binding`. + +--- + +## 2. Почему идеология Terraform требует именно отдельных ресурсов + +### 1. Управление графом зависимостей (DAG — Directed Acyclic Graph) +Terraform строит граф вычислений и определяет строгий порядок выполнения исключительно на уровне **декларативных блоков `resource`**. +* Если операция (например, добавление внешних IP в `vcOrg` или активация SNAT в `vcNsxt`) «спрятана» внутри одного монолитного ресурса, движок Terraform не может вклинить между этапами создание промежуточных объектов (`vcVdc`, базовый `vcNsxt`). +* Выделение модификации в отдельный ресурс даёт Terraform возможность явно связать зависимости: + ``` + vcOrg (создание) + └── vcVdc (создание) + └── vcNsxt (базовое создание) + └── vcOrg_ip_allocation (модификация Org, зависит от nsxt) + └── vcNsxt_snat (модификация Edge, зависит от ip_allocation) + └── k8s_sthutrval_cluster (зависит от snat) + ``` + +### 2. Симметричный и безопасный `terraform destroy` +В монолитном подходе удаление инфраструктуры часто приводит к сбоям: родительский ресурс пытается удалиться раньше дочерних привязок. +В паттерне отдельных ресурсов Terraform автоматически обращает граф вспять: +1. Удаляется кластер `k8s_sthutrval_cluster`. +2. Ресурс `vcNsxt_snat` отключает SNAT на шлюзе. +3. Ресурс `vcOrg_ip_allocation` освобождает выделенные IP-адреса. +4. Удаляются базовые `vcNsxt`, `vcVdc` и `vcOrg`. + +### 3. Предсказуемость плана и изоляция сбоев +* Любые изменения видны пользователю в `terraform plan` как точечные действия над конкретными ресурсами. +* Если падает сетевая модификация, ошибка локализуется в конкретном блоке ресурса привязки, а инфраструктура в Terraform State не переходит в поврежденное («зависшее») состояние. + +--- + +## 3. Точки изменений в пайплайне генерации провайдера Nubes + +Архитектура провайдера строго следует **Immutability Policy**: код конкретных ресурсов генерируется автоматически из универсальных шаблонов. + +Изменения для поддержки данного паттерна вносятся строго в универсальные слои генератора: + +``` +┌────────────────────────────────────────────────────────────────────────┐ +│ 1. TOOLS/yaml-generator/ │ +│ Выделение операций modify/настроек в схеме YAML: │ +│ kind: subresource / kind: association_resource │ +└───────────────────────────────────┬────────────────────────────────────┘ + │ (генерация YAML) + ▼ +┌────────────────────────────────────────────────────────────────────────┐ +│ 2. generated//resources_yaml/*.yaml │ +│ Декларативное описание схемы привязок и их параметров │ +└───────────────────────────────────┬────────────────────────────────────┘ + │ (вход для генератора кода) + ▼ +┌────────────────────────────────────────────────────────────────────────┐ +│ 3. TOOLS/resource-generator/ │ +│ - templates/: универсальные шаблоны для association-ресурсов │ +│ - Генерация Create (вызов modify), Read (GET инстанса), │ +│ Delete (откат настройки) │ +│ - Автоматическая регистрация новых ресурсов в provider.go │ +└───────────────────────────────────┬────────────────────────────────────┘ + │ (компиляция) + ▼ +┌────────────────────────────────────────────────────────────────────────┐ +│ 4. provider/core/ │ +│ Универсальный CRUD-слой для ожидания тасок модификации (polling) │ +└────────────────────────────────────────────────────────────────────────┘ +``` + +### 1. `TOOLS/yaml-generator/` +* Модификации, содержащие отложенные сетевые/квотные параметры (`vIPConfigure`, `ipSpaceName/snat`), размечаются как отдельные дочерние сущности (ассоциации) родительского сервиса. +* Формируются контракты параметров: ссылка на родителя (`instance_id`), изменяемые параметры, возвращаемые идентификаторы. + +### 2. `TOOLS/resource-generator/` +* Добавляется универсальный кодогенератор ресурсов-модификаторов (association/attachment resources). +* Логика CRUD: + * **Create**: отправка запроса `POST /api/v1/svc/{service_id}/{instance_id}/modify`. + * **Read**: запрос текущего состояния родителя `GET /api/v1/svc/{service_id}/{instance_id}` и извлечение привязанных настроек. + * **Update**: повторный `modify` при изменении полей. + * **Delete**: запрос `modify` с возвратом к дефолтному состоянию (отключение SNAT / освобождение пула IP). +* Ресурсы регистрируются в едином перечне провайдера. + +### 3. `provider/core/` +* Универсальное ядро уже содержит абстракции работы с API и polling-задач. Проверяется корректность обработки асинхронных операций `modify` до их полного перехода в статус готовности. + +### Скрипты конвейера остаются неизменными: +* `01_generate_yamls.sh` +* `02_generate_resources_and_docs_v2.sh` +* `03_build_and_upload_provider.sh` +Порядок сборки и публикации не меняется.