Стадия жизненного цикла модуля: General Availability
У модуля есть требования для установки
Руководство описывает, как создавать и изменять ресурсы модуля virtualization в проекте или неймспейсе кластера.
Быстрый старт по созданию виртуальной машины
В разделе показан минимальный сценарий, в котором вы создаёте образ Ubuntu 24.04, диск из этого образа и виртуальную машину (ВМ), подключаетесь к ней по консоли, а затем удаляете созданные ресурсы.
- В командной строке
- В веб-интерфейсе
-
Создайте образ VirtualImage из внешнего источника:
d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualImage metadata: name: ubuntu spec: storage: ContainerRegistry dataSource: type: HTTP http: url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img EOF -
Создайте диск VirtualDisk из этого образа. Убедитесь, что в кластере задан StorageClass по умолчанию, и примените манифест:
d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: linux-disk spec: dataSource: type: ObjectRef objectRef: kind: VirtualImage name: ubuntu EOF -
Создайте виртуальную машину VirtualMachine. В примере используется сценарий cloud-init, который создаёт пользователя
cloud:d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: linux-vm spec: virtualMachineClassName: generic cpu: cores: 1 memory: size: 1Gi provisioning: type: UserData userData: | #cloud-config ssh_pwauth: True users: - name: cloud passwd: <PASSWORD_HASH> shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: False blockDeviceRefs: - kind: VirtualDisk name: linux-disk EOFЗдесь
<PASSWORD_HASH>— хеш пароля пользователя в кавычках. Получите его командойmkpasswd --method=SHA-512 --rounds=4096, она запросит пароль и выведет готовое значение. Формат сценария описан в документации cloud-init. -
Проверьте, что образ и диск созданы, а ВМ запущена. Ресурсы переходят в готовое состояние не мгновенно, поэтому дождитесь нужных значений в колонке
PHASE:d8 k get vi,vd,vmПример вывода:
NAME PHASE CDROM PROGRESS AGE virtualimage.virtualization.deckhouse.io/ubuntu Ready false 100% 7h50m NAME PHASE CAPACITY VIRTUALMACHINE AGE virtualdisk.virtualization.deckhouse.io/linux-disk Ready 4Gi linux-vm 7h40m NAME PHASE UPTIME NODE IPADDRESS AGE virtualmachine.virtualization.deckhouse.io/linux-vm Running 7h30m virtlab-pt-2 10.66.10.2 7h46m -
Подключитесь к ВМ по консоли:
d8 v console linux-vmПример вывода:
Successfully connected to linux-vm console. The escape sequence is ^] linux-vm login: cloud Password: ... cloud@linux-vm:~$Чтобы выйти из консоли, нажмите
Ctrl+]. -
Удалите созданные ресурсы:
d8 k delete vm linux-vm d8 k delete vd linux-disk d8 k delete vi ubuntu
-
Создайте образ из внешнего источника:
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Образы».
- Нажмите кнопку «Создать».
- В блоке «Источник» выберите «По ссылке».
- В открывшейся форме в поле «Имя образа» введите
ubuntu. - В блоке «Хранилище» в поле «Тип хранилища» выберите
ContainerRegistry. - В поле «URL» вставьте
https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img. - Нажмите кнопку «Создать».
- Проверьте статус образа на его странице.
-
Создайте диск из этого образа. Шаг можно пропустить и создать диск сразу при создании ВМ.
- Перейдите в раздел «Виртуализация» → «Диски».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя диска» введите
linux-disk. - В поле «Источник» из выпадающего списка выберите образ
ubuntu. - При необходимости в поле «Размер» укажите больший размер, например
5Gi. - В поле «Класс хранения» выберите StorageClass или оставьте вариант по умолчанию.
- Нажмите кнопку «Создать».
- Проверьте статус диска на его странице.
Если у выбранного StorageClass задан режим
WaitForFirstConsumer, диск ожидает создания ВМ, которая его использует. До этого момента диск отображается со статусом «СОЗДАНИЕ 0%», но его уже можно выбрать при создании ВМ. -
Создайте виртуальную машину:
-
Перейдите в раздел «Виртуализация» → «Виртуальные машины».
-
Нажмите кнопку «Создать».
-
В открывшейся форме в поле «Имя» введите
linux-vm. -
В разделах «Платформа» и «Ресурсы» оставьте настройки по умолчанию.
-
В разделе «Диски» нажмите кнопку «Добавить».
Если диск уже создан, в открывшемся окне «Диски / Образы» выберите «Существующий» и укажите в списке диск
linux-disk.Если диск не создан, в том же окне выберите «Создать из» и задайте параметры:
- в поле «Название» введите
linux-disk; - в поле «Источник» из выпадающего списка выберите образ
ubuntu, в списке указан тип ресурса; - при необходимости в поле «Размер» укажите больший размер, например
5Gi; - в поле «Хранилище» выберите StorageClass или оставьте вариант по умолчанию.
Нажмите кнопку «Добавить».
- в поле «Название» введите
-
Прокрутите страницу вниз до переключателя «Cloud-init» и включите его.
-
В появившееся поле вставьте сценарий, подставив вместо
<PASSWORD_HASH>хеш пароля в кавычках, полученный командойmkpasswd --method=SHA-512 --rounds=4096:#cloud-config ssh_pwauth: True users: - name: cloud passwd: <PASSWORD_HASH> shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: False -
Нажмите кнопку «Создать».
-
Проверьте статус ВМ на её странице.
-
-
Подключитесь к ВМ по консоли:
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- В открывшейся форме перейдите на вкладку «TTY» и войдите в систему в окне консоли.
-
Удалите созданные ресурсы:
- Перейдите в раздел «Виртуализация» и выберите нужный подраздел, например «Виртуальные машины», «Диски» или «Образы».
- В строке ресурса нажмите кнопку с многоточием и выберите «Удалить». В некоторых списках, например в списке снимков ВМ, удаление вынесено отдельной кнопкой.
- В окне подтверждения нажмите кнопку «Удалить» либо откажитесь от действия кнопкой «Не удалять».
Важно: Удаление ресурса необратимо. Диск, подключённый к запущенной виртуальной машине, удалить нельзя, для него пункт «Удалить» неактивен.
Образы
Образ хранит содержимое диска, из которого вы создаёте диски виртуальных машин. Образ VirtualImage создаётся в проекте и доступен только в том проекте или неймспейсе, где он создан.
Чтобы один и тот же образ был доступен всем проектам кластера, нужен кластерный образ ClusterVirtualImage. Создать его может администратор, порядок описан в руководстве администратора.
Виртуальная машина получает доступ к подключённому образу в режиме «только чтение».
Образ появляется в проекте в три шага:
- Вы создаёте ресурс VirtualImage и указываете в нём источник данных.
- Deckhouse Platform (DP) загружает образ из этого источника в хранилище, которым в зависимости от выбранного типа выступает DVCR или PVC.
- Загруженный образ становится доступен для создания дисков.
Источники и варианты хранения
Источником образа может быть HTTP-сервер с файлом образа, хранилище образов контейнеров или файл на вашем компьютере, который вы загружаете из командной строки. Кроме того, образ можно создать из другого образа, из диска виртуальной машины или из снимка диска.
Виды образов, поддерживаемые форматы файлов и алгоритмы сжатия описаны в разделе «Типы и форматы образов» руководства администратора.
Загруженный образ хранится одним из двух способов, который задаёт параметр .spec.storage:
ContainerRegistry— вариант по умолчанию, образ хранится в DVCR.PersistentVolumeClaim— образ хранится в PVC. Этот вариант предпочтителен, если хранилище умеет быстро клонировать PVC, потому что диски из такого образа создаются быстрее.
Образ, сохранённый с параметром storage: PersistentVolumeClaim, годится для создания дисков только в том же классе хранения (StorageClass).
Ход создания образа показывает колонка PHASE в выводе d8 k get vi, её значения описаны в поле .status.phase. Следить за созданием в реальном времени помогает ключ -w, а если образ надолго остаётся не готов, причину подскажет блок .status.conditions и команда d8 k describe vi.
Пока образ не перешёл в фазу Ready, блок .spec можно менять, и после изменения загрузка начнётся заново. У готового образа блок .spec изменить уже нельзя. Все параметры образа описаны в VirtualImage.
Создание образа с HTTP-сервера
Проще всего создать образ, указав ссылку на файл, который лежит на HTTP-сервере.
- В командной строке
- В веб-интерфейсе
-
Создайте ресурс VirtualImage. В примере образ сохраняется в DVCR:
d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualImage metadata: name: ubuntu-24-04 spec: # Сохраняем образ в DVCR. storage: ContainerRegistry # Источник для создания образа. dataSource: type: HTTP http: url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img EOF -
Проверьте, что образ создан:
d8 k get virtualimage ubuntu-24-04 # Короткий вариант команды. d8 k get vi ubuntu-24-04Пример вывода:
NAME PHASE CDROM PROGRESS AGE ubuntu-24-04 Ready false 100% 23h
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Образы».
- Нажмите кнопку «Создать».
- В блоке «Источник» выберите «По ссылке».
- В открывшейся форме в поле «Имя образа» введите имя образа.
- В блоке «Хранилище» в поле «Тип хранилища» выберите
ContainerRegistry. - В поле «URL» укажите ссылку на образ.
- Нажмите кнопку «Создать».
- Проверьте статус образа на его странице.
Проверка целостности загруженного образа
Блок checksum заставляет DP проверить то, что он скачал с HTTP-сервера. Образ перейдёт в фазу Ready, только если загруженный файл совпал со всеми указанными контрольными суммами, иначе ресурс окажется в фазе Failed:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualImage
metadata:
name: ubuntu-24-04
spec:
storage: ContainerRegistry
dataSource:
type: HTTP
http:
url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
checksum:
sha256: 78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5
EOFВозьмите контрольную сумму у зеркала, которое публикует образ, и укажите её в поле соответствующего алгоритма:
| Поле | Алгоритм | Скорость проверки |
|---|---|---|
sha1 |
SHA-1 | ~1,6 ГБ/с |
sha256 |
SHA-256 | ~1,5 ГБ/с |
md5 |
MD5 | ~700 МБ/с |
sha512 |
SHA-512 | ~570 МБ/с |
streebog256 |
ГОСТ Р 34.11-2012 («Стрибог»), 256 бит | ~17 МБ/с |
streebog512 |
ГОСТ Р 34.11-2012 («Стрибог»), 512 бит | ~17 МБ/с |
Скорости даны как порядок величины, а не как обещание. Они измерены на процессоре x86-64 с набором инструкций SHA, а процессор без него считает SHA-1 и SHA-256 в несколько раз медленнее. На любом процессоре сохраняется другое, а именно расстояние между строками. SHA-1 и SHA-256 вычисляются отдельными инструкциями, MD5 и SHA-512 написанным вручную ассемблером, и все четыре хешируют данные быстрее, чем те приходят по сети, поэтому их стоимость остаётся незаметной на фоне самой загрузки.
Алгоритмы «Стрибог» аппаратной поддержки не имеют нигде и медленнее примерно на два порядка. Для образа в 10 ГиБ это около десяти минут одного только хеширования, и создание образа упирается уже в процессор, а не в сеть. Указывайте их только тогда, когда контрольная сумма по ГОСТ действительно требуется. Обе длины стоят одинаково, потому что ГОСТ Р 34.11-2012 использует одну и ту же функцию сжатия и для 256, и для 512 бит, а короткий вариант отличается только начальным значением.
Контрольные суммы считаются за один проход по загружаемым данным, поэтому указание нескольких сумм сразу стоит суммы их времён. Незаполненные поля не стоят ничего.
Тот же блок доступен для источника Upload в параметре dataSource.upload.checksum и работает так же. Загружаемые данные проверяются по всем указанным контрольным суммам, а при несовпадении ресурс остаётся в фазе Failed.
Хранение образа в PVC
Чтобы диски создавались из образа быстрее, храните его в PVC. Тогда DP сможет клонировать том вместо повторной распаковки.
- В командной строке
- В веб-интерфейсе
-
Создайте ресурс VirtualImage с типом хранения
PersistentVolumeClaim:d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualImage metadata: name: ubuntu-24-04-pvc spec: # Настройки хранения проектного образа. storage: PersistentVolumeClaim persistentVolumeClaim: # Подставьте название своего StorageClass. storageClassName: rv-thin-r2 # Источник для создания образа. dataSource: type: HTTP http: url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img EOFЕсли параметр
.spec.persistentVolumeClaim.storageClassNameне указан, DP возьмёт StorageClass по умолчанию на уровне кластера либо класс, заданный для образов в настройках модуля. -
Проверьте, что образ создан:
d8 k get vi ubuntu-24-04-pvcПример вывода:
NAME PHASE CDROM PROGRESS AGE ubuntu-24-04-pvc Ready false 100% 23h
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Образы».
- Нажмите кнопку «Создать».
- В блоке «Источник» выберите «По ссылке».
- В открывшейся форме в поле «Имя образа» введите имя образа.
- В блоке «Хранилище» в поле «Тип хранилища» выберите
PersistentVolumeClaim. - В поле «Класс хранилища» выберите StorageClass или оставьте вариант по умолчанию.
- В поле «URL» укажите ссылку на образ.
- Нажмите кнопку «Создать».
- Проверьте статус образа на его странице.
Создание образа из хранилища образов контейнеров
DP умеет забирать образ из внешнего хранилища образов контейнеров, но файл диска должен лежать в образе контейнера по пути /disk. Ниже показано, как подготовить такой образ контейнера и создать из него образ проекта.
- В командной строке
- В веб-интерфейсе
-
Скачайте файл образа на локальную машину:
curl -L https://cloud-images.ubuntu.com/minimal/releases/noble/release/ubuntu-24.04-minimal-cloudimg-amd64.img -o ubuntu2404.img -
Создайте
Dockerfileсо следующим содержимым:FROM scratch COPY ubuntu2404.img /disk/ubuntu2404.img -
Соберите образ контейнера. В примере используется хранилище docker.com, для работы с которым нужны учётная запись и настроенное окружение:
docker build -t docker.io/<USERNAME>/ubuntu2404:latestЗдесь
<USERNAME>— имя пользователя, указанное при регистрации в хранилище. -
Загрузите собранный образ контейнера в хранилище:
docker push docker.io/<USERNAME>/ubuntu2404:latest -
Создайте ресурс VirtualImage, указав путь к образу контейнера:
d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualImage metadata: name: ubuntu-2404 spec: storage: ContainerRegistry dataSource: type: ContainerImage containerImage: image: docker.io/<USERNAME>/ubuntu2404:latest EOF
DP работает только с теми хранилищами, где включён TLS. Если хранилище использует собственный центр сертификации, передайте цепочку сертификатов в параметре caBundle, а учётные данные для доступа к закрытому хранилищу возьмите из секрета, указанного в параметре imagePullSecret.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Образы».
- Нажмите кнопку «Создать».
- В блоке «Источник» выберите «Из реестра».
- В открывшейся форме в поле «Имя образа» введите имя образа.
- В блоке «Хранилище» в поле «Тип хранилища» выберите
ContainerRegistry. - В поле «Образ в реестре контейнеров» укажите путь к образу контейнера.
- Нажмите кнопку «Создать».
- Проверьте статус образа на его странице.
Загрузка образа из командной строки
Если файл образа лежит на вашем компьютере, загрузите его напрямую. DP создаёт для этого временную точку приёма данных и ждёт загрузки.
- В командной строке
- В веб-интерфейсе
-
Создайте ресурс VirtualImage с источником
Upload:d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualImage metadata: name: some-image spec: # Настройки хранения проектного образа. storage: ContainerRegistry # Настройки источника образа. dataSource: type: Upload EOFРесурс перейдёт в фазу
WaitForUserUploadи будет готов принять файл. Начните загрузку в течение 10 минут, иначе ресурс перейдёт в фазуFailedи его придётся создать заново. -
Получите адреса, по которым принимается файл:
d8 k get vi some-image -o jsonpath="{.status.imageUploadURLs}" | jqПример вывода:
{ "external": "https://virtualization.example.com/upload/<SECRET_URL>", "inCluster": "http://10.222.165.239/upload" }Адрес
inClusterиспользуйте, если загружаете файл с одного из узлов кластера, аexternal— во всех остальных случаях. -
Загрузите файл по выбранному адресу. В примере сначала скачивается образ Cirros, а затем отправляется в кластер:
curl -L http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img -o cirros.img curl https://virtualization.example.com/upload/<SECRET_URL> --progress-bar -T cirros.img | catЗдесь
<SECRET_URL>— последняя часть адреса из предыдущего шага. -
Убедитесь, что образ перешёл в фазу
Ready:d8 k get vi some-imageПример вывода:
NAME PHASE CDROM PROGRESS AGE some-image Ready false 100% 1m
Загруженный файл тоже можно сверить с контрольной суммой, для этого задайте блок checksum в источнике данных. Суммы считаются по байтам, которые передаёт клиент, а при несовпадении ресурс остаётся в фазе Failed, и загрузку придётся повторить на пересозданном ресурсе.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Образы».
- Нажмите кнопку «Создать», затем в блоке «Источник» выберите «Загрузить».
- В поле «Имя образа» введите имя образа.
- В блоке «Загрузить файл» перетащите файл в выделенную область или нажмите «выберите на вашем компьютере».
- Выберите файл в открывшемся файловом менеджере.
- Нажмите кнопку «Создать».
- Дождитесь, когда образ перейдёт в состояние «Готов».
Создание образа из диска
Образ можно создать из диска, если диск не подключён ни к одной виртуальной машине либо машина, к которой он подключён, выключена.
- В командной строке
- В веб-интерфейсе
Создайте образ, указав источником нужный диск:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualImage
metadata:
name: linux-vm-root
spec:
storage: ContainerRegistry
dataSource:
type: ObjectRef
objectRef:
kind: VirtualDisk
name: linux-vm-root
EOF- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Образы».
- Нажмите кнопку «Создать».
- В блоке «Источник» выберите «Создать из».
- В открывшейся форме в поле «Имя образа» введите
linux-vm-root. - В блоке «Хранилище» в поле «Тип хранилища» выберите
ContainerRegistry. - В поле «Источник» выберите нужный диск из выпадающего списка.
- Нажмите кнопку «Создать».
- Проверьте статус образа на его странице.
Создание образа из снимка диска
Образ можно создать из снимка диска, если снимок находится в фазе Ready.
- В командной строке
- В веб-интерфейсе
Создайте образ, указав источником снимок диска:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualImage
metadata:
name: linux-vm-root
spec:
storage: ContainerRegistry
dataSource:
type: ObjectRef
objectRef:
kind: VirtualDiskSnapshot
name: linux-vm-root-snapshot
EOF- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Образы».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя образа» введите имя образа.
- В блоке «Хранилище» в поле «Тип хранилища» выберите тип хранения образа.
- В блоке «Источник» выберите «Создать из».
- В поле «Источник» раскройте список и в группе «Снимки дисков» выберите нужный снимок.
- Нажмите кнопку «Создать».
- Проверьте статус образа на его странице.
Свойства образа удобно смотреть в веб-интерфейсе, в разделе «Виртуализация» → «Образы»:
- список показывает имя образа, статус, размер, формат в колонке «Тип» и область видимости в колонке «Доступность», а фильтры сужают его по статусу, образу и типу;
- на странице образа вкладка «Информация» собирает параметры создания в блоках «Хранилище» и «Источник», а в блоке «Состояние» показывает среднюю скорость загрузки, формат, распакованный размер, размер в хранилище, длительность создания, признак «CD-ROM» и путь к образу в DVCR;
- вкладки «Мета» и «YAML» показывают лейблы с аннотациями и полную спецификацию ресурса.
Диски
Диск хранит данные виртуальной машины (ВМ), включая операционную систему и файлы приложений. Описывает диск ресурс VirtualDisk, а его спецификация состоит из двух блоков:
persistentVolumeClaim— параметры хранения, то есть StorageClass и размер;dataSource— источник данных, которым может быть образ, другой диск или снимок.
Без блока dataSource создаётся пустой диск, и тогда в persistentVolumeClaim нужно указать хотя бы размер. Если источник задан, блок persistentVolumeClaim можно опустить, тогда размер DP возьмёт из источника, а класс хранения подберёт по нему же. Когда подобрать класс не удаётся, DP использует StorageClass по умолчанию на уровне кластера либо класс, заданный для дисков в настройках модуля.
Ход создания диска показывает колонка PHASE в выводе d8 k get vd, её значения описаны в поле .status.phase. Если диск надолго остаётся не готов, причину подскажет блок .status.conditions.
Пока диск не перешёл в фазу Ready, менять можно любые поля блока .spec, и после изменения создание начнётся заново. У готового диска остаются изменяемыми только размер и класс хранения в параметрах .spec.persistentVolumeClaim.size и .spec.persistentVolumeClaim.storageClassName.
Создать диск из ISO-образа нельзя.
Влияние хранилища на диск
Поведение диска зависит от того, какое хранилище стоит за выбранным StorageClass. Различия проявляются в двух свойствах.
Тип тома определяет формат, в котором DP создаёт диск. На томах файловой системы (FileSystem, например NFS) диск создаётся в формате qcow2, на блочных устройствах (Block, например iSCSI или Ceph RBD) данные пишутся напрямую. Некоторые хранилища поддерживают оба типа.
Режим привязки тома определяет момент создания диска:
-
Immediate— диск создаётся сразу, независимо от виртуальных машин, и подключить его можно к машине на любом узле кластера.
-
WaitForFirstConsumer— диск создаётся только после того, как его подключат к виртуальной машине, и размещается на узле, где эта машина запускается.
Остальные параметры, включая формат диска, DP определяет сам по возможностям выбранного StorageClass.
Чтобы посмотреть доступные хранилища, выполните команду:
d8 k get storageclassПример вывода:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
rv-thin-r1 (default) replicated.csi.storage.deckhouse.io Delete Immediate true 48d
rv-thin-r2 replicated.csi.storage.deckhouse.io Delete Immediate true 48d
nfs-4-1-wffc nfs.csi.k8s.io Delete WaitForFirstConsumer true 30d
В веб-интерфейсе тот же список доступен на вкладке «Система» в разделе «Хранилище» → «Классы хранилищ».
Создание пустого диска
Пустой диск нужен, чтобы установить на него операционную систему или хранить данные отдельно от системного диска.
- В командной строке
- В веб-интерфейсе
-
Создайте ресурс VirtualDisk, указав размер и класс хранения:
d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: blank-disk spec: # Настройки параметров хранения диска. persistentVolumeClaim: # Подставьте название своего StorageClass. storageClassName: rv-thin-r2 size: 100Mi EOF -
Проверьте, что диск создан:
d8 k get vd blank-diskПример вывода:
NAME PHASE CAPACITY VIRTUALMACHINE AGE blank-disk Ready 100Mi 1m2s
Шаг можно пропустить и создать диск сразу при создании ВМ.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Диски».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя диска» введите
blank-disk. - В поле «Размер» задайте размер с единицами измерения, например
100Mi. - В поле «Класс хранения» выберите StorageClass или оставьте вариант по умолчанию.
- Нажмите кнопку «Создать».
- Проверьте статус диска на его странице.
Создание диска из образа
Диск можно заполнить данными из образа, созданного ранее, будь то проектный VirtualImage или кластерный ClusterVirtualImage.
Размер диска указывать необязательно. Если вы его не задали, DP создаст диск ровно по распакованному размеру образа, а если задали, размер должен быть не меньше распакованного.
- В командной строке
- В веб-интерфейсе
-
Посмотрите распакованный размер образа в колонке
UNPACKEDSIZE:d8 k get vi ubuntu-24-04 -o wideПример вывода:
NAME PHASE CDROM PROGRESS STOREDSIZE UNPACKEDSIZE REGISTRY URL TARGETPVC AGE ubuntu-24-04 Ready false 100% 285.9Mi 2.5Gi dvcr.d8-virtualization.svc/vi/default/ubuntu-24-04:eac95605-7e0b-4a32-bb50-cc7284fd89d0 122m -
Создайте диск, задав размер больше распакованного:
d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: linux-vm-root spec: # Настройки параметров хранения диска. persistentVolumeClaim: # Размер больше, чем распакованный размер образа. size: 10Gi # Подставьте название своего StorageClass. storageClassName: rv-thin-r2 # Источник, из которого создаётся диск. dataSource: type: ObjectRef objectRef: kind: VirtualImage name: ubuntu-24-04 EOF -
Создайте второй диск, не указывая размер:
d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: linux-vm-root-2 spec: # Настройки параметров хранения диска. persistentVolumeClaim: # Подставьте название своего StorageClass. storageClassName: rv-thin-r2 # Источник, из которого создаётся диск. dataSource: type: ObjectRef objectRef: kind: VirtualImage name: ubuntu-24-04 EOF -
Сравните размеры созданных дисков:
d8 k get vdПример вывода:
NAME PHASE CAPACITY VIRTUALMACHINE AGE linux-vm-root Ready 10Gi 7m52s linux-vm-root-2 Ready 2590Mi 7m15sПервый диск получил заданные 10 ГиБ, второй — распакованный размер образа.
Шаг можно пропустить и создать диск сразу при создании ВМ.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Диски».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя диска» введите
linux-vm-root. - В поле «Источник» из выпадающего списка выберите нужный образ.
- При необходимости в поле «Размер» укажите больший размер или оставьте значение по умолчанию.
- В поле «Класс хранения» выберите StorageClass или оставьте вариант по умолчанию.
- Нажмите кнопку «Создать».
- Проверьте статус диска на его странице.
Загрузка диска из командной строки
Если файл образа лежит на вашем компьютере, загрузите его сразу в диск. DP создаёт для этого временную точку приёма данных и ждёт загрузки.
- В командной строке
- В веб-интерфейсе
-
Создайте ресурс VirtualDisk с источником
Upload:d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: uploaded-disk spec: dataSource: type: Upload EOFРесурс перейдёт в фазу
WaitForUserUploadи будет готов принять файл. Начните загрузку в течение 10 минут, иначе ресурс перейдёт в фазуFailedи его придётся создать заново. -
Получите адреса, по которым принимается файл:
d8 k get vd uploaded-disk -o jsonpath="{.status.imageUploadURLs}" | jqПример вывода:
{ "external": "https://virtualization.example.com/upload/<SECRET_URL>", "inCluster": "http://10.222.165.239/upload" }Адрес
inClusterиспользуйте, если загружаете файл с одного из узлов кластера, аexternal— во всех остальных случаях. -
Загрузите файл по выбранному адресу:
curl https://virtualization.example.com/upload/<SECRET_URL> --progress-bar -T <IMAGE_FILE> | catЗдесь
<SECRET_URL>— адрес из предыдущего шага, а<IMAGE_FILE>— путь к файлу образа на вашем компьютере. -
Убедитесь, что диск перешёл в фазу
Ready:d8 k get vd uploaded-diskПример вывода:
NAME PHASE CAPACITY VIRTUALMACHINE AGE uploaded-disk Ready 3Gi 7d23h
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Диски».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя диска» введите имя диска.
- В блоке «Диск» в поле «Источник данных» выберите «Загрузить».
- Перетащите файл в выделенную область или нажмите на неё и выберите файл на компьютере.
- В поле «Размер» укажите размер диска, а в поле «Класс хранения» — StorageClass.
- Нажмите кнопку «Создать».
Если у выбранного класса хранения режим привязки тома
WaitForFirstConsumer, вариант «Загрузить» недоступен. Без потребителя диск не создаётся, и загружать файл некуда, поэтому выберите класс хранения с режимомImmediateлибо загрузите данные как образ.По этой же причине пустой диск, созданный заранее с таким классом хранения, остаётся в статусе «ОЖИДАНИЕ ВМ» и не предлагается в окне «Диски / Образы» при подключении к виртуальной машине, ведь выбрать можно только готовый диск. Создавайте такие диски прямо из формы виртуальной машины вариантами «Пустой» или «Создать из».
Свойства диска удобно смотреть в веб-интерфейсе, в разделе «Виртуализация» → «Диски»:
- список показывает имя диска, статус, размер, класс хранения в колонке «Класс», использующую диск виртуальную машину в колонке «Используется» и возраст ресурса;
- на странице диска вкладка «Конфигурация» показывает источник данных, размер, класс хранения и список ВМ в строке «Используется в»;
- вкладка «Диагностика» показывает имя PVC, его фазу, размер, класс хранения, имя PV и возраст, а также длительность этапов создания диска в блоке «Сводка диагностики».
Изменение размера диска
Диск можно увеличить, даже если он подключён к работающей виртуальной машине (ВМ). Уменьшить диск нельзя.
- В командной строке
- В веб-интерфейсе
-
Посмотрите текущий размер диска:
d8 k get vd linux-vm-rootПример вывода:
NAME PHASE CAPACITY VIRTUALMACHINE AGE linux-vm-root Ready 10Gi linux-vm 10m -
Задайте новый размер в параметре
.spec.persistentVolumeClaim.size:d8 k patch vd linux-vm-root --type merge -p '{"spec":{"persistentVolumeClaim":{"size":"11Gi"}}}' # Того же результата можно добиться, отредактировав ресурс. d8 k edit vd linux-vm-root -
Убедитесь, что размер изменился:
d8 k get vd linux-vm-rootПример вывода:
NAME PHASE CAPACITY VIRTUALMACHINE AGE linux-vm-root Ready 11Gi linux-vm 12m
Размер можно изменить со страницы виртуальной машины:
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите ВМ, к которой подключён диск, и нажмите на её имя.
- На вкладке «Конфигурация» в разделе «Диски» нажмите на символ карандаша рядом с размером диска.
- В открывшемся окне укажите больший размер.
- Нажмите кнопку «Применить».
Либо со страницы самого диска:
- Перейдите в раздел «Виртуализация» → «Диски».
- Выберите нужный диск и нажмите на его имя.
- На вкладке «Конфигурация» в поле «Размер» укажите больший размер.
- Нажмите появившуюся кнопку «Сохранить».
- Проверьте статус диска на его странице.
Миграция дисков на другие хранилища
В коммерческих редакциях DP диск можно перенести в другое хранилище, изменив его класс хранения. Перенос работает и для дисков, заданных в спецификации ВМ, и для подключённых отдельным ресурсом.
Виртуальная машина должна находиться в фазе Running, а исходное и целевое хранилища должны быть одного типа. Перенести диск с тома файловой системы на блочное устройство или наоборот нельзя.
Чтобы перенести диск, укажите новый класс хранения в параметре .spec.persistentVolumeClaim.storageClassName:
d8 k patch vd disk --type=merge --patch '{"spec":{"persistentVolumeClaim":{"storageClassName":"new-storage-class-name"}}}'
# Того же результата можно добиться, отредактировав ресурс.
d8 k edit vd diskПосле этого запускается живая миграция ВМ, в ходе которой диск переезжает в новое хранилище.
Если перенести нужно несколько дисков одной машины, меняйте класс хранения последовательно, по одному диску за раз:
d8 k patch vd disk1 --type=merge --patch '{"spec":{"persistentVolumeClaim":{"storageClassName":"new-storage-class-name"}}}'
d8 k patch vd disk2 --type=merge --patch '{"spec":{"persistentVolumeClaim":{"storageClassName":"new-storage-class-name"}}}'Неудачную миграцию DP повторяет с растущей задержкой. Первая попытка идёт сразу, следующие через 5 и 10 секунд, дальше задержка удваивается и с седьмой попытки остаётся равной 300 секундам. Чтобы отменить миграцию, верните в спецификации прежний класс хранения.
Экспорт диска или снимка
Экспорт выгружает содержимое диска или его снимка в файл, чтобы перенести данные за пределы кластера. Для работы этой функции должен быть включён модуль storage-volume-data-manager, а в командной строке нужна утилита d8 версии 0.20.7 и выше.
Диск не должен использоваться в момент экспорта. Если диск подключён к виртуальной машине, ВМ необходимо предварительно остановить.
Чтобы импортировать скачанный диск обратно в кластер, загрузите его как образ или как диск.
- В командной строке
- В веб-интерфейсе
Пример экспорта диска, команда выполняется на узле кластера:
d8 data export download -n <NAMESPACE> vd/<VD_NAME> -o file.imgПример экспорта снимка диска, команда выполняется на узле кластера:
d8 data export download -n <NAMESPACE> vds/<VD_SNAPSHOT_NAME> -o file.imgЕсли вы выполняете экспорт данных не с узла кластера (например, с вашей локальной машины), используйте флаг --publish.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Остановите виртуальную машину, к которой подключён диск. Пока диск используется, пункт «Скачать» недоступен.
- Перейдите в раздел «Виртуализация» → «Диски».
- В строке нужного диска нажмите кнопку с многоточием и выберите «Скачать».
- Дождитесь, пока в окне «Скачать» шаг «Подготовка…» сменится на «Готов»: файл скачается автоматически, как только будет создан. Если этого не произошло, нажмите в нём кнопку «Скачать».
Пока выгрузка активна, диск находится в фазе Exporting, и виртуальная машина с этим диском не запустится. Выгрузка завершается по истечении времени жизни или вместе с удалением ресурса DataExport, созданного для неё.
Виртуальные машины
Для создания виртуальной машины (ВМ) используется ресурс VirtualMachine. Его параметры позволяют сконфигурировать:
- класс виртуальной машины;
- ресурсы, требуемые для работы виртуальной машины (процессор, память, диски и образы);
- правила размещения виртуальной машины на узлах кластера;
- настройки загрузчика и оптимальные параметры для гостевой ОС;
- политику запуска виртуальной машины и политику применения изменений;
- сценарии начальной конфигурации (cloud-init);
- перечень блочных устройств.
С полным описанием параметров конфигурации виртуальных машин можно ознакомиться по в документации конфигурации.
Создание виртуальной машины
Ниже показано, как запустить виртуальную машину с Ubuntu 24.04 на диске, созданном ранее. Сценарий cloud-init устанавливает агента qemu-guest-agent и сервис nginx, а также создаёт пользователя cloud с паролем cloud.
- В командной строке
- В веб-интерфейсе
-
Создайте ресурс VirtualMachine:
d8 k apply -f - <<"EOF" apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: linux-vm spec: # Название класса ВМ. virtualMachineClassName: generic # Тип ОС, Generic для Linux и Windows для Windows. По умолчанию Generic. # osType: Generic # Тип загрузчика: BIOS, EFI или EFIWithSecureBoot. По умолчанию BIOS. # bootloader: BIOS # Сценарий первичной инициализации ВМ. provisioning: type: UserData userData: | #cloud-config package_update: true packages: - nginx - qemu-guest-agent runcmd: - systemctl daemon-reload - systemctl enable --now nginx.service - systemctl enable --now qemu-guest-agent.service ssh_pwauth: True users: - name: cloud passwd: <PASSWORD_HASH> shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: False final_message: "The system is finally up, after $UPTIME seconds" # Настройки ресурсов ВМ. cpu: # Количество ядер процессора. cores: 1 # Гарантированная доля процессорного времени одного ядра. coreFraction: 10% memory: # Объём оперативной памяти. size: 1Gi # Список дисков и образов, подключаемых к ВМ. blockDeviceRefs: # Порядок в этом блоке определяет приоритет загрузки. - kind: VirtualDisk name: linux-vm-root EOFЗдесь
<PASSWORD_HASH>— хеш пароля пользователяcloudв кавычках, полученный командойmkpasswd --method=SHA-512 --rounds=4096. -
Проверьте, что машина запустилась:
d8 k get vm linux-vmПример вывода:
NAME PHASE UPTIME NODE IPADDRESS AGE linux-vm Running 11m virtlab-pt-2 10.66.10.12 11mIP-адрес машина получает автоматически из диапазона, заданного администратором в настройках модуля.
-
Перейдите на вкладку «Проекты» и выберите нужный проект.
-
Перейдите в раздел «Виртуализация» → «Виртуальные машины».
-
Нажмите кнопку «Создать».
-
В открывшейся форме в поле «Имя» введите
linux-vm. -
В разделе «Ресурсы» задайте
1в поле «Ядра ЦП»,10%в поле «Доля ядра» и1Giв поле «Объём памяти». -
В разделе «Диски» нажмите кнопку «Добавить».
-
В открывшемся окне «Диски / Образы» выберите «Существующий» и укажите в списке диск
linux-vm-root. -
Прокрутите страницу вниз до переключателя «Cloud-init» и включите его.
-
В появившееся поле вставьте сценарий, подставив вместо
<PASSWORD_HASH>хеш пароля в кавычках:#cloud-config package_update: true packages: - nginx - qemu-guest-agent runcmd: - systemctl daemon-reload - systemctl enable --now nginx.service - systemctl enable --now qemu-guest-agent.service ssh_pwauth: True users: - name: cloud passwd: <PASSWORD_HASH> shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: False final_message: "The system is finally up, after $UPTIME seconds" -
Нажмите кнопку «Создать».
-
Проверьте статус ВМ на её странице.
Жизненный цикл ВМ
От создания до удаления виртуальная машина проходит через несколько фаз. Текущую показывает поле .status.phase, а подробности о том, что с машиной происходит, содержит блок .status.conditions.

