Pular para o conteúdo principal

Обновление до 3.2, Center старой линейки: Windows на NVMe

Отдельная работа после обновления кластера до 3.2 (страница «Шаги» пройдена целиком), с согласия владельца ВМ. Скрипты — из архива шага 2, команды sh tools/vapi.sh … — из того же рабочего каталога с теми же VAPI_URL и VAPI_CRED; обозначения и правила ([раб], [узел], csh на узлах) — там же, в начале страницы.

Зачем и почему не просто флаг​

После Center 3.2 Windows-ВМ остаются на virtio-blk (vm.machine.nvme = false). Они работают как раньше, но запускаются только на узле своего пула (-460), фабрика им недоступна.

Просто поставить nvme = true нельзя. Пока Windows работает на virtio-blk, она держит запрет загрузки драйвера NVMe: HKLM\SYSTEM\ControlSet00N\Services\stornvme\StartOverride\0 = 3. Такая ВМ с диском NVMe дважды падает с INACCESSIBLE_BOOT_DEVICE и уходит в среду восстановления, перезагрузки не помогают.

Поэтому сначала win-nvme-switch.py снимает запрет прямо на томе выключенной ВМ: 4 байта на значение, перед правкой — ZFS-снимок тома. Потом win-nvme-flag.sql ставит nvme = true.

Что проверено​

21–22.10.2026 на тестовом кластере переведены 59 Windows-ВМ на всех четырёх пулах, у каждой один диск: Server 2016, 2019, 2022 и 2025, из них 44 — из старых образов, снятых с действующих кластеров. Каждая после правки загрузилась на NVMe на своём узле, затем по NVMe-oF на другом узле и вернулась на свой. На 22.10, через 2–24 часа после перевода, все 59 работают на NVMe и отвечают по WinRM. У 15 ВМ первого пула дополнительно проверено: запуск на каждом из трёх других узлов, контрольный файл совпал, внутри диск bhyve-NVMe Healthy Online, ошибок дисков в журнале System нет.

У 8 ВМ из 59 до успешной проверки понадобились повторные запуски; итог у них тот же. Одну ВМ перевести не удалось: она не закончила первичную установку Windows (шаг 1, «ВМ в первичной установке»).

Не проверено — это и есть список для пилота на кластере: Server 2012 R2, десктопные Windows, ВМ с несколькими дисками, BitLocker, быстрый запуск и гибернация на живой ВМ.

Что нужно​

  • Скрипты tools/win-nvme/ из архива («Обзор», «Файлы»):
    • win-nvme-switch.py — на узле пула (версия с поддержкой Windows Server 2025);
    • win-nvme-flag.sql — на mgmtVM;
    • postcheck.ps1 — внутри Windows.
  • Root на узле, где импортирован пул ВМ. Запуск — python3.11 -I win-nvme-switch.py (Python 3.11 есть на узле).
  • Доступ на mgmtVM: флаг меняется только SQL-запросом.
  • Разложить файлы, [раб] в tools/win-nvme: scp win-nvme-switch.py root@<узел пула>:/root/ на каждый узел, держащий пул с Windows-ВМ, и scp win-nvme-flag.sql root@<MGMT>:/root/. Команды на узле — из /root.

Первую ВМ кластера проводят через все шаги одну. Остальные — пачками по 3 ВМ одного пула: на тестовом кластере пачка с проверкой на одном чужом узле занимала 5–6 минут, пул из 15 ВМ — около 50 минут, разные пулы шли параллельно. <POOLNODE> — узел, где сейчас импортирован пул ВМ (не путать с <OWN> на странице «Шаги»), <OTHER> — любой другой узел.

Порядок​

1. Выключить ВМ штатно​

