Установка ОС в виртуальной машине из ISO-образа
Рассмотрим пример установки ОС из ISO-образа ОС Windows. Для этого загрузите и опубликуйте его на каком-либо HTTP-сервисе, доступном из кластера.
-
Создайте пустой диск для установки ОС:
apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: win-disk namespace: default spec: persistentVolumeClaim: size: 100Gi storageClassName: local-path -
Создайте ресурсы с ISO-образами ОС Windows и драйверами virtio:
apiVersion: virtualization.deckhouse.io/v1alpha2 kind: ClusterVirtualImage metadata: name: win-11-iso spec: dataSource: type: HTTP http: url: "http://example.com/win11.iso"apiVersion: virtualization.deckhouse.io/v1alpha2 kind: ClusterVirtualImage metadata: name: win-virtio-iso spec: dataSource: type: HTTP http: url: "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso" -
Создайте виртуальную машину:
apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: win-vm namespace: default labels: vm: win spec: virtualMachineClassName: generic runPolicy: Manual osType: Windows bootloader: EFI cpu: cores: 6 coreFraction: 50% memory: size: 8Gi enableParavirtualization: true blockDeviceRefs: - kind: VirtualDisk name: win-disk - kind: ClusterVirtualImage name: win-11-iso - kind: ClusterVirtualImage name: win-virtio-iso -
После создания ресурса запустите ВМ:
d8 v vnc -n default win-vm -
К ней необходимо подключиться и с помощью графического установщика и выполнить установку ОС и драйверов
virtio:d8 v vnc -n default win-vm -
После окончания установки перезагрузите виртуальную машину.
-
Для продолжения работы с виртуальной машиной также используйте команду:
d8 v vnc -n default win-vm
Предоставление файла ответов Windows (Sysprep)
Чтобы выполнить автоматическую установку Windows, создайте файл ответов (обычно именуются unattend.xml или autounattend.xml). Для примера возьмем файл, позволяющий:
- Добавить русский язык и раскладку;
- Указать расположение virtio драйверов, необходимых для установки (поэтому важен порядок дисковых устройств в спецификации ВМ);
- Разметить диски для установки Windows на ВМ c EFI;
- Создать в группе администраторов пользователя cloud с паролем cloud;
- Создать непривилегированного пользователя user с паролем user.
Создайте секрет из этого xml файла:
d8 k create secret generic sysprep-config --type="provisioning.virtualization.deckhouse.io/sysprep" --from-file=./autounattend.xml
Затем можно создать виртуальную машину, которая в процессе установки будет использовать файл ответов. Чтобы предоставить виртуальной машине Windows файл ответов, необходимо указать provisioning с типом SysprepRef. Вы также можете указать здесь другие файлы в формате Base64 (customize.ps1, id_ed25519.pub,…), необходимые для успешного выполнения скриптов внутри файла ответов.
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachine
metadata:
name: win-vm
namespace: default
labels:
vm: win
spec:
virtualMachineClassName: generic
provisioning:
type: SysprepRef
sysprepRef:
kind: Secret
name: sysprep-config
runPolicy: AlwaysOn
osType: Windows
bootloader: EFI
cpu:
cores: 6
coreFraction: 50%
memory:
size: 8Gi
enableParavirtualization: true
blockDeviceRefs:
- kind: VirtualDisk
name: win-disk
- kind: ClusterVirtualImage
name: win-11-iso
- kind: ClusterVirtualImage
name: win-virtio-iso
Использование cloud-init для настройки виртуальных машин
Cloud-Init — это инструмент для автоматической настройки виртуальных машин при первом запуске. Конфигурация записывается в формате YAML и должна начинаться с заголовка #cloud-config.
Обновление и установка пакетов
Пример конфигурации для обновления системы и установки пакетов:
#cloud-config
# Обновить списки пакетов
package_update: true
# Обновить установленные пакеты до последних версий
package_upgrade: true
# Список пакетов для установки
packages:
- nginx
- curl
- htop
# Команды для выполнения после установки пакетов
runcmd:
- systemctl enable --now nginx.service
Создание пользователя
Пример конфигурации для создания пользователя с паролем и SSH-ключом:
#cloud-config
# Список пользователей для создания
users:
- name: cloud # Имя пользователя
passwd: "$6$rounds=4096$saltsalt$..." # Хеш пароля (SHA-512)
lock_passwd: false # Не блокировать учетную запись
sudo: ALL=(ALL) NOPASSWD:ALL # Права sudo без запроса пароля
shell: /bin/bash # Оболочка по умолчанию
ssh-authorized-keys: # SSH-ключи для доступа
- ssh-ed25519 AAAAC3NzaC... your-public-key ...
# Разрешить аутентификацию по паролю через SSH
ssh_pwauth: true
Для генерации хеша пароля используйте команду mkpasswd --method=SHA-512 --rounds=4096.
Создание файла с нужными правами
Пример конфигурации для создания файла с заданными правами доступа:
#cloud-config
# Список файлов для создания
write_files:
- path: /opt/scripts/start.sh # Путь к файлу
content: | # Содержимое файла
#!/bin/bash
echo "Starting application"
owner: cloud:cloud # Владелец файла (пользователь:группа)
permissions: '0755' # Права доступа (восьмеричный формат)
Настройка диска и файловой системы
Пример конфигурации для разметки диска, создания файловой системы и монтирования:
#cloud-config
# Настройка разметки диска
disk_setup:
/dev/sdb: # Устройство диска
table_type: gpt # Тип таблицы разделов (gpt или mbr)
layout: true # Автоматически создать разделы
overwrite: false # Не перезаписывать существующие разделы
# Настройка файловых систем
fs_setup:
- label: data # Лейбл файловой системы
filesystem: ext4 # Тип файловой системы
device: /dev/sdb1 # Устройство раздела
partition: auto # Автоматически определить раздел
# Монтирование файловых систем
mounts:
# [устройство, точка_монтирования, тип_ФС, опции, dump, pass]
- ["/dev/sdb1", "/mnt/data", "ext4", "defaults", "0", "2"]
Использование Ansible для настройки виртуальных машин
Ansible — это инструмент автоматизации, который позволяет выполнять задачи на удаленных серверах с использованием протокола SSH. В данном примере мы рассмотрим, как использовать Ansible для управления виртуальными машинами расположенных в проекте demo-app.
В рамках примера предполагается, что:
- у вас есть виртуальная машина с именем
frontendв проектеdemo-app; - на виртуальной машине создан пользователь
cloudдля доступа по SSH; - приватный SSH-ключ пользователя хранится в файле
/home/user/.ssh/id_rsaна сервере Ansible.
Пример файла inventory:
---
all:
vars:
ansible_ssh_common_args: '-o ProxyCommand="d8 v port-forward --stdio=true %h %p"'
# Пользователь по умолчанию, для доступа по SSH.
ansible_user: cloud
# Путь к приватному ключу.
ansible_ssh_private_key_file: /home/user/.ssh/id_rsa
hosts:
# Название узла в формате <название ВМ>.<название проекта>.
frontend.demo-app:
Чтобы проверить значение аптайма виртуальной машины, используйте следующую команду:
ansible -m shell -a "uptime" -i inventory.yaml all
Пример вывода:
frontend.demo-app | CHANGED | rc=0 >>
12:01:20 up 2 days, 4:59, 0 users, load average: 0.00, 0.00, 0.00
Если вы не хотите использовать файл inventory, можно передать все параметры прямо в командной строке:
ansible -m shell -a "uptime" \
-i "frontend.demo-app," \
-e "ansible_ssh_common_args='-o ProxyCommand=\"d8 v port-forward --stdio=true %h %p\"'" \
-e "ansible_user=cloud" \
-e "ansible_ssh_private_key_file=/home/user/.ssh/id_rsa" \
all
Как автоматически сгенерировать inventory для Ansible?
Для использования команды d8 v ansible-inventory требуется версия d8 v0.27.0 или выше.
Команда работает только для виртуальных машин, у которых подключена основная сеть кластера (Main).
Вместо ручного создания inventory-файла можно использовать команду d8 v ansible-inventory, которая автоматически генерирует инвентарь Ansible из виртуальных машин в указанном неймспейсе. Команда совместима с интерфейсом ansible inventory script.
Команда включает в инвентарь только виртуальные машины с назначенными IP-адресами в состоянии Running. Имена хостов формируются в формате <vmname>.<namespace> (например, frontend.demo-app).
При необходимости настройте переменные хоста через аннотации (например, пользователя для SSH):
d8 k -n demo-app annotate vm frontend provisioning.virtualization.deckhouse.io/ansible_user="cloud"
Используйте команду напрямую:
ANSIBLE_INVENTORY_ENABLED=yaml ansible -m shell -a "uptime" all -i <(d8 v ansible-inventory -n demo-app -o yaml)
Конструкция <(...) необходима, потому что Ansible ожидает файл или скрипт в качестве источника списка хостов. Простое указание команды в кавычках не сработает — Ansible попытается выполнить строку как скрипт. Конструкция <(...) передаёт вывод команды как файл, который Ansible может прочитать.
Или сохраните инвентарь в файл:
d8 v ansible-inventory --list -o yaml -n demo-app > inventory.yaml
ansible -m shell -a "uptime" -i inventory.yaml all
Перенаправление трафика на виртуальную машину
Виртуальная машина функционирует в кластере Kubernetes, поэтому направление сетевого трафика к ней осуществляется аналогично направлению трафика к подам. Для маршрутизации сетевого трафика на виртуальную машину применяется стандартный механизм Kubernetes — ресурс Service, который выбирает целевые объекты по лейблам (label selector).
-
Создайте сервис с требуемыми настройками.
В качестве примера приведена виртуальная машина с лейблом
vm: frontend-0, HTTP-сервисом, опубликованным на портах 80 и 443, и открытым SSH на порту 22:apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: frontend-0 namespace: dev labels: vm: frontend-0 spec: ... -
Чтобы направить сетевой трафик на порты виртуальной машины, создайте Service:
Следующий Service обеспечивает доступ к виртуальной машине: он слушает порты 80 и 443 и перенаправляет трафик на соответствующие порты целевой виртуальной машины. SSH-доступ извне предоставляется по порту 2211:
apiVersion: v1 kind: Service metadata: name: frontend-0-svc namespace: dev spec: type: LoadBalancer ports: - name: ssh port: 2211 protocol: TCP targetPort: 22 - name: http port: 80 protocol: TCP targetPort: 80 - name: https port: 443 protocol: TCP targetPort: 443 selector: vm: frontend-0
Изменение лейблов виртуальной машины без необходимости перезапуска
Можно изменять лейблы виртуальной машины без необходимости перезапуска, что позволяет настраивать перенаправление сетевого трафика между различными сервисами в реальном времени.
Предположим, что был создан новый сервис и требуется перенаправить трафик на виртуальную машину от этого сервиса:
apiVersion: v1
kind: Service
metadata:
name: svc-2
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 80
selector:
app: new
При изменении лейбла на виртуальной машине, трафик с сервиса svc-2 будет перенаправлен на виртуальную машину:
metadata:
labels:
app: old