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

Принцип работы живой миграции

Процесс живой миграции состоит из нескольких этапов:

  1. На целевом узле создаётся новая ВМ в приостановленном состоянии. Её конфигурация (процессор, диски, сеть) копируется с исходного узла.

  2. Вся оперативная память ВМ копируется на целевой узел по сети. Это называется первичной передачей.

  3. Пока память передаётся, ВМ продолжает работать на исходном узле и может изменять некоторые страницы памяти. Такие страницы называются «грязными» (dirty pages), и гипервизор их помечает.

  4. После первичной передачи начинается повторная отправка только изменённых страниц. Этот процесс повторяется в несколько циклов:

    • Чем выше нагрузка на ВМ, тем больше «грязных» страниц появляется, и тем дольше длится миграция.
    • При хорошей пропускной способности сети объём несинхронизированных данных постепенно уменьшается.
  5. Когда количество «грязных» страниц становится минимальным, ВМ на исходном узле приостанавливается (обычно на 100 миллисекунд):

    • Оставшиеся изменения памяти передаются на целевой узел.
    • Состояние процессора, устройств и открытых соединений синхронизируется.
    • ВМ запускается на новом узле, а исходная копия удаляется.

До момента переключения ВМ на новый узел (шаг 5) ВМ на исходном узле продолжает работать в обычном режиме и предоставлять сервис пользователям.

Миграция

Требования и ограничения

Живая миграция удаётся не всегда. Ниже перечислено, что должно совпасть на исходном и целевом узлах.

Доступность дисков. Все подключённые к ВМ диски должны быть доступны на целевом узле. У сетевых хранилищ вроде NFS или Ceph это требование выполняется само, потому что диски видны со всех узлов кластера. Локальному хранилищу нужна возможность создать новый локальный том на целевом узле, а если такое хранилище есть только на исходном узле, миграция не выполнится.

Подключение и отключение дисков. Пока миграция готовит целевой узел, диски нельзя ни подключить к машине ресурсом VirtualMachineBlockDeviceAttachment, ни отключить, удалив такой ресурс. Подключаемый ресурс остаётся в фазе Pending с причиной BlockedByMigration в условии Attached, а удаляемый в фазе Terminating, пока миграция не завершится. Пока миграция стоит в очереди и целевой узел ещё не готовится, например когда она ждёт освобождения квоты проекта, подключение и отключение работают как обычно. Верно и обратное, уже отправленный запрос на подключение или отключение миграция дожидается, и всё это время ресурс VirtualMachineOperation остаётся в фазе Pending с причиной WaitingForBlockDeviceAttachment. Если запрос не завершится за 5 минут, операция завершается ошибкой.

Пропускная способность сети. Чем медленнее сеть, тем больше итераций синхронизации памяти проходит миграция и тем дольше простой ВМ на финальном этапе, а в худшем случае миграция не укладывается в таймаут. Ходом миграции управляет политика миграции, а с медленной сетью помогает механизм AutoConverge.

Версии ядра. На всех узлах кластера должна работать одна версия ядра Linux. Различия в версиях приводят к несовместимости интерфейсов, системных вызовов и работы с ресурсами, из-за чего миграция срывается.

Совместимость процессоров. Требования к процессорам задаёт тип CPU в классе виртуальной машины. Тип Host разрешает миграцию только между узлами с похожими процессорами, поэтому она не работает ни между Intel и AMD, ни между разными поколениями CPU, у которых различаются наборы инструкций. Тип HostPassthrough требует на целевом узле точно такой же процессор, как на исходном. Чтобы машина мигрировала между узлами с разными процессорами, задайте в классе тип Discovery, Model или Features.

Время выполнения. У миграции есть таймаут завершения, равный 800 секундам на каждый гибибайт памяти ВМ, а при переносе дисков вместе с ней ещё и на каждый гибибайт диска. Например, машине с 4 ГиБ памяти и диском на 20 ГиБ отводится 800 × (4 + 20) = 19200 секунд, то есть около 5,3 часа. Миграция, не уложившаяся в это время, считается неудачной и отменяется, а происходит это при медленной сети или высокой нагрузке на ВМ.