vms-stop Center Windows почти никогда не выключает: агент шлёт ACPI и примерно через 30 секунд убивает bhyve. С hard_timeout: 600 после долгого аптайма Windows игнорирует ACPI все 600 секунд. Убитая ВМ даст BLOCKED, на диск скрипт ничего не запишет. Работают два способа:

  • изнутри Windows: «Завершение работы» или Stop-Computer -Force (на тестовом кластере — 36 раз из 37);

  • без доступа в гостя (6 из 6, ВМ выключилась примерно за 11 секунд):

    sh tools/vapi.sh vms-stop '{"id":<id>}'; sh tools/vapi.sh wait <id> 1 # ВМ будет убита — так и надо
    sh tools/vapi.sh vms-start '{"id":<id>,"node_id":<POOLNODE>}'; sh tools/vapi.sh wait <id> 3
    # подождать 3 минуты после старта, не дольше
    sh tools/vapi.sh vms-stop '{"id":<id>,"hard_timeout":600}'; sh tools/vapi.sh wait <id> 1 900

    Ушла в Offline ровно через 600 секунд — её убили, повторить.

ВМ в статусе Suspended сначала возобновить, потом выключить.

ВМ в первичной установке. Сначала посмотреть консоль: Windows должна дойти до экрана входа. Пока идёт первичная установка, Windows на ACPI не реагирует, а убитая посреди установки ВМ уже не ставится: на консоли окно «Install Windows: The computer restarted unexpectedly or encountered an unexpected error. Windows installation cannot proceed». Такую ВМ не переводить — пересоздать. create_completed в Center этого не показывает: на тестовом кластере у такой ВМ он был true.

2. Проверить​

[<POOLNODE>]: python3.11 -I win-nvme-switch.py check <id> [<id>…]. Без номеров — все Windows-ВМ пулов узла; работающие ВМ дают BLOCKED, так что это безопасно.

ВердиктЗначит
READYможно править
OKзапрета нет, флаг ставить можно
BLOCKEDне трогать, причина в отчёте — таблица ниже

3. Править​

[<POOLNODE>]: python3.11 -I win-nvme-switch.py patch <id> [<id>…] --yes. Для каждой READY — снимок <том>@pre-nvme-<дата>, запись, перепроверка. В конце строка ids=…: ВМ, которые можно переводить. Код выхода: 0 — всё прошло; 2 — есть BLOCKED; 1 — ошибка правки (ERROR, разбирать руками, снимок назван в отчёте).

4. Сменить флаг — сразу после шага 3​

[mgmt]:

cd /tmp; su -m postgres -c "psql -X -d vstack -v ids=<строка ids= из шага 3>" < /root/win-nvme-flag.sql

Файл подаётся на вход, а не через -f: каталог /root на mgmtVM пользователю postgres не читается (Permission denied). Пример в шапке самого win-nvme-flag.sql — с -f из каталога, доступного postgres; так тоже можно. Ожидается UPDATE N и COMMIT. Транзакция откатится целиком, если хоть одна ВМ не найдена, не Windows или не Offline в Center.

Между шагами 3 и 4 ВМ не запускать. Запуск на virtio-blk вернёт запрет, и после смены флага будет синий экран. Клиент может запустить ВМ из портала, поэтому шаг 4 идёт сразу за шагом 3. SQL ответил «не Offline в Center» — ВМ запускали: выключить по шагу 1 и начать с шага 2.

5. Запуск на своём узле​

vapi.sh vms-start '{"id":<id>,"node_id":<POOLNODE>}', vapi.sh wait <id> 3. Экран входа в консоли — примерно через минуту; чёрный экран — Windows погасила монитор, нажать клавишу.

Внутри Windows (PowerShell от администратора) — postcheck.ps1 или:

Get-Disk | Format-Table Number, FriendlyName, HealthStatus, OperationalStatus, IsOffline
Get-WinEvent -FilterHashtable @{LogName='System'; Level=1,2,3; StartTime=(Get-Date).Date} -ErrorAction SilentlyContinue |
Where-Object ProviderName -match 'disk|stornvme|Ntfs|volmgr|BugCheck'

Ожидается: диски bhyve-NVMe, Healthy, Online, ошибок дисков нет. Диск данных Offline — Set-Disk -Number <N> -IsOffline $false. Проверить буквы дисков и службы.

