Модуль находится в процессе активного развития. Функциональность может существенно измениться.
Быстрый старт
Пример создания виртуальной машины с Ubuntu 22.04.
Создадим namespace, где будем создавать виртуальные машины:
kubectl create ns vms
Создадим диск виртуальной машины из внешнего источника:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineDisk
metadata:
name: linux-disk
namespace: vms
spec:
persistentVolumeClaim:
size: 10Gi
storageClassName: local-path
dataSource:
type: HTTP
http:
url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img"
После создания VirtualMachineDiks
в namespace vms, запустится под с именем importer-*
, который осуществит загрузку заданного образа.
Посмотрим на текущий статус ресурса:
kubectl -n vms get virtualmachinedisk -o wide
# NAME PHASE CAPACITY PROGRESS TARGET PVC AGE
# linux-disk Ready 10Gi 100% vmd-vmd-blank-001-10c7616b-ba9c-4531-9874-ebcb3a2d83ad 1m
Далее создадим виртуальную машину из следующей спецификации:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachine
metadata:
name: linux-vm
namespace: vms
labels:
vm: linux
spec:
runPolicy: AlwaysOn # Виртуальная машина должна быть всегда включена.
enableParavirtualization: true # Использовать паравиртуализацию (virtio).
osType: Generic
bootloader: BIOS
cpu:
cores: 1
coreFraction: 10% # Запросить 10% процессорного времени одного ядра.
memory:
size: 1Gi
provisioning: # Пример cloud-init-сценария для создания пользователя cloud с паролем cloud.
type: UserData
userData: |
#cloud-config
users:
- name: cloud
passwd: $6$rounds=4096$vln/.aPHBOI7BMYR$bBMkqQvuGs5Gyd/1H5DP4m9HjQSy.kgrxpaGEHwkX7KEFV8BS.HZWPitAtZ2Vd8ZqIZRqmlykRCagTgPejt1i.
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
chpasswd: { expire: False }
lock_passwd: false
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTXjTmx3hq2EPDQHWSJN7By1VNFZ8colI5tEeZDBVYAe9Oxq4FZsKCb1aGIskDaiAHTxrbd2efoJTcPQLBSBM79dcELtqfKj9dtjy4S1W0mydvWb2oWLnvOaZX/H6pqjz8jrJAKXwXj2pWCOzXerwk9oSI4fCE7VbqsfT4bBfv27FN4/Vqa6iWiCc71oJopL9DldtuIYDVUgOZOa+t2J4hPCCSqEJK/r+ToHQbOWxbC5/OAufXDw2W1vkVeaZUur5xwwAxIb3wM3WoS3BbwNlDYg9UB2D8+EZgNz1CCCpSy1ELIn7q8RnrTp0+H8V9LoWHSgh3VCWeW8C/MnTW90IR
blockDevices:
- type: VirtualMachineDisk
virtualMachineDisk:
name: linux-disk
Проверим, что виртуальная машина создана и запущена:
kubectl -n default get virtualmachine
# NAME PHASE NODENAME IPADDRESS AGE
# linux-vm Running virtlab-1 10.66.10.1 5m
Подключимся к виртуальной машине с использованием консоли (для выхода из консоли необходимо нажать Ctrl+]
):
dvp console -n vms linux-vm
Подключимся к машине с использованием VNC:
dvp vnc -n vms linux-vm
После выполнения команды запустится VNC-клиент, используемый в системе по умолчанию. Альтернативный способ подключения — с помощью параметра --proxy-only
пробросить VNC-порт на локальную машину.
Образы
VirtualMachineImage
и ClusterVirtualMachineImage
предназначены для хранения образов дисков виртуальных машин или установочных образов в формате iso
, чтобы создавать и однотипно воспроизводить диски виртуальных машин. При подключении к виртуальной машине эти образы доступны только для чтения, и установочный образ в формате iso
будет подключен в виде cdrom-устройства.
Ресурс VirtualMachineImage
доступен только в том пространстве имен, в котором он был создан, а ClusterVirtualMachineImage
доступен для всех пространств имен внутри кластера.
В зависимости от конфигурации, ресурс VirtualMachineImage
может хранить данные в DVCR
или использовать дисковое хранилище, предоставляемое платформой (PV). С другой стороны, ClusterVirtualMachineImage
хранит данные только в DVCR
, обеспечивая единый доступ ко всем образам для всех пространств имен в кластере.
Рассмотрим на примерах создание этих ресурсов.
Создание и использование образа c HTTP-ресурса
Создадим VirtualMachineImage
и в качестве хранилища образов будем использовать DVCR
:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineImage
metadata:
name: ubuntu-img
namespace: vms
spec:
storage: ContainerRegistry
dataSource:
type: HTTP
http:
url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img"
Посмотрим, что получилось:
kubectl -n vms get virtualmachineimage
# NAME PHASE CDROM PROGRESS AGE
# ubuntu-img Ready false 100% 10m
Для хранения образа в дисковом хранилище, предоставляемом платформой, настройки storage
будут выглядеть следующим образом:
spec:
storage: Kubernetes
persistentVolumeClaim:
storageClassName: "your-storage-class-name"
где your-storage-class-name
— это название StorageClass, который будет использоваться.
Для просмотра списка доступных StorageClass’ов выполните следующую команду:
kubectl get storageclass
# Пример вывода команды:
# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
# linstor-thin-r1 linstor.csi.linbit.com Delete WaitForFirstConsumer true 20d
# linstor-thin-r2 linstor.csi.linbit.com Delete WaitForFirstConsumer true 20d
# linstor-thin-r3 linstor.csi.linbit.com Delete WaitForFirstConsumer true 20d
Ресурс ClusterVirtualMachineImage
создается по аналогии, но не требует указания настроек storage
:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: ClusterVirtualMachineImage
metadata:
name: ubuntu-img
spec:
dataSource:
type: HTTP
http:
url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img"
Просмотрим статус ClusterVirtualMachineImage
:
kubectl get clustervirtualmachineimage
# NAME PHASE CDROM PROGRESS AGE
# ubuntu-img Ready false 100% 11m
Образы могут быть созданы из различных внешних источников, таких как HTTP-сервер, где размещены файлы образов или контейнерный реестр (container registry), где образы хранятся и доступны для загрузки. Кроме того, возможно загрузить образы напрямую из командной строки, используя утилиту curl. Давайте рассмотрим каждый из этих вариантов более подробно.
Создание и использование образа из container registry
Первое, что необходимо, — это сформировать сам образ для хранения в container registry.
В качестве примера рассмотрим вариант создания docker-образа c диском Ubuntu 22.04.
Загрузим образ локально:
curl -L https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img -o ubuntu2204.img
Создадим Dockerfile со следующим содержимым:
FROM scratch
COPY ubuntu2204.img /disk/ubuntu2204.img
Соберем образ и загрузим его в container registry. В качестве container registry будем использовать docker.io, для этого вам необходимо иметь учетную запись сервиса и настроенное окружение.
docker build -t docker.io/username/ubuntu2204:latest
где username
— ваше имя пользователя, указанное при регистрации в docker.io.
Загрузим созданный образ в container registry:
docker push docker.io/username/ubuntu2204:latest
Чтобы использовать этот образ, создадим в качестве примера ресурс ClusterVirtualMachineImage
:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: ClusterVirtualMachineImage
metadata:
name: ubuntu-2204
spec:
dataSource:
type: ContainerImage
containerImage:
image: docker.io/username/ubuntu2204:latest
Чтобы посмотреть ресурс и его статус, выполните команду:
kubectl get clustervirtalmachineimage
Загрузка образа из командной строки
Чтобы загрузить образ из командной строки, нам предварительно нужно создать следующий ресурс, рассмотрим на примере ClusterVirtualMachineImage
:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: ClusterVirtualMachineImage
metadata:
name: some-image
spec:
dataSource:
type: Upload
После того как ресурс будет создан, посмотрим его статус:
kubectl get clustervirtualmachineimages some-image -o json | jq .status.uploadCommand -r
> uploadCommand: curl https://virtualization.example.com/upload/dSJSQW0fSOerjH5ziJo4PEWbnZ4q6ffc
-T example.iso
Стоит отметить, что CVMI с типом Upload ожидает начала загрузки образа 15 минут после создания. По истечении данного таймаута ресурс перейдет в состояние Failed.
Загрузим для примера образ Cirros и загрузим его:
curl -L http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img -o cirros.img
https://virtualization.example.com/upload/dSJSQW0fSOerjH5ziJo4PEWbnZ4q6ffc -T cirros.img
После завершения работы команды curl
образ должен быть создан.
Проверить, что все прошло успешно, можно, проверив статус созданного образа:
kubectl get clustervirtualmachineimages
# NAME PHASE CDROM PROGRESS AGE
# some-image Ready false 100% 10m
Диски
Диски используются в виртуальных машинах для записи и хранения данных. Для хранения дисков используется хранилище, предоставляемое платформой.
Чтобы посмотреть доступные варианты, выполните команду:
kubectl get storageclass
Рассмотрим варианты, какие диски мы можем создавать:
Создание пустого диска
Первое, что стоит отметить, — это то, что диски мы можем создавать пустыми!
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineDisk
metadata:
name: vmd-blank
spec:
persistentVolumeClaim:
storageClassName: "your-storage-class-name"
size: 100M
После создания диска мы его можем использовать для подключения к виртуальной машине.
Посмотреть состояние созданного ресурса можно командой:
kubectl get virtualmachinedisk
# NAME PHASE CAPACITY AGE
# vmd-blank Ready 100Mi 1m
Создание диска из образа
Мы можем создавать диски, используя уже имеющиеся образы дисков, а также внешние источники, подобно образам.
При создании ресурса диска мы можем указать желаемый размер. Если размер не указан, то будет создан диск с размером, соответствующим исходному образу диска, который хранится в ресурсе VirtualMachineImage
или ClusterVirtualMachineImage
. Если необходимо создать диск большего размера, необходимо явно указать это.
В качестве примера используем ранее созданный ClusterVirtualMachineImage
с именем ubuntu-2204
:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineDisk
metadata:
name: ubuntu-root
spec:
persistentVolumeClaim:
size: 10Gi
storageClassName: "your-storage-class-name"
dataSource:
type: ClusterVirtualMachineImage
clusterVirtualMachineImage:
name: ubuntu-img
Изменение размера диска
Размер дисков можно менять (пока только в сторону увеличения), даже если они подключены к виртуальной машине, для этого необходимо отредактировать поле spec.persistentVolumeClame.size
:
kubectl patch ubuntu-root --type merge -p '{"spec":{"persistentVolumeClaim":{"size":"11Gi"}}}'
Подключение дисков к запущенным виртуальным машинам
Диски можно подключать «на живую», к уже запущенной виртуальной машине, для этого используется ресурс VirtualMachineBlockDeviceAttachment
, например:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineBlockDeviceAttachment
metadata:
name: vmd-blank-attachment
spec:
virtualMachineName: linux-vm # Имя виртуальной машины, к которой будет подключен диск.
blockDevice:
type: VirtualMachineDisk
virtualMachineDisk:
name: vmd-blank # Имя подключаемого диска.
Если изменить имя машины в этом ресурсе на имя другой машины, диск будет переподключен от одной виртуальной машины к другой.
При удалении ресурса VirtualMachineBlockDeviceAttachment
диск от виртуальной машины будет отключен.
Чтобы посмотреть список подключенных «на живую» дисков, выполните команду:
kubectl get virtualmachineblockdeviceattachments
Виртуальные машины
Итак, теперь у нас есть диски и образы, перейдем к самому главному — созданию виртуальной машины.
Для создания виртуальной машины используется ресурс VirtualMachine
, его параметры позволяют сконфигурировать:
- ресурсы, требуемые для работы виртуальной машины (процессор, память, диски и образы);
- правила размещения виртуальной машины на узлах кластера;
- настройки загрузчика и оптимальные параметры для гостевой ОС;
- политику запуска виртуальной машины и политику применения изменений;
- сценарии начальной конфигурации (cloud-init).
Cоздадим виртуальную машину и настроим ее по шагам:
0. Создание диска для виртуальной машины
Первое, что нужно, прежде чем создавать ресурс виртуальной машины, — это создать диск с установленной ОС.
Создадим диск для виртуальной машины:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineDisk
metadata:
name: ubuntu-2204-root
spec:
persistentVolumeClaim:
size: 10Gi
dataSource:
type: HTTP
http:
url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img"
1. Создание виртуальной машины
Ниже представлен пример простейшей конфигурации виртуальной машины, запускающей ОС Ubuntu 22.04. В примере используется сценарий первичной инициализации виртуальной машины (cloud-init), который устанавливает пакет nginx и создает пользователя cloud
с паролем cloud
:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachine
metadata:
name: linux-vm
namespace: default
labels:
vm: linux
spec:
runPolicy: AlwaysOn
provisioning:
type: UserData
userData: |
#cloud-config
package_update: true
packages:
- nginx
run_cmd:
- systemctl daemon-relaod
- systemctl enable --now nginx
users:
- name: cloud
# password: cloud
passwd: $6$rounds=4096$vln/.aPHBOI7BMYR$bBMkqQvuGs5Gyd/1H5DP4m9HjQSy.kgrxpaGEHwkX7KEFV8BS.HZWPitAtZ2Vd8ZqIZRqmlykRCagTgPejt1i.
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
chpasswd: { expire: False }
lock_passwd: false
cpu:
cores: 1
memory:
size: 2Gi
blockDevices:
# Порядок дисков и образов в данном блоке определяет приоритет загрузки.
- type: VirtualMachineDisk
virtualMachineDisk:
name: ubuntu-2204-root
При наличии каких-то приватных данных сценарий начальной инициализации виртуальной машины может быть создан в Secret’е.
Пример Secret’а:
apiVersion: v1
kind: Secret
metadata:
name: linux-vm-cloud-init
namespace: default
data:
userData: # Тут cloud-init-конфиг в Base64.
type: Opaque
Как это будет выглядеть в спецификации виртуальной машины:
spec:
provisioning:
type: UserDataSecret
userDataSercertRef:
name: linux-vm-cloud-init
Создадим виртуальную машину из манифеста выше.
После запуска виртуальня машина должна быть в статусе Ready
.
kubectl get virtualmachine
# NAME PHASE NODENAME IPADDRESS AGE
# linux-vm Running node-name-x 10.66.10.1 5m
После создания виртуальная машина автоматически получит IP-адрес из диапазона, указанного в настройках модуля (блок virtualMachineCIDRs
).
Если мы хотим зафиксировать конкретный IP-адрес для машины перед ее запуском, необходимо выполнить следующие шаги:
- Создать ресурс
VirtualMachineIPAddressClaim
, в котором зафиксировать желаемый IP-адрес виртуальной машины:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineIPAddressClaim
metadata:
name: <claim-name>
namespace: <namespace>
spec:
address: "W.X.Y.Z"
- Соответствующим образом зафиксировать изменения в спецификации виртуальной машины:
spec:
virtualMachineIPAddressClaimName: <claim-name>
2. Настройка правил размещения виртуальной машины
Допустим, нам необходимо, чтобы виртуальная машина запускалась на заданном наборе узлов, например на группе узлов system
. В этом нам поможет следующий фрагмент конфигурации:
spec:
tolerations:
- key: "node-role.kubernetes.io/system"
operator: Exists
effect: NoSchedule
nodeSelector:
node-role.kubernetes.io/system: ""
Внесите изменения в ранее созданную спецификацию виртуальной машины.
3. Настройка порядка применения изменений
После внесения изменений в конфигурацию машины ничего не произойдет, так как по умолчанию применяется политика применения изменений Manual
, а это значит, что изменения нужно подтвердить.
Как мы можем это понять?
Посмотрим на статус VM:
kubectl get linux-vm -o jsonpath='{.status}'
В поле .status.pendingChanges
мы увидим изменения, которые требуют применения. В поле .status.message
сообщение, о том что для применения требуемых изменений необходим рестарт виртуальной машины.
Создадим и применим следующий ресурс, от отвечает за декларативный способ управления состоянием виртуальной машины:
cat <<EOF | kubectl apply -f -
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachineOperation
metadata:
name: restart
spec:
virtualMachineName: linux-vm
type: Restart
EOF
Посмотрим за состоянием созданного ресурса:
kubectl get vmops restart
# NAME PHASE VMNAME AGE
# restart Completed linux-vm 1m
Как только он перейдет в состояние Completed
- перезагрузка виртуальной машины завершилась, и новые параметры конфигурации виртуальной машины - применены.
Что делать, если мы хотим, чтобы изменения требуемые перезагрузки виртуальной машины применялись автоматически? Для этого необходимо сконфигурировать политику применения изменений следующим образом:
spec:
disruptions:
approvalMode: Automatic
4. Политика запуска виртуальной машины
Подключимся к виртуальной машине с использованием серийной консоли:
dvp console -n default linux-vm
Завершим работу виртуальной машины:
cloud@linux-vm$ sudo poweroff
Далее посмотрим на статус виртуальной машины:
kubectl get virtualmachine
# NAME PHASE NODENAME IPADDRESS AGE
# linux-vm Running node-name-x 10.66.10.1 5m
Виртуальная машина снова запущена! Но почему так произошло?
Во отличие от классических систем виртуализации, для определения состояния виртуальной машины мы используем политику запуска, которая определяет желаемое состояние виртуальной машины в любой момент времени.
При создании виртуальной машины мы указали параметр runPolicy: AlwaysOn
, а это значит, что виртуальная машина должна быть запущена, даже если по какой-то причине произошло ее выключение, рестарт или сбой, повлекший завершение ее работы.
Чтобы выключить машину, поменяем значение политики на AlwaysOff
, при этом произойдет корректное завершение работы виртуальной машины.