Для улучшения работы сайта мы используем файлы cookies. Оставаясь на сайте, вы соглашаетесь с политикой обработки персональных данных.

Миграция на zVirt Provider версии 2.0

В версии 2.0 провайдера обновлены схемы ресурсов zvirt_vm и zvirt_router.

Основные изменения архитектуры:
  1. Изменение структуры сетевых интерфейсов ВМ

    Тип атрибута zvirt_vm.nic изменен с набора объектов (set of objects) на карту (map). Ключ карты — имя сетевого интерфейса, что исключает необходимость вложенного поля name внутри каждого объекта.

  2. Декомпозиция ресурса zvirt_router

    Вложенные блоки конфигурации вынесены в отдельные ресурсы для обеспечения модульности инфраструктуры:

    • интерфейсы теперь управляются через ресурс zvirt_router_interface.

    • правила NAT выделены в независимый ресурс zvirt_router_nat.

  3. Рефакторинг шлюза по умолчанию

    Структура атрибута zvirt_router.gateway изменена на вложенный атрибут (nested block) и использует синтаксис атрибутов (gateway.ip, gateway.mac_address).

Таблица 1. Сводка изменений ресурса zvirt_vm
До (provider < 2.0) После (provider >= 2.0)

Тип атрибута

Набор (set) объектов сетевых интерфейсов

Карта (map) объектов сетевых интерфейсов

Идентичность NIC

Поле name внутри каждого элемента

Ключ карты

Вложенное поле name

Обязательно

Удалено

Пустой список NIC

Опустить атрибут nic или использовать пустой набор ([])

Опустить атрибут nic или использовать nic = {}

initialization.nic_configuration

Без изменений

Без изменений

Механизм работы сетевых интерфейсов остался без изменений. Изменениям подвергся только синтаксис описания в HCL.

Таблица 2. Сводка изменений ресурса zvirt_router
До (provider < 2.0) После (provider >= 2.0)

Блоки interface на маршрутизаторе

Отдельные ресурсы zvirt_router_interface

Блоки nat_rule на маршрутизаторе

Отдельные ресурсы zvirt_router_nat

Синтаксис блока gateway { …​ }

Синтаксис вложенного атрибута: gateway = { …​ }

Необязательные поля шлюза

Поля шлюза обязательны при его конфигурации

Существующие интерфейсы и правила NAT необходимо импортировать в новые ресурсы: zvirt_router_interface и zvirt_router_nat.

Не удаляйте и не редактируйте старые записи напрямую в состоянии Terraform (state).

После завершения процедуры импорта последующее выполнение команды terraform refresh (или любое плановое обновление состояния) автоматически удалит поля interface и nat_rule из состояния ресурса zvirt_router.

1. Рекомендуемый порядок обновления

Выполняйте шаги строго в указанной последовательности. В частности, не применяйте план (apply), который создает новые дочерние ресурсы маршрутизатора до того, как будут импортированы существующие объекты.

  1. Выполните команду terraform apply с провайдером версии 1.x, чтобы подтвердить, что текущее состояние актуально.

  2. Зафиксируйте идентификаторы всех существующих маршрутизаторов, их интерфейсов и правил NAT. Идентификаторы интерфейсов и правил NAT необходимы для импорта в версию 2.0 (они отсутствуют в старой вложенной схеме маршрутизатора); получить их можно через API или интерфейс zVirt.

  3. Зафиксируйте версию провайдера в манифестах:

    terraform {
      required_providers {
        zvirt = {
          source  = "terraform-registry.orionsoft.ru/orionsoft/zvirt"
          version = "~> 2.0.0"
        }
      }
    }
  4. Обновите полностью конфигурации ресурсов zvirt_vm (а также переменные модулей и выходные данные, которые передают данные о сетевых интерфейсах) на синтаксис map, описанный ниже.

  5. Обновите польностью конфигурации ресурсов zvirt_router:

    • Перепишите блок gateway, используя синтаксис вложенных атрибутов.

    • Удалите вложенные блоки interface и nat_rule.

    • Добавьте по одному ресурсу zvirt_router_interface для каждого существующего интерфейса.

    • Добавьте по одному ресурсу zvirt_router_nat для каждого существующего правила NAT.

  6. Выполните команду terraform init -upgrade для установки провайдера версии 2.0.0.

  7. Импортируйте каждый существующий интерфейс маршрутизатора и правило NAT по его новому адресу ресурса, как описано ниже. Не выполняйте terraform apply до завершения всех операций импорта.

  8. Запустите команду terraform plan. Её фаза обновления состояния (refresh) автоматически удалит устаревшие вложенные данные об интерфейсах и правилах NAT из состояния каждого маршрутизатора.

  9. Убедитесь, что план не предлагает создать, удалить или заменить существующие ВМ, маршрутизаторы, их интерфейсы или правила NAT.

  10. Применяйте изменения (terraform apply) только в том случае, если план показывает исключительно запланированные модификации конфигурации.

После успешного завершения миграции последующее выполнение apply не должно приводить к непреднамеренным изменениям сетевых интерфейсов ВМ (NIC), интерфейсов маршрутизатора или правил NAT.

