Для создания виртуальной машины используется ресурс VirtualMachine, его параметры позволяют сконфигурировать:
- класс виртуальной машины;
- ресурсы, требуемые для работы виртуальной машины (процессор, память, диски и образы);
- правила размещения виртуальной машины на узлах кластера;
- настройки загрузчика и оптимальные параметры для гостевой ОС;
- политику запуска виртуальной машины и политику применения изменений;
- сценарии начальной конфигурации (cloud-init);
- перечень блочных устройств.
Создание виртуальной машины
Ниже представлен пример простой конфигурации виртуальной машины, запускающей ОС Ubuntu 22.04. В примере используется сценарий первичной инициализации виртуальной машины (cloud-init), который устанавливает гостевого агента qemu-guest-agent
и сервис nginx
, а также создает пользователя cloud
с паролем cloud
:
Пароль в примере был сгенерирован с использованием команды mkpasswd --method=SHA-512 --rounds=4096 -S saltsalt
и при необходимости вы можете его поменять на свой:
-
Создайте виртуальную машину с диском:
d8 k apply -f - <<"EOF" apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: linux-vm spec: # Название класса ВМ. virtualMachineClassName: host # Блок скриптов первичной инициализации ВМ. provisioning: type: UserData # Пример cloud-init-сценария для создания пользователя cloud с паролем cloud и установки сервиса агента qemu-guest-agent и сервиса nginx. userData: | #cloud-config package_update: true packages: - nginx - qemu-guest-agent run_cmd: - systemctl daemon-reload - systemctl enable --now nginx.service - systemctl enable --now qemu-guest-agent.service ssh_pwauth: True users: - name: cloud passwd: '$6$rounds=4096$saltsalt$fPmUsbjAuA7mnQNTajQM6ClhesyG0.yyQhvahas02ejfMAq1ykBo1RquzS0R6GgdIDlvS.kbUwDablGZKZcTP/' shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: False final_message: "The system is finally up, after $UPTIME seconds" # Настройки ресурсов ВМ. cpu: # Количество ядер ЦП. cores: 1 # Запросить 10% процессорного времени одного физического ядра. coreFraction: 10% memory: # Объем оперативной памяти. size: 1Gi # Список дисков и образов, используемых в ВМ. blockDeviceRefs: # Порядок дисков и образов в данном блоке определяет приоритет загрузки. - kind: VirtualDisk name: linux-vm-root EOF
После создания ресурс
VirtualMachine
может находиться в следующих состояниях:Pending
— ожидание готовности всех зависимых ресурсов, требующихся для запуска виртуальной машины.Starting
— идет процесс запуска виртуальной машины.Running
— виртуальная машина запущена.Stopping
— идет процесс остановки виртуальной машины.Stopped
— виртуальная машина остановлена.Terminating
— виртуальная машина удаляется.Migrating
— виртуальная машина находится в состоянии онлайн-миграции на другой узел.
-
Проверьте состояние виртуальной машины после создания:
d8 k get vm linux-vm
Пример вывода:
NAME PHASE NODE IPADDRESS AGE linux-vm Running virtlab-pt-2 10.66.10.12 11m
После создания виртуальная машина автоматически получит IP-адрес из диапазона, указанного в настройках (блок
virtualMachineCIDRs
).
Жизненный цикл виртуальной машины
Виртуальная машина (ВМ) проходит через несколько этапов своего существования — от создания до удаления. Эти этапы называются фазами и отражают текущее состояние ВМ. Чтобы понять, что происходит с ВМ, нужно проверить её статус (поле .status.phase
), а для более детальной информации — блок .status.conditions
. Ниже описаны все основные фазы жизненного цикла ВМ, их значение и особенности.
-
Pending
— ожидание готовности ресурсовВМ только что создана, перезапущена или запущена после остановки и ожидает готовности необходимых ресурсов (дисков, образов, IP-адресов и т.д.).
- Возможные проблемы:
- не готовы зависимые ресурсы: диски, образы, классы ВМ, секрет со сценарием начальной конфигурации и пр.
-
Диагностика: В
.status.conditions
стоит обратить внимание на условия*Ready
. По ним можно определить, что блокирует переход к следующей фазе, например, ожидание готовности дисков (BlockDevicesReady) или класса ВМ (VirtualMachineClassReady).d8 k get vm <vm-name> -o json | jq '.status.conditions[] | select(.type | test(".*Ready"))'
- Возможные проблемы:
-
Starting
— запуск виртуальной машиныВсе зависимые ресурсы ВМ — готовы, и система пытается запустить ВМ на одном из узлов кластера.
- Возможные проблемы:
- Нет подходящего узла для запуска.
- На подходящих узлах недостаточно CPU или памяти.
- Превышены квоты неймспейса или проекта.
- Диагностика:
-
Если запуск затягивается, проверьте
.status.conditions
, условиеtype: Running
d8 k get vm <vm-name> -o json | jq '.status.conditions[] | select(.type=="Running")'
-
- Возможные проблемы:
-
Running
— виртуальная машина запущенаВМ успешно запущена и работает.
- Особенности:
- При установленном в гостевой системе qemu-guest-agent, условие
AgentReady
будет истинно,а в.status.guestOSInfo
будет отображена информация о запущенной гостевой ОС. - Условие
type: FirmwareUpToDate, status: False
информирует о том, что прошивку ВМ требуется обновить. - Условие
type: ConfigurationApplied, status: False
информирует о том, что конфигурация ВМ не применена для запущенной ВМ. - Условие
type: AwaitingRestartToApplyConfiguration, status: True
отображает информацию о необходимости выполнить вручную перезагрузку ВМ, т.к. некоторые изменения конфигурации невозможно применить без перезагрузки ВМ.
- При установленном в гостевой системе qemu-guest-agent, условие
- Возможные проблемы:
- Внутренний сбой в работе ВМ или гипервизора.
- Диагностика:
-
Проверьте
.status.conditions
, условиеtype: Running
d8 k get vm <vm-name> -o json | jq '.status.conditions[] | select(.type=="Running")'
-
- Особенности:
-
Stopping
— ВМ останавливается или перезагружается -
Stopped
— ВМ остановлена и не потребляет вычислительные ресурсы -
Terminating
— ВМ удаляется.Данная фаза необратима. Все связанные с ВМ ресурсы освобождаются, но не удаляются автоматически.
-
Migrating
— живая миграция ВМВМ переносится на другой узел кластера (живая миграция).
- Особенности:
- Миграция ВМ поддерживается только для нелокальных дисков, условие
type: Migratable
отображает информацию о том может ли ВМ мигрировать или нет.
- Миграция ВМ поддерживается только для нелокальных дисков, условие
- Возможные проблемы:
- Несовместимость процессорных инструкций (при использовании типов процессоров host или host-passthrough).
- Различие версиях ядер на узлах гипервизоров.
- На подходящих узлах недостаточно CPU или памяти.
- Превышены квоты неймспейса или проекта.
- Диагностика:
- Проверьте
.status.conditions
условиеtype: Migrating
, а также блок.status.migrationState
d8 k get vm <vm-name> -o json | jq '.status | {condition: .conditions[] | select(.type=="Migrating"), migrationState}'
- Проверьте
- Особенности:
Условие type: SizingPolicyMatched, status: False
отображает несоответствие конфигурации ресурсов политике сайзинга используемого VirtualMachineClass. При нарушении политики сохранить параметры ВМ без приведения ресурсов в соответствие политике — невозможно.
Условия отображают информацию о состоянии ВМ, а также на возникающие проблемы. Понять, что не так с ВМ можно путем их анализа:
d8 k get vm fedora -o json | jq '.status.conditions[] | select(.message != "")'
Агент гостевой ОС
Для повышения эффективности управления ВМ рекомендуется установить QEMU Guest Agent — инструмент, который обеспечивает взаимодействие между гипервизором и операционной системой внутри ВМ.
Чем поможет агент?
- Обеспечит создание консистентных снимков дисков и ВМ.
-
Позволит получать информацию о работающей ОС, которая будет отражена в статусе ВМ. Пример:
status: guestOSInfo: id: fedora kernelRelease: 6.11.4-301.fc41.x86_64 kernelVersion: '#1 SMP PREEMPT_DYNAMIC Sun Oct 20 15:02:33 UTC 2024' machine: x86_64 name: Fedora Linux prettyName: Fedora Linux 41 (Cloud Edition) version: 41 (Cloud Edition) versionId: "41"
-
Позволит отслеживать, что ОС действительно загрузилась:
d8 k get vm -o wide
Пример вывода (колонка
AGENT
):NAME PHASE CORES COREFRACTION MEMORY NEED RESTART AGENT MIGRATABLE NODE IPADDRESS AGE fedora Running 6 5% 8000Mi False True True virtlab-pt-1 10.66.10.1 5d21h
Как установить QEMU Guest Agent:
Для Debian-based ОС:
sudo apt install qemu-guest-agent
Для Centos-based ОС:
sudo yum install qemu-guest-agent
Запуск службы агента:
sudo systemctl enable --now qemu-guest-agent
Автоматическая конфигурация топологии CPU
Топология CPU виртуальной машины (ВМ) определяет, как ядра процессора распределяются по сокетам. Это важно для обеспечения оптимальной производительности и совместимости с приложениями, которые могут зависеть от конфигурации процессора. В конфигурации ВМ вы задаете только общее количество ядер процессора, а топология (количество сокетов и ядер в каждом сокете) рассчитывается автоматически на основе этого значения.
Количество ядер процессора указывается в конфигурации ВМ следующим образом:
spec:
cpu:
cores: 1
Далее система автоматически определяет топологию в зависимости от заданного числа ядер. Правила расчета зависят от диапазона количества ядер и описаны ниже.
- Если количество ядер от 1 до 16 (1 ≤
.spec.cpu.cores
≤ 16):- Используется 1 сокет.
- Количество ядер в сокете равно заданному значению.
- Шаг изменения: 1 (можно увеличивать или уменьшать количество ядер по одному).
- Допустимые значения: любое целое число от 1 до 16 включительно.
- Пример: Если задано
.spec.cpu.cores
= 8, то топология: 1 сокет с 8 ядрами.
- Если количество ядер от 17 до 32 (16 <
.spec.cpu.cores
≤ 32):- Используется 2 сокета.
- Ядра равномерно распределяются между сокетами (количество ядер в каждом сокете одинаковое).
- Шаг изменения: 2 (общее количество ядер должно быть четным).
- Допустимые значения: 18, 20, 22, 24, 26, 28, 30, 32.
- Ограничения: минимум 9 ядер в сокете, максимум 16 ядер в сокете.
- Пример: Если задано
.spec.cpu.cores
= 20, то топология: 2 сокета по 10 ядер каждый.
- Если количество ядер от 33 до 64 (32 <
.spec.cpu.cores
≤ 64):- Используется 4 сокета.
- Ядра равномерно распределяются между сокетами.
- Шаг изменения: 4 (общее количество ядер должно быть кратно 4).
- Допустимые значения: 36, 40, 44, 48, 52, 56, 60, 64.
- Ограничения: минимум 9 ядер в сокете, максимум 16 ядер в сокете.
- Пример: Если задано
.spec.cpu.cores
= 40, то топология: 4 сокета по 10 ядер каждый.
- Если количество ядер больше 64 (
.spec.cpu.cores
> 64):- Используется 8 сокетов.
- Ядра равномерно распределяются между сокетами.
- Шаг изменения: 8 (общее количество ядер должно быть кратно 8).
- Допустимые значения: 72, 80, 88, 96 и так далее до 248
- Ограничения: минимум 9 ядер в сокете.
- Пример: Если задано
.spec.cpu.cores
= 80, то топология: 8 сокетов по 10 ядер каждый.
Шаг изменения указывает, на сколько можно увеличивать или уменьшать общее количество ядер, чтобы они равномерно распределялись по сокетам.
Максимально возможное количество ядер — 248.
Текущая топология ВМ (количество сокетов и ядер в каждом сокете) отображается в статусе ВМ в следующем формате:
status:
resources:
cpu:
coreFraction: 10%
cores: 1
requestedCores: "1"
runtimeOverhead: "0"
topology:
sockets: 1
coresPerSocket: 1
Подключение к виртуальной машине
Для подключения к виртуальной машине доступны следующие способы:
- протокол удаленного управления (например SSH), который должен быть предварительно настроен на виртуальной машине;
- серийная консоль (serial console);
- протокол VNC.
Пример подключения к виртуальной машине с использованием серийной консоли:
d8 v console linux-vm
Пример вывода:
Successfully connected to linux-vm console. The escape sequence is ^]
linux-vm login: cloud
Password: cloud
Для завершения работы с серийной консолью нажмите Ctrl+]
.
Пример команды для подключения по VNC:
d8 v vnc linux-vm
Пример команды для подключения по SSH.
d8 v ssh cloud@linux-vm --local-ssh
Политика запуска и управление состоянием виртуальной машины
Политика запуска виртуальной машины предназначена для автоматизированного управления состоянием виртуальной машины. Определяется она в виде параметра .spec.runPolicy
в спецификации виртуальной машины. Поддерживаются следующие политики:
AlwaysOnUnlessStoppedManually
— (по умолчанию) после создания ВМ всегда находится в рабочем состоянии. В случае сбоев работа ВМ восстанавливается автоматически. Остановка ВМ возможна только путем вызова командыd8 v stop
или создания соответствующей операции.AlwaysOn
— после создания ВМ всегда находится в работающем состоянии, даже в случае ее выключения средствами ОС. В случае сбоев работа ВМ восстанавливается автоматически.Manual
— после создания состоянием ВМ управляет пользователь вручную с использованием команд или операций.AlwaysOff
— после создания ВМ всегда находится в выключенном состоянии. Возможность включения ВМ через команды\операции - отсутствует.
Состоянием виртуальной машины можно управлять с помощью следующих методов:
- Создание ресурса VirtualMachineOperation (
vmop
). - Использование утилиты
d8
с соответствующей подкомандой.
Ресурс VirtualMachineOperation
декларативно определяет действие, которое должно быть выполнено на виртуальной машине.
Пример операции для выполнения перезагрузки виртуальной машины с именем linux-vm
:
d8 k create -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
generateName: restart-linux-vm-
spec:
virtualMachineName: linux-vm
# Тип применяемой операции = применяемая операция.
type: Restart
EOF
Посмотреть результат действия можно с использованием команды:
d8 k get virtualmachineoperation
# или
d8 k get vmop
Аналогичное действие можно выполнить с использованием утилиты d8
:
d8 v restart linux-vm
Возможные операции:
d8 | vmop type | Действие |
---|---|---|
d8 v stop |
Stop |
Остановить ВМ |
d8 v start |
Start |
Запустить ВМ |
d8 v restart |
Restart |
Перезапустить ВМ |
d8 v evict |
Evict |
Мигрировать ВМ на другой узел |
Изменение конфигурации виртуальной машины
Конфигурацию виртуальной машины можно изменять в любое время после создания ресурса VirtualMachine
. Однако то, как эти изменения будут применены, зависит от текущей фазы виртуальной машины и характера внесённых изменений.
Изменения в конфигурацию виртуальной машины можно внести с использованием следующей команды:
d8 k edit vm linux-vm
Если виртуальная машина находится в выключенном состоянии (.status.phase: Stopped
), внесённые изменения вступят в силу сразу после её запуска.
Если виртуальная машина работает (.status.phase: Running
), то способ применения изменений зависит от их типа:
Блок конфигурации | Как применяется |
---|---|
.metadata.labels |
Сразу |
.metadata.annotations |
Сразу |
.spec.liveMigrationPolicy |
Сразу |
.spec.runPolicy |
Сразу |
.spec.disruptions.restartApprovalMode |
Сразу |
.spec.affinity |
EE, SE+ : Сразу, CE: Требуется перезапуск ВМ |
.spec.nodeSelector |
EE, SE+ : Сразу, CE: Требуется перезапуск ВМ |
.spec.* |
Требуется перезапуск ВМ |
Рассмотрим пример изменения конфигурации виртуальной машины:
Предположим, мы хотим изменить количество ядер процессора. В данный момент виртуальная машина запущена и использует одно ядро, что можно подтвердить, подключившись к ней через серийную консоль и выполнив команду nproc
.
d8 v ssh cloud@linux-vm --local-ssh --command "nproc"
Пример вывода:
1
Примените следующий патч к виртуальной машине, чтобы изменить количество ядер с 1 на 2.
d8 k patch vm linux-vm --type merge -p '{"spec":{"cpu":{"cores":2}}}'
Пример вывода:
virtualmachine.virtualization.deckhouse.io/linux-vm patched
Изменения в конфигурацию внесены, но ещё не применены к виртуальной машине. Проверьте это, повторно выполнив:
d8 v ssh cloud@linux-vm --local-ssh --command "nproc"
Пример вывода:
1
Для применения этого изменения необходим перезапуск виртуальной машины. Выполните следующую команду, чтобы увидеть изменения, ожидающие применения (требующие перезапуска):
d8 k get vm linux-vm -o jsonpath="{.status.restartAwaitingChanges}" | jq .
Пример вывода:
[
{
"currentValue": 1,
"desiredValue": 2,
"operation": "replace",
"path": "cpu.cores"
}
]
Выполните команду:
d8 k get vm linux-vm -o wide
Пример вывода:
NAME PHASE CORES COREFRACTION MEMORY NEED RESTART AGENT MIGRATABLE NODE IPADDRESS AGE
linux-vm Running 2 100% 1Gi True True True virtlab-pt-1 10.66.10.13 5m16s
В колонке NEED RESTART
мы видим значение True
, а это значит что для применения изменений требуется перезагрузка.
Выполните перезагрузку виртуальной машины:
d8 v restart linux-vm
После перезагрузки изменения будут применены и блок .status.restartAwaitingChanges
будет пустой.
Выполните команду для проверки:
d8 v ssh cloud@linux-vm --local-ssh --command "nproc"
Пример вывода:
2
Порядок применения изменений виртуальной машины через «ручной» рестарт является поведением по умолчанию. Если есть необходимость применять внесенные изменения сразу и автоматически, для этого нужно изменить политику применения изменений:
spec:
disruptions:
restartApprovalMode: Automatic
Сценарии начальной инициализации
Сценарии начальной инициализации предназначены для первичной конфигурации виртуальной машины при её запуске.
В качестве сценариев начальной инициализации поддерживаются:
Сценарий CloudInit можно встраивать непосредственно в спецификацию ВМ, но этот сценарий ограничен максимальной длиной в 2048 байт:
spec:
provisioning:
type: UserData
userData: |
#cloud-config
package_update: true
...
При более длинных сценариях и/или наличии приватных данных, сценарий начальной инициализации виртуальной машины может быть создан в ресурсе Secret. Пример Secret со сценарием CloudInit приведен ниже:
apiVersion: v1
kind: Secret
metadata:
name: cloud-init-example
data:
userData: <base64 data>
type: provisioning.virtualization.deckhouse.io/cloud-init
Фрагмент конфигурации виртуальной машины при использовании скрипта начальной инициализации CloudInit хранящегося в ресурсе Secret:
spec:
provisioning:
type: UserDataRef
userDataRef:
kind: Secret
name: cloud-init-example
Примечание: значение поля .data.userData
должно быть закодировано в формате Base64.
Для конфигурирования виртуальных машин под управлением ОС Windows с использованием Sysprep, поддерживается только вариант с Secret.
Пример Secret с сценарием Sysprep:
apiVersion: v1
kind: Secret
metadata:
name: sysprep-example
data:
unattend.xml: <base64 data>
type: provisioning.virtualization.deckhouse.io/sysprep
Примечание: Значение поля .data.unattend.xml
должно быть закодировано в формате Base64.
Фрагмент конфигурации виртуальной машины с использованием скрипта начальной инициализации Sysprep в ресурсе Secret:
spec:
provisioning:
type: SysprepRef
sysprepRef:
kind: Secret
name: sysprep-example
Размещение ВМ по узлам
Для управления размещением виртуальных машин по узлам можно использовать следующие подходы:
- Простое связывание по меткам —
nodeSelector
; - Предпочтительное связывание —
Affinity
; - Избежание совместного размещения —
AntiAffinity
.
Параметры размещения виртуальных машин можно изменить в реальном времени (доступно только в Enterprise-редакции). Однако, если новые параметры размещения не совпадают с текущими, виртуальная машина будет перемещена на узлы, соответствующие новым требованиям.
Простое связывание по меткам — nodeSelector
nodeSelector
— это простейший способ контролировать размещение виртуальных машин, используя набор меток. Он позволяет задать, на каких узлах могут запускаться виртуальные машины, выбирая узлы с необходимыми метками.
spec:
nodeSelector:
disktype: ssd
В этом примере виртуальная машина будет размещена только на узлах, которые имеют метку disktype
со значением ssd
.
Предпочтительное связывание — Affinity
Affinity
предоставляет более гибкие и мощные инструменты по сравнению с nodeSelector
. Он позволяет задавать «предпочтения» и «обязательности» для размещения виртуальных машин. Affinity
поддерживает два вида: nodeAffinity
и virtualMachineAndPodAffinity
.
nodeAffinity
позволяет определять, на каких узлах может быть запущена виртуальная машина, с помощью выражений меток, и может быть предпочтительным (preferred
) или обязательным (required
).
Пример использования nodeAffinity
:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
В этом примере виртуальная машина будет размещена только на узлах, которые имеют метку disktype
со значением ssd
.
virtualMachineAndPodAffinity
управляет размещением одних виртуальных машин относительно других виртуальных машин. Он позволяет задавать предпочтение размещения виртуальных машин на тех же узлах, где уже запущены определенные виртуальные машины.
Пример:
spec:
affinity:
virtualMachineAndPodAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
virtualMachineAndPodAffinityTerm:
labelSelector:
matchLabels:
server: database
topologyKey: "kubernetes.io/hostname"
В этом примере виртуальная машина будет размещена, если будет такая возможность (так как используется метка preferred
), только на узлах на которых присутствует виртуальная машина с меткой server
и значением database
.
Избежание совместного размещения — AntiAffinity
AntiAffinity
— это противоположность Affinity
, которая позволяет задавать требования для избегания размещения виртуальных машин на одних и тех же узлах. Это полезно для распределения нагрузки или обеспечения отказоустойчивости.
Термины Affinity
и AntiAffinity
применимы только к отношению между виртуальными машинами. Для узлов используемые привязки называются nodeAffinity
. В nodeAffinity
нет отдельного обратного термина, как в случае с virtualMachineAndPodAffinity
, но можно создать противоположные условия, задав отрицательные операторы в выражениях меток. Чтобы акцентировать внимание на исключении определенных узлов, можно воспользоваться nodeAffinity
с оператором, таким как NotIn
.
Пример использования virtualMachineAndPodAntiAffinity
:
spec:
affinity:
virtualMachineAndPodAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
server: database
topologyKey: "kubernetes.io/hostname"
В данном примере создаваемая виртуальная машина не будет размещена на одном узле с виртуальной машиной с меткой server: database
.
Статические и динамические блочные устройства
Блочные устройства можно разделить на два типа по способу их подключения: статические и динамические (hotplug).
Статические блочные устройства
Блочные устройства и их особенности представлены в таблице:
Тип блочного устройства | Комментарий |
---|---|
VirtualImage |
подключается в режиме для чтения, или как cd-rom для iso-образов |
ClusterVirtualImage |
подключается в режиме для чтения, или как cd-rom для iso-образов |
VirtualDisk |
подключается в режиме для чтения и записи |
Статические блочные устройства указываются в спецификации виртуальной машины в блоке .spec.blockDeviceRefs
в виде списка. Порядок устройств в этом списке определяет последовательность их загрузки. Таким образом, если диск или образ указан первым, загрузчик сначала попробует загрузиться с него. Если это не удастся, система перейдет к следующему устройству в списке и попытается загрузиться с него. И так далее до момента обнаружения первого загрузчика.
Изменение состава и порядка устройств в блоке .spec.blockDeviceRefs
возможно только с перезагрузкой виртуальной машины.
Фрагмент конфигурации VirtualMachine со статически подключенными диском и проектным образом:
spec:
blockDeviceRefs:
- kind: VirtualDisk
name: <virtual-disk-name>
- kind: VirtualImage
name: <virtual-image-name>
Динамические блочные устройства
Динамические блочные устройства можно подключать и отключать от виртуальной машины, находящейся в запущенном состоянии, без необходимости её перезагрузки.
Для подключения динамических блочных устройств используется ресурс VirtualMachineBlockDeviceAttachment (vmbda
). На данный момент для подключения в качестве динамического блочного устройства поддерживается только VirtualDisk.
Создайте ресурс, который подключит пустой диск blank-disk к виртуальной машине linux-vm:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineBlockDeviceAttachment
metadata:
name: attach-blank-disk
spec:
blockDeviceRef:
kind: VirtualDisk
name: blank-disk
virtualMachineName: linux-vm
EOF
После создания VirtualMachineBlockDeviceAttachment
может находиться в следующих состояниях:
Pending
— ожидание готовности всех зависимых ресурсов.InProgress
— идет процесс подключения устройства.Attached
— устройство подключено.
Диагностика проблем с ресурсом осуществляется путем анализа информации в блоке .status.conditions
.
Проверьте состояние вашего ресурса:
d8 k get vmbda attach-blank-disk
Пример вывода:
NAME PHASE VIRTUAL MACHINE NAME AGE
attach-blank-disk Attached linux-vm 3m7s
Подключитесь к виртуальной машине и удостоверьтесь, что диск подключен:
d8 v ssh cloud@linux-vm --local-ssh --command "lsblk"
Пример вывода:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 10G 0 disk <--- статично подключенный диск linux-vm-root
|-sda1 8:1 0 9.9G 0 part /
|-sda14 8:14 0 4M 0 part
`-sda15 8:15 0 106M 0 part /boot/efi
sdb 8:16 0 1M 0 disk <--- cloudinit
sdc 8:32 0 95.9M 0 disk <--- динамически подключенный диск blank-disk
Для отключения диска от виртуальной машины удалите ранее созданный ресурс:
d8 k delete vmbda attach-blank-disk
Подключение образов, осуществляется по аналогии. Для этого в качестве kind
указать VirtualImage или ClusterVirtualImage и имя образа:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineBlockDeviceAttachment
metadata:
name: attach-ubuntu-iso
spec:
blockDeviceRef:
kind: VirtualImage # Или ClusterVirtualImage.
name: ubuntu-iso
virtualMachineName: linux-vm
EOF
Миграция виртуальной машины в реальном времени (живая миграция)
Живая миграция виртуальных машин (ВМ) — это процесс перемещения работающей ВМ с одного физического узла на другой без её отключения. Эта функция играет ключевую роль в управлении виртуализованной инфраструктурой, обеспечивая непрерывность работы приложений во время технического обслуживания, балансировки нагрузки или обновлений.
Как работает живая миграция
Процесс живой миграции включает несколько этапов:
-
Создание нового экземпляра ВМ
На целевом узле создаётся новая ВМ в приостановленном состоянии. Её конфигурация (процессор, диски, сеть) копируется с исходного узла.
-
Первичная передача памяти
Вся оперативная память ВМ копируется на целевой узел по сети. Это называется первичной передачей.
-
Отслеживание изменений (Dirty Pages)
Пока память передаётся, ВМ продолжает работать на исходном узле и может изменять некоторые страницы памяти. Такие страницы называются «грязными» (dirty pages), и гипервизор их помечает.
-
Итеративная синхронизация
После первичной передачи начинается повторная отправка только изменённых страниц. Этот процесс повторяется в несколько циклов:
- Чем выше нагрузка на ВМ, тем больше «грязных» страниц появляется, и тем дольше длится миграция.
- При хорошей пропускной способности сети объём несинхронизированных данных постепенно уменьшается.
-
Финальная синхронизация и переключение
Когда количество «грязных» страниц становится минимальным, ВМ на исходном узле приостанавливается (обычно на 100 миллисекунд):
- Оставшиеся изменения памяти передаются на целевой узел.
- Состояние процессора, устройств и открытых соединений синхронизируется.
- ВМ запускается на новом узле, а исходная копия удаляется.
Скорость сети играет важную роль. Если пропускная способность низкая, итераций становится больше, а время простоя ВМ может увеличиться. В худшем случае миграция может вообще не завершиться.
Механизм AutoConverge
Если сеть не справляется с передачей данных, а количество «грязных» страниц продолжает расти, будет полезен механизм AutoConverge. Он помогает завершить миграцию даже при низкой пропускной способности сети.
Принципы работы механизма AutoConverge:
-
Замедление процессора ВМ.
Гипервизор постепенно снижает частоту процессора исходной ВМ. Это уменьшает скорость появления новых «грязных» страниц. Чем выше нагрузка на ВМ, тем сильнее замедление.
-
Ускорение синхронизации.
Как только скорость передачи данных превышает скорость изменения памяти, запускается финальная синхронизация, и ВМ переключается на новый узел.
-
Автоматическое завершение.
Финальная синхронизация запускается, когда скорость передачи данных превышает скорость изменения памяти.
AutoConverge — это своего рода «страховка», которая гарантирует, что миграция завершится, даже если сеть не справляется с передачей данных. Однако замедление процессора может повлиять на производительность приложений, работающих на ВМ, поэтому его использование нужно контролировать.
Настройка политики миграции
Для настройки поведения миграции используйте параметр .spec.liveMigrationPolicy
в конфигурации ВМ. Допустимые значения параметра:
AlwaysSafe
— миграция всегда выполняется без замедления процессора (AutoConverge не используется). Подходит для случаев, когда важна максимальная производительность ВМ, но требует высокой пропускной способности сети.PreferSafe
(используется в качестве политики по умолчанию) — миграция выполняется без замедления процессора (AutoConverge не используется). Однако можно запустить миграцию с замедлением процессора, используя ресурс VirtualMachineOperation с параметрамиtype=Evict
иforce=true
.AlwaysForced
— миграция всегда использует AutoConverge, то есть процессор замедляется при необходимости. Это гарантирует завершение миграции даже при плохой сети, но может снизить производительность ВМ.PreferForced
— миграция использует AutoConverge, то есть процессор замедляется при необходимости. Однако можно запустить миграцию без замедления процессора, используя ресурс VirtualMachineOperation с параметрамиtype=Evict
иforce=false
.
Виды миграции
Миграция может осуществляться пользователем вручную, либо автоматически при следующих системных событиях:
- Обновление «прошивки» виртуальной машины.
- Перераспределение нагрузки в кластере.
- Перевод узла в режим технического обслуживания (Drain узла)
- При изменении параметров размещения ВМ (не доступно в Community-редакции).
Триггером к живой миграции является появление ресурса VirtualMachineOperations
с типом Evict
.
В таблице приведены префиксы названия ресурса VirtualMachineOperations
с типом Evict
, создаваемые для живых миграций вызванных системными событиями:
Вид системного события | Префикс имени ресурса |
---|---|
Обновлении «прошивки» | firmware-update-* |
Перераспределение нагрузки | evacuation-* |
Drain узла | evacuation-* |
Изменение параметров размещения | nodeplacement-update-* |
Данный ресурс может находится в следующих состояниях:
Pending
— ожидается выполнение операции.InProgress
— живая миграция выполняется.Completed
— живая миграция виртуальной машины завершилась успешно.Failed
— живая миграция виртуальной машины завершилась неуспешно.
Посмотреть активные операции можно с использованием команды:
d8 k get vmop
Пример вывода:
NAME PHASE TYPE VIRTUALMACHINE AGE
firmware-update-fnbk2 Completed Evict linux-vm 1m
Прервать любую живую миграцию пока она находится в фазе Pending
, InProgress
можно удалив соответствующий ресурс VirtualMachineOperations
.
Как выполнить живую миграцию виртуальной машины с использованием VirtualMachineOperations
Перед запуском миграции посмотрите текущий статус виртуальной машины:
d8 k get vm
Пример вывода:
NAME PHASE NODE IPADDRESS AGE
linux-vm Running virtlab-pt-1 10.66.10.14 79m
Виртуальная машина запущена на узле virtlab-pt-1
.
Для осуществления миграции виртуальной машины с одного узла на другой, с учетом требований к размещению виртуальной машины используется команда:
d8 v evict -n <namespace> <vm-name>
Выполнение данной команды приводит к созданию ресурса VirtualMachineOperation.
Запустить миграцию можно также создав ресурс VirtualMachineOperation (vmop
) с типом Evict
вручную:
d8 k create -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
generateName: evict-linux-vm-
spec:
# Имя виртуальной машины.
virtualMachineName: linux-vm
# Операция для миграции.
type: Evict
# Разрешить замедление процессора механизмом AutoConverge, для гарантии, что миграция выполнится.
force: true
EOF
Для отслеживания миграции виртуальной машины сразу после создания ресурса vmop
, выполните команду:
d8 k get vm -w
Пример вывода:
NAME PHASE NODE IPADDRESS AGE
linux-vm Running virtlab-pt-1 10.66.10.14 79m
linux-vm Migrating virtlab-pt-1 10.66.10.14 79m
linux-vm Migrating virtlab-pt-1 10.66.10.14 79m
linux-vm Running virtlab-pt-2 10.66.10.14 79m
Также для выполнения миграции можно использовать команду:
d8 v evict <vm-name>
Живая миграция виртуальной машины при изменении параметров размещения (недоступно в CE редакции)
Рассмотрим механизм миграции на примере кластера с двумя группами узлов (NodeGroups
): green и blue . Допустим, виртуальная машина (ВМ) изначально запущена на узле группы green , а её конфигурация не содержит ограничений на размещение.
Шаг 1. Добавление параметра размещения Укажем в спецификации ВМ требование к размещению в группе green :
spec:
nodeSelector:
node.deckhouse.io/group: green
После сохранения изменений ВМ продолжит работать на текущем узле, так как условие nodeSelector
уже выполняется.
Шаг 2. Изменение группы размещения Изменим требование на размещение в группе blue :
spec:
nodeSelector:
node.deckhouse.io/group: blue
Теперь текущий узел (группы green) не соответствует новым условиям. Система автоматически создаст объект VirtualMachineOperations
типа Evict, что инициирует живую миграцию ВМ на доступный узел группы blue.
Пример вывода ресурса
NAME PHASE TYPE VIRTUALMACHINE AGE
nodeplacement-update-dabk4 Completed Evict linux-vm 1m
Режим обслуживания
При выполнении работ на узлах с запущенными виртуальными машинами существует риск нарушения их работоспособности. Чтобы этого избежать, узел можно перевести в режим обслуживания и мигрировать виртуальные машины на другие свободные узлы. Для этого необходимо выполнить следующую команду:
d8 k drain <nodename> --ignore-daemonsets --delete-emptydir-dat
где <nodename>
— узел, на котором предполагается выполнить работы и который должен быть освобожден от всех ресурсов (в том числе и от системных).
Если есть необходимость вытеснить с узла только виртуальные машины, выполните следующую команду:
d8 k drain <nodename> --pod-selector vm.kubevirt.internal.virtualization.deckhouse.io/name --delete-emptydir-data
После выполнения команд d8 k drain
— узел перейдет в режим обслуживания и виртуальные машины на нем запускаться не смогут. Чтобы вывести его из режима обслуживания выполните следующую команду:
d8 k uncordon <nodename>
IP-адреса виртуальных машин
Блок .spec.settings.virtualMachineCIDRs
в конфигурации задает список подсетей для назначения IP-адресов виртуальным машинам (общий пул IP-адресов). Все адреса в этих подсетях доступны для использования, за исключением первого (адрес сети) и последнего (широковещательный адрес).
Ресурс VirtualMachineIPAddressLease (vmipl
): кластерный ресурс, который управляет временным выделением IP-адресов из общего пула, указанного в virtualMachineCIDRs
.
Чтобы посмотреть список временно выделенных IP-адресов (vmipl
), используйте команду:
d8 k get vmipl
Пример вывода:
NAME VIRTUALMACHINEIPADDRESS STATUS AGE
ip-10-66-10-14 {"name":"linux-vm-7prpx","namespace":"default"} Bound 12h
Ресурс VirtualMachineIPAddress (vmip
) — это ресурс проекта или пространства имен, который отвечает за резервирование выделенных IP-адресов и их привязку к виртуальным машинам. IP-адреса могут выделяться автоматически или по запросу.
Проверить назначенный IP-адрес можно с помощью команды:
d8 k get vmip
Пример вывода:
NAME VIRTUALMACHINEIPADDRESS STATUS AGE
ip-10-66-10-14 {"name":"linux-vm-7prpx","namespace":"default"} Bound 12h
Алгоритм автоматического присвоения IP-адреса виртуальной машине выглядит следующим образом:
- Пользователь создает виртуальную машину с именем
<vmname>
. - Контроллер автоматически создает ресурс
vmip
с именем<vmname>-<hash>
, чтобы запросить IP-адрес и связать его с виртуальной машиной. - Для этого
vmip
создается ресурс арендыvmipl
, который выбирает случайный IP-адрес из общего пула. - Как только ресурс
vmip
создан, виртуальная машина получает назначенный IP-адрес.
По умолчанию IP-адрес для виртуальной машины назначается автоматически, из подсетей, и закрепляется за ней до её удаления. После удаления виртуальной машины ресурс vmip
также удаляется, но IP-адрес временно остается закрепленным за проектом/пространством имен и может быть повторно запрошен.
Запрос требуемого IP-адреса
Создайте ресурс vmip
:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineIPAddress
metadata:
name: linux-vm-custom-ip
spec:
staticIP: 10.66.20.77
type: Static
EOF
Создайте новую или измените существующую виртуальную машину и в спецификации укажите требуемый ресурс vmip
явно:
spec:
virtualMachineIPAddressName: linux-vm-custom-ip
Сохранение IP-адреса, присвоенного виртуальной машине
Чтобы автоматически выданный IP-адрес виртуальной машины не удалился вместе с самой виртуальной машиной, выполните следующие действия.
Получите название ресурса vmip
для заданной виртуальной машины:
d8 k get vm linux-vm -o jsonpath="{.status.virtualMachineIPAddressName}"
Пример вывода:
linux-vm-7prpx
Удалите блоки .metadata.ownerReferences
из найденного ресурса:
d8 k patch vmip linux-vm-7prpx --type=merge --patch '{"metadata":{"ownerReferences":null}}'
После удаления виртуальной машины, ресурс vmip
сохранится и его можно будет использовать во вновь созданной виртуальной машине:
spec:
virtualMachineIPAddressName: linux-vm-7prpx
Даже если ресурс vmip
будет удален, он остается арендованным для текущего проекта/пространства имен еще 10 минут и существует возможность вновь его занять по запросу:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineIPAddress
metadata:
name: linux-vm-custom-ip
spec:
staticIP: 10.66.20.77
type: Static
EOF