Условия в блоке .status.conditions отвечают на вопрос, почему машина находится в текущей фазе. Посмотреть те из них, где есть сообщение, можно так:
d8 k get vm <VM_NAME> -o json | jq '.status.conditions[] | select(.message != "")'Здесь <VM_NAME> — имя виртуальной машины.
Диагностика по фазам
Пока ВМ находится в фазе Pending, она ждёт готовности зависимых ресурсов, то есть дисков, образов, класса ВМ, секрета со сценарием начальной конфигурации. Задержка на этой фазе означает, что какой-то из ресурсов не готов либо исчерпаны квоты неймспейса или проекта. Что именно блокирует запуск, показывают условия, оканчивающиеся на Ready:
d8 k get vm <VM_NAME> -o json | jq '.status.conditions[] | select(.type | test(".*Ready"))'В фазе Starting зависимые ресурсы готовы, и DP запускает ВМ на одном из узлов. Если запуск затягивается, подходящего узла нет либо на подходящих узлах не хватает процессора или памяти. Причину сообщает условие Running:
d8 k get vm <VM_NAME> -o json | jq '.status.conditions[] | select(.type=="Running")'В фазе Migrating машина переезжает на другой узел живой миграцией. Миграция не начнётся или прервётся, если наборы процессорных инструкций на узлах несовместимы, версии ядра различаются, ни один узел не подходит под правила размещения или на подходящих узлах не хватает ресурсов. Ход миграции показывает условие Migrating вместе с блоком .status.migrationState:
d8 k get vm <VM_NAME> -o json | jq '.status | {condition: .conditions[] | select(.type=="Migrating"), migrationState}'Фаза Terminating необратима, все связанные с ВМ ресурсы освобождаются, но сами ресурсы не удаляются.
Условия запущенной ВМ
У работающей машины стоит следить за несколькими условиями:
AgentReadyсо статусомTrueозначает, что в гостевой системе работаетqemu-guest-agent, и тогда блок.status.guestOSInfoсодержит сведения о гостевой ОС.FirmwareUpToDateсо статусомFalseозначает, что прошивку ВМ пора обновить.ConfigurationAppliedсо статусомFalseозначает, что заданная конфигурация к запущенной машине ещё не применена.AwaitingRestartToApplyConfigurationсо статусомTrueозначает, что часть изменений применится только после перезагрузки, и выполнить её нужно вручную.SizingPolicyMatchedсо статусомFalseозначает, что ресурсы машины не отвечают политике сайзинга её класса. Пока вы не приведёте параметры в соответствие политике, сохранить изменения конфигурации не получится.Migratableпоказывает, можно ли перенести машину живой миграцией. Условие вычисляется только для запущенной ВМ, у выключенной оно отсутствует. СтатусFalseс причинойVirtualMachineNoMigrationTargetозначает, что сама машина к миграции пригодна, но подходящего узла в кластере нет. СтатусTrueс причинойVirtualMachineWaitingForMigrationTargetозначает, что подходящие узлы есть, но сейчас ни один не может принять машину, и такое состояние проходит само.
Вытеснение с узла
Условие EvictionRequired появляется, когда узел с вашей ВМ переводят в режим обслуживания. Если узел только вывели из планирования командой d8 k cordon, но обслуживание не начали, условие не появляется.
Сообщение условия говорит, что произойдёт с машиной, а именно перенос живой миграцией без остановки гостевой ОС, перезапуск силами DP с разрешения администратора кластера либо ожидание, пока машину не перезапустят. Машину, которую можно перенести живой миграцией, ради освобождения узла не перезапускают. Пока вытеснение не началось, условие носит предупреждающий характер, потому что обслуживание могут отменить.
После перезапуска машина запускается на другом подходящем узле. Если такого узла нет, она остаётся в фазе Pending, а причину от планировщика показывает условие Running. Узел в режиме обслуживания новые машины не принимает, поэтому ВМ, закреплённая за ним правилами размещения или использующая проброшенное с него устройство, запустится только после возвращения узла в работу.
Просмотр состояния в веб-интерфейсе
Веб-интерфейс показывает фазу машины, её ресурсы и текущие проблемы на странице самой машины.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
В шапке страницы показаны текущая фаза ВМ, её IP-адрес, класс, конфигурация ресурсов, количество подключённых дисков и образов, узел размещения, признак работы агента гостевой ОС и время с момента запуска. Сама страница разделена на вкладки «Конфигурация», «Мониторинг», «Операции», «События», «VNC», «TTY», «Сетевые политики», «Снимки», «Диагностика», «Мета» и «YAML».
На вкладке «Конфигурация» у запущенной ВМ рядом с полями «Ядра ЦП» и «Объём памяти» отображаются графики использования. В блоке «Диски» для каждого устройства показаны порядковый номер загрузки, имя, размер, статус, способ подключения, класс хранения и текущая нагрузка на диск. В блоке «Сети» показаны имя сети, её статус, IP- и MAC-адреса, а основная сеть кластера обозначена как «Main».
Настройки CPU и coreFraction
Процессорные ресурсы машины задают два параметра. Параметр .spec.cpu.cores определяет число виртуальных ядер, а .spec.cpu.coreFraction — гарантированную долю мощности каждого из них.
spec:
cpu:
cores: 2
coreFraction: 20%В этом примере машина получает два виртуальных ядра и гарантированные 20% мощности каждого, то есть 0,4 ядра в сумме, независимо от загрузки узла. Когда на узле есть свободные ресурсы, машина может занять оба ядра целиком. Такой запас позволяет держать на узле больше машин, чем на нём физических ядер, и при этом не терять стабильность под нагрузкой.
Если coreFraction не задан, каждое виртуальное ядро получает 100% физического.
Администратор может ограничить набор допустимых значений coreFraction в политике сайзинга класса ВМ, и тогда выбирать придётся из них.
Гарантированная доля учитывается при выборе узла, поэтому машина не запустится там, где узел не может обеспечить гарантии всем размещённым на нём машинам. На рисунке показаны две машины с одним ядром каждая, у первой coreFraction: 20%, у второй coreFraction: 80%.