2. Миграция конфигурации маршрутизатора

Порядок действий
  1. Перепишите шлюз (gateway)

    Измените синтаксис шлюза и его вложенных значений с блочного на атрибутивный.

    Было (до версии 2.0):
    resource "zvirt_router" "router" {
      name = "router_1"
    
      gateway {
        network_id = "dda9c7d7-bf2c-41e9-b96f-6454a0bd6e88"
    
        external_fixed_ips {
          ip_address = "192.168.0.200"
          subnet_id  = "56d5dcfe-f20d-40c1-82fc-67f9f4f83c50"
        }
    
        gateway_chassis {
          chassis_name = "host-01.example.com"
          priority     = 0
        }
      }
    }
    Стало (провайдер >= 2.0):
    resource "zvirt_router" "router" {
      name = "router_1"
    
      gateway = {
        network_id = "dda9c7d7-bf2c-41e9-b96f-6454a0bd6e88"
    
        external_fixed_ips = {
          ip_address = "192.168.0.200"
          subnet_id  = "56d5dcfe-f20d-40c1-82fc-67f9f4f83c50"
        }
    
        gateway_chassis = [{
          chassis_name = "host-01.example.com"
          priority     = 0
        }]
      }
    }

    Начиная с версии 2.0, при конфигурации шлюза (gateway) поля network_id, external_fixed_ips и gateway_chassis являются обязательными.

    Если маршрутизатор не использует шлюз, атрибут gateway необходимо полностью опустить из конфигурации (вместо передачи пустого объекта).

  2. Перенос интерфейсов в отдельные ресурсы

    Замените каждый вложенный блок interface на отдельный ресурс zvirt_router_interface.

    Было (до версии 2.0):
    resource "zvirt_router" "router" {
      name = "router_1"
    
      interface {
        subnet_id = "b2a43abb-7111-442d-838c-4f241f447473"
      }
    }
    Стало (провайдер >= 2.0):
    resource "zvirt_router" "router" {
      name = "router_1"
    }
    
    resource "zvirt_router_interface" "application" {
      router_id = zvirt_router.router.id
      subnet_id = "b2a43abb-7111-442d-838c-4f241f447473"
    }

    Выполните импорт существующего интерфейса, используя составной идентификатор ROUTER_ID/INTERFACE_ID:

    terraform import zvirt_router_interface.application ROUTER_ID/INTERFACE_ID

    Повторите объявление ресурса и операцию импорта для каждого интерфейса, который ранее был вложен в маршрутизатор.

  3. Перенос правил NAT в отдельные ресурсы

    Замените каждое вложенное правило nat_rule на отдельный ресурс zvirt_router_nat. Новый ресурс также требует наличия имени (name) существующего правила NAT.

    Было (до версии 2.0):
    resource "zvirt_router" "router" {
      name = "router_1"
    
      nat_rule {
        type        = "dnat"
        external_ip = "192.168.0.201"
        logical_ip  = "10.0.0.100"
      }
    }
    Стало (провайдер >= 2.0):
    resource "zvirt_router" "router" {
      name = "router_1"
    }
    
    resource "zvirt_router_nat" "application" {
      router_id   = zvirt_router.router.id
      name        = "application-dnat"
      type        = "dnat"
      external_ip = "192.168.0.201"
      logical_ip  = "10.0.0.100"
    }

    Используйте текущее имя правила NAT и его значения из zVirt, чтобы после импорта план (plan) был пустым. Выполните импорт существующего правила, используя составной идентификатор ROUTER_ID/NAT_RULE_ID:

    terraform import zvirt_router_nat.application ROUTER_ID/NAT_RULE_ID

    Повторите объявление ресурса и операцию импорта для каждого правила NAT, которое ранее было вложено в маршрутизатор.

    Провайдер версии 2.0 также поддерживает дополнительные атрибуты NAT, а также типы fip (Floating IP) и pat (Port Address Translation). Указывать их при миграции существующих правил (nat, dnat или snat) не требуется, если они уже настроены непосредственно в zVirt.

  4. Проверка миграции маршрутизатора

    После завершения всех операций импорта выполните:

    terraform plan

    Ожидаемый результат: План должен показать только удаление устаревших полей interface и nat_rule из состояния (state) ресурса zvirt_router. СЮДА НУЖЕН ПРИМЕР ВЫВОДА

