Files
tf_provider/docs/30_registry/resources/vm_best_practices.md
T
2026-06-30 15:45:24 +04:00

6.6 KiB
Raw Blame History

VM Resource Best Practices

Критичные параметры для устойчивого создания VM

1. JSON Параметры - ОБЯЗАТЕЛЬНО использовать jsonencode()

НЕПРАВИЛЬНО:

resource "nubes_vm" "web" {
  access_port_list = "22,80,443"        # ОШИБКА: не JSON!
  access_ip_list   = ""                  # ОШИБКА: пустая строка!
}

ПРАВИЛЬНО:

resource "nubes_vm" "web" {
  access_port_list = jsonencode(["22", "80", "443"])
  access_ip_list   = jsonencode(["1.2.3.4", "10.0.0.0/8"])
  
  # Если нужен доступ отовсюду - не указывайте параметр:
  # access_ip_list не указан = доступ с 0.0.0.0/0
}

2. Валидация на этапе plan

Провайдер автоматически проверит:

  • access_port_list - валидный JSON массив
  • access_ip_list - валидный JSON массив (если указан)
  • vm_cpu, vm_ram, vm_disk >= 1
  • image_vm - один из разрешённых образов

Ошибка при некорректном формате:

Error: Invalid JSON Array
│ 
│   with nubes_vm.web,
│   on main.tf line 10:
│   10:   access_port_list = "22,80"
│ 
│ Value must be a valid JSON array: invalid character ',' after top-level value

3. Default значения

Параметр Default Поведение
access_ip_list ["0.0.0.0/0"] Если не указан или пустой - доступ отовсюду
deletion_protection true При terraform destroy ресурс удаляется только из state, не из облака

4. Специальные значения

ip_space_name

  • "no-needed" - не выделять внешний IP
  • Любое другое значение - имя ipSpace для публикации VIP

access_ip_list

  • Не указан → доступ с 0.0.0.0/0
  • jsonencode(["1.2.3.4"]) → доступ только с указанного IP
  • jsonencode(["10.0.0.0/8", "192.168.0.0/16"]) → доступ с нескольких подсетей

5. Lifecycle операции

Create

  1. Создаётся instance в API
  2. Создаётся operation "create"
  3. Отправляются все параметры (включая defaults)
  4. Важно: Если access_ip_list не задан, отправляется ["0.0.0.0/0"]
  5. Запускается выполнение через /run
  6. Polling до завершения (статус running)

Update (Modify)

Модифицируемые поля:

  • vm_cpu - можно увеличивать/уменьшать
  • vm_ram - можно увеличивать/уменьшать
  • vm_disk - только увеличение! (нельзя уменьшить)
  • ip_space_name - изменение внешнего IP
  • access_ip_list - изменение белого списка
  • access_port_list - изменение портов
  • need_add_zabbix_template - включить/выключить мониторинг

Delete

  • С deletion_protection = true (default): Ресурс удаляется из Terraform state, остаётся в облаке
  • С deletion_protection = false: Отправляется операция suspend (карантин 14 дней), затем ресурс удаляется из state

6. Известные ловушки (из HAR анализа)

Проблема: VM создалась, но FW зависает

Причина: Пустая строка в accessIpList или accessPortList

Решение: Провайдер теперь автоматически заменяет:

  • Пустой access_ip_list["0.0.0.0/0"]
  • Пустой vm_disk → параметр не отправляется

Проблема: ColdFusion Type Mismatch Error

Причина: Сервер получил массив вместо GUID или наоборот

Решение: Провайдер использует динамическое мапирование параметров по Code (как в Postgres ресурсе)

7. Debugging

При проблемах с созданием VM проверьте:

  1. Terraform logs (уровень TRACE):
TF_LOG=TRACE terraform apply
  1. Параметры операции в выводе:
submitVMOperationParams: sending accessIpList (ID 413) = ["0.0.0.0/0"]
  1. Статус операции в Read:
Operation Status: isSuccessful=false, isInProgress=true
Stages: [{"stage":"Добавление правил FW","isSuccessful":false}]

8. Пример корректной конфигурации

resource "nubes_vm" "app_server" {
  display_name = "app-prod-01"
  description  = "Application server"
  
  vapp_uid = nubes_vapp.my_app.id
  vm_name  = "app-prod-01"
  
  # Ресурсы (обязательно >= 1)
  vm_cpu = 2
  vm_ram = 4
  vm_disk = 50  # GB, можно только увеличивать
  
  # Образ (проверяется валидатором)
  image_vm = "Ubuntu_22-20G"
  
  # SSH доступ
  user_login      = "ubuntu"
  user_public_key = file("~/.ssh/id_ed25519.pub")
  
  # Firewall (JSON массивы!)
  access_port_list = jsonencode(["22", "80", "443"])
  access_ip_list   = jsonencode(["1.2.3.4/32", "10.0.0.0/8"])
  
  # Внешний IP
  ip_space_name = "k8s-3.ext.nubes.ru"  # или "no-needed"
  
  # Мониторинг
  need_add_zabbix_template = true
  
  # Cloud-init (опционально)
  cloud_init = <<-EOT
    #cloud-config
    packages:
      - nginx
    runcmd:
      - systemctl start nginx
  EOT
  
  # Защита от удаления
  deletion_protection = true  # default, можно не указывать
}

Миграция с предыдущих версий

Если у вас есть конфигурации без JSON валидации:

  1. Проверьте все access_port_list и access_ip_list
  2. Оберните в jsonencode()
  3. Запустите terraform plan - валидаторы покажут ошибки
  4. Исправьте до применения

Провайдер версии ≥ v1.1.0 отклонит некорректные конфигурации на этапе plan, что предотвратит зависание на FW правилах.