Проверка готовности ВМ к миграции

Условие type: Migratable в статусе ВМ показывает, можно ли перенести ВМ живой миграцией. Оно учитывает как саму ВМ (диски, проброшенные устройства, тип процессора), так и состояние кластера (есть ли узел, на который её можно перенести). Значение True отвечает на вопрос о возможности переноса, а не о том, поедет ли ВМ в это мгновение, поэтому вместе со значением смотрите причину.

Общая картина по всем ВМ:

d8 k get vm -o wide

Значение в колонке MIGRATABLE показывает результат, причина описывается в условии:

d8 k get vm <VM_NAME> -o json | jq '.status.conditions[] | select(.type=="Migratable")'

Причины, которые встречаются чаще всего:

Причина Что это значит Что делать
VirtualMachineMigratable ВМ можно перенести живой миграцией
VirtualMachineNoMigrationTarget ВМ способна мигрировать, но ни один другой узел кластера не может её разместить Проверьте spec.nodeSelector, spec.affinity и spec.tolerations ВМ и такие же параметры её VirtualMachineClass
VirtualMachineWaitingForMigrationTarget ВМ способна мигрировать, в кластере есть подходящие узлы, но принять её сейчас не может ни один, потому что узлы выведены из планирования, не готовы или на них не работает виртуализация Если идёт обслуживание, миграция станет возможна, как только такой узел вернётся. В других случаях проверьте, почему узлы выведены из планирования и работает ли на них виртуализация
VirtualMachineDisksNotMigratable Диски ВМ лежат в хранилище, доступном только с одного узла Перенесите диски в хранилище с режимом доступа ReadWriteMany
VirtualMachineHostDevicesNotMigratable К ВМ подключено устройство, которое нельзя перенести на другой узел Отключите устройство и перезапустите ВМ
VirtualMachineNonMigratable ВМ нельзя перенести живой миграцией, причина указана в поле message условия. Прочитайте message условия. Если дело в процессоре, используйте в классе ВМ типы Discovery, Model или Features
VirtualMachineDisksShouldBeMigrating ВМ можно перенести, её локальные диски будут перенесены вместе с ней

Перенос дисков вместе с ВМ доступен в коммерческих редакциях Deckhouse Platform (DP), поэтому причина VirtualMachineDisksShouldBeMigrating встречается только в них. В DP Open ВМ с дисками в хранилище, доступном с одного узла, получает причину VirtualMachineDisksNotMigratable.

Особенности условия Migratable

Несколько особенностей условия, которые важно учитывать при планировании обслуживания и при чтении статуса:

  • Условие Migratable описывает не только ВМ, но и сам кластер. Если с единственного подходящего узла снять нужный лейбл, не изменяя параметры ВМ, условие всё равно станет False. При появлении подходящего узла условие вернётся в значение True.

  • При выведении узла из планирования ВМ остаётся способной мигрировать. Кордон, перезагрузка и обслуживание узлов проходят сами, поэтому условие остаётся в значении True, а причина меняется на VirtualMachineWaitingForMigrationTarget. Иначе плановое обслуживание соседнего узла превращало бы изменение процессора и памяти в перезапуск ВМ. В DP Open такие изменения требуют перезагрузки в любом случае.

  • Значение True означает способность ВМ мигрировать, а не готовность мигрировать прямо сейчас. Перед миграцией смотрите причину. Значение VirtualMachineMigratable означает, что узел для миграции есть, а VirtualMachineWaitingForMigrationTarget — что подходящего узла на этот момент нет. Метрика d8_virtualization_virtualmachine_migratable несёт тот же ответ в лейбле reason, поэтому дашборд, фильтрующий ВМ только по значению, посчитает ожидающие ВМ вместе с готовыми к миграции.

  • Миграция, запущенная с причиной VirtualMachineWaitingForMigrationTarget, не ожидает узел бесконечно. Если целевой под не удаётся запланировать в течение пяти минут, операция завершается ошибкой, а условие Completed ресурса VirtualMachineOperation получает причину TargetUnschedulable. Если обслуживание затянулось, перезапустите миграцию.

  • У остановленной ВМ нет условия, так как способность ВМ мигрировать вычисляется только для запущенной ВМ. За время простоя диски могли переехать в другое хранилище, а устройство могло быть отключено.

  • В DP Open изменения размещения учитываются после перезапуска ВМ. Пока ВМ работает, она использует параметры, с которыми была запущена, и условие описывает именно их. Новые nodeSelector, affinity или класс ВМ попадут в расчёт только после перезапуска. В коммерческих редакциях DP такие изменения применяются без перезапуска и сразу попадают в расчёт условия.

  • Локальные диски не мешают миграции, но узел всё равно нужен. В коммерческих редакциях DP ВМ с локальными дисками переносится вместе с ними, поэтому условие остаётся True с причиной VirtualMachineDisksShouldBeMigrating. Если же ни один узел кластера не подходит под её правила размещения, условие будет False, так как переносить диски вместе с ВМ некуда.

