Hyper-V. Часть 8: Переносим виртуальные машины между хостами

Все части серии «Hyper-V»

До сих пор машина жила на одном хосте. Но хост нужно обновлять, ремонтировать, а однажды и заменить, и машины с него приходится переносить. Разберём все способы: экспорт и импорт, живую миграцию работающей машины между хостами без кластера, перенос файлов машины на другой том, что мешает переезду между разными процессорами, когда поднимать версию конфигурации после переезда на новую Windows Server и как держать на другом хосте копию машины на случай аварии.


Экспорт и импорт

Самый простой способ перенести машину — экспортировать её в папку и импортировать на другом хосте (экспорт и импорт). Экспорт работает и с запущенной машиной: в папку попадают конфигурация, диски и контрольные точки.

Export-VM -Name app1 -Path '\\fs1\export'

У импорта три режима (Import-VM):

  • Регистрация на месте — машина остаётся там, где лежат файлы, с тем же идентификатором.
  • Восстановление (-Copy) — файлы копируются в указанные папки, идентификатор сохраняется.
  • Копия (-Copy -GenerateNewId) — машина получает новый идентификатор; так из одной экспортированной машины делают несколько.
$vmcx = Get-ChildItem '\\fs1\export\app1\Virtual Machines\*.vmcx'
Import-VM -Path $vmcx.FullName -Copy `
          -VirtualMachinePath 'D:\Hyper-V' -VhdDestinationPath 'D:\Hyper-V\Virtual Hard Disks\app1'

Если на новом хосте нет коммутатора с тем же именем или версия конфигурации не поддерживается, импорт падает. Заранее проверить это и поправить несовместимости помогает Compare-VM: он возвращает отчёт с объектами несовместимости, которые можно исправить и передать в Import-VM -CompatibilityReport (Compare-VM).

$report = Compare-VM -Path $vmcx.FullName -Copy -GenerateNewId
$report.Incompatibilities | Format-Table Message, MessageId
$report.Incompatibilities[0].Source | Connect-VMNetworkAdapter -SwitchName 'LAN'
Import-VM -CompatibilityReport $report

Source у несовместимости — объект, к которому она относится: здесь сетевой адаптер, которому не нашлось коммутатора, и его подключают к существующему.

Живая миграция без кластера

Живая миграция (live migration) переносит работающую машину на другой хост без заметного простоя (обзор). Память копируется на новый хост, пока машина продолжает работать; изменённые за это время страницы досылаются повторными проходами, и в конце машина на долю секунды замирает, чтобы перенести последний остаток и состояние процессора. Начиная с Windows Server 2016 для этого не нужен кластер: два одиночных хоста одного домена переносят машину вместе с дисками — такой перенос называют shared nothing, общего хранилища у хостов нет.

Настройка — на обоих хостах (настройка хостов):

Enable-VMMigration
Add-VMMigrationNetwork 192.168.40.0/24
Set-VMHost -VirtualMachineMigrationAuthenticationType Kerberos `
           -VirtualMachineMigrationPerformanceOption Compression `
           -MaximumVirtualMachineMigrations 2 -MaximumStorageMigrations 2
Get-VMHost | Format-List VirtualMachineMigrationEnabled, VirtualMachineMigrationAuthenticationType,
    VirtualMachineMigrationPerformanceOption, UseAnyNetworkForMigration
Get-VMMigrationNetwork

Сеть миграции. Add-VMMigrationNetwork добавляет сеть, по которой хост принимает миграцию, Set-VMMigrationNetwork меняет уже добавленную, Remove-VMMigrationNetwork убирает (Add-VMMigrationNetwork). Пока UseAnyNetworkForMigration выключен, хост принимает миграцию только по сетям из этого списка, а с пустым списком не принимает вовсе (Set-VMHost). Без отдельной сети гигабайты памяти пойдут через ту же карту, что и трафик пользователей. Обычно это отдельный адаптер хоста в своём VLAN — тот LiveMigration, который мы добавляли поверх SET в части о сети. Set-VMHost -UseAnyNetworkForMigration $true снимает ограничение.

Способ передачи памяти (там же): TCPIP — как есть, Compression — со сжатием (по умолчанию), SMB — через SMB 3 с SMB Multichannel и, на картах с RDMA, SMB Direct. На картах с RDMA вариант SMB самый быстрый; без RDMA обычно выигрывает сжатие. MaximumVirtualMachineMigrations и MaximumStorageMigrations — сколько миграций хост выполняет одновременно.

Аутентификация

Миграцию запускают с хоста-источника, а ему нужно действовать на хосте-приёмнике от имени администратора. Вариантов два:

  • CredSSP работает без настройки домена, но только если администратор вошёл на хост-источник интерактивно — консолью, по RDP или в сессии PowerShell на нём. Запустить миграцию с рабочей станции так нельзя.
  • Kerberos с ограниченным делегированием: хосту-источнику разрешают получать от имени пользователя билеты к двум службам приёмника — Microsoft Virtual System Migration Service для самой машины и cifs для её дисков. Тогда миграцию можно запускать удалённо, с рабочей станции администратора.

На Windows Server 2025 выбор фактически сделан за вас: на всех членах домена, кроме контроллеров, по умолчанию включён Credential Guard, и живая миграция через CredSSP перестаёт работать — нужен Kerberos (там же).

Настройка CredSSP

CredSSP не требует никаких изменений в Active Directory: на Windows Server 2022 и старше это способ по умолчанию. Если на хостах раньше выбрали Kerberos, CredSSP возвращают явно на обоих:

Invoke-Command -ComputerName hv1, hv2 { Set-VMHost -VirtualMachineMigrationAuthenticationType CredSSP }

Дальше всё зависит от того, где выполняется Move-VM. Учётные данные администратора должны оказаться на хосте-источнике, поэтому миграцию запускают в сеансе, открытом на нём самом (там же):

  • в консоли или по RDP на хосте-источнике — Move-VM работает сразу, без дополнительной настройки;
  • в удалённом сеансе PowerShell — только если сеанс открыт с аутентификацией CredSSP. Обычный сеанс по Kerberos учётных данных на хост не передаёт, и миграция падает так же, как без входа.

Сеансы CredSSP к хостам включают один раз (Enable-WSManCredSSP): на рабочей станции — для всех хостов, с которых будут уходить машины, по их FQDN, на хостах — роль сервера:

Enable-WSManCredSSP -Role Client -DelegateComputer 'hv1.corp.example.com', 'hv2.corp.example.com' -Force   # на рабочей станции
Invoke-Command -ComputerName hv1, hv2 { Enable-WSManCredSSP -Role Server -Force }                          # на хостах
Get-WSManCredSSP

И сам перенос с рабочей станции:

$cred = Get-Credential 'CORP\hv-admin'
Invoke-Command -ComputerName hv1.corp.example.com -Authentication CredSSP -Credential $cred {
    Move-VM -Name app1 -DestinationHost hv2 -IncludeStorage -DestinationStoragePath 'D:\Hyper-V\app1'
}

Имя в -ComputerName должно совпадать с указанным в -DelegateComputer, поэтому здесь FQDN. Как CredSSP включается для PowerShell Remoting и чем он опасен, разобрано в части про WinRM серии о Windows Server.

У CredSSP два ограничения. Сеанс нужен на том хосте, с которого машина уходит: чтобы вернуть её с hv2 на hv1, сеанс открывают уже на hv2, иначе миграция падает с «No credentials are available in the security package 0x8009030E» (там же). И учётные данные администратора при этом целиком передаются хосту-источнику: для членов группы Protected Users CredSSP не работает, а на Windows Server 2025 его, как сказано выше, блокирует Credential Guard. Поэтому там, где это возможно, выбирают Kerberos.

Настройка ограниченного делегирования

Делегирование настраивается в Active Directory, на учётных записях компьютеров-хостов, поэтому нужна учётная запись с правом их менять: документация требует членства в Domain Admins. Хосты должны быть в одном домене или в доменах с доверием (там же).

Правило одно: каждому хосту, с которого машины уходят, разрешают делегирование к службам каждого хоста, на который они приходят. Для пары hv1 и hv2 это две настройки: на учётной записи hv1 — службы hv2, на учётной записи hv2 — службы hv1. Служб две, и каждую указывают в двух написаниях — коротким именем и FQDN, потому что хост может обратиться к соседу и так, и так:

Служба Зачем
Microsoft Virtual System Migration Service/<хост> перенос самой машины — памяти и состояния
cifs/<хост> перенос дисков (Move-VM -IncludeStorage) и хранилища на другой хост

SPN службы миграции Hyper-V регистрирует на учётной записи хоста сам, при установке роли: setspn -L hv2 покажет Microsoft Virtual System Migration Service/hv2 и Microsoft Virtual System Migration Service/hv2.corp.example.com. Для cifs отдельных записей нет — её обслуживают записи HOST/…, которые есть у любого компьютера домена.

В оснастке «Active Directory — пользователи и компьютеры» это вкладка «Делегирование» в свойствах учётной записи хоста-источника: «Доверять компьютеру делегирование указанных служб» → «Использовать любой протокол проверки подлинности» → «Добавить» → хост-приёмник → две службы из списка. В PowerShell — сразу для всех пар хостов; скрипт выполняют на любой машине с модулем ActiveDirectory:

$hosts  = 'hv1', 'hv2', 'hv3'
$domain = 'corp.example.com'
foreach ($src in $hosts) {
    $spns = foreach ($dst in $hosts | Where-Object { $_ -ne $src }) {
        foreach ($svc in 'Microsoft Virtual System Migration Service', 'cifs') { "$svc/$dst"; "$svc/$dst.$domain" }
    }
    $have = (Get-ADComputer $src -Properties msDS-AllowedToDelegateTo).'msDS-AllowedToDelegateTo'
    $add  = $spns | Where-Object { $_ -notin $have }
    if ($add) { Set-ADComputer -Identity $src -Add @{ 'msDS-AllowedToDelegateTo' = [string[]]$add } }
    Set-ADAccountControl -Identity "$src$" -TrustedToAuthForDelegation $true
}

Атрибут msDS-AllowedToDelegateTo — список служб, к которым учётной записи разрешено делегирование, тот самый список на вкладке «Делегирование». Флаг TrustedToAuthForDelegation соответствует пункту «Использовать любой протокол проверки подлинности». Скрипт только добавляет недостающие службы, поэтому его можно запускать повторно — например, когда появился новый хост, — а делегирование к другим службам, если оно уже было, он не трогает.

Проверить результат:

Get-ADComputer -Filter "Name -like 'hv*'" -Properties msDS-AllowedToDelegateTo, TrustedToAuthForDelegation |
    Select-Object Name, TrustedToAuthForDelegation, @{n='DelegateTo'; e={$_.'msDS-AllowedToDelegateTo' -join "`n"}} |
    Format-List

