Миграция на zVirt Provider версии 2.0
В версии 2.0 провайдера обновлены схемы ресурсов zvirt_vm и zvirt_router.
-
Изменение структуры сетевых интерфейсов ВМ
Тип атрибута
zvirt_vm.nicизменен с набора объектов (set of objects) на карту (map). Ключ карты — имя сетевого интерфейса, что исключает необходимость вложенного поляnameвнутри каждого объекта. -
Декомпозиция ресурса
zvirt_routerВложенные блоки конфигурации вынесены в отдельные ресурсы для обеспечения модульности инфраструктуры:
-
интерфейсы теперь управляются через ресурс
zvirt_router_interface. -
правила NAT выделены в независимый ресурс
zvirt_router_nat.
-
-
Рефакторинг шлюза по умолчанию
Структура атрибута
zvirt_router.gatewayизменена на вложенный атрибут (nested block) и использует синтаксис атрибутов (gateway.ip, gateway.mac_address).
| До (provider < 2.0) | После (provider >= 2.0) | |
|---|---|---|
Тип атрибута |
Набор (set) объектов сетевых интерфейсов |
Карта (map) объектов сетевых интерфейсов |
Идентичность NIC |
Поле name внутри каждого элемента |
Ключ карты |
Вложенное поле name |
Обязательно |
Удалено |
Пустой список NIC |
Опустить атрибут nic или использовать пустой набор ([]) |
Опустить атрибут nic или использовать nic = {} |
|
Без изменений |
Без изменений |
Механизм работы сетевых интерфейсов остался без изменений. Изменениям подвергся только синтаксис описания в HCL.
| До (provider < 2.0) | После (provider >= 2.0) |
|---|---|
Блоки |
Отдельные ресурсы |
Блоки |
Отдельные ресурсы |
Синтаксис блока |
Синтаксис вложенного атрибута: |
Необязательные поля шлюза |
Поля шлюза обязательны при его конфигурации |
Существующие интерфейсы и правила NAT необходимо импортировать в новые ресурсы: zvirt_router_interface и zvirt_router_nat.
|
Не удаляйте и не редактируйте старые записи напрямую в состоянии Terraform (state). После завершения процедуры импорта последующее выполнение команды terraform refresh (или любое плановое обновление состояния) автоматически удалит поля |
1. Рекомендуемый порядок обновления
|
Выполняйте шаги строго в указанной последовательности. В частности, не применяйте план (apply), который создает новые дочерние ресурсы маршрутизатора до того, как будут импортированы существующие объекты. |
-
Выполните команду
terraform applyс провайдером версии 1.x, чтобы подтвердить, что текущее состояние актуально. -
Зафиксируйте идентификаторы всех существующих маршрутизаторов, их интерфейсов и правил NAT. Идентификаторы интерфейсов и правил NAT необходимы для импорта в версию 2.0 (они отсутствуют в старой вложенной схеме маршрутизатора); получить их можно через API или интерфейс zVirt.
-
Зафиксируйте версию провайдера в манифестах:
terraform { required_providers { zvirt = { source = "terraform-registry.orionsoft.ru/orionsoft/zvirt" version = "~> 2.0.0" } } } -
Обновите полностью конфигурации ресурсов
zvirt_vm(а также переменные модулей и выходные данные, которые передают данные о сетевых интерфейсах) на синтаксисmap, описанный ниже. -
Обновите польностью конфигурации ресурсов
zvirt_router:-
Перепишите блок
gateway, используя синтаксис вложенных атрибутов. -
Удалите вложенные блоки
interfaceиnat_rule. -
Добавьте по одному ресурсу
zvirt_router_interfaceдля каждого существующего интерфейса. -
Добавьте по одному ресурсу
zvirt_router_natдля каждого существующего правила NAT.
-
-
Выполните команду
terraform init -upgradeдля установки провайдера версии 2.0.0. -
Импортируйте каждый существующий интерфейс маршрутизатора и правило NAT по его новому адресу ресурса, как описано ниже. Не выполняйте terraform apply до завершения всех операций импорта.
-
Запустите команду
terraform plan. Её фаза обновления состояния (refresh) автоматически удалит устаревшие вложенные данные об интерфейсах и правилах NAT из состояния каждого маршрутизатора. -
Убедитесь, что план не предлагает создать, удалить или заменить существующие ВМ, маршрутизаторы, их интерфейсы или правила NAT.
-
Применяйте изменения (terraform apply) только в том случае, если план показывает исключительно запланированные модификации конфигурации.
После успешного завершения миграции последующее выполнение apply не должно приводить к непреднамеренным изменениям сетевых интерфейсов ВМ (NIC), интерфейсов маршрутизатора или правил NAT.
2. Миграция конфигурации маршрутизатора
-
Перепишите шлюз (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необходимо полностью опустить из конфигурации (вместо передачи пустого объекта). -
Перенос интерфейсов в отдельные ресурсы
Замените каждый вложенный блок
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Повторите объявление ресурса и операцию импорта для каждого интерфейса, который ранее был вложен в маршрутизатор.
-
Перенос правил 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.
-
Проверка миграции маршрутизатора
После завершения всех операций импорта выполните:
terraform planОжидаемый результат: План должен показать только удаление устаревших полей interface и nat_rule из состояния (state) ресурса zvirt_router. СЮДА НУЖЕН ПРИМЕР ВЫВОДА
3. Миграция конфигурации сетевых интерфейсов (NIC)
-
Перенесите каждое прежнее значение атрибута
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 } } -
Выполните рефакторинг конфигурации 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 } } } -
Исправьте конфигурации виртуальных машин без сетевых интерфейсов.
В сценарии, когда виртуальная машина не требует подключения к сети (отсутствуют NIC), следует использовать один из следующих подходов:
-
полностью исключить атрибут
nicиз конфигурации ресурса; -
инициализировать атрибут
nicкак пустую карту (map): nic = {}.
Пример:nic = {} -
4. Обновление выражений и выходных данных
Замените доступ через наборы/списки на доступ через ключи карты (map).
| До (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 внутрь каждого элемента конфигурации и использовать вместо этого ключи карты.