Автоматический coreFraction (Auto)
Долю процессорного времени DP может подбирать сам, следя за тем, сколько машина потребляет.
Возможность доступна в коммерческих редакциях DP и находится в стадии Alpha. Она требует включённого модуля vertical-pod-autoscaler, который подбирает долю ядра, и функции HotplugCPUAndMemoryWithInPlaceResize в настройках модуля. Функция работает с Kubernetes версии 1.33 и выше на управляющем слое и на всех узлах, где запускаются ВМ.
Вместо фиксированного процента можно задать coreFraction: Auto. Тогда долю подбирает DP, повышая её, когда машине не хватает процессора, и понижая, когда машина простаивает. Число ядер и объём памяти при этом не меняются, а новая доля применяется без перезагрузки.
spec:
cpu:
cores: 4
coreFraction: AutoПодбор устроен так:
- Начальная доля ядра — 10% или ближайшее значение, разрешённое политикой сайзинга.
- Доля меняется шагами. Если в политике сайзинга класса задан список
coreFractions, шагами становятся его значения, иначе используются 5%, 10%, 15%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% и 99%. - Значение 100% автоматически не выбирается, потому что при нём запросы процессора сравниваются с лимитами, а такую машину нельзя изменить без перезагрузки. Если 100% указан в
coreFractions, он просто не используется, и потолком становится следующее значение вниз, а без политики сайзинга потолок равен 99%. - По той же причине политика сайзинга должна оставлять хотя бы два значения на выбор. Политика, разрешающая только 50% либо 50% и 100%, навсегда зафиксировала бы машину на 50%, поэтому такое сочетание отклоняется, и долю придётся задать явно.
- Рекомендованное значение публикуется в поле
.status.recommendedResources.cpu.coreFraction, а применённое — в.status.resources.cpu.coreFraction. О каждом изменении сообщает событиеCoreFractionScaling. - Если на узле не хватает места под новые запросы, машина переезжает на другой узел и продолжает работать.
Идёт ли подбор, показывает условие CoreFractionAutoscaling. Пока подбор работает, условие имеет статус True, а первые минуты, пока не накопится статистика, причиной будет WaitingForRecommendation, затем CoreFractionAutoscalingEnabled.
Если подбор стал недоступен, условие переходит в False, и причина объясняет, почему это произошло:
CoreFractionAutoscalingDisabled— выключено вертикальное автомасштабирование;InPlaceResizeDisabled— выключено изменение ресурсов на лету;SizingPolicyHasNoSteps— политику сайзинга сузили до одного значения.
Машина при этом продолжает работать с текущей долей, но перестаёт следовать за нагрузкой.
Чтобы отказаться от автоматического подбора, задайте явный процент. Переход между 100% и Auto в любую сторону требует перезагрузки машины, потому что меняет её класс QoS, а остальные переходы применяются на лету.
Политика сайзинга
Администратор может ограничить сочетания ресурсов, доступные машинам определённого класса, задав политику сайзинга в параметре .spec.sizingPolicies ресурса VirtualMachineClass. Если политики нет, ресурсы задаются произвольно.
Политика делит число ядер на диапазоны и для каждого задаёт допустимый объём памяти и разрешённые значения coreFraction:
spec:
sizingPolicies:
- cores:
min: 1
max: 4
memory:
min: 1Gi
max: 8Gi
coreFractions: [5, 10, 20, 50, 100]
- cores:
min: 5
max: 8
memory:
min: 5Gi
max: 16Gi
coreFractions: [20, 50, 100]С такой политикой машина с двумя ядрами попадает в первый диапазон, получает от 1 до 8 ГиБ памяти и одно из значений 5%, 10%, 20%, 50% или 100%. Машина с шестью ядрами попадает во второй диапазон, где памяти доступно от 5 до 16 ГиБ, а долей ядра — 20%, 50% или 100%.
Политика ограничивает и переподписку. Например, минимальное значение coreFraction: 20% гарантирует каждой машине пятую часть ядра, а значит переподписка не превысит 5 к 1.
Если конфигурация машины политике не отвечает, в статусе появляется условие SizingPolicyMatched со статусом False. Такая машина продолжает работать, но сохранить изменения её конфигурации не получится, пока ресурсы не приведут в соответствие политике. Это же происходит, когда администратор меняет политику у класса уже работающих машин.
Кроме границ диапазон может задавать шаг сетки в параметрах cores.step и memory.step, а также границы памяти в расчёте на одно ядро в блоке memory.perCore.
Запрос, нарушающий политику, отклоняется с сообщением, в котором указаны параметр и допустимые значения. Каждое сообщение заканчивается подсказкой check the sizing policy of the VirtualMachineClass or contact the administrator for more information, ниже она опущена.
Для класса supercpu с политикой выше сообщения выглядят так:
- число ядер вне всех диапазонов,
cores: 10—does not match any sizing policy of VirtualMachineClass "supercpu": its 10 CPU core(s) fall outside the allowed ranges (1-4, 5-8); set the number of cores (spec.cpu.cores) accordingly; - недопустимая доля ядра,
cores: 2иcoreFraction: 30%—the CPU core fraction "30%" is not allowed; set the core fraction (spec.cpu.coreFraction) to one of: 5%, 10%, 20%, 50%, 100%; - память вне диапазона,
cores: 2иsize: 16Gi—the memory size (16Gi) is out of the range allowed by the sizing policy; set the memory size (spec.memory.size) between 1Gi and 8Gi.
Если в диапазоне заданы шаг или границы памяти на ядро, добавляются ещё четыре сообщения:
- ядра не на сетке шага —
the number of CPU cores (7) does not match the sizing policy step; set the number of cores (spec.cpu.cores) to 6 or 8; - память не на сетке шага —
the memory size (1536Mi) does not match the sizing policy step; set the memory size (spec.memory.size) to 1Gi or 2Gi; - память на ядро вне диапазона —
the memory size (18Gi) is not allowed for 6 CPU core(s); set the memory size (spec.memory.size) between 6Gi and 12Gi, or change the number of cores (spec.cpu.cores) (the sizing policy allows between 1Gi and 2Gi of memory per core); - память на ядро не на сетке шага —
the memory size (2560Mi) does not match the per-core sizing policy step for 2 CPU core(s); set the memory size (spec.memory.size) to 2Gi or 4Gi, or change the number of cores (spec.cpu.cores).
Когда нарушений несколько, все причины перечисляются в одном сообщении под заголовком does not match the sizing policy of VirtualMachineClass "supercpu" for several reasons:.
Топологии CPU
Топология определяет, как ядра процессора машины распределяются по сокетам, и от неё зависит совместимость с приложениями, чувствительными к конфигурации процессора. Вы задаёте только общее число ядер в параметре .spec.cpu.cores, а число сокетов DP рассчитывает сам:
spec:
cpu:
cores: 20Чем больше ядер, тем на большее число сокетов они делятся, и тем крупнее шаг, с которым можно менять их количество. Общее число ядер должно быть кратно числу сокетов, иначе запрос отклоняется.
| Число ядер | Сокетов | Кратность | Ядер в сокете |
|---|---|---|---|
1 ≤ cores ≤ 16 |
1 | 1 | от 1 до 16 |
16 < cores ≤ 32 |
2 | 2 | от 9 до 16 |
32 < cores ≤ 64 |
4 | 4 | от 9 до 16 |
64 < cores ≤ 248 |
8 | 8 | от 9 до 31 |
Например, 20 ядер дают два сокета по 10 ядер, а 80 ядер — восемь сокетов по 10. Максимум для одной машины составляет 248 ядер.
Рассчитанную топологию DP публикует в статусе:
status:
resources:
cpu:
topology:
coresPerSocket: 10
sockets: 2Накладные расходы памяти зависят от фактически активных ядер и составляют 8 МиБ на каждое логическое ядро, то есть на произведение числа сокетов, ядер в сокете и потоков на ядро.
Настройка типа ОС и загрузчика
Параметр osType определяет тип операционной системы и применяет оптимальный набор виртуальных устройств и параметров для корректной работы виртуальной машины (ВМ).
Поддерживаемые значения:
Generic(по умолчанию) — для Linux и других операционных систем. Используется стандартная конфигурация виртуальных устройств.Windows— для операционных систем семейства Microsoft Windows. Автоматически включает функции Hyper-V, TPM-устройство и другие настройки, оптимизированные для работы Windows.Legacy— для операционных систем без встроенных драйверов AHCI и virtio, то есть Windows XP, Windows 2000, Windows Server 2003, систем эпохи DOS и Linux с ядром старше 2.6.19. Такая ВМ получает чипсет i440fx, а сenableParavirtualization: false— ещё и шину IDE для дисков и CD-ROM и сетевой адаптер RTL8139, драйверы которых есть в этих операционных системах.
Виртуальная машина получает эмулированный TPM, состояние которого хранится в памяти и не сохраняется. При перезагрузке или миграции ВМ состояние TPM сбрасывается. Учитывайте это ограничение при использовании функций безопасности Windows, зависящих от TPM.
Набор виртуальных устройств, которые видит гостевая ОС:
| Устройство | Generic |
Windows |
Legacy |
|---|---|---|---|
| Чипсет | q35 | q35 | i440fx |
| Загрузчик | BIOS, EFI, EFIWithSecureBoot |
BIOS, EFI, EFIWithSecureBoot |
только BIOS |
| Шина дисков | virtio-scsi, при enableParavirtualization: false — SATA |
virtio-scsi, при enableParavirtualization: false — SATA |
virtio-blk, при enableParavirtualization: false — IDE |
| Шина CD-ROM | virtio-scsi, при enableParavirtualization: false — SATA |
virtio-scsi, при enableParavirtualization: false — SATA |
IDE |
Блочных устройств в .spec.blockDeviceRefs |
не более 16 | не более 16 | не более 16, при enableParavirtualization: false — не более 4 |
| Сетевой адаптер | virtio-net, при enableParavirtualization: false — e1000 |
virtio-net, при enableParavirtualization: false — e1000 |
virtio-net, при enableParavirtualization: false — RTL8139 |
| USB-контроллер | xHCI (USB 3.0) | xHCI (USB 3.0) | UHCI (USB 1.1) |
| TPM | нет | TPM 2.0 | нет |
| Генератор случайных чисел | virtio-rng | нет | нет |
| Функции Hyper-V | нет | да | нет |
| Подключение дисков на ходу | да | да | только при enableParavirtualization: true и только если у гостевой ОС есть драйвер virtio-scsi |
| Изменение CPU и памяти на ходу | да | да | нет |
Проброс USB-устройств для Legacy работает, но контроллер UHCI ограничен скоростью USB 1.1 в 12 Мбит/с, поэтому быстрый накопитель в такой ВМ упрётся в шину.
Выбирайте Legacy, когда гостевая операционная система не умеет работать с контроллером AHCI, а не просто потому, что она старая. Для Linux с ядром 2.6.19 и новее подходит osType: Generic с enableParavirtualization: false — там нет ограничения в четыре устройства и диски можно подключать на ходу через VirtualMachineBlockDeviceAttachment.
Для Legacy недоступны:
- изменение числа ядер процессора и объёма памяти на работающей ВМ, потому что эти гостевые ОС не вводят их в работу. Изменение принимается, ВМ показывает его в
.status.restartAwaitingChangesвместе с условиемAwaitingRestartToApplyConfiguration, а применяется оно после перезапуска; - изменение состава
.spec.blockDeviceRefsу работающей ВМ, потому что в обоих режимах паравиртуализации эти диски остаются статическими, поэтому блочное устройство добавляйте до запуска ВМ; - загрузчики
EFIиEFIWithSecureBoot, а также начальная инициализация (cloud-initи Sysprep), потому что эти гостевые ОС их не поддерживают; - сведения о гостевой ОС в статусе ВМ и информация о файловых системах.
Гостевой агент QEMU в такую ОС поставить можно, из архивного выпуска virtio-win, и ВМ действительно покажет AgentReady, но его версия слишком старая для DP. У ВМ появляется условие AgentVersionNotSupported, сведения о гостевой ОС не собираются, а обновить агента не на что.
Снимок с requiredConsistency: true тоже не завершится успешно, но по другой причине. DP запрашивает заморозку файловой системы, а агент отвечает, что команда в его сборке отключена, сообщением guest-fsfreeze-status has been disabled for this instance. На Windows заморозка идёт через провайдер VSS, которого в этой сборке нет. Снимок около десяти минут ждёт в фазе InProgress и переходит в Failed, поэтому для таких ВМ задавайте requiredConsistency: false.
С enableParavirtualization: false добавляется ещё одно ограничение. Блочных устройств может быть не более четырёх суммарно, потому что шина IDE предоставляет два канала по два устройства.
Пример конфигурации для виртуальной машины с Windows XP:
spec:
osType: Legacy
bootloader: BIOS
enableParavirtualization: false
# остальные параметры...Параметр bootloader определяет тип загрузчика виртуальной машины:
BIOS(по умолчанию) — использование устаревшего BIOS;EFI— использование Unified Extensible Firmware Interface (UEFI/EFI);EFIWithSecureBoot— использование UEFI/EFI с поддержкой Secure Boot.
Пример конфигурации для виртуальной машины с Windows:
spec:
osType: Windows
bootloader: EFI
# остальные параметры...Пример конфигурации для виртуальной машины с Linux (значения по умолчанию можно не указывать):
spec:
osType: Generic
bootloader: BIOS
# остальные параметры...Для современных Linux-дистрибутивов выбирайте bootloader: EFI, а для Windows — bootloader: EFI или bootloader: EFIWithSecureBoot.
Для EFIWithSecureBoot нужен постоянный том под состояние Secure Boot, а для его создания — StorageClass по умолчанию в кластере. Если его нет, виртуальная машина не запускается и остаётся в состоянии Pending, а в её статусе указывается, что StorageClass по умолчанию не найден. Как только StorageClass по умолчанию появится, машина запустится автоматически.
Параметр enableParavirtualization управляет использованием шины virtio для подключения виртуальных устройств ВМ. Изменение значения параметра учитывается только после перезагрузки ВМ.
true(по умолчанию) — используется шинаvirtioдля дисков, сетевых интерфейсов и других устройств, что обеспечивает лучшую производительность. Состав.spec.blockDeviceRefsу работающей ВМ можно менять без перезагрузки — добавляя и удаляя устройства, если диск доступен на узле, где выполняется ВМ.false— используется эмуляция стандартных устройств (SATA для дисков, e1000 для сетевых интерфейсов; IDE и RTL8139 для типа ОСLegacy), что может быть необходимо для совместимости со старыми ОС без драйверовVirtIO. Изменения в.spec.blockDeviceRefsна работающей ВМ (добавление и удаление дисков и образов, в том числе ISO) вступают в силу после перезагрузки ВМ. Подключать и отключать диски без перезагрузки можно через ресурс VirtualMachineBlockDeviceAttachment (vmbda), не меняя список в спецификации ВМ.
Для использования режима паравиртуализации (virtio) в некоторых операционных системах требуется установка соответствующих драйверов. Если драйверы не установлены, ВМ может не загрузиться или устройства могут работать некорректно.
Для типа ОС Legacy значение по умолчанию true не подходит, потому что встроенных драйверов virtio у этих операционных систем нет, поэтому для ВМ, которую предстоит установить с оригинального носителя, укажите enableParavirtualization: false — иначе установщик сообщит, что не нашёл жёстких дисков. При создании и изменении такой ВМ выдаётся предупреждение.
Оставляйте enableParavirtualization: true для ВМ с типом ОС Legacy только тогда, когда драйверы virtio уже установлены в гостевой ОС. Тогда ВМ сохраняет чипсет i440fx и загрузчик BIOS, но получает диски на virtio-blk, адаптер virtio-net и лишается ограничения в четыре устройства. CD-ROM остаётся на шине IDE, потому что у virtio-blk привода нет.
Переключить уже установленную систему можно так:
- Установите драйверы virtio в гостевой ОС. Для Windows XP, 2000 и Server 2003 возьмите архивный выпуск virtio-win, потому что в текущих выпусках драйверов для этих систем уже нет, и установите
viostor, драйвер virtio-blk. Драйвера virtio-scsi для этих ОС в пакете нет. - Выключите ВМ.
- Задайте
enableParavirtualization: true. - Запустите ВМ.
Порядок шагов важен. Драйвер дискового контроллера должен появиться в гостевой ОС до переключения, а не после, ведь именно с этого контроллера ВМ загружается. Если после переключения ВМ не загрузилась, верните enableParavirtualization: false и перезапустите её. Диски вернутся на шину IDE, и гостевая ОС загрузится как прежде.
Пример конфигурации с отключенной паравиртуализацией:
spec:
enableParavirtualization: false
# остальные параметры...Сценарии начальной инициализации ВМ
Сценарии начальной инициализации предназначены для первичной конфигурации виртуальной машины при её запуске.
В качестве сценариев начальной инициализации поддерживаются:
Cloud-Init
Cloud-Init — это инструмент для автоматической настройки виртуальных машин при первом запуске. Он позволяет выполнять широкий спектр задач конфигурации без ручного вмешательства.
Конфигурация Cloud-Init записывается в формате YAML и должна начинаться с заголовка #cloud-config в начале блока конфигурации. О других возможных заголовках и их назначении вы можете узнать в официальной документации по cloud-init.
Основные возможности Cloud-Init:
- создание пользователей, установка паролей, добавление SSH-ключей для доступа;
- автоматическая установка необходимого программного обеспечения при первом запуске;
- запуск произвольных команд и скриптов для настройки системы;
- автоматический запуск и включение системных сервисов (например,
qemu-guest-agent).
Ниже приведены типичные сценарии.
-
Добавление SSH-ключа для предустановленного пользователя, который уже может присутствовать в cloud-образе (например, пользователь
ubuntuв официальных образах Ubuntu). Имя такого пользователя зависит от образа. Уточните его в документации к вашему дистрибутиву.#cloud-config ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD... your-public-key ... -
Создание пользователя с паролем и SSH-ключом:
#cloud-config users: - name: cloud passwd: <PASSWORD_HASH> lock_passwd: false sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh-authorized-keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD... your-public-key ... ssh_pwauth: TrueЗдесь
<PASSWORD_HASH>— хеш пароля в кавычках, полученный командойmkpasswd --method=SHA-512 --rounds=4096. -
Установка пакетов и сервисов:
#cloud-config package_update: true packages: - nginx - qemu-guest-agent runcmd: - systemctl daemon-reload - systemctl enable --now nginx.service - systemctl enable --now qemu-guest-agent.service
Ниже показано, как передать сценарий виртуальной машине:
- В командной строке
- В веб-интерфейсе
Сценарий Cloud-Init можно встраивать непосредственно в спецификацию виртуальной машины, но этот сценарий ограничен максимальной длиной в 2048 байт:
spec:
provisioning:
type: UserData
userData: |
#cloud-config
package_update: true
...Если сценарий длинный или содержит приватные данные, создайте его в ресурсе Secret. Пример ресурса Secret со сценарием Cloud-Init приведён ниже:
apiVersion: v1
kind: Secret
metadata:
name: cloud-init-example
data:
userData: <base64 data>
type: provisioning.virtualization.deckhouse.io/cloud-initФрагмент конфигурации виртуальной машины при использовании скрипта начальной инициализации Cloud-Init, хранящегося в ресурсе Secret:
spec:
provisioning:
type: UserDataRef
userDataRef:
kind: Secret
name: cloud-init-exampleЗначение поля
.data.userDataдолжно быть закодировано в формате Base64. Для кодирования можно использовать командуbase64 -w 0илиecho -n "content" | base64.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Создайте виртуальную машину или выберите существующую и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу вниз до переключателя «Cloud-init» и включите его.
- Выберите режим заполнения:
- «Базовая настройка» — заполните поля «Имя пользователя», «Пароль» и «Публичный SSH-ключ», при необходимости включите переключатель «Неограниченный sudo-доступ». Конфигурацию cloud-init DP сформирует сама;
- «Редактирование» — введите конфигурацию cloud-init вручную в поле «Параметры». Под полем отображается использованный объём (не более 2048 байт). В поле «Связанный секрет» можно выбрать существующий скрипт инициализации, и его содержимое загрузится в поле. Если секрет не привязан, конфигурация хранится в спецификации ВМ.
- Нажмите появившуюся кнопку «Сохранить» (при создании ВМ — кнопку «Создать»).
Сценарий можно хранить отдельным ресурсом и переиспользовать для нескольких ВМ. Чтобы создать такой ресурс:
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Скрипты инициализации».
- Нажмите кнопку «Создать».
- В поле «Имя» введите имя скрипта, в поле «Тип» выберите
cloud-initилиsysprep. - В блоке «Файлы» в поле «Имя файла» задайте ключ (по умолчанию —
userData), а содержимое введите вручную, перетащите файл в поле или нажмите на него, чтобы загрузить файл. - Нажмите кнопку «Создать».
В разделе «Скрипты инициализации» отображаются секреты с типом provisioning.virtualization.deckhouse.io/*, для каждого показаны имя, тип (cloud-init или sysprep), список ключей и возраст ресурса. Чтобы виртуальная машина использовала такой скрипт, сошлитесь на него в параметре .spec.provisioning.userDataRef.
Sysprep
Для конфигурирования виртуальных машин под управлением ОС 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. Для кодирования можно использовать команду base64 -w 0 или echo -n "content" | base64.
Фрагмент конфигурации виртуальной машины с использованием скрипта начальной инициализации Sysprep в ресурсе Secret:
spec:
provisioning:
type: SysprepRef
sysprepRef:
kind: Secret
name: sysprep-exampleАгент гостевой ОС
Установите в гостевую систему QEMU Guest Agent, чтобы DP мог взаимодействовать с операционной системой внутри ВМ. Агент нужен для трёх вещей:
- он позволяет создавать консистентные снимки дисков и ВМ;
- он сообщает сведения о работающей системе, и они попадают в блок
.status.guestOSInfo; - по нему видно, что операционная система действительно загрузилась, а не просто запустилась виртуальная машина.
DP работает с qemu-guest-agent версии 5.2.0 и выше. Проверить установленную версию можно командой:
qemu-guest-agent --versionСведения о гостевой системе выглядят так:
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"Работает ли агент, показывает колонка AGENT:
d8 k get vm -o wideПример вывода:
NAME PHASE UPTIME CORES COREFRACTION MEMORY NEED RESTART AGENT MIGRATABLE NODE IPADDRESS AGE
fedora Running 5d21h 6 5% 8000Mi False True True virtlab-pt-1 10.66.10.1 5d21h
Установите агента командой для вашего дистрибутива и запустите службу:
# Debian и производные.
sudo apt install qemu-guest-agent
# CentOS и производные.
sudo yum install qemu-guest-agent
sudo systemctl enable --now qemu-guest-agentДля Linux установку удобно автоматизировать сценарием начальной инициализации:
#cloud-config
package_update: true
packages:
- qemu-guest-agent
runcmd:
- systemctl enable --now qemu-guest-agent.serviceНастраивать агента после установки не требуется. Если снимкам нужна согласованность данных приложения, положите скрипты подготовки в каталог /etc/qemu-ga/hooks.d/ на Debian и Ubuntu либо /etc/qemu/fsfreeze-hook.d/ на RHEL, CentOS и Fedora. Скрипты должны быть исполняемыми, агент запускает их до заморозки файловой системы и после её разморозки, поэтому сервисы приложения останавливать не приходится.
Подключение к виртуальной машине
К виртуальной машине (ВМ) можно подключиться четырьмя способами. Первый — по протоколу удалённого управления вроде SSH, который вы настраиваете в гостевой ОС сами. Второй — через серийную консоль. Третий — по VNC. Четвёртый — по SPICE, если он включён у машины.
- В командной строке
- В веб-интерфейсе
Серийная консоль:
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Подключение по SPICE:
d8 v spice linux-vmПодключение по SSH:
d8 v ssh cloud@linux-vm- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- Перейдите на вкладку «TTY» для работы с серийной консолью или на вкладку «VNC» для подключения по VNC.
Серийная консоль и VNC эксклюзивны, в них работает только один пользователь, и новое подключение отключает того, кто уже работает с машиной.
Перед подключением d8 v console и d8 v vnc сообщают, кто занял поток и с какого времени, и предлагают выбор:
The serial console of linux-vm is in use:
user serviceaccount default/alice
connected 12 minutes ago (14:32), from the d8 v command line
Connect and disconnect them? [y] yes [N] no [w] wait until free:
Ответ w означает дождаться, пока другой пользователь отключится, и подключиться автоматически. Нажатие Enter отменяет подключение, потому что по умолчанию выбран безопасный вариант. Флаг --force подключает без вопроса, и он же нужен при неинтерактивном запуске в скрипте.
Серийная консоль не меняет размер терминала автоматически. Если вывод команд переносится неправильно, задайте размер вручную командой stty rows <ROWS> cols <COLUMNS>, например stty rows 50 cols 200. Когда в системе установлен пакет xterm, ту же задачу решает команда resize.
SPICE
SPICE — второй протокол удалённого дисплея, который в отличие от VNC передаёт из гостевой системы звук, пробрасывает в неё USB-устройства с вашего компьютера и разделяет с ней буфер обмена. Он работает рядом с VNC, поэтому уже открытые VNC-сессии и веб-интерфейс продолжают работать.
По умолчанию SPICE выключен. Чтобы включить его, задайте параметр .spec.spice.enabled и перезапустите машину:
spec:
spice:
enabled: trueВместе со SPICE машина получает видеоадаптер virtio-gpu. Если драйвера для него в гостевой системе нет, как в Windows 7 и Windows XP, задайте другую модель адаптера аннотацией virtualization.deckhouse.io/video со значением vga, bochs или ramfb.
Общий буфер обмена, подстройку разрешения под окно клиента и локальный курсор добавляет гостевой агент SPICE. Установите его в гостевой системе, в Linux это пакет spice-vdagent, в Windows — spice-guest-tools.
Для подключения нужен клиент remote-viewer из пакета virt-viewer, и команда d8 v spice открывает его сама. Если такого клиента нет, запустите только прокси и подключитесь своим клиентом на порт, который выведет команда:
d8 v spice linux-vm --proxy-onlySPICE-дисплей эксклюзивен так же, как серийная консоль и VNC, и d8 v spice предупреждает, прежде чем отключить того, кто уже подключён.
SPICE резервирует память независимо от того, подключён клиент или нет. Эта память входит в накладные расходы машины, поэтому на узле машина занимает больше памяти, чем указано в её спецификации.
Политика запуска и управление состоянием ВМ
Политика запуска определяет, как DP поддерживает состояние машины. Её задаёт параметр .spec.runPolicy:
AlwaysOnUnlessStoppedManually— вариант по умолчанию. Машина всегда работает, а остановить её можно только вручную;AlwaysOn— машина всегда работает, и даже после выключения из гостевой ОС DP запускает её снова;Manual— состоянием машины вы управляете сами;AlwaysOff— машина всегда выключена, и запустить её нельзя.
Управлять состоянием машины можно двумя способами, создавая ресурс VirtualMachineOperation или пользуясь утилитой d8. Ресурс описывает действие декларативно, а утилита создаёт такой же ресурс за вас.
Команда d8 |
Тип операции | Действие |
|---|---|---|
d8 v stop |
Stop |
Остановить ВМ |
d8 v start |
Start |
Запустить ВМ |
d8 v restart |
Restart |
Перезапустить ВМ |
d8 v evict |
Evict |
Вытеснить ВМ на другой узел |
d8 v migrate |
Migrate |
Мигрировать ВМ на другой узел |
Ниже показано, как выполнить операцию над виртуальной машиной:
- В командной строке
- В веб-интерфейсе
Перезапустить машину проще всего утилитой d8:
d8 v restart 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Политика запуска задаётся на странице машины:
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу вниз до раздела «Жизненный цикл».
- Выберите нужную политику из списка «Политика запуска».
Операции доступны из списка машин:
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную виртуальную машину и нажмите кнопку с многоточием.
- В открывшемся меню выберите операцию.
Для одной машины одновременно выполняется только одна операция. Новая операция либо вытесняет активную, либо завершается неудачей, и какой из вариантов сработает, зависит от пары типов:
| Активная операция | Чем её можно вытеснить |
|---|---|
Start |
Stop |
Stop или Restart без force |
Stop или Restart с force: true |
Migrate, Evict |
Stop, Restart |
Stop или Restart с force: true |
ничем |
Вытесненная операция переходит в фазу Superseded. Операция, которая вытеснить активную не может, переходит в фазу Failed, поэтому её нужно создать заново после того, как активная завершится. Восстановление и клонирование другие операции не вытесняют.
Изменение конфигурации ВМ
Конфигурацию виртуальной машины (ВМ) можно менять в любой момент после создания. У выключенной машины изменения применяются сразу, у работающей — по-разному, в зависимости от того, что именно вы изменили.
| Блок конфигурации | Как применяется у работающей ВМ |
|---|---|
.metadata.labels |
Сразу и распространяется на под ВМ |
.metadata.annotations |
Сразу и распространяется на под ВМ |
.spec.liveMigrationPolicy |
Сразу |
.spec.runPolicy |
Сразу |
.spec.disruptions.restartApprovalMode |
Сразу |
.spec.affinity |
Сразу в коммерческих редакциях DP, в DP Open нужен перезапуск |
.spec.nodeSelector |
Сразу в коммерческих редакциях DP, в DP Open нужен перезапуск |
.spec.cpu.cores |
Без перезапуска, если включено изменение числа ядер без перезапуска в коммерческих редакциях DP, иначе нужен перезапуск |
.spec.networks |
Добавление и удаление сетей применяется на работающей ВМ, если гостевая ОС поддерживает подключение интерфейсов на ходу |
Остальные поля .spec |
Нужен перезапуск |
Ниже показано, как изменить конфигурацию виртуальной машины:
- В командной строке
- В веб-интерфейсе
Ниже показан пример с изменением числа ядер.
-
Посмотрите, сколько ядер видит гостевая ОС сейчас:
d8 v ssh cloud@linux-vm --command "nproc"Пример вывода:
1 -
Задайте новое число ядер:
d8 k patch vm linux-vm --type merge -p '{"spec":{"cpu":{"cores":2}}}' # Того же результата можно добиться, отредактировав ресурс. d8 k edit vm linux-vm -
Убедитесь, что изменение принято, но ещё не применено. Гостевая ОС по-прежнему видит одно ядро, а список ожидающих изменений не пуст:
d8 k get vm linux-vm -o jsonpath="{.status.restartAwaitingChanges}" | jq .Пример вывода:
[ { "currentValue": 1, "desiredValue": 2, "operation": "replace", "path": "cpu.cores" } ]То же самое показывает колонка
NEED RESTART:d8 k get vm linux-vm -o wideПример вывода:
NAME PHASE UPTIME CORES COREFRACTION MEMORY NEED RESTART AGENT MIGRATABLE NODE IPADDRESS AGE linux-vm Running 5m16s 2 100% 1Gi True True True virtlab-pt-1 10.66.10.13 5m16s -
Перезапустите машину:
d8 v restart linux-vm -
Проверьте результат. После перезапуска блок
.status.restartAwaitingChangesпуст, а гостевая ОС видит два ядра:d8 v ssh cloud@linux-vm --command "nproc"Пример вывода:
2
По умолчанию перезапуск подтверждаете вы. Чтобы DP применял изменения сам, задайте в параметре .spec.disruptions.restartApprovalMode значение Automatic:
spec:
disruptions:
restartApprovalMode: Automatic- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- Внесите изменения на вкладке «Конфигурация». Если машину требуется перезапустить, DP покажет предупреждение и список ожидающих изменений.
- Чтобы изменения применялись без вашего подтверждения, прокрутите страницу до раздела «Жизненный цикл», включите переключатель «Автоприменение изменений» и нажмите кнопку «Сохранить».
Изменение числа ядер без перезапуска
Число ядер работающей машины можно менять, не перезагружая её, если изменение применимо через живую миграцию. В пределах текущей топологии CPU ядра можно и добавлять, и убирать.
Возможность выключена по умолчанию. Чтобы её включить, администратор добавляет HotplugCPUWithLiveMigration в параметр .spec.settings.featureGates:
kind: ModuleConfig
metadata:
name: virtualization
spec:
settings:
featureGates:
- HotplugCPUWithLiveMigrationВ веб-интерфейсе тот же переключатель называется «Изменение CPU без перезагрузки» и находится в блоке «Экспериментальные возможности» на вкладке «Система» → «Deckhouse» → «Модули» → virtualization → «Конфигурация». Права на это есть только у администратора DP.
Когда возможность включена, а новое значение .spec.cpu.cores остаётся в пределах текущей топологии, DP применяет изменение живой миграцией. Если изменение требует смены топологии, машину придётся перезагрузить. Правила расчёта топологии описаны в разделе «Топологии CPU».
- В командной строке
- В веб-интерфейсе
Задайте новое число ядер:
d8 k patch vm linux-vm --type merge -p '{"spec":{"cpu":{"cores":4}}}'- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» в разделе «Ресурсы» задайте новое значение в поле «Ядра ЦП».
- Нажмите появившуюся кнопку «Сохранить».
Гостевая ОС не всегда вводит новые ядра в работу сама, особенно после живой миграции. В Linux ядро включается через sysfs:
echo 1 > /sys/devices/system/cpu/cpu1/onlineЧтобы это происходило автоматически, добавьте правило udev:
cat <<'EOF' > /etc/udev/rules.d/99-hotplug-cpu.rules
SUBSYSTEM=="cpu",ACTION=="add",RUN+="/bin/sh -c '[ ! -e /sys$devpath/online ] || echo 1 > /sys$devpath/online'"
EOFВведённые в работу ядра появляются в выводе nproc, cat /proc/cpuinfo и top.
При уменьшении числа ядер в пределах текущей топологии распределение ядер по сокетам сохраняется.
Изменение объёма памяти без перезапуска
Объём памяти работающей машины можно увеличивать, не перезагружая её. Уменьшение требует перезапуска.
Возможность выключена по умолчанию. Чтобы её включить, администратор добавляет HotplugMemoryWithLiveMigration в параметр .spec.settings.featureGates:
kind: ModuleConfig
metadata:
name: virtualization
spec:
settings:
featureGates:
- HotplugMemoryWithLiveMigrationВ веб-интерфейсе переключатель называется «Изменение памяти без перезагрузки» и лежит там же, в блоке «Экспериментальные возможности» настроек модуля.
Когда возможность включена, новое значение .spec.memory.size больше текущего и машина допускает миграцию, DP применяет изменение живой миграцией. Перезапуск понадобится, если память уменьшают, если исходный размер меньше 1 ГиБ или если машину нельзя мигрировать. Без перезапуска память растёт до 256 ГиБ, это предел, заложенный в конфигурацию машины при первом запуске.
- В командной строке
- В веб-интерфейсе
Задайте новый объём памяти:
d8 k patch vm linux-vm --type merge -p '{"spec":{"memory":{"size":"4Gi"}}}'- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» в разделе «Ресурсы» задайте новое значение в поле «Объём памяти».
- Нажмите появившуюся кнопку «Сохранить».
Как и с ядрами, гостевая ОС может не ввести новые блоки памяти в работу сама. В Linux блок включается через sysfs, а имя устройства видно в выводе lsmem или в каталоге /sys/bus/memory/devices/:
echo 1 > /sys/bus/memory/devices/memoryXXX/onlineЧтобы это происходило автоматически, добавьте правило udev:
cat <<'EOF' > /etc/udev/rules.d/99-hotplug-memory.rules
SUBSYSTEM=="memory",ACTION=="add",DEVPATH=="/devices/system/memory/memory[0-9]*", TEST=="state", ATTR{state}!="online", ATTR{state}="online"
EOFРазмещение ВМ по узлам
Тем, где именно запускается виртуальная машина (ВМ), управляют четыре механизма:
.spec.nodeSelector— самый простой способ, выбирает узлы с нужными лейблами;.spec.affinity.nodeAffinity— задаёт приоритетные узлы для размещения;.spec.affinity.virtualMachineAndPodAffinity— размещает машину рядом с другими машинами и рабочими нагрузками;.spec.affinity.virtualMachineAndPodAntiAffinity— наоборот, разводит их по разным узлам.
Условия бывают жёсткими и мягкими. Жёсткое условие requiredDuringSchedulingIgnoredDuringExecution обязательно к исполнению, и машина не запустится, если подходящего узла нет. Мягкое условие preferredDuringSchedulingIgnoredDuringExecution планировщик учитывает по возможности.
Все правила, включая .spec.nodeSelector из класса ВМ, применяются вместе. Если хотя бы одно жёсткое условие выполнить нельзя, машина остаётся в фазе Pending. Поэтому задавайте непротиворечивые правила, предпочитайте комбинации лейблов одиночным жёстким ограничениям и держите в запасе узлы для критичных нагрузок. Учитывайте и порядок запуска. Если одна машина обязана оказаться рядом с другой, сначала должна запуститься вторая. Если на нужных узлах стоят ограничения taints, добавьте машине соответствующие tolerations.
Когда вы меняете правила размещения у работающей машины, а её текущий узел новым требованиям больше не отвечает, в коммерческих редакциях DP переносит машину живой миграцией, а в DP Open изменения применяются только после перезагрузки. Машина, которая новым требованиям и так отвечает, остаётся на месте.
Как задать правила размещения в веб-интерфейсе:
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу до переключателя «Размещение ВМ».
- Выберите режим заполнения. В режиме «Базовая настройка» правила задаются переключателями «Совместное размещение» и «Раздельное размещение», в режиме «Редактирование» блок размещения задаётся вручную в виде YAML.
- Включите нужный переключатель и заполните поля. В поле «Выберите режим правила» доступны «Принудительное» (
requiredDuringSchedulingIgnoredDuringExecution) и «Предпочтительное» (preferredDuringSchedulingIgnoredDuringExecution), а в поле «Правило размещения» — размещение относительно других ВМ или относительно лейблов узлов. - Нажмите появившуюся кнопку «Сохранить».
Толерантность к ограничениям узлов
Tolerations позволяют ВМ запускаться на узлах с ограничениями (taints), которые иначе блокируют планирование (scheduling). Это полезно, когда нужно запускать ВМ на специальных узлах (например, тестовых) или узлах с определёнными характеристиками.
Пример использования tolerations для разрешения запуска на узлах с taint node.deckhouse.io/group=:NoSchedule:
spec:
tolerations:
- key: "node.deckhouse.io/group"
operator: "Exists"
effect: "NoSchedule"Каждый элемент списка tolerations должен соответствовать taint на узле, чтобы ВМ могла быть размещена на этом узле.
Для просмотра информации об узлах кластера (включая taints) требуется роль пользователя с правами доступа к ресурсам уровня кластера.
Чтобы посмотреть taints на узлах кластера, выполните команду:
d8 k get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taintsЧтобы посмотреть подробную информацию об узле, выполните команду:
d8 k describe node <NODE_NAME>Простое связывание по меткам (nodeSelector)
nodeSelector — это простейший способ контролировать размещение виртуальных машин, используя набор меток. Он позволяет задать, на каких узлах могут запускаться виртуальные машины, выбирая узлы с необходимыми метками.
spec:
nodeSelector:
disktype: ssd
В этом примере в кластере три узла, два из них с быстрыми дисками (disktype=ssd) и один с медленными (disktype=hdd). Виртуальная машина будет размещена только на узлах, которые имеют метку disktype со значением ssd.
Как выполнить операцию в веб-интерфейсе в разделе «Размещение»:
- Включите переключатель «Совместное размещение».
- В поле «Выберите режим правила» выберите «Принудительное».
- В поле «Правило размещения» выберите «На выбранных узлах».
- В поле «Как определить группу узлов» выберите «По лейблам» и укажите лейблы узлов (например,
disktype: ssd); вариант «По имени» позволяет выбрать конкретные узлы. - Нажмите появившуюся кнопку «Сохранить».
Предпочтительное связывание (Affinity)
Affinity предоставляет более гибкие и мощные инструменты по сравнению с nodeSelector. Он позволяет задавать «предпочтения» и «обязательности» для размещения виртуальных машин. Affinity поддерживает два вида, nodeAffinity и virtualMachineAndPodAffinity.
nodeAffinity — определяет узлы для запуска ВМ с помощью выражений селекторов меток.
Пример использования nodeAffinity с жестким правилом:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
В этом примере в кластере три узла, два из них с быстрыми дисками (disktype=ssd) и один с медленными (disktype=hdd). Виртуальная машина будет размещена только на узлах, которые имеют метку disktype со значением ssd.
Если использовать мягкое требование (preferredDuringSchedulingIgnoredDuringExecution), то при отсутствии ресурсов для запуска ВМ на узлах с дисками disktype=ssd она будет запланирована на узле с дисками disktype=hdd.
virtualMachineAndPodAffinity управляет размещением виртуальных машин относительно других виртуальных машин. Он позволяет задавать предпочтение размещения виртуальных машин на тех же узлах, где уже запущены определенные виртуальные машины.
Пример мягкого правила:
spec:
affinity:
virtualMachineAndPodAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchLabels:
server: database
topologyKey: "kubernetes.io/hostname"
В этом примере виртуальная машина размещается только на узлах, где уже работает виртуальная машина с лейблом server: database. Правило мягкое (preferred), поэтому при отсутствии таких узлов машина запустится на любом подходящем.
Чтобы размещать ВМ по зонам доступности (а не привязывать к конкретным узлам), задайте topologyKey: topology.kubernetes.io/zone (раздел «Размещение ВМ по зонам доступности»).
Как задавать «предпочтения» и «обязательности» для размещения виртуальных машин в веб-интерфейсе в разделе «Размещение»:
- Включите переключатель «Совместное размещение» — он соответствует настройкам
spec.affinity.virtualMachineAndPodAffinity. - В поле «Выберите режим правила» выберите «Принудительное» или «Предпочтительное».
- В поле «Правило размещения» выберите «На узлах с выбранными ВМ».
- В поле «Выберите лейблы» выберите лейблы нужных ВМ из списка или введите свой в формате
key: value. - Нажмите появившуюся кнопку «Сохранить».
Избежание совместного размещения (AntiAffinity)
AntiAffinity используется для предотвращения совместного размещения ВМ на узлах. Полезно для обеспечения отказоустойчивости или балансировки нагрузки.
Будьте осторожны при использовании жестких требований в небольших кластерах, где мало узлов для запуска виртуальных машин. Если используется параметр virtualMachineAndPodAntiAffinity с типом requiredDuringSchedulingIgnoredDuringExecution для виртуальных машин, это означает, что каждая копия ВМ должна размещаться на отдельном узле. В условиях ограниченного количества узлов в кластере это может привести к ситуации, когда некоторые ВМ не смогут быть запущены из-за недостатка доступных узлов.
Термины Affinity и AntiAffinity описывают отношения между виртуальными машинами. Для узлов такого антонима нет, но того же результата можно добиться через nodeAffinity с оператором NotIn, исключив нужные узлы.
Пример использования virtualMachineAndPodAntiAffinity:
spec:
affinity:
virtualMachineAndPodAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
server: database
topologyKey: "kubernetes.io/hostname"
В данном примере создаваемая виртуальная машина не будет размещена на одном узле с виртуальной машиной с меткой server: database.
Чтобы размещать ВМ по зонам доступности (а не привязывать к конкретным узлам), задайте topologyKey: topology.kubernetes.io/zone (раздел «Размещение ВМ по зонам доступности»).
Как настроить предотвращение совместного размещения ВМ на узлах в веб-интерфейсе в разделе «Размещение»:
- Включите переключатель «Раздельное размещение» — он соответствует настройкам
spec.affinity.virtualMachineAndPodAntiAffinity. - В поле «Выберите режим правила» выберите «Принудительное» или «Предпочтительное».
- В поле «Правило размещения» выберите «На узлах с выбранными ВМ».
- В поле «Выберите лейблы» выберите лейблы ВМ, рядом с которыми размещать машину не нужно, или введите свой лейбл в формате
key: value. - Нажмите появившуюся кнопку «Сохранить».
Размещение ВМ по зонам доступности
Правила размещения работают не только на уровне узлов, но и на уровне зон доступности.
Зоны доступности должны быть предварительно настроены на узлах кластера. Для этого на узлах должна быть установлена метка topology.kubernetes.io/zone с указанием зоны доступности.
В примерах выше используется topologyKey: "kubernetes.io/hostname", что размещает ВМ на одном узле. Для размещения ВМ по зонам доступности вместо узлов используйте topologyKey: "topology.kubernetes.io/zone".
При использовании Affinity с topologyKey: "topology.kubernetes.io/zone" ВМ будут размещаться в той же зоне доступности, где присутствует виртуальная машина с указанными метками.
При использовании AntiAffinity с topologyKey: "topology.kubernetes.io/zone" ВМ не будут размещаться в той же зоне доступности, что и виртуальная машина с указанными метками. Это полезно для обеспечения отказоустойчивости при распределении ВМ по разным зонам доступности.
Чтобы посмотреть зоны доступности на узлах кластера (если эти зоны заданы), выполните команду:
d8 k get nodes -o custom-columns=NAME:.metadata.name,ZONE:.metadata.labels.topology\.kubernetes\.io/zoneПодключение блочных устройств (диски и образы)
К виртуальной машине (ВМ) можно подключать диски и образы. Они описываются как блочные устройства (BlockDevices).
Типы блочных устройств и режимы доступа:
| Тип блочного устройства | Комментарий |
|---|---|
| VirtualImage | Подключается в режиме для чтения, или как CD-ROM для ISO-образов. |
| ClusterVirtualImage | Подключается в режиме для чтения, или как CD-ROM для ISO-образов. |
| VirtualDisk | Подключается в режиме для чтения и записи. |
Подключение устройств возможно двумя способами:
- через спецификацию ВМ (
.spec.blockDeviceRefs) — диски указываются в конфигурации VirtualMachine и для них задаётся порядок загрузки (по позиции в списке или через полеbootOrder). Рекомендуется при настройке ВМ вручную, а также когда нужен контроль порядка загрузки (например, ISO для установки ОС). - через VirtualMachineBlockDeviceAttachment (
vmbda) — диск подключается отдельным ресурсом и не участвует в порядке загрузки. Диски подключаются через шинуvirtio-scsi, независимо от значенияenableParavirtualization. Рекомендуется для автоматизации и когда нет прав на редактирование ВМ.
При enableParavirtualization: true оба способа позволяют подключать и отключать диски у работающей ВМ без перезагрузки, если диск доступен на узле, где она выполняется. При enableParavirtualization: false состав .spec.blockDeviceRefs у запущенной ВМ меняется только после перезагрузки; без перезагрузки диски можно подключать и отключать через VirtualMachineBlockDeviceAttachment (vmbda).
Когда паравиртуализация выключена (enableParavirtualization: false), устройства из .spec.blockDeviceRefs работают на шине SATA, а у типа ОС Legacy — на шине IDE. У работающей ВМ изменения этого списка, включая подключение и отключение ISO-образа, вступают в силу только после перезагрузки.
Диски, подключённые через VirtualMachineBlockDeviceAttachment, используют шину virtio-scsi и подключаются без перезагрузки, если в гостевой ОС есть драйвер этой шины. Для типа ОС Legacy с выключенной паравиртуализацией такая привязка отклоняется, потому что шина IDE подключение на ходу не поддерживает. Добавьте устройство в .spec.blockDeviceRefs и перезапустите ВМ.
Подключить диск к работающей ВМ можно только тогда, когда хранилище доступно на том узле кластера, где выполняется виртуальная машина. При создании и обновлении ВМ, а также при создании VirtualMachineBlockDeviceAttachment, учитываются правила размещения (nodeSelector, affinity, tolerations) тома, виртуальной машины и класса ВМ, и хотя бы одно общее допустимое размещение у них должно найтись. Если ВМ уже запущена и работает на конкретном узле, новый диск должен быть доступен на этом узле.
Пока живая миграция машины готовит целевой узел, диск нельзя ни подключить, ни отключить. Новый ресурс VirtualMachineBlockDeviceAttachment остаётся в фазе Pending с причиной BlockedByMigration в условии Attached, а удаляемый остаётся в фазе Terminating, и оба доводятся до конца после миграции. Пока миграция стоит в очереди и целевой узел ещё не готовится, подключение и отключение работают как обычно.
Подключение через спецификацию ВМ
Устройства, перечисленные в спецификации машины, подключаются при её запуске и остаются на месте всё время работы. Их список задаёт поле .spec.blockDeviceRefs ресурса VirtualMachine.
Порядок загрузки по умолчанию совпадает с порядком устройств в списке, а задать его явно позволяет необязательное поле bootOrder (меньшее значение — выше приоритет). Если bootOrder указан хотя бы у одного устройства, в цепочку загрузки попадают только устройства с заданным bootOrder. Допустимы целые числа от 1 и выше, уникальные в пределах списка. При удалении устройства из списка порядок загрузки пересчитывается для оставшихся устройств.
Изменение порядка устройств в списке или значений bootOrder вступает в силу после перезагрузки ВМ. Например, можно подключить ISO-образ для установки ОС с нужным приоритетом загрузки, а после установки удалить его из списка. Если у ВМ отключена паравиртуализация (enableParavirtualization: false), правки в .spec.blockDeviceRefs у работающей ВМ, в том числе с ISO-образом, применяются после перезагрузки ВМ.
- В командной строке
- В веб-интерфейсе
Фрагмент конфигурации виртуальной машины с блочными устройствами и явным порядком загрузки:
spec:
blockDeviceRefs:
- kind: VirtualDisk
name: <VD_NAME>
bootOrder: 1
- kind: VirtualImage
name: <VI_NAME>
bootOrder: 2Для подключения диска к работающей виртуальной машине добавьте его в список .spec.blockDeviceRefs:
spec:
blockDeviceRefs:
- kind: VirtualDisk
name: <VD_NAME>
- kind: VirtualImage
name: <VI_NAME>
- kind: VirtualDisk
name: <ADDITIONAL_DISK_NAME>Для отключения диска удалите его из списка. При enableParavirtualization: false изменение списка у запущенной ВМ вступит в силу после перезагрузки ВМ.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу до раздела «Диски».
- В списке дисков доступны следующие действия:
- «Добавить» — подключить к ВМ новый диск или образ;
- «Извлечь» — отключить устройство от ВМ (образ или диск остаётся в проекте, его можно снова подключить к этой или другой ВМ);
- «Удалить» — удалить сам ресурс образа или диска из кластера (после удаления его нельзя использовать повторно);
- изменить размер диска — по значку карандаша рядом с текущим размером;
- изменить порядок загрузки — изменив позицию диска в списке.
Подключение через VirtualMachineBlockDeviceAttachment
Ресурс VirtualMachineBlockDeviceAttachment подключает и отключает блочное устройство у ВМ, не затрагивая её спецификацию. Он подходит для автоматизации и для случаев, когда у пользователя нет прав на редактирование машины.
Устройство подключено, когда ресурс переходит в фазу Attached. Остальные фазы описаны в поле .status.phase, а причину задержки показывает блок .status.conditions.
- В командной строке
- В веб-интерфейсе
Создайте ресурс, который подключит пустой диск 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Проверьте состояние вашего ресурса:
d8 k get vmbda attach-blank-diskПример вывода:
NAME PHASE VIRTUALMACHINE AGE
attach-blank-disk Attached linux-vm 3m7s
Подключитесь к виртуальной машине и удостоверитесь, что диск подключён:
d8 v ssh cloud@linux-vm --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- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу до раздела «Диски».
- В списке дисков доступны следующие действия:
- «Добавить» — подключить к ВМ новый диск или образ; чтобы устройство подключилось как дополнительное (через VirtualMachineBlockDeviceAttachment, без перезагрузки ВМ), в окне «Диски / Образы» установите флажок «Дополнительный»;
- «Извлечь» — отключить устройство от ВМ (образ или диск остаётся в проекте, его можно снова подключить к этой или другой ВМ);
- «Удалить» — удалить сам ресурс образа или диска из кластера (после удаления его нельзя использовать повторно);
- изменить размер диска — по значку карандаша рядом с текущим размером.
Именование дисков в гостевой ОС
Имена дисков в гостевой системе не постоянны, поэтому опираться на них в настройках опасно.
Имена блочных устройств (/dev/sda, /dev/sdb, /dev/sdc и так далее) присваиваются ядром Linux в порядке обнаружения устройств при загрузке. Этот порядок может меняться между перезагрузками, поэтому имена устройств могут измениться даже при неизменных SCSI-адресах.
Если использовать /dev/sdX в конфигурационных файлах (например, /etc/fstab) или скриптах, после перезагрузки ВМ можно смонтировать не тот диск или получить некорректную работу системы.
Пример:
После первой загрузки ВМ:
$ lsscsi
[0:0:0:1] disk QEMU QEMU HARDDISK /dev/sda
[0:0:0:2] disk QEMU QEMU HARDDISK /dev/sdb
После перезагрузки ВМ:
$ lsscsi
[0:0:0:1] disk QEMU QEMU HARDDISK /dev/sdb
[0:0:0:2] disk QEMU QEMU HARDDISK /dev/sda
SCSI-адреса (0:0:0:1, 0:0:0:2) остаются неизменными, но имена устройств (/dev/sda, /dev/sdb) меняются местами.
Используйте стабильные идентификаторы вместо /dev/sdX:
/dev/disk/by-uuid/— по UUID разделов (предпочтительно для/etc/fstab);/dev/disk/by-path/— по SCSI пути подключения;/dev/disk/by-id/— по SCSI ID устройства.
В конфигурационных файлах и скриптах используйте UUID разделов или символические ссылки из /dev/disk/by-* вместо имён /dev/sdX.
Именование сетевых интерфейсов в гостевой ОС
В системах без поддержки предсказуемого именования интерфейсов (predictable network interface naming) имена сетевых интерфейсов (eth0, eth1, eth2 и так далее) присваиваются ядром Linux в порядке обнаружения устройств при загрузке. При добавлении новых сетевых интерфейсов или изменении порядка сетей в .spec.networks порядок интерфейсов может измениться, из-за чего IP-адреса могут быть назначены не тем интерфейсам.
Использование ethX в конфигурационных файлах (например, /etc/network/interfaces, netplan, systemd-networkd) или в скриптах при добавлении новых интерфейсов или изменении порядка сетей может привести к сбоям в работе сети или подключению к неверной сети.
В современных дистрибутивах с systemd (Ubuntu 16.04+, Debian 9+, CentOS 7+, RHEL 7+) по умолчанию используются предсказуемые имена интерфейсов (enpXsY, ensX, enoX), которые основаны на физических характеристиках устройства (PCI координаты) и остаются стабильными между перезагрузками и при добавлении новых интерфейсов.
Но даже с предсказуемыми именами привязывайте конфигурацию сети к MAC-адресам интерфейсов, особенно если порядок сетей меняется в .spec.networks или добавлении новых интерфейсов.
Пример для систем без предсказуемого именования:
Изначально ВМ имеет два интерфейса:
$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
После добавления нового интерфейса в начало списка .spec.networks и перезагрузки ВМ:
$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 # Новый интерфейс
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 # Старый eth0
4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 # Старый eth1
MAC-адреса остаются неизменными, но имена интерфейсов (eth0, eth1) сдвигаются, что может привести к назначению IP-адресов не тем интерфейсам.
Используйте стабильные идентификаторы вместо ethX:
enpXsY— предсказуемые имена на основе физического расположения (systemd networkd naming scheme, включены по умолчанию в современных системах);- привязка по MAC-адресу — в конфигурации
netplan,systemd-networkdили/etc/network/interfaces(предпочтительно для гарантированной стабильности).
В конфигурационных файлах и скриптах используйте стабильные имена интерфейсов (enpXsY) или привязку по MAC-адресу вместо имён ethX.
Предсказуемый порядок интерфейсов соблюдается только в гостевых ОС с systemd (например, Ubuntu, Debian). В Alpine и других дистрибутивах без systemd порядок может не совпадать.
Чтобы открыть приложение машины другим машинам или пользователям снаружи кластера, настройте сервис или Ingress, как описано в разделе «Доступ к приложениям на виртуальной машине».
Живая миграция ВМ
Живая миграция виртуальных машин (ВМ) — это процесс перемещения работающей ВМ с одного физического узла на другой без её отключения. Эта функция играет ключевую роль в управлении виртуализованной инфраструктурой, обеспечивая непрерывность работы приложений во время технического обслуживания, балансировки нагрузки или обновлений.
Принцип работы живой миграции
Процесс живой миграции состоит из нескольких этапов:
-
На целевом узле создаётся новая ВМ в приостановленном состоянии. Её конфигурация (процессор, диски, сеть) копируется с исходного узла.
-
Вся оперативная память ВМ копируется на целевой узел по сети. Это называется первичной передачей.
-
Пока память передаётся, ВМ продолжает работать на исходном узле и может изменять некоторые страницы памяти. Такие страницы называются «грязными» (dirty pages), и гипервизор их помечает.
-
После первичной передачи начинается повторная отправка только изменённых страниц. Этот процесс повторяется в несколько циклов:
- Чем выше нагрузка на ВМ, тем больше «грязных» страниц появляется, и тем дольше длится миграция.
- При хорошей пропускной способности сети объём несинхронизированных данных постепенно уменьшается.
-
Когда количество «грязных» страниц становится минимальным, ВМ на исходном узле приостанавливается (обычно на 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 |
ВМ можно перенести, её локальные диски будут перенесены вместе с ней | — |
Перенос дисков вместе с ВМ доступен в коммерческих редакциях 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
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную виртуальную машину и нажмите кнопку с многоточием.
- В открывшемся меню выберите «Мигрировать».
- В открывшемся окне «Миграция виртуальной машины» выберите режим:
- «Мигрировать на произвольный узел» — узел назначения выберет планировщик;
- «Мигрировать на выбранный узел» — узел указывается вручную в поле «Доступные для миграции узлы» (в списке только узлы, подходящие под параметры размещения ВМ и её класс).
- При необходимости включите дополнительные параметры:
- «Мигрировать диски» — вместе с ВМ перенести её диски (используется при смене хранилища);
- «Принудительно (замедлить CPU гостя)» — применить AutoConverge, чтобы миграция завершилась даже при нехватке пропускной способности сети.
- В окне показана текущая политика миграции ВМ, например «Политика миграции ВМ: PreferSafe».
- Нажмите кнопку «Мигрировать» или откажитесь от операции кнопкой «Отмена».
Настройка политики миграции
Политика миграции определяет, когда использовать механизм AutoConverge (замедление процессора) для гарантированного завершения миграции.
Механизм AutoConverge помогает завершить миграцию даже при низкой пропускной способности сети, что позволяет с высокой вероятностью успешно завершить операцию. Однако он замедляет процессор виртуальной машины, что может повлиять на производительность приложений, работающих на виртуальной машине.
Механизм AutoConverge работает в два этапа:
-
Замедление процессора виртуальной машины
Гипервизор постепенно снижает частоту процессора исходной виртуальной машины. Это уменьшает скорость появления новых «грязных» страниц. Чем выше нагрузка на виртуальную машину, тем сильнее замедление.
-
Автоматическое завершение миграции
Как только скорость передачи данных превышает скорость изменения памяти, запускается финальная синхронизация, и виртуальная машина переключается на новый узел.
Для настройки политики миграции используйте параметр .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). Здесь хорошо видно, что частота процессора снижается поэтапно, чтобы уменьшить скорость изменения содержимого памяти.

Если сеть ограничивает скорость миграции, можно:
-
Дождаться, когда операция завершится с ошибкой из-за таймаута.
-
Отменить текущую операцию миграции, удалив ресурс VirtualMachineOperation, где
<VMOP_NAME>— имя этого ресурса:d8 k delete vmop <VMOP_NAME> -
Повторно запустить миграцию с использованием флага
--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
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- Перейдите на вкладку «Операции».
Живая миграция ВМ при изменении параметров размещения
Когда правила размещения меняются у работающей машины, 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
Сбор отладочной информации
Если машина ведёт себя не так, как ожидалось, соберите её состояние и состояние связанных ресурсов в один архив.
Для использования команды collect-debug-info требуется версия d8 v0.27.0 или выше.
В архив попадает следующая информация:
- конфигурация виртуальной машины;
- операции над виртуальной машиной;
- информация о миграциях;
- блочные устройства;
- связанные PVC и PV;
- поды, связанные с ВМ, включая их логи (последние 10000 строк);
- события (Events) для всех связанных ресурсов;
- XML-конфигурация домена ВМ.
Собранные данные лежат в архиве в формате YAML (для ресурсов) и в текстовых файлах (для логов). Такой архив можно передать в службу технической поддержки для анализа проблемы.
Ниже показано, как собрать такой архив:
- В командной строке
- В веб-интерфейсе
Команда collect-debug-info собирает диагностические данные о виртуальной машине и всех связанных ресурсах в сжатый архив (tar.gz), который выводится в stdout, поэтому вывод нужно перенаправить в файл.
Пример использования:
# Сбор отладочной информации для виртуальной машины 'linux-vm'
d8 v collect-debug-info linux-vm > debug-info.tar.gz
# Сбор отладочной информации для ВМ с указанием неймспейса
d8 v collect-debug-info linux-vm -n mynamespace > debug-info.tar.gz
# Сбор отладочной информации для ВМ с указанием полного имени (name.namespace)
d8 v collect-debug-info linux-vm.mynamespace > debug-info.tar.gzБез перенаправления вывода в файл команда завершится с ошибкой, а при успешном выполнении вы получите архив debug-info.tar.gz.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- Перейдите на вкладку «Диагностика».
- В блоке «Поды ВМ» отображаются поды виртуальной машины, их фаза и узел размещения.
- В блоке «Логи подов ВМ» можно посмотреть логи пода, отфильтровать строки регулярным выражением и задать количество последних строк.
- Чтобы выгрузить архив с диагностическими данными, нажмите кнопку «Скачать данные диагностики».
Текущие и завершённые операции над ВМ отображаются на вкладке «Операции»: для каждой операции показаны дата, имя ресурса VirtualMachineOperation, тип («Запустить», «Остановить» и другие), статус, прогресс и сообщение; список можно ограничить периодом «День», «Неделя» или «Месяц». События отображаются на вкладке «События», графики потребления ресурсов — на вкладке «Мониторинг».
Сеть виртуальных машин
Каждая виртуальная машина (ВМ) получает адрес в основной сети кластера, а при необходимости подключается к дополнительным сетям. В этом разделе описано, как управлять адресами машины, открывать доступ к её приложениям и подключать дополнительные интерфейсы.
IP-адреса ВМ
Адрес машины в основной сети кластера описывают два ресурса, аренда адреса в кластере и закреплённый за проектом адрес.
Блок .spec.settings.virtualMachineCIDRs в настройках модуля задаёт подсети, из которых машины получают IP-адреса. Доступны все адреса подсети, кроме первого и последнего.
Кластерный ресурс VirtualMachineIPAddressLease (vmipl) управляет арендой IP-адресов из общего пула, указанного в virtualMachineCIDRs, а проектный ресурс VirtualMachineIPAddress (vmip) отвечает за резервирование арендованных адресов и их привязку к машинам. Адрес закреплён за машиной, когда ресурс переходит в фазу Attached. Остальные фазы описаны в поле .status.phase.
По умолчанию DP назначает машине адрес сам и держит его закреплённым до удаления машины. Происходит это так:
- Вы создаёте виртуальную машину с именем
<VM_NAME>. - DP создаёт ресурс VirtualMachineIPAddress с именем
<VM_NAME>-<HASH>, чтобы запросить IP-адрес и связать его с виртуальной машиной. - Для этого VirtualMachineIPAddress создаётся ресурс аренды VirtualMachineIPAddressLease, который выбирает случайный IP-адрес из общего пула.
- Как только ресурс VirtualMachineIPAddress создан, виртуальная машина получает назначенный IP-адрес.
После удаления машины ресурс VirtualMachineIPAddress тоже удаляется, но сам адрес какое-то время остаётся закреплённым за проектом, и его можно запросить повторно.
- В командной строке
- В веб-интерфейсе
Чтобы посмотреть список аренд IP-адресов (vmipl), используйте команду:
d8 k get vmiplПример вывода:
NAME VIRTUALMACHINEIPADDRESS STATUS AGE
ip-10-66-10-14 {"name":"linux-vm-7prpx","namespace":"default"} Bound 12h
Посмотреть адрес, назначенный машине, можно командой:
d8 k get vmipПример вывода:
NAME ADDRESS STATUS VM AGE
linux-vm-7prpx 10.66.10.14 Attached linux-vm 12h
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «IP адреса».
- В списке отображаются имя ресурса, статус, адрес, тип (
AutoилиStatic), виртуальная машина, которая использует адрес, и возраст ресурса.
Назначение конкретного IP-адреса
Вместо случайного адреса из пула машине можно выдать адрес, выбранный заранее.
- В командной строке
- В веб-интерфейсе
-
Создайте ресурс VirtualMachineIPAddress:
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 -
Создайте новую или измените существующую виртуальную машину и в спецификации укажите требуемый ресурс VirtualMachineIPAddress явно:
spec: virtualMachineIPAddressName: linux-vm-custom-ip
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «IP адреса».
- Нажмите кнопку «Создать».
- В открывшемся окне «Создать ресурс» в поле «Имя» введите имя ресурса.
- На вкладке «Конфигурация» в поле «Тип» выберите
Static, а в поле «Статический IP-адрес» укажите нужный адрес. - Нажмите кнопку «Применить».
- Укажите имя созданного ресурса в параметре
.spec.virtualMachineIPAddressNameвиртуальной машины.
Сохранение IP-адреса за проектом
Чтобы автоматически выданный ip-адрес виртуальной машины не удалился вместе с самой виртуальной машиной выполните следующие действия.
Получите название ресурса VirtualMachineIPAddress для заданной виртуальной машины:
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}}'
# Или внесите аналогичные изменения, отредактировав ресурс.
d8 k edit vmip linux-vm-7prpxПосле удаления виртуальной машины ресурс VirtualMachineIPAddress сохранится, и его можно будет переиспользовать снова во вновь созданной виртуальной машине:
spec:
virtualMachineIPAddressName: linux-vm-7prpxДаже если ресурс VirtualMachineIPAddress удалить, IP-адрес остаётся арендованным за проектом ещё 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Доступ к приложениям на виртуальной машине
К виртуальной машине (ВМ) можно обращаться напрямую по её IP-адресу, но у такого подхода есть ограничения. Адрес приходится знать заранее, при пересоздании машины он может смениться, а обратиться сразу к группе машин не получится. Все эти задачи решают сервисы Kubernetes.
Сервис даёт машине или группе машин постоянное имя, за которым скрываются их адреса, и равномерно распределяет между ними запросы. Имя формируется как <SERVICE_NAME>.<NAMESPACE>.svc.<CLUSTER_NAME>, а внутри того же неймспейса достаточно короткой формы <SERVICE_NAME>.
Какой тип сервиса выбрать, зависит от задачи:
Headless— прямой доступ к конкретным машинам внутри кластера без единой точки входа;ClusterIP— единый внутренний адрес с балансировкой между машинами;NodePort— доступ извне через порт на узлах кластера;LoadBalancer— доступ извне через внешний балансировщик.
Если подключение к ВМ с узла кластера не проходит, проверьте NetworkPolicy в проекте. Политика может запрещать трафик к машине.
Машина попадает в сервис по лейблам. Проставьте машине лейбл, который сервис будет искать:
- В командной строке
- В веб-интерфейсе
Проставьте лейбл командой d8 k label:
d8 k label vm linux-vm app=nginxПример вывода:
virtualmachine.virtualization.deckhouse.io/linux-vm labeled
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- Перейдите на вкладку «Мета».
- Нажмите кнопку «Добавить» в секции «Лейблы» или «Аннотации».
- В открывшемся окне задайте ключ и значение, затем нажмите клавишу «Enter».
- Нажмите появившуюся кнопку «Сохранить».
Headless сервис
Headless-сервис не выделяет собственный IP-адрес, а возвращает адреса самих машин. Так вы обращаетесь к конкретной машине по DNS-имени, не заводя для неё отдельную точку входа. Даже для одной машины это удобнее фиксированного адреса, потому что имя не меняется при пересоздании.
- В командной строке
- В веб-интерфейсе
Создайте сервис с clusterIP: None:
d8 k apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: http
namespace: default
spec:
clusterIP: None
selector:
# Лейбл, по которому сервис отбирает виртуальные машины.
app: nginx
EOFПосле создания к машине можно обратиться по имени http.default.svc.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Сеть» → «Services».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя» введите имя сервиса.
- В поле «Тип» выберите
Headless. - В блоке «Селектор нагрузок» отметьте нужные виртуальные машины, их лейблы попадут в селектор сервиса.
- В блоке «Порты» задайте значения «Порт» и «Целевой порт».
- Нажмите кнопку «Создать».
Сервис с типом ClusterIP
Такой сервис даёт приложению машины постоянный адрес внутри кластера.
ClusterIP — это стандартный тип сервиса, который предоставляет внутренний IP-адрес для доступа к сервису внутри кластера. Этот IP-адрес используется для маршрутизации трафика между различными компонентами системы и позволяет виртуальным машинам взаимодействовать друг с другом через предсказуемый и стабильный адрес.
- В командной строке
- В веб-интерфейсе
Пример конфигурации ClusterIP:
d8 k apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: http
spec:
selector:
# Лейбл по которому сервис определяет на какую виртуальную машину направлять трафик.
app: nginx
EOF- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Сеть» → «Services».
- В открывшемся окне выполните настройки сервиса.
- Нажмите кнопку «Создать».
Сервис с типом NodePort
Такой сервис открывает приложение машины на порту каждого узла кластера.
NodePort — это расширение сервиса ClusterIP, которое обеспечивает доступ к сервису через заданный порт на всех узлах кластера. Это делает сервис доступным извне кластера через комбинацию IP-адреса узла и порта и подходит для случаев, когда внешний балансировщик не нужен.
- В командной строке
- В веб-интерфейсе
Создайте следующий сервис:
d8 k apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: linux-vm-nginx-nodeport
spec:
type: NodePort
selector:
# Лейбл по которому сервис определяет на какую виртуальную машину направлять трафик.
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 31880
EOF
В данном примере будет создан сервис с типом NodePort, который открывает внешний порт 31880 на всех узлах вашего кластера. Этот порт будет направлять входящий трафик на внутренний порт 80 виртуальной машины, где запущено приложение Nginx.
Если не указывать значение nodePort явно, для сервиса будет назначен произвольный порт, который можно посмотреть в статусе сервиса, сразу после его создания.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Сеть» → «Services».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя» введите имя сервиса.
- В поле «Тип» выберите
NodePort. - В блоке «Селектор нагрузок» отметьте нужные виртуальные машины.
- В блоке «Порты» задайте значения «Порт», «Целевой порт» и, при необходимости, «Порт узла».
- Нажмите кнопку «Создать».
Сервис с типом LoadBalancer
Такой сервис выдаёт приложению внешний адрес через балансировщик нагрузки.
LoadBalancer — это тип сервиса, который автоматически создаёт внешний балансировщик нагрузки с постоянным IP-адресом. Этот балансировщик распределяет входящий трафик среди виртуальных машин, обеспечивая доступность сервиса из интернета.
- В командной строке
- В веб-интерфейсе
d8 k apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: linux-vm-nginx-lb
spec:
type: LoadBalancer
selector:
# Лейбл по которому сервис определяет на какую виртуальную машину направлять трафик
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
EOF
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Сеть» → «Services».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя» введите имя сервиса.
- В поле «Тип» выберите
LoadBalancer. - В блоке «Селектор нагрузок» отметьте нужные виртуальные машины.
- В блоке «Порты» задайте значения «Порт» и «Целевой порт».
- Нажмите кнопку «Создать».
- Внешний адрес сервиса отображается в списке сервисов в колонке «Внешний IP».
Публикация сервисов ВМ с использованием Ingress
Ingress открывает приложение машины по доменному имени и берёт на себя терминацию TLS.
Ingress позволяет управлять входящими HTTP/HTTPS-запросами и маршрутизировать их к различным серверам в рамках вашего кластера. Это наиболее подходящий метод, если вы хотите использовать доменные имена и SSL-терминацию для доступа к вашим виртуальным машинам.
- В командной строке
- В веб-интерфейсе
Для публикации сервиса виртуальной машины через Ingress необходимо создать следующие ресурсы:
Внутренний сервис для связки с Ingress. Пример:
d8 k apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: linux-vm-nginx
spec:
selector:
# лейбл по которому сервис определяет на какую виртуальную машину направлять трафик
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
EOFИ ресурс Ingress для публикации. Пример:
d8 k apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: linux-vm
spec:
rules:
- host: linux-vm.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: linux-vm-nginx
port:
number: 80
EOF
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Сеть» → «Ingresses».
- Нажмите кнопку «Создать».
- В открывшейся форме «Создать Ingress» в поле «Наименование» введите имя ресурса, а в поле «Ingress Class» выберите класс контроллера (
spec.ingressClassName). - В блоке «Правила» нажмите кнопку «Добавить правило (хост)» и опишите хост и пути маршрутизации на нужный сервис.
- Если требуется HTTPS, в блоке «TLS-сертификаты» нажмите кнопку «Добавить сертификат» и укажите секрет с сертификатом; при необходимости задайте «Бэкенд по умолчанию».
- Нажмите кнопку «Создать».
Дополнительные сетевые интерфейсы
Кроме основной сети кластера машину можно подключить к дополнительным сетям, проектным (Network) и кластерным (ClusterNetwork). Нужные сети перечисляют в блоке .spec.networks, а если этот блок не задан, машина работает только в основной сети кластера.
Для работы с дополнительными сетями необходимо, чтобы модуль sdn был активирован.
Основную сеть кластера (type: Main) указывать необязательно, и машина может работать только в дополнительных сетях. Но если основная сеть указана, она должна быть первой в списке.
Особенности дополнительных сетевых интерфейсов:
- порядок перечисления сетей в
.spec.networksопределяет порядок подключения интерфейсов внутри виртуальной машины; - добавление или удаление дополнительной сети (
NetworkилиClusterNetwork) на работающей ВМ применяется без перезагрузки. ACPI-индексы существующих интерфейсов сохраняются при добавлении и удалении, поэтому имена интерфейсов в гостевой ОС остаются стабильными; - добавление или удаление основной сети (
type: Main) по-прежнему требует перезагрузки ВМ, так как она связана с основным сетевым интерфейсом пода и не может быть изменена на работающем поде; - чтобы сохранить порядок сетевых интерфейсов внутри гостевой операционной системы, добавляйте новые сети в конец списка
.spec.networksи не меняйте порядок существующих; - политики сетевой безопасности (NetworkPolicy) не применяются к дополнительным сетевым интерфейсам;
- параметры сети (IP-адреса, шлюзы, DNS и так далее) для дополнительных сетей настраиваются вручную изнутри гостевой ОС (например, с помощью Cloud-Init), если для сети не настроен IPAM, описанный в подразделе «IPAM для дополнительных сетевых интерфейсов».
Для каждого дополнительного сетевого интерфейса автоматически создаётся и резервируется уникальный MAC-адрес, что обеспечивает отсутствие коллизий MAC-адресов. Для этого служат ресурсы VirtualMachineMACAddress (vmmac) и VirtualMachineMACAddressLease (vmmacl).
MAC-адрес генерируется случайным образом из пула разрешённых диапазонов.
- Диапазоны:
x2-xx-xx-xx-xx-xx,x6-xx-xx-xx-xx-xx,xA-xx-xx-xx-xx-xx,xE-xx-xx-xx-xx-xx. - Первые три октета (OUI) формируются на основе UUID кластера, последние три (NIC) — выбираются случайно из 16 миллионов возможных комбинаций.
Кластерный ресурс VirtualMachineMACAddressLease (vmmacl) управляет арендой адресов из общего пула, а проектный ресурс VirtualMachineMACAddress (vmmac) отвечает за резервирование арендованных адресов и их привязку к машинам. Адрес закрепляется за машиной до её удаления.
При удалении сети из конфигурации ВМ:
- MAC-адрес интерфейса освобождается.
- Автоматически удаляются связанные ресурсы VirtualMachineMACAddress и VirtualMachineMACAddressLease.
- Автоматически удаляется выделенный ресурс
IPAddress(если использовался IPAM).
Ниже показано, как подключить машину к дополнительной сети:
- В командной строке
- В веб-интерфейсе
Перечислите нужные сети в блоке .spec.networks спецификации машины.
Пример подключения ВМ к основной сети кластера и проектной сети user-net:
spec:
networks:
- type: Main # Если указана, должна быть первой
- type: Network # Тип сети (Network \ ClusterNetwork)
name: user-net # Название сетиПример подключения к нескольким сетям, включая кластерную сеть corp-net:
spec:
networks:
- type: Main # Если указана, должна быть первой
- type: Network
name: user-net
- type: ClusterNetwork
name: corp-net # Название сетиПример подключения ВМ только к дополнительным сетям (без основной сети кластера):
spec:
networks:
- type: Network
name: isolated-net
- type: ClusterNetwork
name: corp-netИнформацию о подключённых сетях и их MAC-адресах можно посмотреть в статусе ВМ:
status:
networks:
- type: Main
- type: Network
name: user-net
macAddress: aa:bb:cc:dd:ee:01
- type: ClusterNetwork
name: corp-net
macAddress: aa:bb:cc:dd:ee:02Чтобы посмотреть список аренд MAC-адресов (vmmacl), используйте команду:
d8 k get vmmaclПример вывода:
NAME VIRTUALMACHINEMACADDRESS STATUS AGE
mac-5e-e6-19-22-0f-d8 {"name":"vm-01-fz9cr","namespace":"pr-sdn"} Bound 45s
mac-5e-e6-19-29-89-cf {"name":"vm-01-99qj6","namespace":"pr-sdn"} Bound 45s
mac-5e-e6-19-54-f9-be {"name":"vm-01-5jqxg","namespace":"pr-sdn"} Bound 45s
Проверить назначенные MAC-адреса можно с помощью команды:
d8 k get vmmacПример вывода:
NAME ADDRESS STATUS VM AGE
vm-01-5jqxg 5e:e6:19:54:f9:be Attached vm-01 5m42s
vm-01-99qj6 5e:e6:19:29:89:cf Attached vm-01 5m42s
vm-01-fz9cr 5e:e6:19:22:0f:d8 Attached vm-01 5m42s
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу до раздела «Сети» и нажмите кнопку «Добавить».
- В открывшемся окне «Добавить сеть» в поле «Выберите сеть» укажите нужную сеть.
- Нажмите кнопку «Добавить», затем — появившуюся кнопку «Сохранить».
Чтобы создать сеть проекта:
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Сеть» → «SDN» → «Сети».
- Нажмите кнопку «Создать».
- В открывшемся окне «Создать ресурс» в поле «Имя» введите имя сети.
- На вкладке «Конфигурация» в поле «Сетевой класс» выберите Network-класс, в поле «Type» — тип сети, в поле «VLAN» — идентификатор VLAN. При необходимости задайте «Mtu» и параметры блока «IPAM».
- Нажмите кнопку «Применить».
- Созданные сети отображаются в списке с колонками «Статус», «Тип», «VLAN» и «Network-класс».
Именование интерфейсов и ARP Flux в гостевой ОС
При настройке сетевых интерфейсов в гостевой ОС используйте стабильные идентификаторы (предсказуемые имена enpXsY или привязку по MAC-адресу) вместо имён ethX, как описано в разделе «Именование сетевых интерфейсов в гостевой ОС».
На гостевой системе Linux с несколькими интерфейсами в одной подсети может возникать проблема ARP Flux, при которой ядро отвечает на ARP-запросы через произвольный интерфейс, а не через тот, на который пришёл запрос, что приводит к нестабильному соединению и потере пакетов из-за некорректного MAC-адреса в кеше маршрутизаторов.
Чтобы это исправить, установите параметры, которые заставляют систему отвечать на запросы строго через интерфейс с целевым IP и использовать корректный исходный адрес:
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2Пример для cloud-init:
write_files:
- path: /etc/sysctl.d/90-arp-strict.conf
content: |
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2Значения параметров описаны в документации IP sysctl.
IPAM для дополнительных сетевых интерфейсов
Адреса в дополнительной сети DP может выдавать сам, если администратор настроил для этой сети пул адресов.
Если в модуле sdn для дополнительной сети настроен IPAM (пул IP-адресов, привязанный к сети через spec.ipam.ipAddressPoolRef), DP может автоматически выделять IP-адреса для дополнительных интерфейсов ВМ и доставлять их в гостевую ОС через DHCP.
Поддерживаются два режима:
-
Автоматический (DHCP) — если в
.spec.networks[]не указано полеipAddressName, контроллер автоматически создаёт ресурс IPAddress (типAuto), привязанный к ВМ черезownerReferences, и передаёт его в модульsdn. Модульsdnвыделяет адрес из пула и доставляет его в гостевую ОС через DHCP. Адрес сохраняется при перезагрузках и миграции ВМ, поскольку привязан к ВМ, а не к поду. Для работы этого режима в гостевой ОС на соответствующем интерфейсе должен быть включён DHCP-клиент. -
Статический — если в
.spec.networks[]указано полеipAddressName, контроллер использует предоставленный пользователем ресурс IPAddress (типStatic,network.deckhouse.io/v1alpha1). Адрес определяется пользователем и не изменяется автоматически.
Если у дополнительной сети не настроен пул IPAM, функция IPAM не включается. Интерфейс работает в режиме L2-only, а IP-адресацию необходимо настроить вручную в гостевой ОС.
Если для дополнительной сети настроен пул IPAM, не настраивайте статический IP-адрес на дополнительном интерфейсе в гостевой ОС вручную (через Cloud-Init). Используйте автоматический (DHCP) или статический (ipAddressName) режим, чтобы избежать конфликтов адресов.
Если у дополнительной сети есть пул IPAM, но ресурс IPAddress ещё не выделен или находится в состоянии Pending (например, из-за исчерпания пула адресов), интерфейс временно пропускается. ВМ запускается без него, а в условии NetworkReady сообщается об ошибке. После появления доступного IP-адреса интерфейс подключается автоматически.
- В командной строке
- В веб-интерфейсе
Пример конфигурации ВМ с автоматическим выделением IP-адреса для дополнительной сети:
spec:
networks:
- type: Main
- type: ClusterNetwork
name: corp-net
# ipAddressName не указан → используется автоматический режим (DHCP)Пример конфигурации ВМ со статическим IP-адресом для дополнительной сети:
spec:
networks:
- type: Main
- type: ClusterNetwork
name: corp-net
ipAddressName: my-static-ip # Имя ресурса IPAddress (SDN)Пример конфигурации статического ресурса IPAddress:
apiVersion: network.deckhouse.io/v1alpha1
kind: IPAddress
metadata:
name: my-static-ip
namespace: my-namespace
spec:
networkRef:
kind: ClusterNetwork
name: corp-net
type: Static
static:
ip: 192.168.200.42Выделенный IP-адрес отображается в статусе ВМ:
status:
ipAddress: 10.66.10.2 # IP-адрес основной сети.
virtualMachineIPAddressName: vm-01-main-ip # Имя IPAddress основной сети.
networks:
- type: Main
- type: ClusterNetwork
name: corp-net
macAddress: 32:a6:a1:0a:92:48
virtualMachineMACAddressName: vm-01-rxzd6
ipAddress: 192.168.200.4 # IP-адрес дополнительной сети (из IPAM).- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Сеть» → «SDN» → «IP-пулы».
- Нажмите кнопку «Создать».
- В открывшемся окне «Создать ресурс» в поле «Имя» введите имя пула.
- На вкладке «Конфигурация» в поле «Lease TTL» задайте время жизни аренды, а в блоке «Pools» — сеть («Network»), диапазоны адресов («Ranges») и маршруты («Routes»).
- Нажмите кнопку «Применить».
Настройка гостевой ОС для интерфейсов, добавленных на ходу
Когда дополнительный сетевой интерфейс подключают к уже запущенной ВМ, гостевая ОС должна быть настроена на автоматический подъём новых сетевых интерфейсов и запрос DHCP-аренды. Linux по умолчанию не запускает DHCP-клиент на интерфейсах, добавленных на ходу.
Чтобы такие интерфейсы настраивались сами, используйте в гостевой ОС один из следующих подходов:
-
NetworkManager (Ubuntu, RHEL, CentOS) — автоматически настраивает новые интерфейсы с DHCP, если запущен сервис
network-manager; -
udev-правило (Alpine и другие системы без
network-manager) — добавьте udev-правило для подъёма новых интерфейсов:write_files: - path: /etc/udev/rules.d/90-hotplug-network.rules content: | SUBSYSTEM=="net", ACTION=="add", RUN+="/sbin/ifup %k"
Для интерфейсов, присутствующих при загрузке ВМ (включённых в начальную сетевую конфигурацию), дополнительная настройка не требуется — гостевая ОС настраивает их при запуске через Cloud-Init.
Снимки, восстановление и клонирование
Снимки позволяют зафиксировать текущее состояние ресурса для последующего восстановления или клонирования. Снимок диска сохраняет только данные выбранного диска, а снимок виртуальной машины (ВМ) включает в себя её параметры и состояние всех дисков.
Консистентные снимки
Снимки могут быть консистентными и неконсистентными. За это отвечает параметр requiredConsistency, по умолчанию его значение равно true, что означает требование консистентного снимка.
Консистентный снимок фиксирует согласованное и целостное состояние данных диска. Такой снимок можно создать при выполнении одного из следующих условий:
- диск не подключён ни к одной виртуальной машине — снимок всегда будет консистентным;
- виртуальная машина выключена;
- в гостевой ОС установлен и запущен
qemu-guest-agent. При создании снимка он временно приостанавливает («замораживает») работу файловой системы, чтобы обеспечить согласованность данных.
Неконсистентный снимок может не отражать согласованное состояние дисков виртуальной машины и её компонентов. Такой снимок создаётся, если ВМ запущена, и в гостевой ОС не установлен или не запущен qemu-guest-agent.
Если в манифесте снимка явно указан параметр requiredConsistency: false, но qemu-guest-agent при этом запущен, будет также предпринята попытка заморозки файловой системы, чтобы снимок получился консистентным.
QEMU Guest Agent поддерживает скрипты hooks, которые позволяют подготовить приложения к созданию снимка без остановки сервисов, обеспечивая согласованное состояние на уровне приложений. Настройка скриптов hooks описана в разделе «Агент гостевой ОС».
При восстановлении из такого снимка возможны проблемы с целостностью файловой системы, поскольку состояние данных может быть не согласовано.
Создание снимков дисков
Снимок диска сохраняет его данные на момент создания и служит источником для новых дисков.
Снимки дисков описывает ресурс VirtualDiskSnapshot. Они могут служить источником данных при создании новых дисков, например для клонирования или восстановления информации.
Целостность данных гарантирована, когда снимок создают в одном из следующих случаев:
- Диск не подключён ни к одной виртуальной машине.
- ВМ выключена.
- ВМ запущена, в гостевой ОС установлен qemu-guest-agent, и файловая система успешно «заморожена» (операция fsfreeze).
Если консистентность данных не требуется (например, для тестовых сценариев), задайте в снимке параметр .spec.requiredConsistency со значением false. Тогда снимок создаётся и на работающей ВМ без «заморозки» файловой системы, в том числе когда диск подключён к ней.
Снимок диска проходит следующие фазы:
Pending— ожидание готовности всех зависимых ресурсов, требующихся для создания снимка.InProgress— идёт процесс создания снимка виртуального диска.Ready— создание снимка успешно завершено, и снимок виртуального диска доступен для использования.Failed— произошла ошибка во время процесса создания снимка виртуального диска.Terminating— ресурс находится в процессе удаления.
Причину проблемы с ресурсом показывает блок .status.conditions.
- В командной строке
- В веб-интерфейсе
Пример манифеста для создания снимка диска:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualDiskSnapshot
metadata:
name: linux-vm-root-snapshot
spec:
requiredConsistency: true
virtualDiskName: linux-vm-root
EOFДля просмотра списка снимков дисков, выполните следующую команду:
d8 k get vdsnapshotПример вывода:
NAME PHASE CONSISTENT AGE
linux-vm-root-snapshot Ready true 3m2s
Значение true в колонке CONSISTENT означает, что снимок консистентен. Оно определяется автоматически по условиям создания снимка и вручную не меняется.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Снимки дисков».
- Нажмите кнопку «Создать».
- В открывшемся окне «Создать ресурс» в поле «Имя» введите имя для снимка.
- На вкладке «Конфигурация» в поле «Имя виртуального диска» выберите диск, с которого будет создан снимок.
- Включите переключатель «Требуемая консистентность».
- Нажмите кнопку «Применить».
- Статус снимка отображается в колонке «Статус».
Восстановление дисков из снимков
Из снимка создаётся новый диск, а исходный остаётся нетронутым.
- В командной строке
- В веб-интерфейсе
Для того чтобы восстановить диск из ранее созданного снимка диска, необходимо в качестве dataSource указать соответствующий объект:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualDisk
metadata:
name: linux-vm-root
spec:
# Настройки параметров хранения диска.
persistentVolumeClaim:
# Укажем размер больше чем значение .
size: 10Gi
# Подставьте ваше название StorageClass.
storageClassName: rv-thin-r2
# Источник из которого создается диск.
dataSource:
type: ObjectRef
objectRef:
kind: VirtualDiskSnapshot
name: linux-vm-root-snapshot
EOF- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Диски».
- Нажмите кнопку «Создать».
- В открывшейся форме в поле «Имя диска» введите имя для диска.
- В поле «Источник» из выпадающего списка выберите снимок диска, из которого хотите восстановиться.
- В поле «Размер» установите размер такой же или больше, чем размер оригинального диска.
- В поле «Класс хранения» выберите StorageClass оригинального диска.
- Нажмите кнопку «Создать».
- Статус диска отображается на его странице.
Создание снимков ВМ
Снимок виртуальной машины — это сохранённое состояние виртуальной машины в определённый момент времени. Для создания снимков виртуальных машин используется ресурс VirtualMachineSnapshot.
Рекомендуется отключить все образы (VirtualImage/ClusterVirtualImage) от виртуальной машины перед созданием её снимка. Образы дисков не сохраняются вместе со снимком ВМ, и их отсутствие в кластере при восстановлении может привести к тому, что виртуальная машина не сможет запуститься и будет находиться в состоянии Pending, ожидая доступности образа.
Создание снимка виртуальной машины будет неудачным, если выполнится хотя бы одно из следующих условий:
- не все зависимые устройства виртуальной машины готовы;
- среди зависимых устройств есть диск, находящийся в процессе изменения размера.
Если на момент создания снимка в виртуальной машине есть изменения, ожидающие перезапуска, в снимок попадёт обновлённая конфигурация.
При создании снимка динамический IP-адрес ВМ автоматически преобразуется в статический и сохраняется для восстановления. Если преобразование и использование старого адреса не нужны, задайте параметру .spec.keepIPAddress значение Never, и тогда тип адреса останется прежним (Auto или Static).
Ниже показано, как создать снимок виртуальной машины:
- В командной строке
- В веб-интерфейсе
Пример манифеста для создания снимка виртуальной машины:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineSnapshot
metadata:
name: linux-vm-snapshot
spec:
virtualMachineName: linux-vm
requiredConsistency: true
keepIPAddress: Never
EOFПосле успешного создания снимка в его статусе отражается перечень сохранённых ресурсов.
Пример вывода:
status:
...
resources:
- apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachine
name: linux-vm
- apiVersion: v1
kind: Secret
name: cloud-init
- apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualDisk
name: linux-vm-root- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- Перейдите на вкладку «Снимки».
- Нажмите кнопку «Добавить».
- В открывшейся форме в поле «Имя снимка» введите
linux-vm-snapshot. - Включите переключатель «Гарантия целостности».
- Нажмите кнопку «Создать».
- Статус снимка отображается на его странице.
- Созданные снимки перечислены на вкладке «Снимки» виртуальной машины с колонками «Имя», «Статус», «Дата создания» и «Консистентный».
Восстановление ВМ
Восстановление возвращает машину и её диски к состоянию, сохранённому в снимке. Запускает его ресурс VirtualMachineOperation с типом Restore, у которого есть три режима:
DryRun— холостой запуск операции восстановления, необходим для проверки возможных конфликтов, которые будут отображены в статусе ресурса (status.resources).Strict— режим строгого восстановления, когда требуется восстановление ВМ «как в снимке», отсутствующие внешние зависимости могут привести к тому, что ВМ после восстановления будет вPending.BestEffort— отсутствующие внешние зависимости (ClusterVirtualImage, VirtualImage) игнорируются и удаляются из конфигурации ВМ.
Восстановление виртуальной машины из снимка возможно только при выполнении всех следующих условий:
- Восстанавливаемая ВМ присутствует в кластере (ресурс VirtualMachine существует, а его
.metadata.uidсовпадает с идентификатором, использованным при создании снимка). - Восстанавливаемые диски (определяются по имени) либо не подключены к другим ВМ, либо отсутствуют в кластере.
- Восстанавливаемый IP-адрес либо не занят другой ВМ, либо отсутствует в кластере.
- Восстанавливаемые MAC-адреса либо не используются другими ВМ, либо отсутствуют в кластере.
Вместе с машиной восстанавливаются и её диски, поэтому в спецификации диска будет указан параметр dataSource со ссылкой на нужный снимок диска.
Если некоторые ресурсы, от которых зависит ВМ (например, VirtualMachineClass, VirtualImage, ClusterVirtualImage), отсутствуют в кластере, но существовали на момент создания снимка, ВМ после восстановления останется в состоянии Pending. В этом случае необходимо вручную отредактировать конфигурацию ВМ и обновить или удалить отсутствующие зависимости.
Не отменяйте операцию восстановления из снимка, то есть не удаляйте ресурс VirtualMachineOperation в фазе InProgress, потому что это может привести к неконсистентному состоянию восстанавливаемой виртуальной машины.
- В командной строке
- В веб-интерфейсе
Восстановление запускает ресурс VirtualMachineOperation с типом Restore:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
name: <VMOP_NAME>
spec:
type: Restore
virtualMachineName: <VM_NAME>
restore:
mode: DryRun | Strict | BestEffort
virtualMachineSnapshotName: <VM_SNAPSHOT_NAME>Информацию о конфликтах при восстановлении ВМ из снимка можно посмотреть в статусе ресурса:
d8 k get vmop <VMOP_NAME> -o json | jq '.status.resources'- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную виртуальную машину и нажмите кнопку с многоточием.
- В открывшемся меню выберите «Восстановить».
- В открывшемся окне «Восстановление машины» в поле «Имя снимка виртуальной машины» выберите снимок.
- В поле «Режим восстановления» выберите
StrictилиBestEffort. - Нажмите кнопку «Восстановить».
Клонирование ВМ
Клон виртуальной машины (ВМ) создаётся либо из уже существующей ВМ, либо из ранее созданного снимка этой машины.
Клонируемой ВМ будет назначен новый IP-адрес для кластерной сети и MAC-адреса для дополнительных сетевых интерфейсов (если они есть), поэтому после клонирования потребуется перенастроить сетевые параметры гостевой ОС.
Лейблы не копируются с исходной ВМ на клон. Это предотвращает маршрутизацию трафика Service (Service выбирают ВМ по меткам) на клон. Если клон должен входить в Service, добавьте нужные лейблы после клонирования. Например:
d8 k label vm <VM_NAME> label-name=label-valueКлонирование создаёт копию ВМ, поэтому ресурсы новой ВМ должны иметь уникальные имена. Для этого используются параметры nameReplacements и/или customization:
nameReplacements— позволяет заменить имена существующих ресурсов на новые, чтобы избежать конфликтов.customization— задаёт префикс или суффикс для имен всех клонируемых ресурсов ВМ (дисков, IP-адресов и так далее).
Пример переименования конкретных ресурсов:
nameReplacements:
- from:
kind: VirtualMachine
name: <OLD_VM_NAME>
to:
name: <NEW_VM_NAME>
- from:
kind: VirtualDisk
name: <OLD_DISK_NAME>
to:
name: <NEW_DISK_NAME>
...В результате будет создана ВМ с именем <NEW_VM_NAME>, а указанные ресурсы будут переименованы согласно правилам замены.
Пример добавления префикса или суффикса ко всем ресурсам:
customization:
namePrefix: <PREFIX>
nameSuffix: <SUFFIX>В результате будет создана ВМ с именем <PREFIX><ORIGINAL_VM_NAME><SUFFIX>, а все ресурсы (диски, IP-адреса и так далее) получат префикс и суффикс.
Для операции клонирования возможно использовать один из трех режимов:
DryRun— тестовый запуск для проверки возможных конфликтов. Результаты отображаются в полеstatus.resourcesсоответствующего ресурса операции.Strict— строгий режим, требующий наличия всех ресурсов с новыми именами и их зависимостей (например, образов) в клонируемой ВМ.BestEffort— режим, при котором отсутствующие внешние зависимости (например, ClusterVirtualImage, VirtualImage) автоматически удаляются из конфигурации клонируемой ВМ.
Информацию о конфликтах, возникших при клонировании, можно просмотреть в статусе ресурса операции:
# Для клонирования из существующей ВМ.
d8 k get vmop <VMOP_NAME> -o json | jq '.status.resources'
# Для клонирования из снимка ВМ.
d8 k get vmsop <VMSOP_NAME> -o json | jq '.status.resources'Создание клона существующей ВМ
Клон собирается из временных снимков машины, поэтому останавливать её не нужно.
Клонирование ВМ выполняется с использованием ресурса VirtualMachineOperation с типом операции Clone и поддерживается как для выключенных, так и для работающих машин. При клонировании работающей ВМ автоматически создаётся консистентный снимок, из которого затем формируется клон.
В процессе клонирования для виртуальной машины и всех её дисков автоматически создаются временные снимки, из которых собирается новая ВМ. После завершения клонирования временные снимки удаляются, поэтому в списке ресурсов их не будет. При этом в спецификации клонированных дисков остаётся ссылка (dataSource) на соответствующий снимок, даже если самого снимка уже не существует. Это ожидаемое поведение, а не признак проблемы, ведь к моменту запуска клона все необходимые данные уже перенесены на новые диски.
Задавайте параметр .spec.runPolicy: AlwaysOff в конфигурации клонируемой ВМ, чтобы предотвратить автоматический запуск клона: клон наследует поведение родительской ВМ.
Перед клонированием подготовьте гостевую ОС, чтобы избежать конфликтов уникальных идентификаторов и сетевых настроек.
Linux:
- очистить
machine-idс помощью командыsudo truncate -s 0 /etc/machine-id(для systemd) или удалить файл/var/lib/dbus/machine-id; - удалить SSH-ключи хоста:
sudo rm -f /etc/ssh/ssh_host_*; - очистить конфигурации сетевых интерфейсов (если используются статические настройки);
- очистить кеш Cloud-Init (если используется):
sudo cloud-init clean.
Windows:
- выполнить генерализацию с помощью
sysprepс параметром/generalizeили использовать инструменты для очистки уникальных идентификаторов (SID, hostname и так далее).
- В командной строке
- В веб-интерфейсе
Для создания клона ВМ используйте следующий ресурс:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
name: <VMOP_NAME>
spec:
type: Clone
virtualMachineName: <name of the VM to be cloned>
clone:
mode: DryRun | Strict | BestEffort
nameReplacements: []
customization: {}Параметры nameReplacements и customization задаются в блоке .spec.clone.
В следующем примере показано клонирование ВМ с именем database и подключенного к ней диска database-root:
Пример с переименованием конкретных ресурсов:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
name: clone-database
spec:
type: Clone
virtualMachineName: database
clone:
mode: Strict
nameReplacements:
- from:
kind: VirtualMachine
name: database
to:
name: database-clone
- from:
kind: VirtualDisk
name: database-root
to:
name: database-clone-rootВ результате будет создана ВМ с именем database-clone и диск с именем database-clone-root.
Пример с использованием префикса для всех ресурсов:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
name: clone-database
spec:
type: Clone
virtualMachineName: database
clone:
mode: Strict
customization:
namePrefix: clone-
nameSuffix: -prodВ результате будет создана ВМ с именем clone-database-prod и диск с именем clone-database-root-prod.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную виртуальную машину и нажмите кнопку с многоточием.
- В открывшемся меню выберите «Клонировать».
- В открывшемся окне «Клонирование машины» в поле «Имя снимка виртуальной машины» выберите снимок, из которого будет создан клон. Клон создаётся из снимка, поэтому снимок нужно подготовить заранее.
- В поле «Режим клонирования» выберите
StrictилиBestEffort. - При необходимости в блоке «Кастомизация» → «Переименование ресурсов» задайте новые имена ресурсов клона, указав тип ресурса, исходное и новое имя.
- Нажмите кнопку «Клонировать».
Создание клона из снимка ВМ
Клонирование ВМ из снимка выполняется с использованием ресурса VirtualMachineSnapshotOperation с типом операции CreateVirtualMachine.
Для создания клона ВМ из снимка используйте следующий ресурс:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineSnapshotOperation
metadata:
name: <VMSOP_NAME>
spec:
type: CreateVirtualMachine
virtualMachineSnapshotName: <name of the VM snapshot from which to clone>
createVirtualMachine:
mode: DryRun | Strict | BestEffort
nameReplacements: []
customization: {}Параметры nameReplacements и customization настраиваются в блоке .spec.createVirtualMachine (общее описание выше).
Чтобы посмотреть список ресурсов, сохранённых в снимке, используйте команду:
d8 k get vmsnapshot <SNAPSHOT_NAME> -o jsonpath='{.status.resources}' | jqПри клонировании ВМ из снимка связанные с ней диски также создаются из соответствующих снимков, поэтому в спецификации диска будет указан параметр dataSource с ссылкой на нужный снимок диска.
В следующем примере показано клонирование из снимка ВМ с именем database-snapshot, который содержит ВМ database и диск database-root:
Пример с переименованием конкретных ресурсов:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineSnapshotOperation
metadata:
name: clone-database-from-snapshot
spec:
type: CreateVirtualMachine
virtualMachineSnapshotName: database-snapshot
createVirtualMachine:
mode: Strict
nameReplacements:
- from:
kind: VirtualMachine
name: database
to:
name: database-clone
- from:
kind: VirtualDisk
name: database-root
to:
name: database-clone-rootВ результате будет создана ВМ с именем database-clone и диск с именем database-clone-root.
Пример с использованием префикса для всех ресурсов:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineSnapshotOperation
metadata:
name: clone-database-from-snapshot
spec:
type: CreateVirtualMachine
virtualMachineSnapshotName: database-snapshot
createVirtualMachine:
mode: Strict
customization:
namePrefix: clone-
nameSuffix: -prodВ результате будет создана ВМ с именем clone-database-prod и диск с именем clone-database-root-prod.
Пулы виртуальных машин
Доступно в коммерческих редакциях DP.
Ресурс VirtualMachinePool поддерживает заданное число одинаковых виртуальных машин (ВМ) и позволяет масштабировать их через субресурс scale, HorizontalPodAutoscaler (HPA) или KEDA. Поле virtualMachineTemplate.spec совпадает с обычным VirtualMachineSpec, поэтому реплика ничем не отличается от вручную созданной виртуальной машины.
Тип ОС Legacy в пуле не поддерживается, потому что реплики различают начальной инициализацией, которой у этих операционных систем нет, поэтому каждая реплика оказалась бы побайтовой копией одного диска — для гостевых ОС семейства Windows это ещё и одинаковый SID в сети. Шаблон пула с osType: Legacy отклоняется. Создавайте такие виртуальные машины по отдельности.
Ниже показано, как создать пул виртуальных машин:
- В командной строке
- В веб-интерфейсе
Создайте пул с нужным числом реплик и шаблоном виртуальной машины. Диски пула описываются в двух блоках:
virtualDiskTemplatesописывает каждый диск реплики один раз, задавая политикуreclaim, размер и источник данных;blockDeviceRefsшаблона ссылается на эти диски по имени сkind: VirtualDiskи задаёт порядок устройств, то есть порядок загрузки, ровно как в обычной VirtualMachine.
Каждая запись virtualDiskTemplates должна встречаться в blockDeviceRefs ровно один раз, иначе DP отклонит пул. Имена шаблонов дисков при этом уникальны.
Помимо дисков реплики в blockDeviceRefs можно перечислить общие образы VirtualImage и ClusterVirtualImage, например единый ISO или CD-ROM для всех реплик. Такие образы подключаются только на чтение, они одни на весь пул, и записи в virtualDiskTemplates им не нужны.
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachinePool
metadata:
name: runners
namespace: ci
spec:
replicas: 3
scaleDownPolicy: NewestFirst
virtualMachineTemplate:
spec:
runPolicy: AlwaysOn
virtualMachineClassName: generic
cpu:
cores: 2
memory:
size: 4Gi
# Cloud-init: каждая реплика самонастраивается при первом запуске (одинаково для всех).
provisioning:
type: UserData
userData: |
#cloud-config
users:
- name: cloud
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- <SSH_PUBLIC_KEY>
# Устройства и порядок загрузки (первый = загрузочный). Записи VirtualDisk
# ссылаются на virtualDiskTemplates по имени, у каждой реплики свой диск;
# VirtualImage/ClusterVirtualImage — общий образ только для чтения для всех реплик.
blockDeviceRefs:
- kind: VirtualDisk
name: root # загрузочный диск
- kind: VirtualDisk
name: cache
- kind: ClusterVirtualImage
name: tools-iso # общий CD-ROM, подключается ко всем репликам
# Параметры дисков реплики (reclaim, размер, источник). Каждый должен быть указан выше.
virtualDiskTemplates:
# Записываемый корневой диск: свой на каждую реплику, клонируется из образа, удаляется вместе с репликой.
- name: root
reclaim:
onScaleDown: Delete
spec:
persistentVolumeClaim:
size: 30Gi
dataSource:
type: ObjectRef
objectRef:
kind: VirtualImage
name: ubuntu
# Переиспользуемый кеш, переживает уменьшение пула и переподключается при росте.
- name: cache
reclaim:
onScaleDown: Retain
keep: 5
ttl: 30m
spec:
persistentVolumeClaim:
size: 50Gi
EOFРеплики именуются <POOL>-<RANDOM>. Диски следуют той же схеме, и диск на реплику (Delete) называется <REPLICA>-<TEMPLATE> (например, runners-1b2e84-root), переиспользуемый (Retain) получает имя <POOL>-<TEMPLATE>-<RANDOM>. Посмотреть реплики можно через d8 k get vm -l vmpool.virtualization.deckhouse.io/pool=runners.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Пулы ВМ».
- Нажмите кнопку «Создать».
- В открывшемся окне «Создать ресурс» в поле «Имя» введите имя пула.
- На вкладке «Конфигурация» задайте число реплик в поле «Replicas» и политику удаления реплик в поле «Scale Down Policy».
- В блоке «Virtual Disk Templates» опишите диски реплик, в блоке «Virtual Machine Template» — шаблон виртуальной машины.
- Нажмите кнопку «Применить».
Форма пула построена по спецификации ресурса VirtualMachinePool, поэтому названия полей совпадают с параметрами ресурса. Готовую спецификацию можно вставить на вкладке «YAML».
Подключение общего CD-ROM (или любого общего образа) ко всем репликам
Помимо дисков реплики, в blockDeviceRefs можно сослаться на образы только для чтения, ClusterVirtualImage или VirtualImage. Такой образ общий, и все реплики подключают один и тот же файл, например ISO с инструментами или драйверами. В virtualDiskTemplates образы не перечисляются, потому что своей копии у реплики для них нет, и во взаимно однозначное соответствие с шаблонами они не входят.
Добавьте образ в blockDeviceRefs на нужную позицию в порядке загрузки. Установочный ISO поставьте перед диском, а CD-ROM с инструментами после него:
spec:
virtualMachineTemplate:
spec:
blockDeviceRefs:
- kind: VirtualDisk # Записываемый корневой диск на реплику, грузится первым.
name: root
- kind: ClusterVirtualImage # Общий CD-ROM только для чтения, подключается ко всем репликам.
name: tools-iso
virtualDiskTemplates:
- name: root
spec:
persistentVolumeClaim:
size: 30Gi
dataSource:
type: ObjectRef
objectRef:
kind: ClusterVirtualImage
name: ubuntuОбраз подключается к существующим репликам так же, как любое другое устройство. Изменение blockDeviceRefs применяется к работающей реплике при её следующем пересоздании, будь то обновление реплик или рост пула.
Масштабирование пула
Число реплик в пуле меняется вручную или автоматически, средствами автомасштабирования.
Пул поддерживает стандартный субресурс scale и публикует status.selector, поэтому HPA читает метрики CPU и памяти прямо с реплик без дополнительной обвязки.
Помимо процессора и памяти пул работает и с кастомными метриками (Pods/External через custom.metrics.k8s.io/external.metrics.k8s.io) и с KEDA, например для масштабирования по длине внешней очереди.
Поле spec.scaleDownPolicy определяет, какая реплика удаляется при безадресном сжатии:
NewestFirst— первыми удаляются самые молодые реплики;OldestFirst— первыми удаляются самые старые реплики;Explicit— безадресное сжатие запрещено; реплики можно убирать только по имени. Используйте, когда только вызывающая сторона знает, какую реплику можно безопасно убрать (например, простаивающую).
При scaleDownPolicy: Explicit автомасштабирование может только увеличивать число реплик, а безадресное сжатие через субресурс scale отклоняется.
- В командной строке
- В веб-интерфейсе
Чтобы изменить число реплик вручную, выполните:
d8 k scale virtualmachinepool/runners -n ci --replicas=8Пример настройки HPA для пула:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: runners
namespace: ci
spec:
scaleTargetRef:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachinePool
name: runners
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Пулы ВМ».
- Из списка выберите нужный пул и нажмите на его имя.
- На вкладке «Конфигурация» задайте новое значение в поле «Replicas».
- Нажмите кнопку «Применить».
- Ход масштабирования отображается в списке пулов в колонках «Статус» и «Готово».
Удаление конкретных реплик
По умолчанию при сжатии пула контроллер сам выбирает, какую реплику удалить.
Чтобы убрать именно заданные реплики (и сжать пул на это число), используйте субресурс scaleDownWith:
d8 k create --raw \
/apis/subresources.virtualization.deckhouse.io/v1alpha2/namespaces/ci/virtualmachinepools/runners/scaledownwith \
-f - <<'EOF'
{"targets": ["runners-1b2e84", "runners-9c0d11"]}
EOFОбычный d8 k delete vm пул не сжимает, потому что контроллер воспринимает это как утрату реплики и создаёт замену.
Переиспользуемые диски (reclaim)
Политика reclaim задаёт, что происходит с диском реплики при её удалении из пула.
Параметр reclaim.onScaleDown элемента virtualDiskTemplates определяет это поведение. reclaim необязателен; если не задан, диск считается Delete.
Delete(по умолчанию) — диск принадлежит виртуальной машине и удаляется вместе с ней; после реплики ничего не остаётся.Retain— диск принадлежит пулу, переживает реплику и переподключается к следующей при масштабировании вверх. Подходит для состояния, которое дорого пересоздавать и которое должно пережить пересоздание ВМ, чтобы возврат вверх был «тёплым», а не «холодным».
keep и ttl настраивают пул свободных Retain-дисков (применимы только к Retain):
keep— сколько недавно освободившихся дисков всегда держать тёплыми для мгновенного масштабирования вверх. На них не действуетttl.ttl— сколько свободный диск живёт сверх тёплого буфера до сборки мусором.
Примеры:
# Эфемерный диск: удаляется вместе с репликой (Delete по умолчанию).
- name: root
spec:
persistentVolumeClaim: { size: 30Gi }
dataSource: { type: ObjectRef, objectRef: { kind: VirtualImage, name: ubuntu } }
# Переиспользуемый диск. Три остаются наготове для быстрого роста пула, остальные освобождаются через 1h простоя.
- name: cache
reclaim:
onScaleDown: Retain
keep: 3
ttl: 1h
spec:
persistentVolumeClaim: { size: 100Gi }
# Переиспользуемый диск без ограничения: переиспользуется всегда, не удаляется автоматически (нет ttl).
- name: data
reclaim:
onScaleDown: Retain
spec:
persistentVolumeClaim: { size: 20Gi }Неверные комбинации отклоняются при создании и изменении. Параметры keep и ttl допустимы только с Retain, а keep > 0 требует ttl, потому что без ttl ничего не собирается и keep ни на что не влияет. Retain-диск без ttl хранит все освободившиеся диски бессрочно; ограничивайте ttl, если это не то, что нужно.
Ограничения и особенности пула
Ниже перечислены ограничения и неочевидное поведение пула, о которых стоит помнить при эксплуатации.
- Удаление записи из
virtualDiskTemplatesудаляет её диски. ДляRetain-дисков это уничтожает переиспользуемые данные, поэтому убирайте шаблон только когда он больше не нужен. - Пул поддерживает число реплик, а не их работоспособность. Существующая, но неисправная машина не пересоздаётся, её восстанавливает перезапуск на уровне самой машины. Остановленная реплика сохраняется, а не заменяется, и пересоздаётся только полностью удалённая.
- Диски с политикой
Retainобщие между репликами. При росте пула новая реплика может получить освободившийся диск другой реплики вместе с его данными, жёсткой привязки между репликой и диском нет. - Изменение
virtualDiskTemplates[].specвлияет только на новые диски, кромеsize, который увеличивает существующие (уменьшать нельзя).dataSource,storageClassNameи прочее к уже созданным дискам не применяются. - У каждой реплики своя копия каждого диска из
virtualDiskTemplates. Общий образ только для чтения, VirtualImage или ClusterVirtualImage, например единый ISO, можно подключить ко всем репликам, перечислив его вblockDeviceRefsшаблона, а записываемый диск между репликами не разделяется. - Правка
blockDeviceRefsв шаблоне, будь то перестановка, добавление или удаление общего образа, применяется к новым репликам. Работающие реплики сохраняют текущие устройства до пересоздания, как и при других изменениях шаблона, требующих перезапуска. - Изменения шаблона, требующие перезапуска, применяются только после перезапуска реплики согласно
.spec.disruptions.restartApprovalModeв шаблоне.
GPU-устройства
Проброс GPU-устройств — экспериментальная возможность, доступная в коммерческих редакциях DP.
DP подключает физические GPU-устройства к виртуальным машинам с помощью DRA (Dynamic Resource Allocation). Устройство запрашивается по ссылке на GPUClass в блоке .spec.gpus ресурса VirtualMachine.
Ресурсы GPUClass готовит администратор, поэтому узнайте у него, какие классы доступны в кластере.
Чтобы запросить GPU-устройство, добавьте блок .spec.gpus в спецификацию машины:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachine
metadata:
name: linux-vm
spec:
# ... другие настройки ВМ ...
gpus:
- gpuClassName: nvidia-h100В параметре gpuClassName укажите имя существующего ресурса GPUClass. Чтобы подключить несколько устройств, добавьте в список ещё элементы, порядок в нём не важен. К одной машине подключается не более 16 устройств.
Изменение блока .spec.gpus применяется только после перезапуска виртуальной машины.
USB-устройства
Проброс USB-устройств доступен в коммерческих редакциях DP.
DP поддерживает проброс USB-устройств в виртуальные машины (ВМ) с использованием DRA (Dynamic Resource Allocation). Физическое устройство подключено к узлу кластера, а виртуальная машина работает с ним так, как будто устройство подключено напрямую к ней.
Администратор подключает устройство к узлу и делает его доступным вашему неймспейсу. После этого в неймспейсе появляется ресурс USBDevice, который вы подключаете к виртуальной машине. Если нужного устройства в списке нет, обратитесь к администратору.
Требования к узлам и версиям кластера обеспечивает администратор, от вас они не зависят.
Устройства проекта (USBDevice)
USBDevice — namespaced-ресурс, представляющий USB-устройство, доступное для подключения к виртуальным машинам в заданном неймспейсе. Появляется автоматически после того, как администратор назначит устройство неймспейсу.
Пример просмотра USB-устройств в неймспейсе:
d8 k get usbdevice -n my-projectПример вывода:
NAME NODE MANUFACTURER PRODUCT ATTACHED AGE
logitech-webcam node-2 Logitech Webcam C920 False 10m
Идентификаторы производителя и продукта, шину, номер устройства, серийный номер, скорость и остальные сведения об устройстве ресурс хранит в блоке .status.attributes.
Условия USBDevice
Состояние устройства описывают два условия в блоке .status.conditions.
Условие Ready показывает, готово ли устройство к использованию, и принимает одну из причин:
Ready— устройство готово к использованию;NotReady— устройство существует, но не готово;NotFound— устройство отсутствует на узле.
Условие Attached показывает, подключено ли устройство к виртуальной машине:
AttachedToVirtualMachine— устройство подключено к ВМ;Available— устройство свободно и его можно подключить;DetachedForMigration— устройство отключено на время миграции ВМ и подключится снова на целевом узле;NoFreeUSBIPPort— устройство запрошено виртуальной машиной, но на целевом узле не осталось свободных USBIP-портов, поэтому условие имеет статусFalse.
Подключение USB-устройства к ВМ
Устройство подключается к машине и отключается от неё без её остановки. USB-устройство автоматически пробрасывается по сети (USBIP) на узел, где запущена машина, поэтому размещать машину на узле с устройством вручную не нужно.
Во время миграции ВМ USB-устройство ненадолго отключится и подключится на новом узле в момент переключения машины. При сбое миграции устройство останется на старом узле.
- В командной строке
- В веб-интерфейсе
Добавьте устройство в параметр .spec.usbDevices ресурса VirtualMachine:
d8 k apply -f - <<EOF
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachine
metadata:
name: linux-vm
spec:
# ... другие настройки ВМ ...
usbDevices:
- name: logitech-webcam
EOFПосле создания или обновления ВМ USB-устройство будет подключено к указанной виртуальной машине.
Инфраструктурные требования, лимиты USBIP-портов и обнаружение устройств на узлах описаны в руководстве администратора.
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу до раздела «USB-устройства» и нажмите кнопку «Добавить».
- В открывшемся окне «Подключить USB-устройство» в поле «Выберите USB-устройство» выберите устройство и нажмите кнопку «Добавить».
- Нажмите появившуюся кнопку «Сохранить».
Доступные в проекте USB-устройства отображаются в разделе «Виртуализация» → «USB-устройства»: имя ресурса, статус, производитель, продукт, серийный номер, узел, шина и номер устройства.
PCI-устройства
Проброс PCI-устройств доступен в коммерческих редакциях DP.
Проброс PCI-устройств позволяет использовать в виртуальной машине (ВМ) физическое устройство узла, например промышленный контроллер, аппаратный модуль безопасности, плату видеозахвата или ПЛИС. Устройство работает в гостевой операционной системе под её собственным драйвером, поэтому установите этот драйвер в гостевой системе самостоятельно.
Устройства выдаёт проекту администратор, он же обеспечивает требования к узлам и версиям кластера.
Подключение PCI-устройства к ВМ
Устройства, которые администратор предоставил вашему проекту, доступны в неймспейсе как ресурсы PCIDevice. Чтобы подключить такое устройство к машине, выполните следующие шаги.
-
Выберите устройство среди доступных:
d8 k get pcidevice -n my-projectПример вывода:
NAME NODE ADDRESS ATTACHED AGE pci-4f2c0b1e8d9a3c5b7e1f0a2d4c6b8e0f1a3c5d7e node-1 0000:3b:00.0 False 10mЕсли список пуст, обратитесь к администратору, чтобы он назначил устройство вашему неймспейсу.
-
Добавьте устройство в параметр
.spec.pciDevicesресурса VirtualMachine:d8 k apply -f - <<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: linux-vm spec: # ... другие настройки ВМ ... pciDevices: - name: pci-4f2c0b1e8d9a3c5b7e1f0a2d4c6b8e0f1a3c5d7e EOFУстройства подключаются при запуске машины, поэтому изменение этого параметра требует её перезапуска.
-
Убедитесь, что устройство подключено к машине:
d8 k get vm linux-vm -o jsonpath='{.status.pciDevices}'Значение
trueв полеreadyозначает, что устройство доступно, а значениеtrueв полеattachedозначает, что устройство подключено к работающей машине. После запуска машины устройство появляется в гостевой системе, например в выводе командыlspci.
Чтобы отключить устройство, уберите его из параметра .spec.pciDevices и перезапустите машину. До этого устройство остаётся занятым, даже если машина остановлена, поэтому подключить его к другой машине нельзя.
Если устройство извлечено из узла, машина не запускается и остаётся в фазе Pending. В параметре .status.pciDevices такое устройство перестаёт быть готовым, но остаётся у машины, пока указано в её спецификации. Работающую машину DP при этом не останавливает, в том числе когда устройство стало недоступно проекту.
Ограничения
Подключая PCI-устройства, учитывайте следующие ограничения:
- машина с PCI-устройством запускается только на узле этого устройства и живой миграцией не переносится, поэтому при выводе узла на обслуживание её придётся остановить;
- все PCI-устройства одной машины должны находиться на одном узле, иначе спецификация будет отклонена;
- устройство подключается только к одной машине. Если оно уже указано в спецификации другой, DP отклонит вашу спецификацию;
- к одной машине подключается не более восьми PCI-устройств;
- проброшенная сетевая карта работает в обход сетевой подсистемы кластера. Она не отражается в параметре
.spec.networks, а адреса IP и MAC на ней DP не выдаёт и не учитывает.