Затем на каждом хосте выбирают Kerberos — той же командой Set-VMHost, что и в начале раздела; на Windows Server 2022 и старше по умолчанию там CredSSP:

Invoke-Command -ComputerName $hosts { Set-VMHost -VirtualMachineMigrationAuthenticationType Kerberos }

Изменения в AD начинают действовать, когда они дошли репликацией до контроллеров домена, к которым обращаются хосты, и хосты получили новые билеты Kerberos (там же). Чтобы не ждать, на каждом хосте сбрасывают кеш билетов учётной записи компьютера:

Invoke-Command -ComputerName $hosts { klist purge -li 0x3e7 }

0x3e7 — сеанс входа SYSTEM, под которым работает служба VMMS. После этого миграцию можно запускать прямо с рабочей станции. Если делегирование настроено не до конца — только в одну сторону или без cifs, — перенос в другую сторону или перенос дисков упадёт с ошибкой аутентификации на хосте-источнике, а подробности будут в журнале Microsoft-Windows-Hyper-V-VMMS-Admin.

Перенос

Сам перенос — одна команда (живая миграция без кластера, Move-VM):

Move-VM -Name app1 -DestinationHost hv2 -IncludeStorage -DestinationStoragePath 'D:\Hyper-V\app1'

С рабочей станции добавляют -ComputerName hv1 — хост, на котором машина сейчас. -IncludeStorage переносит и диски; без него Move-VM переносит только память и состояние, а диски должны быть доступны обоим хостам — например, лежать на общей папке. Ход миграции виден в Get-VM как Status, а ошибки — в журнале Microsoft-Windows-Hyper-V-VMMS-Admin.