3. Миграция конфигурации сетевых интерфейсов (NIC)

  1. Перенесите каждое прежнее значение атрибута name в ключ карты (map) и удалите вложенный атрибут name.

    Один сетевой интерфейс

    Было (до версии 2.0):
    resource "zvirt_vm" "vm" {
      # ...
    
      nic {
        name            = "nic1"
        interface       = "virtio"
        vnic_profile_id = data.zvirt_vnic_profile.ovirtmgmt.id
      }
    }
    Стало (провайдер >= 2.0):
    resource "zvirt_vm" "vm" {
      # ...
    
      nic = {
        nic1 = {
          interface       = "virtio"
          vnic_profile_id = data.zvirt_vnic_profile.ovirtmgmt.id
        }
      }
    }

    Несколько сетевых интерфейсов (NIC)

    Было (до версии 2.0):
    nic {
      name            = "nic1"
      interface       = "virtio"
      vnic_profile_id = data.zvirt_vnic_profile.mgmt.id
    }
    
    nic {
      name            = "nic2"
      interface       = "e1000"
      vnic_profile_id = data.zvirt_vnic_profile.app.id
    }
    Стало (провайдер >= 2.0):
    nic = {
      nic1 = {
        interface       = "virtio"
        vnic_profile_id = data.zvirt_vnic_profile.mgmt.id
      }
      nic2 = {
        interface       = "e1000"
        vnic_profile_id = data.zvirt_vnic_profile.app.id
      }
    }
  2. Выполните рефакторинг конфигурации SDN-порта

    Вложенные настройки SDN остаются на уровне значения (value) сетевого интерфейса. В провайдере версии 2.0.0 атрибут sdn_port представляет собой одиночный вложенный объект, а не вложенный набор (set).

    Было (до версии 2.0):
    nic {
      name            = "nic1"
      interface       = "virtio"
      vnic_profile_id = data.zvirt_vnic_profile.ovirtmgmt.id
    
      sdn_port {
        security_groups_enabled = true
        security_group_ids = [
          "600f8bba-9479-4d3f-b1de-52c43950bc00",
        ]
    
        fixed_ip {
          subnet_id  = "005fb3cf-666d-4a27-ba4e-31a329fa13ea"
          ip_address = "192.168.0.1"
        }
    
        mac_learning = true
      }
    }
    Стало (провайдер >= 2.0):
    nic = {
      nic1 = {
        interface       = "virtio"
        vnic_profile_id = data.zvirt_vnic_profile.ovirtmgmt.id
    
        sdn_port = {
          security_groups_enabled = true
          security_group_ids = [
            "600f8bba-9479-4d3f-b1de-52c43950bc00",
          ]
    
          fixed_ip = {
            subnet_id  = "005fb3cf-666d-4a27-ba4e-31a329fa13ea"
            ip_address = "192.168.0.1"
          }
    
          mac_learning = true
        }
      }
    }
  3. Исправьте конфигурации виртуальных машин без сетевых интерфейсов.

    В сценарии, когда виртуальная машина не требует подключения к сети (отсутствуют NIC), следует использовать один из следующих подходов:

    • полностью исключить атрибут nic из конфигурации ресурса;

    • инициализировать атрибут nic как пустую карту (map): nic = {}.

    Пример:
    nic = {}

4. Обновление выражений и выходных данных

Замените доступ через наборы/списки на доступ через ключи карты (map).

Таблица 3. Преобразование выражений доступа к NIC при миграции на провайдер 2.0
До (provider < 2.0) После (provider >= 2.0)

tolist(zvirt_vm.vm.nic)[0]

zvirt_vm.vm.nic["nic1"]

zvirt_vm.vm.nic[0].sdn_port

zvirt_vm.vm.nic["nic1"].sdn_port

length(zvirt_vm.vm.nic)

length(zvirt_vm.vm.nic) (по-прежнему допустимо; подсчитывает количество записей в карте)

keys(zvirt_vm.vm.nic)

{ for name, nic in zvirt_vm.vm.nic : name ⇒ nic if …​ }

Пример выходных значений (Outputs)

До миграции:
output "vm1_sdn" {
  value = tolist(zvirt_vm.vm1.nic)[0].sdn_port
}
После миграции:
output "vm1_sdn" {
  value = zvirt_vm.vm1.nic["nic1"].sdn_port
}

Когда имя NIC задаётся через переменную, используйте то же самое значение в качестве ключа карты (map key). .Пример использования

variable "nic_name" {
  default = "nic1"
}

resource "zvirt_vm" "vm" {
  nic = {
    (var.nic_name) = {
      interface       = "virtio"
      vnic_profile_id = data.zvirt_vnic_profile.ovirtmgmt.id
    }
  }
}

output "sdn_port" {
  value = zvirt_vm.vm.nic[var.nic_name].sdn_port
}

5. Миграция интерфейсов модулей

В версиях провайдера 2.0 и выше, если модуль принимает или возвращает конфигурацию сетевых интерфейсов (NIC), тип данных для соответствующих переменных необходимо изменить со списка объектов (list) на коллекцию (map).

Пример преобразования переменной модуля

До миграции:
variable "nics" {
  type = list(object({
    name            = string
    interface       = string
    vnic_profile_id = string
  }))
}
После миграции:
variable "nics" {
  type = map(object({
    interface       = string
    vnic_profile_id = string
  }))
}

Пример передачи данных в модуль

Вызывающий код обеспечивает прямую передачу значения переменной:
module "vm" {
  source = "./modules/vm"
  nics   = var.nics
}

После миграции вызывающие модули должны прекратить встраивать поле name внутрь каждого элемента конфигурации и использовать вместо этого ключи карты.