Запуск живой миграции

Миграцию запускает операция Migrate ресурса VirtualMachineOperation, которую можно создать вручную или командой утилиты d8. Прервать миграцию, пока она находится в фазе Pending или InProgress, можно удалением этого ресурса.

Целевая миграция на конкретный узел доступна в коммерческих редакциях DP.

Чтобы виртуальная машина оставалась планируемой, селектор узла не должен конфликтовать с другими правилами размещения, такими как affinity виртуальной машины, селекторы узлов и правила селектора узлов класса виртуальной машины.

  • В командной строке
  • В веб-интерфейсе

Перед запуском миграции посмотрите текущий статус виртуальной машины:

d8 k get vm

Пример вывода:

NAME       PHASE     UPTIME   NODE           IPADDRESS     AGE
linux-vm   Running   79m      virtlab-pt-1   10.66.10.14   79m

На этот момент она запущена на узле virtlab-pt-1.

Для миграции виртуальной машины с одного узла на другой с учётом требований к её размещению используйте команду:

d8 v migrate -n <NAMESPACE> <VM_NAME> [--force] [--target-node-name string]

Выполнение этой команды приводит к созданию ресурса VirtualMachineOperations.

Флаг --force при выполнении миграции виртуальной машины активирует механизм AutoConverge. Этот механизм автоматически снижает нагрузку на процессор виртуальной машины (замедляет её CPU), если требуется ускорить завершение миграции и обеспечить её успешное выполнение, даже если передача памяти ВМ идёт слишком медленно. Используйте этот флаг, если стандартная миграция не может завершиться из-за высокой активности ВМ.

Чтобы разместить виртуальную машину на конкретном целевом узле, укажите имя этого узла в опции --target-node-name. Например, если виртуальная машина должна быть размещена на узле production-1:

d8 v migrate -n project-1 linux-vm --target-node-name production-1

Под капотом будет создана операция виртуальной машины с конкретным селектором узла kubernetes.io/hostname: production-1, где production-1 — это имя узла.

Запустить миграцию можно также, вручную создав ресурс VirtualMachineOperation (vmop) с типом Migrate:

d8 k create -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
  generateName: migrate-linux-vm-
  namespace: project-1
spec:
  # Имя виртуальной машины.
  virtualMachineName: linux-vm
  # Операция для миграции.
  type: Migrate
  # Определяет операцию миграции виртуальной машины.
  migrate:
    nodeSelector:
      # Кроме того, вы можете установить любой подходящий селектор узлов.
      kubernetes.io/hostname: production-1
  # Разрешить замедление процессора механизмом AutoConverge, для гарантии, что миграция выполнится.
  force: true
EOF

Если вам не нужно указывать параметры целевого узла, вы можете опустить поле migrate или вытеснить виртуальную машину на другой подходящий узел, используя команду d8 v evict или создав ресурс VirtualMachineOperation типа Evict.

Для отслеживания миграции виртуальной машины сразу после создания ресурса VirtualMachineOperation, выполните команду:

d8 k get vm -w

Пример вывода:

NAME       PHASE       UPTIME   NODE           IPADDRESS     AGE
linux-vm   Running     79m      virtlab-pt-1   10.66.10.14   79m
linux-vm   Migrating   79m      virtlab-pt-1   10.66.10.14   79m
linux-vm   Migrating   79m      virtlab-pt-1   10.66.10.14   79m
linux-vm   Running     79m      virtlab-pt-2   10.66.10.14   79m
  1. Перейдите на вкладку «Проекты» и выберите нужный проект.
  2. Перейдите в раздел «Виртуализация» → «Виртуальные машины».
  3. Из списка выберите нужную виртуальную машину и нажмите кнопку с многоточием.
  4. В открывшемся меню выберите «Мигрировать».
  5. В открывшемся окне «Миграция виртуальной машины» выберите режим:
    • «Мигрировать на произвольный узел» — узел назначения выберет планировщик;
    • «Мигрировать на выбранный узел» — узел указывается вручную в поле «Доступные для миграции узлы» (в списке только узлы, подходящие под параметры размещения ВМ и её класс).
  6. При необходимости включите дополнительные параметры:
    • «Мигрировать диски» — вместе с ВМ перенести её диски (используется при смене хранилища);
    • «Принудительно (замедлить CPU гостя)» — применить AutoConverge, чтобы миграция завершилась даже при нехватке пропускной способности сети.
  7. В окне показана текущая политика миграции ВМ, например «Политика миграции ВМ: PreferSafe».
  8. Нажмите кнопку «Мигрировать» или откажитесь от операции кнопкой «Отмена».

Настройка политики миграции

Политика миграции определяет, когда использовать механизм AutoConverge (замедление процессора) для гарантированного завершения миграции.

Механизм AutoConverge помогает завершить миграцию даже при низкой пропускной способности сети, что позволяет с высокой вероятностью успешно завершить операцию. Однако он замедляет процессор виртуальной машины, что может повлиять на производительность приложений, работающих на виртуальной машине.

Механизм AutoConverge работает в два этапа:

  1. Замедление процессора виртуальной машины

    Гипервизор постепенно снижает частоту процессора исходной виртуальной машины. Это уменьшает скорость появления новых «грязных» страниц. Чем выше нагрузка на виртуальную машину, тем сильнее замедление.

  2. Автоматическое завершение миграции

    Как только скорость передачи данных превышает скорость изменения памяти, запускается финальная синхронизация, и виртуальная машина переключается на новый узел.

Для настройки политики миграции используйте параметр .spec.liveMigrationPolicy в конфигурации виртуальной машины. Допустимые значения параметра:

  • AlwaysSafe — миграция всегда выполняется без замедления процессора (AutoConverge не используется). Подходит для случаев, когда важна максимальная производительность виртуальной машины, но требует высокой пропускной способности сети.
  • PreferSafe (используется в качестве политики по умолчанию) — миграция выполняется без замедления процессора (AutoConverge не используется). Однако можно запустить миграцию с замедлением процессора, используя ресурс VirtualMachineOperation с параметрами type=Migrate и force=true.
  • AlwaysForced — миграция всегда использует AutoConverge, то есть процессор замедляется при необходимости. Это гарантирует завершение миграции даже при плохой сети, но может снизить производительность виртуальной машины.
  • PreferForced — миграция использует AutoConverge, то есть процессор замедляется при необходимости. Однако можно запустить миграцию без замедления процессора, используя ресурс VirtualMachineOperation с параметрами type=Migrate и force=false.

Миграции при недостаточной пропускной способности сети

При живой миграции виртуальной машины может возникнуть ситуация, когда пропускной способности сети недостаточно для передачи данных быстрее, чем они изменяются в памяти виртуальной машины. В этом случае количество «грязных» страниц продолжает расти, и миграция может не завершиться в течение таймаута.

Для решения этой проблемы используется механизм AutoConverge, который настраивается через политику миграции.

