feat: add minimal PROD VM example
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -74,14 +74,15 @@ Terraform. Репозиторий — **эталонные примеры**, н
|
||||
|
||||
| Папка | Что это | Состояние | Документация |
|
||||
|---|---|---|---|
|
||||
| **`fullpipe_chain/`** | vDC → Edge → внешние IP → SNAT → vApp → ВМ → Штурвал (полная цепочка) | **рекомендовано использовать** — повторяет рабочую конфигурацию стенда | `/nubes-dev/curated/pipeline/vdc_edge_ip_snat/` |
|
||||
| **`vm_v3_minimal/`** | ручная организация → vDC → Edge → 3 IP → SNAT → vApp → одна ВМ, без Штурвала | отдельный VM-сценарий, проверенный на PROD 2026-10-17 | — |
|
||||
| **`fullpipe_chain/`** | vDC → Edge → внешние IP → SNAT → vApp → ВМ → Штурвал (полная цепочка) | расширенный сценарий с Штурвалом; VM/vApp в прежнем опыте пользователя не удалось завершить из-за проблемы с vApp | `/nubes-dev/curated/pipeline/vdc_edge_ip_snat/` |
|
||||
| **`Maria_CRUD/`** | MariaDB + три приложения (Lucee/Flask/Node.js) + HTTP-проверка | проверен на TEST-стенде | `/nubes-test/curated/mariadb/three_apps/` |
|
||||
| `CRUD/` | PostgreSQL + три приложения (Lucee/Flask/Node.js) | черновик (устаревшая схема, старый пин провайдера) — **с оговорками** | `/nubes-test/curated/crud/three_apps/` |
|
||||
| `modify_resources/` | внешние IP на организации + SNAT на шлюзе (для уже существующих услуг) | черновик | — |
|
||||
|
||||
**Что рекомендовать пользователю:** `fullpipe_chain` (полный цикл) или `Maria_CRUD`
|
||||
(проверенный CRUD-пример). Остальные папки — черновики от прошлых работ: могут содержать
|
||||
неактуальные версии провайдера и работать некорректно. Не выдавай черновик за рабочий образец.
|
||||
**Что рекомендовать пользователю:** для отдельной ВМ — `vm_v3_minimal`; для сценария
|
||||
с Штурвалом — `fullpipe_chain`; для CRUD — `Maria_CRUD`. Не используй `fullpipe_chain`
|
||||
как доказательство успешного самостоятельного развёртывания VM/vApp.
|
||||
|
||||
---
|
||||
|
||||
@@ -235,6 +236,20 @@ provider "nubes" {
|
||||
`terraform.tfvars`: `api_token`, `organization`, `nsxt_uid` (UUID шлюза Edge из карточки
|
||||
услуги), `ip_space_name`, `ip_count`.
|
||||
|
||||
### 6.5. `vm_v3_minimal` — одна ВМ без дополнительных рабочих нагрузок
|
||||
|
||||
Создаёт только цепочку **vDC → Edge → выделение IP → SNAT → vApp → ВМ** внутри
|
||||
организации, которую пользователь предварительно создал вручную в ЛК. Штурвал,
|
||||
базы данных и приложения в пример не входят.
|
||||
|
||||
**Минимум IP для проверенного PROD-сценария — 3.** При `org_vip_count = 2` API
|
||||
сообщил, что свободных IP нет и для создания ВМ требуется ещё один; с `3` развёртывание
|
||||
ВМ запустилось. Если другие услуги используют тот же ipSpace, квоту нужно увеличить.
|
||||
Не делай вывод о занятых адресах только по статусам услуг в ЛК.
|
||||
|
||||
Пример основан на отдельном сценарии `PROD_STAND/VM_TF_Docs`; он не зависит от
|
||||
`fullpipe_chain` и не включает его дополнительные ресурсы.
|
||||
|
||||
---
|
||||
|
||||
## 7. Секреты — жёсткое правило
|
||||
@@ -352,4 +367,3 @@ provider "nubes" {
|
||||
| **HCL** | язык конфигурации Terraform (файлы `.tf`) |
|
||||
| `terraform.tfvars` | файл значений переменных; в этом репозитории — в `.gitignore` |
|
||||
| `terraform.tfstate` | файл состояния Terraform; хранит соответствие «код ↔ облако» |
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
# Минимальная цепочка для одной ВМ (PROD)
|
||||
|
||||
Пример создаёт одну ВМ и только необходимые для неё услуги:
|
||||
|
||||
```text
|
||||
организация (создана вручную в ЛК)
|
||||
-> vDC
|
||||
-> Edge с routed-сетью
|
||||
-> выделение IP организации (минимум 3)
|
||||
-> SNAT
|
||||
-> vApp
|
||||
-> одна ВМ
|
||||
```
|
||||
|
||||
Штурвал, базы данных и приложения в примере отсутствуют. Он основан на успешно
|
||||
запущенной в PROD конфигурации `VM_TF_Docs`, а не на `fullpipe_chain`.
|
||||
Провайдер зафиксирован на PROD-версии `1.5.0`.
|
||||
|
||||
## Важное условие: организация создаётся вручную
|
||||
|
||||
До запуска создайте организацию **«Организация в Cloud Director»** через ЛК. Terraform
|
||||
не создаёт и не удаляет организацию: `nubes_vc_vdc` получает её имя или UUID через
|
||||
`organization`.
|
||||
|
||||
В ЛК проверьте, что организации доступны выбранные resource pool, Provider VDC,
|
||||
storage policy и IP space. Значения из примера (`msk1`, `Intel Cascade Lake 3.1`,
|
||||
`SSD SDS`) подтверждены для использованного PROD-пула; для другого пула их нужно
|
||||
заменить на значения из ЛК.
|
||||
|
||||
## Почему выделяется 3 IP
|
||||
|
||||
Для проверенной цепочки с одной ВМ минимальное значение `org_vip_count` — **3**.
|
||||
При значении 2 API сообщил, что свободных IP — 0, а для операции требуется ещё 1;
|
||||
при значении 3 развёртывание ВМ запустилось. Поэтому в этом примере не уменьшайте
|
||||
квоту до 2, даже если из дополнительных потребителей IP оставлена только одна ВМ.
|
||||
|
||||
`org_vip_count` задаёт количество IP в выбранном `ip_space_name` на организации —
|
||||
это не количество адресов, которое сама ВМ получит. Точное внутреннее распределение
|
||||
резервов платформой эта конфигурация не показывает. Если другие услуги используют
|
||||
адреса из того же IP space или там уже есть занятые адреса, квоту нужно увеличить.
|
||||
Список услуг со статусами `running`/`suspended` сам по себе не показывает, какие IP
|
||||
заняты.
|
||||
|
||||
В конфигурации VM установлен `same_snat = true`: согласно PROD-схеме при этом для ВМ
|
||||
создаётся собственный внешний IP. SNAT на Edge также задаётся отдельным ресурсом,
|
||||
как в проверенной цепочке.
|
||||
|
||||
## Подготовка параметров
|
||||
|
||||
1. Скопируйте шаблоны:
|
||||
|
||||
```bash
|
||||
cp terraform.tfvars.example terraform.tfvars
|
||||
cp secrets.auto.tfvars.example secrets.auto.tfvars
|
||||
```
|
||||
|
||||
2. В `secrets.auto.tfvars` замените заглушку на PROD API token из ЛК → Профиль →
|
||||
Токены → «Технический». Не присылайте и не коммитьте этот файл.
|
||||
3. В `terraform.tfvars` замените:
|
||||
- `organization` на имя или UUID вручную созданной организации;
|
||||
- `ip_space_name` на точное имя IP space из ЛК;
|
||||
- `vm_user_public_key` на содержимое вашего `~/.ssh/id_ed25519.pub`;
|
||||
- `vm_access_ip_list` на доверенный публичный IP/CIDR для входящего доступа.
|
||||
4. Убедитесь, что имена vDC, Edge, vApp и ВМ уникальны в организации. Не оставляйте
|
||||
значения-заглушки `REPLACE_WITH_...`.
|
||||
5. Если выбранный resource pool отличается от проверенного PROD-пула, замените
|
||||
`vdc_network_provider`, `vdc_provider_vdc`, `vdc_storage_config`, DNS и routed subnet
|
||||
на значения, допустимые в ЛК. Routed subnet `/24` не должен пересекаться с другой сетью.
|
||||
|
||||
Все переменные и значения по умолчанию прокомментированы в `variables.tf` и
|
||||
`terraform.tfvars.example`. Параметры ресурсов сверены с PROD YAML-схемами.
|
||||
|
||||
## Запуск
|
||||
|
||||
Команды выполняет владелец инфраструктуры; `apply` в этом примере не запускался:
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform validate
|
||||
terraform plan
|
||||
```
|
||||
|
||||
Проверьте план: ожидаются шесть услуг — vDC, Edge, выделение IP на организации,
|
||||
SNAT, vApp и ВМ. Убедитесь, что в плане нет неожиданных изменений уже существующих
|
||||
услуг. Только после проверки владелец запускает:
|
||||
|
||||
```bash
|
||||
terraform apply
|
||||
```
|
||||
|
||||
После завершения:
|
||||
|
||||
```bash
|
||||
terraform output vm_state_flat
|
||||
```
|
||||
|
||||
`externalConnect` — внешний адрес ВМ, `internalConnect` — адрес в routed-сети,
|
||||
`fqdn` — DNS-имя, если платформа его вернула.
|
||||
|
||||
## Параметры ВМ и операции
|
||||
|
||||
- Образ `Ubuntu_22-20G` включает базовый диск 20 GB; `vm_disk = 128` задаёт
|
||||
**дополнительный** диск.
|
||||
- `vm_access_port_list` разрешает только заданные порты. `vm_access_ip_list` ограничивает
|
||||
адреса-источники; не оставляйте доступ SSH открытым для `0.0.0.0/0`, если это не требуется.
|
||||
- `git_revision` оставлен `null` при создании. Новое значение этого маркера запускает
|
||||
redeploy при последующем Update.
|
||||
- `reconcile_trigger` также оставлен `null` при создании. Новое значение запускает
|
||||
reconcile при Update; при Create reconcile не выполняется.
|
||||
- В проверке PROD от 17.10.2026 файл-маркер в `/home/ubuntu` отсутствовал после redeploy.
|
||||
Считайте локальные данные ВМ потенциально теряемыми при redeploy и храните важные данные
|
||||
вне системного диска.
|
||||
|
||||
## Состав файлов
|
||||
|
||||
| Файл | Назначение |
|
||||
|---|---|
|
||||
| `versions.tf` | Версия Terraform и PROD-провайдера |
|
||||
| `provider.tf` | Подключение к PROD API |
|
||||
| `variables.tf` | Типы, значения по умолчанию и пояснения к входным переменным |
|
||||
| `vdc.tf` | Виртуальный датацентр |
|
||||
| `edge.tf` | Edge и routed-сеть |
|
||||
| `network.tf` | Квота IP организации и SNAT |
|
||||
| `vm.tf` | vApp и одна ВМ |
|
||||
| `outputs.tf` | Идентификаторы услуг и состояние ВМ |
|
||||
| `terraform.tfvars.example` | Несекретные значения и параметры примера |
|
||||
| `secrets.auto.tfvars.example` | Шаблон локального файла для API token |
|
||||
@@ -0,0 +1,35 @@
|
||||
# Create the perimeter gateway and its routed network inside the VDC.
|
||||
resource "nubes_vc_nsxt" "edge" {
|
||||
# Name shown for this Edge service in the personal account.
|
||||
resource_name = var.nsxt_resource_name
|
||||
|
||||
# Attach the gateway directly to a VDC, not to a VDC group.
|
||||
vdc_type = "vdc"
|
||||
|
||||
# UUID of the VDC created above; this reference also orders creation.
|
||||
vdc_uid = nubes_vc_vdc.vdc.id
|
||||
|
||||
# AVI/ALB is not needed for this standalone VM example.
|
||||
need_enable_avi = false
|
||||
|
||||
# Only required when AVI/ALB is enabled; keep it null when ALB is disabled.
|
||||
virtual_services_count = null
|
||||
|
||||
# Routed subnet and DNS servers assigned to VMs behind this Edge.
|
||||
routed_net_configuration = {
|
||||
# Non-overlapping /24 range for the routed network.
|
||||
ip_addr_pool = var.nsxt_ip_addr_pool
|
||||
|
||||
# Primary DNS server configured in VMs.
|
||||
main_dns = var.nsxt_main_dns
|
||||
|
||||
# Secondary DNS server configured in VMs.
|
||||
second_dns = var.nsxt_second_dns
|
||||
}
|
||||
|
||||
# Allow provider destroy handling to delete the Edge when dependencies permit.
|
||||
keep_on_destroy = false
|
||||
|
||||
# Reuse an existing same-name Edge rather than failing during Create.
|
||||
adopt_existing_on_create = true
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# Allocate organization-level public IP capacity after the VDC and Edge exist.
|
||||
resource "nubes_vc_org_ip_allocation" "org_ip" {
|
||||
# Existing organization used by the VDC.
|
||||
organization = var.organization
|
||||
|
||||
# Configure the selected IP space with the tested minimum count of 3.
|
||||
# The API expects count as a string inside the vIPConfigure JSON array.
|
||||
vip_configure = jsonencode([
|
||||
{
|
||||
name = var.ip_space_name
|
||||
count = tostring(var.org_vip_count)
|
||||
}
|
||||
])
|
||||
|
||||
# Keep the organization allocation when this Terraform resource is destroyed.
|
||||
keep_on_destroy = true
|
||||
|
||||
# PROD exposes the organization's usable IP spaces after the VDC and Edge exist.
|
||||
depends_on = [nubes_vc_nsxt.edge]
|
||||
}
|
||||
|
||||
# Enable the tested SNAT configuration on the Edge using the same IP space.
|
||||
resource "nubes_vc_nsxt_snat" "snat" {
|
||||
# UUID of the Edge created above.
|
||||
nsxt_uid = nubes_vc_nsxt.edge.id
|
||||
|
||||
# IP space allocated to the organization in the resource above.
|
||||
ip_space_name = var.ip_space_name
|
||||
|
||||
# Leave SNAT enabled when this Terraform resource is destroyed.
|
||||
keep_on_destroy = true
|
||||
|
||||
# The IP space must be allocated before SNAT is configured.
|
||||
depends_on = [nubes_vc_org_ip_allocation.org_ip]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
# UUID of the created VDC.
|
||||
output "vdc_id" {
|
||||
description = "UUID of the VDC."
|
||||
value = nubes_vc_vdc.vdc.id
|
||||
}
|
||||
|
||||
# UUID of the created Edge.
|
||||
output "edge_id" {
|
||||
description = "UUID of the Edge gateway."
|
||||
value = nubes_vc_nsxt.edge.id
|
||||
}
|
||||
|
||||
# UUID of the created vApp.
|
||||
output "vapp_id" {
|
||||
description = "UUID of the vApp."
|
||||
value = nubes_vapp.vapp.id
|
||||
}
|
||||
|
||||
# UUID of the created VM.
|
||||
output "vm_id" {
|
||||
description = "UUID of the VM."
|
||||
value = nubes_vc_vm_v3.vm.id
|
||||
}
|
||||
|
||||
# VM IP addresses and connection data returned by the API.
|
||||
output "vm_state_flat" {
|
||||
description = "Flat VM state; inspect externalConnect, internalConnect, and fqdn."
|
||||
value = nubes_vc_vm_v3.vm.state_out_flat
|
||||
}
|
||||
|
||||
# The configured organization allocation count, not the count of addresses in use.
|
||||
output "org_ip_allocation" {
|
||||
description = "Configured IP-space name and organization allocation count."
|
||||
value = {
|
||||
ip_space_name = var.ip_space_name
|
||||
count = var.org_vip_count
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Connect to the Nubes PROD API. The token is stored separately in
|
||||
# secrets.auto.tfvars and must never be committed.
|
||||
provider "nubes" {
|
||||
api_token = var.api_token
|
||||
api_endpoint = var.api_endpoint
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Copy to secrets.auto.tfvars and insert a Nubes PROD API token.
|
||||
# secrets.auto.tfvars is ignored by git; never commit the real token.
|
||||
api_token = "REPLACE_WITH_NUBES_PROD_API_TOKEN"
|
||||
@@ -0,0 +1,74 @@
|
||||
# Copy this file to terraform.tfvars and replace organization-specific values.
|
||||
# Put the API token only in secrets.auto.tfvars, never in this file.
|
||||
|
||||
# Existing organization created manually in the Nubes personal account.
|
||||
organization = "REPLACE_WITH_ORGANIZATION_NAME_OR_UUID"
|
||||
|
||||
# Exact IP space visible to this organization in the personal account.
|
||||
ip_space_name = "internet-no-antiddos-v1"
|
||||
|
||||
# Tested minimum for this VM-only PROD chain. Two IPs left no free address
|
||||
# when the VM requested its external IP; three allowed the deployment to start.
|
||||
org_vip_count = 3
|
||||
|
||||
# API endpoint for the PROD stand.
|
||||
api_endpoint = "https://lk-api-gateway.ngcloud.ru/api/v1/svc"
|
||||
|
||||
# Unique VDC service name.
|
||||
vdc_resource_name = "vm-minimal-vdc"
|
||||
|
||||
# Values from the tested PROD resource pool. Replace with values available
|
||||
# to the manually created organization if its resource pool differs.
|
||||
vdc_network_provider = "msk1"
|
||||
vdc_provider_vdc = "Intel Cascade Lake 3.1"
|
||||
|
||||
# VDC capacity: vCPU, guaranteed share (0/50/80), and RAM in GB.
|
||||
vdc_cpu_allocated = 8
|
||||
vdc_cpu_guaranteed = 0
|
||||
vdc_mem_allocated = 200
|
||||
|
||||
# JSON array of storage policies available to the selected Provider VDC.
|
||||
# Confirm the policy name and size in the personal account before applying.
|
||||
vdc_storage_config = "[{\"name\":\"SSD SDS\",\"size\":\"2000\"}]"
|
||||
|
||||
# Unique Edge service name.
|
||||
nsxt_resource_name = "vm-minimal-edge"
|
||||
|
||||
# Non-overlapping /24 routed subnet plus primary and secondary VM DNS servers.
|
||||
nsxt_ip_addr_pool = "10.10.102.0/24"
|
||||
nsxt_main_dns = "81.22.46.22"
|
||||
nsxt_second_dns = "185.247.187.77"
|
||||
|
||||
# Unique vApp service name and vApp name.
|
||||
vapp_resource_name = "vm-minimal-vapp"
|
||||
vapp_name = "vm-minimal-vapp"
|
||||
|
||||
# Unique VM service name and hostname/IP-set name.
|
||||
vm_resource_name = "vm-minimal"
|
||||
vm_name = "vm-minimal"
|
||||
|
||||
# Tested VM sizing: Ubuntu base image (20 GB) plus 128 GB additional disk.
|
||||
vm_image = "Ubuntu_22-20G"
|
||||
vm_cpu = 2
|
||||
vm_ram = 4
|
||||
vm_disk = 128
|
||||
|
||||
# Linux account name and your OpenSSH PUBLIC key.
|
||||
vm_user_login = "ubuntu"
|
||||
vm_user_public_key = "ssh-ed25519 REPLACE_WITH_YOUR_PUBLIC_KEY"
|
||||
|
||||
# Inbound ports. Narrow the source CIDR below to trusted addresses.
|
||||
vm_access_port_list = [
|
||||
{ port = "22", type = "tcp" },
|
||||
{ port = "80", type = "tcp" }
|
||||
]
|
||||
vm_access_ip_list = ["REPLACE_WITH_YOUR_PUBLIC_IP/32"]
|
||||
|
||||
# The tested VM gets its own external IP; do not change without checking
|
||||
# the consequences for inbound access.
|
||||
vm_same_snat = true
|
||||
|
||||
# Keep both triggers null for initial creation. To request an operation later,
|
||||
# set its marker to a new, unique value.
|
||||
git_revision = null
|
||||
reconcile_trigger = null
|
||||
@@ -0,0 +1,203 @@
|
||||
# =============================================================================
|
||||
# Inputs for the standalone PROD VM example.
|
||||
# Values that depend on the organization or resource pool are in
|
||||
# terraform.tfvars.example; the API token is in secrets.auto.tfvars.example.
|
||||
# =============================================================================
|
||||
|
||||
variable "api_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
description = "Nubes PROD API token from the Technical token section in the personal account."
|
||||
}
|
||||
|
||||
variable "api_endpoint" {
|
||||
type = string
|
||||
default = "https://lk-api-gateway.ngcloud.ru/api/v1/svc"
|
||||
description = "Nubes PROD API endpoint. Change only when targeting another stand."
|
||||
}
|
||||
|
||||
variable "organization" {
|
||||
type = string
|
||||
description = "Name or UUID of the Cloud Director organization created manually in the personal account."
|
||||
}
|
||||
|
||||
variable "ip_space_name" {
|
||||
type = string
|
||||
description = "Exact IP space name available to this organization; used for the allocation, Edge SNAT, and VM."
|
||||
}
|
||||
|
||||
variable "org_vip_count" {
|
||||
type = number
|
||||
default = 3
|
||||
description = "Organization IP allocation count. Three is the tested minimum for this VM-only deployment; increase if other services need IPs from this space."
|
||||
|
||||
validation {
|
||||
condition = var.org_vip_count >= 3 && floor(var.org_vip_count) == var.org_vip_count
|
||||
error_message = "This tested VM-only example requires at least 3 IPs; use a whole number and increase it for additional consumers."
|
||||
}
|
||||
}
|
||||
|
||||
variable "vdc_resource_name" {
|
||||
type = string
|
||||
default = "vm-minimal-vdc"
|
||||
description = "Unique service name for the virtual data center."
|
||||
}
|
||||
|
||||
variable "vdc_network_provider" {
|
||||
type = string
|
||||
default = "msk1"
|
||||
description = "Network provider selected for this organization in the VDC creation form."
|
||||
}
|
||||
|
||||
variable "vdc_provider_vdc" {
|
||||
type = string
|
||||
default = "Intel Cascade Lake 3.1"
|
||||
description = "Provider VDC selected in the personal account; it must be compatible with the network provider."
|
||||
}
|
||||
|
||||
variable "vdc_cpu_allocated" {
|
||||
type = number
|
||||
default = 8
|
||||
description = "Number of vCPUs allocated to the VDC."
|
||||
}
|
||||
|
||||
variable "vdc_cpu_guaranteed" {
|
||||
type = number
|
||||
default = 0
|
||||
description = "Guaranteed vCPU percentage. PROD schema allows 0, 50, or 80; this value is fixed at VDC creation."
|
||||
|
||||
validation {
|
||||
condition = contains([0, 50, 80], var.vdc_cpu_guaranteed)
|
||||
error_message = "vdc_cpu_guaranteed must be 0, 50, or 80."
|
||||
}
|
||||
}
|
||||
|
||||
variable "vdc_mem_allocated" {
|
||||
type = number
|
||||
default = 200
|
||||
description = "Memory allocated to the VDC, in GB."
|
||||
}
|
||||
|
||||
variable "vdc_storage_config" {
|
||||
type = string
|
||||
default = "[{\"name\":\"SSD SDS\",\"size\":\"2000\"}]"
|
||||
description = "JSON array of storage policies available to the selected Provider VDC; size is in GB."
|
||||
}
|
||||
|
||||
variable "nsxt_resource_name" {
|
||||
type = string
|
||||
default = "vm-minimal-edge"
|
||||
description = "Unique service name for the perimeter Edge gateway."
|
||||
}
|
||||
|
||||
variable "nsxt_ip_addr_pool" {
|
||||
type = string
|
||||
default = "10.10.102.0/24"
|
||||
description = "Unused /24 routed-network range for this Edge. Verify that it does not overlap another network."
|
||||
}
|
||||
|
||||
variable "nsxt_main_dns" {
|
||||
type = string
|
||||
default = "81.22.46.22"
|
||||
description = "Primary DNS server assigned to VMs on the routed network."
|
||||
}
|
||||
|
||||
variable "nsxt_second_dns" {
|
||||
type = string
|
||||
default = "185.247.187.77"
|
||||
description = "Secondary DNS server assigned to VMs on the routed network."
|
||||
}
|
||||
|
||||
variable "vapp_resource_name" {
|
||||
type = string
|
||||
default = "vm-minimal-vapp"
|
||||
description = "Unique service name for the vApp in the personal account."
|
||||
}
|
||||
|
||||
variable "vapp_name" {
|
||||
type = string
|
||||
default = "vm-minimal-vapp"
|
||||
description = "Unique vApp name matching the platform pattern; it is used when forming the VM DNS name."
|
||||
}
|
||||
|
||||
variable "vm_resource_name" {
|
||||
type = string
|
||||
default = "vm-minimal"
|
||||
description = "Unique service name for the virtual machine in the personal account."
|
||||
}
|
||||
|
||||
variable "vm_name" {
|
||||
type = string
|
||||
default = "vm-minimal"
|
||||
description = "VM name matching the platform pattern; it also identifies the VM IP set."
|
||||
}
|
||||
|
||||
variable "vm_image" {
|
||||
type = string
|
||||
default = "Ubuntu_22-20G"
|
||||
description = "Available PROD VM image. The base disk size is part of the image and cannot be changed here."
|
||||
}
|
||||
|
||||
variable "vm_cpu" {
|
||||
type = number
|
||||
default = 2
|
||||
description = "Number of VM vCPUs (PROD schema range: 1-64)."
|
||||
}
|
||||
|
||||
variable "vm_ram" {
|
||||
type = number
|
||||
default = 4
|
||||
description = "VM memory in GB (PROD schema range: 1-256)."
|
||||
}
|
||||
|
||||
variable "vm_disk" {
|
||||
type = number
|
||||
default = 128
|
||||
description = "Additional VM disk size in GB. The image supplies the separate base disk."
|
||||
}
|
||||
|
||||
variable "vm_user_login" {
|
||||
type = string
|
||||
default = "ubuntu"
|
||||
description = "Linux account created for SSH access; it is set during VM creation."
|
||||
}
|
||||
|
||||
variable "vm_user_public_key" {
|
||||
type = string
|
||||
description = "Your OpenSSH public key, such as the contents of ~/.ssh/id_ed25519.pub. Never put a private key here."
|
||||
}
|
||||
|
||||
variable "vm_access_port_list" {
|
||||
type = list(object({
|
||||
port = string
|
||||
type = string
|
||||
}))
|
||||
default = [
|
||||
{ port = "22", type = "tcp" },
|
||||
{ port = "80", type = "tcp" }
|
||||
]
|
||||
description = "Inbound VM ports and protocols. Restrict this list to the services the VM actually needs."
|
||||
}
|
||||
|
||||
variable "vm_access_ip_list" {
|
||||
type = list(string)
|
||||
description = "Source IP addresses or CIDRs allowed to reach the VM. Set this to trusted addresses; avoid 0.0.0.0/0 where possible."
|
||||
}
|
||||
|
||||
variable "vm_same_snat" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "When true, the VM is published through its own external IP created during deployment."
|
||||
}
|
||||
|
||||
variable "git_revision" {
|
||||
type = string
|
||||
default = null
|
||||
description = "Optional redeploy trigger. Set a new non-empty marker to request redeploy on Update; leave null for normal VM creation."
|
||||
}
|
||||
|
||||
variable "reconcile_trigger" {
|
||||
type = string
|
||||
default = null
|
||||
description = "Optional reconcile trigger. Change the marker to request reconcile on Update; reconcile does not run on Create."
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
# Create a VDC inside the organization that already exists in the personal account.
|
||||
resource "nubes_vc_vdc" "vdc" {
|
||||
# Name shown for this VDC service in the personal account.
|
||||
resource_name = var.vdc_resource_name
|
||||
|
||||
# Existing organization name or UUID; this example does not create the organization.
|
||||
organization_uid = var.organization
|
||||
|
||||
# Resource-platform network provider chosen for this organization.
|
||||
network_provider = var.vdc_network_provider
|
||||
|
||||
# Provider VDC compatible with the selected network provider.
|
||||
provider_vdc = var.vdc_provider_vdc
|
||||
|
||||
# vCPU capacity allocated to the VDC.
|
||||
cpu_allocated = var.vdc_cpu_allocated
|
||||
|
||||
# Guaranteed share of allocated vCPU; PROD accepts 0, 50, or 80.
|
||||
cpu_guaranteed = var.vdc_cpu_guaranteed
|
||||
|
||||
# Memory capacity allocated to the VDC, in GB.
|
||||
mem_allocated = var.vdc_mem_allocated
|
||||
|
||||
# JSON storage-policy array; each policy name must exist in the selected Provider VDC.
|
||||
storage_config = var.vdc_storage_config
|
||||
|
||||
# Suspend the VDC rather than fully deleting it on terraform destroy.
|
||||
suspend_on_destroy = true
|
||||
|
||||
# Adopt an existing same-name VDC instead of failing during Create.
|
||||
adopt_existing_on_create = true
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# This standalone example targets the tested Nubes PROD provider.
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
|
||||
required_providers {
|
||||
nubes = {
|
||||
source = "tf-registry.containerk8s.services.ngcloud.ru/nubes/nubes"
|
||||
version = "1.5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
# Create the vApp after the VDC, Edge, organization IP allocation, and SNAT are ready.
|
||||
resource "nubes_vapp" "vapp" {
|
||||
# Name shown for this vApp service in the personal account.
|
||||
resource_name = var.vapp_resource_name
|
||||
|
||||
# vApp name; must be unique in the organization and match the platform naming pattern.
|
||||
vapp_name = var.vapp_name
|
||||
|
||||
# UUID of the VDC where the vApp will reside.
|
||||
vdc_uid = nubes_vc_vdc.vdc.id
|
||||
|
||||
# UUID of the Edge whose routed network will be used by the vApp.
|
||||
nsxt_uid = nubes_vc_nsxt.edge.id
|
||||
|
||||
# Suspend the vApp rather than fully deleting it on terraform destroy.
|
||||
suspend_on_destroy = true
|
||||
|
||||
# Adopt an existing same-name vApp rather than failing during Create.
|
||||
adopt_existing_on_create = true
|
||||
|
||||
# The tested PROD vApp deployment requires the IP/SNAT configuration to be ready.
|
||||
depends_on = [nubes_vc_nsxt_snat.snat]
|
||||
}
|
||||
|
||||
# Create one VM inside the vApp.
|
||||
resource "nubes_vc_vm_v3" "vm" {
|
||||
# Name shown for this VM service in the personal account.
|
||||
resource_name = var.vm_resource_name
|
||||
|
||||
# VM hostname/IP-set name; it must match the platform naming pattern.
|
||||
vm_name = var.vm_name
|
||||
|
||||
# UUID of the vApp created above.
|
||||
vapp_uid = nubes_vapp.vapp.id
|
||||
|
||||
# Operating-system image; its base disk is separate from vm_disk.
|
||||
image_vm = var.vm_image
|
||||
|
||||
# Number of vCPUs allocated to the VM.
|
||||
vm_cpu = var.vm_cpu
|
||||
|
||||
# VM memory in GB.
|
||||
vm_ram = var.vm_ram
|
||||
|
||||
# Additional disk size in GB, excluding the image's base disk.
|
||||
vm_disk = var.vm_disk
|
||||
|
||||
# Linux account created for SSH access.
|
||||
user_login = var.vm_user_login
|
||||
|
||||
# Public key installed for that account; never use a private key here.
|
||||
user_public_key = var.vm_user_public_key
|
||||
|
||||
# Organization IP space used by this VM.
|
||||
ip_space_name = var.ip_space_name
|
||||
|
||||
# true gives this VM its own external IP during deployment.
|
||||
same_snat = var.vm_same_snat
|
||||
|
||||
# JSON-encoded inbound port/protocol allow-list.
|
||||
access_port_list = jsonencode(var.vm_access_port_list)
|
||||
|
||||
# JSON-encoded source IP/CIDR allow-list; keep it as narrow as practical.
|
||||
access_ip_list = jsonencode(var.vm_access_ip_list)
|
||||
|
||||
# Optional marker: changing it requests redeploy on Update.
|
||||
git_revision = var.git_revision
|
||||
|
||||
# Optional marker: changing it requests reconcile on Update, not on Create.
|
||||
reconcile_trigger = var.reconcile_trigger
|
||||
|
||||
# Suspend the VM rather than fully deleting it on terraform destroy.
|
||||
suspend_on_destroy = true
|
||||
|
||||
# Adopt an existing same-name VM rather than failing during Create.
|
||||
adopt_existing_on_create = true
|
||||
}
|
||||
Reference in New Issue
Block a user