6. Запуск на чужом узле​

Выключить по шагу 1, затем vapi.sh vms-start '{"id":<id>,"node_id":<OTHER>}', vapi.sh wait <id> 3; в vm-list — rstart: 1; гость — как в шаге 5. -440 — бюджет RAM Center на <OTHER>: запускать по 2–3 ВМ на свободный узел. Потом вернуть ВМ на <POOLNODE> или оставить. Теперь vms-start без node_id сам выбирает для неё наименее загруженный узел.

7. Снимки​

Через несколько дней работы на NVMe — удалить на <POOLNODE>, по одному: zfs list -H -t snapshot -o name | grep @pre-nvme-, затем zfs destroy <том>@pre-nvme-<дата>.

Если BLOCKED​

Причина в отчётеЧто делать
vstack-vm: состояние …, «ВМ работает», «есть /dev/vmm»ВМ не выключена — шаг 1
«Том открыт (… spdk_tgt …)»ВМ работает на другом узле по NVMe-oF (на узле пула vstack-vm при этом показывает Offline). Выключить — шаг 1
«Том открыт» с другим процессом или без процессатом держит процесс из отчёта fstat или ядро (ctl) — разобраться
журнал NTFS не закрыт, том NTFS грязный, куст SYSTEM не чистыйВМ убили, а не выключили — шаг 1
«ВМ приостановлена (Suspended)»возобновить, выключить — шаг 1
в hiberfil.sys сохранено ядровнутри Windows powercfg /h off, выключить, повторить check
«Раздел зашифрован BitLocker», «системный раздел Windows не найден»снять запрет изнутри Windows (ниже), выключить и сразу шаг 4, вписав ВМ в ids вручную
«NTFS не разбирается (… нет $INDEX_ROOT)» на Server 2025запущена старая версия скрипта — взять win-nvme-switch.py из архива этого раздела
нет драйвера stornvmeWindows старше 8.1 / Server 2012 R2 без NVMe — оставить на virtio-blk
«тома … на узле нет», «vm.json на этом узле нет»пул импортирован на другом узле — запускать там

Снять запрет изнутри Windows (PowerShell от администратора), после этого ВМ выключить и до смены флага не запускать:

Get-ChildItem HKLM:\SYSTEM | Where-Object PSChildName -match '^ControlSet\d{3}$' | ForEach-Object {
$svc = Join-Path $_.PSPath 'Services\stornvme'
Set-ItemProperty -Path $svc -Name Start -Value 0 -Type DWord
Remove-Item -Path (Join-Path $svc 'StartOverride') -Recurse -Force -ErrorAction SilentlyContinue
}

Синий экран после смены флага​

Бывает, если флаг поставили без patch или ВМ запускали между шагами 3 и 4. Признаки: два перезапуска bhyve, затем INACCESSIBLE_BOOT_DEVICE и экран «Choose an option». Данные целы.

  1. В консоли Center нажать «Turn off your PC» — это штатное выключение, журнал NTFS останется чистым.
  2. Шаги 2–4. Флаг уже true, поэтому SQL шага 4 ответит UPDATE 0.
  3. Шаг 5.

Откат​

  • ВМ уже работала на NVMe, а нужен virtio-blk. После загрузки на NVMe Windows ставит такой же запрет драйверу virtio-blk viostor (на тестовом кластере — у всех 15 ВМ). Выключить по шагу 1, на <POOLNODE> — python3.11 -I win-nvme-switch.py patch <id> --driver viostor --yes (строки ids= в этом режиме нет), на [mgmt] — UPDATE vm.machine SET nvme = false WHERE id = <id>;, затем шаг 5.
  • Синий экран на NVMe после правки. Выключить, nvme = false, запустить на virtio-blk. Обратная загрузка не проверялась.
  • zfs rollback <том>@pre-nvme-<дата> — только если ВМ после правки не работала, иначе потеряются её данные.