Чтобы понять, что пропускной способности сети не хватает для живой миграции виртуальной машины, проверьте графики в разделе «Namespace / Virtual Machine» → «VM Status details» → «Live migration memory metrics»:

  • Processed memory rate (скорость передачи памяти) меньше Dirty memory rate (скорость изменения памяти);
  • Remaining memory rate (оставшаяся память) долго не уменьшается.

Это означает, что сеть стала узким местом для миграции.

Пример ситуации, когда миграция не может быть завершена из-за недостаточной пропускной способности сети. Внутри виртуальной машины непрерывно меняется память при помощи stress-ng.

График метрик памяти при миграции, которая не может завершиться

Пример выполнения миграции той же виртуальной машины с использованием флага --force команды d8 v migrate (который включает механизм AutoConverge). Здесь хорошо видно, что частота процессора снижается поэтапно, чтобы уменьшить скорость изменения содержимого памяти.

График метрик памяти при миграции с механизмом AutoConverge

Если сеть ограничивает скорость миграции, можно:

  1. Дождаться, когда операция завершится с ошибкой из-за таймаута.

  2. Отменить текущую операцию миграции, удалив ресурс VirtualMachineOperation, где <VMOP_NAME> — имя этого ресурса:

    d8 k delete vmop <VMOP_NAME>
    
  3. Повторно запустить миграцию с использованием флага --force, чтобы включить механизм AutoConverge. Использование флага --force должно соответствовать текущей политике миграции виртуальной машины.

Миграции, запускаемые системой

Часть миграций DP запускает сам, создавая ресурс VirtualMachineOperation с типом Evict. Что именно вызвало такую миграцию, видно по префиксу имени ресурса:

Что вызвало миграцию Префикс имени ресурса
Обновление «прошивки» виртуальной машины firmware-update-
Перераспределение нагрузки в кластере evacuation-
Перевод узла в режим технического обслуживания (drain узла) evacuation-
Изменение параметров размещения ВМ nodeplacement-update-
Изменение числа ядер или объёма памяти без перезапуска hotplug-resources-
Перенос дисков в другое хранилище volume-migration-

Миграция завершилась успешно, когда ресурс переходит в фазу Completed. Остальные фазы описаны в поле .status.phase, а для отмены миграции ресурс удаляют.

Ниже показано, как посмотреть список таких операций:

  • В командной строке
  • В веб-интерфейсе

Посмотреть активные операции можно командой:

d8 k get vmop

Пример вывода:

NAME                    PHASE       PROGRESS   TYPE    VIRTUALMACHINE   AGE
firmware-update-fnbk2   Completed   100%       Evict   linux-vm         1m
  1. Перейдите на вкладку «Проекты» и выберите нужный проект.
  2. Перейдите в раздел «Виртуализация» → «Виртуальные машины».
  3. Из списка выберите нужную ВМ и нажмите на её имя.
  4. Перейдите на вкладку «Операции».

Живая миграция ВМ при изменении параметров размещения

Когда правила размещения меняются у работающей машины, DP переносит её на подходящий узел живой миграцией.

Возможность доступна в коммерческих редакциях DP.

Ниже механизм миграции показан на примере кластера с двумя группами узлов, green и blue. Допустим, виртуальная машина изначально запущена на узле группы green, а её конфигурация не содержит ограничений на размещение.

Сначала добавьте в спецификацию ВМ требование размещаться в группе green:

spec:
  nodeSelector:
    node.deckhouse.io/group: green

После сохранения изменений ВМ продолжит работать на текущем узле, так как условие nodeSelector уже выполняется.

Теперь измените требование на группу blue:

spec:
  nodeSelector:
    node.deckhouse.io/group: blue

Текущий узел из группы green новым условиям больше не отвечает. DP создаст ресурс VirtualMachineOperation с типом Evict и запустит живую миграцию ВМ на доступный узел группы blue.

Пример вывода:

NAME                         PHASE       PROGRESS   TYPE    VIRTUALMACHINE   AGE
nodeplacement-update-dabk4   Completed   100%       Evict   linux-vm         1m

Дополнительные ресурсы