С -IncludeStorage диски на приёмнике ложатся не прямо в -DestinationStoragePath, а в его подпапку Virtual Hard Disks, рядом с Virtual Machines, Snapshots и другими папками машины; так же раскладывает файлы и Move-VMStorage. На источнике после переноса остаётся пустое дерево папок машины — его удаляют вручную.

Запускать перенос может и администратор из другого домена, которому доверяет домен хостов: делегирование настраивается на учётных записях хостов, а пользователь лишь получает билеты на свою учётную запись. Uptime машины на новом хосте начинается с нуля — это не перезапуск: гость продолжает работать, а счётчик на приёмнике просто стартует заново. Что перенос был именно живым, видно по журналу — о нём в конце части.

Перенос хранилища

Иногда переносить машину на другой хост не нужно, а нужно перенести её файлы на другой том того же хоста — например, освободить заканчивающийся диск. Это тоже делается на работающей машине (Move-VMStorage):

Move-VMStorage -VMName app1 -DestinationStoragePath 'E:\Hyper-V\app1'

Так переносятся сразу все файлы машины — конфигурация, диски, контрольные точки, файл Smart Paging. Разнести их по разным томам позволяют параметры -VirtualMachinePath, -SnapshotFilePath и -VHDs.

Совместимость процессоров

Работающая машина видит набор инструкций процессора своего хоста. Если на новом хосте процессор старше и каких-то инструкций нет, миграция запрещена. Режим совместимости процессора скрывает от машины расширенные инструкции, и она переезжает между разными поколениями процессоров одного производителя; между Intel и AMD живая миграция невозможна в любом случае (совместимость процессоров). Включается при выключенной машине:

Stop-VM -Name app1
Set-VMProcessor -VMName app1 -CompatibilityForMigrationEnabled $true
Start-VM -Name app1

В Windows Server 2025 режим стал динамическим: в кластере он вычисляет общий для всех узлов набор возможностей, а не урезает машину до минимального (там же).

Версия конфигурации после переезда

Машина, перенесённая или импортированная на хост с более новой Windows Server, сохраняет свою версию конфигурации из второй части и может вернуться на старый хост. Обновление требует выключения и необратимо: понизить версию потом нельзя, а машина с новой версией не запустится и не импортируется на старых хостах (Update-VMVersion).

Get-VM | Sort-Object Version | Format-Table Name, State, Version
Stop-VM -Name app1
Update-VMVersion -Name app1 -Force
Start-VM -Name app1

Порядок при переходе на новую Windows Server: сначала все хосты, потом версии машин — в окна обслуживания, по одной. Пока в обороте есть хоть один старый хост, на который машину может понадобиться вернуть, версию не трогают. В кластере между этими шагами есть ещё один — повышение функционального уровня кластера, о нём в части об обслуживании кластера.

Hyper-V Replica

Живая миграция — это плановый переезд. Для аварии, когда исходный хост уже недоступен, есть Hyper-V Replica: асинхронная репликация машины на другой хост с интервалом 30 секунд, 5 или 15 минут, с историей до 24 точек восстановления, с аутентификацией Kerberos внутри домена или по сертификатам между независимыми хостами (обзор Hyper-V Replica). Реплика выключена, пока её не запустят вручную; потерять можно данные за последний интервал.

# на приёмнике
Set-VMReplicationServer -ReplicationEnabled $true -AllowedAuthenticationType Kerberos `
    -ReplicationAllowedFromAnyServer $true -DefaultStorageLocation 'D:\Replica'
# на источнике
Enable-VMReplication -VMName app1 -ReplicaServerName hv2.corp.example.com `
    -ReplicaServerPort 80 -AuthenticationType Kerberos -ReplicationFrequencySec 300
Start-VMInitialReplication -VMName app1
Measure-VMReplication -VMName app1

Параметры — в Enable-VMReplication. Порт 80 здесь — HTTP-слушатель репликации, данные при Kerberos не шифруются; для шифрования используют аутентификацию по сертификату и порт 443. На приёмнике нужно ещё открыть входящий порт в брандмауэре — правило «Hyper-V Replica HTTP Listener (TCP-In)».

Переключение на реплику — на приёмнике, когда источник недоступен (Start-VMFailover):

Start-VMFailover -VMName app1          # на приёмнике: подготовить реплику к запуску
Start-VM -Name app1
Complete-VMFailover -VMName app1       # зафиксировать выбор точки восстановления

Плановое переключение, когда источник жив, начинают на источнике командой Start-VMFailover -Prepare на выключенной машине: тогда последние изменения успевают доехать до реплики, и данные не теряются.

Смотрим руками

Состояние репликации всех машин хоста:

Get-VMReplication | Format-Table VMName, State, Health, Mode, PrimaryServer, ReplicaServer, LastReplicationTime

Как прошли последние живые миграции — события 20413 (источник начал перенос), 20415 (источник закончил; в тексте — время, на которое машина замирала, blackout time) и 20418 (приёмник принял машину):

Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-Hyper-V-VMMS-Admin'; Id = 20413, 20415, 20418; StartTime = (Get-Date).AddDays(-1) } |
    Format-Table TimeCreated, Id, Message -Wrap

Источник пишет 20413 и 20415, приёмник — 20418, поэтому полную картину дают журналы обоих хостов. У небольшой машины пауза — доли секунды; она растёт вместе с объёмом памяти, которую машина успевает изменить во время копирования.

Последние ошибки миграции:

Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-Hyper-V-VMMS-Admin'; Level = 2; StartTime = (Get-Date).AddDays(-1) } |
    Format-Table TimeCreated, Id, Message -Wrap

Источники


Машину можно перенести выключенной — экспортом и импортом, работающей — живой миграцией вместе с дисками, а на случай аварии держать её реплику на другом хосте. Но все эти переезды запускает администратор; чтобы машины сами перезапускались на исправном хосте, нужен кластер.

Дальше — часть 9: собираем отказоустойчивый кластер. Что кластер даёт и чего не даёт, варианты общего хранилища, общие тома CSV, кворум и свидетели, проверка и сборка кластера, его сети и добавление машин в кластер.

Оставить комментарий могут только зарегистрированные пользователи.

Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.