понедельник, 16 сентября 2024 г.

Делаем собственные шаблоны апплайнсов для oVirt

Аннотация

В данной серии статей я планирую рассказать о том, как создавать виртуальные апплайнсы для платформы виртуализации oVirt. Несмотря на использование oVirt в качестве эталонной платформы, приведенные ниже инструкции и рекомендации могут быть легко адаптированы и для других решений вроде Proxmox, Open Nebula, Open Stack или обычного KVM.

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

Все скрипты, приведенные в данной статье, доступны на странице в GitHub: https://github.com/omnimod/ovirt-appliance

Введение

До сих пор виртуальные апплайнсы остаются одним из самых удобных способов доставки и развертывания ПО в виртуальных инфраструктурах. Идейным вдохновителем данной концепции стала компания VMware, которая поставляет большую часть своего ПО в виртуальных апплайнсах. В качестве примера на ум приходит VMware vCenter Server, который присутствует буквально в каждой инфраструктуре vSphere, SDN контроллер NSX Manager, сервер мониторинга Aria Operations и многие другие. Для других платформ такой подход также часто применяется. Например, сервер управления oVirt Engine - аналог vCenter также может поставляться в виде виртуального апплайнса.

Несколько лет назад я уже писал о том, как создавать виртуальные апплайнсы в vSphere. Данная возможность реализована благодаря поддержке OVF (Open Virtualization Format) - специальному формату, который позволяет описывать конфигурацию ВМ, а также дополнительные параметры для настройки гостевой ОС и приложений при развертывании ВМ из шаблона.

Дополнительную информацию о возможностях OVF и работе с ним вы можете узнать из статьи: https://blog.vmpress.org/2017/01/appliance.html

Несмотря на то, что формат OVF является открытым и поддерживается во многих Open Source решениях, не все платформы виртуализации предоставляют одинаковые возможности при работе с OVF шаблонами. Например, oVirt в отличие от VMware vSphere не поддерживает работу с расширенными свойствами и конфигурациями в OVF шаблоне. Также не все платформы виртуализации поддерживают виртуальные flat и sparse диски vmdk. Из-за данных ограничений OVF шаблоны не выглядят столь эффективными для передачи и развертывание ВМ на платформах виртуализации, отличных от VMware.

С другой стороны, oVirt поддерживает Cloud-init - другой распространенный способ для автоматической настройки ВМ в виртуальных инфраструктурах и облаках, благодаря которому можно реализовать схожие возможности по настройке ВМ.

Для наглядности я опишу процесс подготовки шаблона виртуального апплайнса с веб-сервером Nginx и покажу, как с помощью Cloud-init, нескольких скриптов и утилит можно выполнять автоматическую настройку гостевой ОС и приложения.

Установка ОС

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

В качестве основы возьмём Ubuntu Server 22.04. Для тестов не играет особой роли, какой дистрибутив вы выберите, но на практике всегда следует стремиться к тому, чтобы апплайнс занимал минимальное место на диске, не был перегружен лишними утилитами и сервисами, и на нём были установлены только те инструменты, которые требуются для его работы.

Для чистовой установки загрузите дистрибутив Ubuntu Live Server 22.04.5 с сайта Canonical: https://ubuntu.com/download/alternative-downloads

Создайте ВМ с необходимыми ресурсами, например: 2 vCPU, 2 GB RAM, 6 GB Disk и одним сетевым адаптером. Создайте тонкий диск в формате QCOW2, чтобы после подготовки образ не занимал лишнее дисковое пространство, и его было проще загружать и импортировать.

Из дополнительных параметров ВМ выберите:
  • General -> Chipset/Firmware Type: Q35 Chipset with UEFI, но если требуется образ минимального размера, то можно выбрать Q35 Chipset with BIOS и сэкономить место, которое используется под раздел /boot/efi.

Остальные настройки ВМ оставьте по умолчанию.

Подключите к ВМ ISO образ с дистрибутивом Ubuntu Server и запустите ВМ. При установке ОС выберите следующие параметры:
  • Choose the base for the installation: Ubuntu Server (minimized) - выполнит установку ОС, которая будет занимать минимальное пространство на диске, содержащую только базовые компоненты и утилиты, необходимые для работы.
  • Configure a guided storage layout: Use an entire disk
  • Разметка диска: оставьте по умолчанию
  • Default user: user (здесь и далее для настройки будет использоваться учетная запись пользователя с именем user)
  • Пароль по умолчанию: на ваше усмотрение
  • Install OpenSSH server: включено
Остальные параметры оставьте по умолчанию.

В качестве альтернативного варианта вместо установки ВМ можно загрузить готовый образ виртуального диска с предустановленной ОС (jammy-server-cloudimg-amd64.img) с сайта: https://cloud-images.ubuntu.com/jammy/current/

Видеоинструкция по импорту виртуального диска в oVirt, созданию ВМ и подключению к ней диска доступна по ссылке: https://www.youtube.com/watch?v=dUNYrCoCcmg

Настройка ОС

После создания ВМ и установки ОС все дальнейшие операции будут выполняться под учетной записью user с повышенными привилегиями. Для удобства настройки можно выполнять, подключившись к машине по SSH.

Обновление ОС и установка пакетов

Для начала обновите ОС и установите несколько дополнительных пакетов:
sudo apt update && sudo apt upgrade -y
sudo apt install cockpit nano network-manager nginx pvm-dev qemu-guest-agent whiptail -y
Данный набор пакетов является минимально необходимым для дальнейшей настройки апплайнса. При желании вы можете заменить nano на другой привычный вам редактор. По остальным пакетам:
  • cockpit и pvm-dev - сервис для удаленной настройки сервера через веб-интерфейс.
  • network-manager - используется для настройки сетевых интерфейсов.
  • nginx - веб-сервер, который будет играть роль ПО, работающего на апплайнсе, которое мы будем настраивать.
  • qemu-guest-agent - агент для получения oVirt'ом информации о статусе гостевой ОС и дополнительной служебной информации, вроде имени хоста и назначенных сетевых адресов.
  • whiptail - утилита для отрисовки псевдографического интерфейса в консоли.

Настройка сети

Если вы планируете настраивать сетевые интерфейсы апплайнса с помощью Network Manager, отредактируйте файл 50-cloud-init.yaml в каталоге /etc/netplan/, либо создайте новый файл конфигурации netplan и добавьте в него строчку renderer: NetworkManager в раздел network, например:
network:
  version: 2
  renderer: NetworkManager
  ethernets:
    enp1s0:
      dhcp4: yes

Затем примените примените настройки Netplan:
sudo netplan apply

Запуск SUDO без ввода пароля

При работе с апплайнсом из командной строки можно настроить запуск команд в режиме sudo без необходимости вводить пароль. Для этого потребуется отредактировать файл /etc/sudoers, добавив в него строку:
user ALL=(ALL) NOPASSWD:ALL
, где user - имя учетной записи пользователя, для которого требуется запускать sudo без запроса пароля.

Автоматический вход в систему

Для упрощения настройки апплайнса на первом этапе можно настроить автоматический вход под учетной записью пользователя при подключении к локальной консоли (например, tty1) без аутентификации. Такой вариант можно совместить с мастером первоначальной настройки, который будет запускаться при первом старте апплайнса и выполнять базовую конфигурацию ОС, например, задавать имя хоста, сетевые настройки, менять пароль администратора и пр.

Для примера выполним настройки для двух виртуальных терминалов. Для tty1, который будет отображаться по умолчанию, настроим автоматический вход под учетной записью user, а для tty2 оставим возможность входа по логину и паролю.

Для настройки автоматического локального входа в систему нужно отредактировать файл /etc/systemd/logind.conf, раскомментировать в нем следующие строки и указать количество виртуальных терминалов:
NAutoVTs=1
ReserverVT=2
А также создать файл настроек для автоматического входа в систему:
sudo mkdir /etc/systemd/system/getty@tty1.service.d/
sudo sh -c "cat << 'EOF' > /etc/systemd/system/getty@tty1.service.d/override.conf
[Service]
ExecStart=
ExecStart=-/sbin/agetty --noissue --autologin user %I $TERM
Type=idle
EOF"
, где user - имя пользователя для автоматического входа в систему.

Теперь при каждом запуске апплайнса или завершении сеанса в ttyt1 будет выполняться автоматический вход в систему под учетной записью user. Для отключения автоматического входа достаточно удалить или переименовать файл override.conf в каталоге /etc/systemd/system/getty@tty1.service.d/.
sudo mv /etc/systemd/system/getty@tty1.service.d/override.conf /etc/systemd/system/getty@tty1.service.d/override.conf.old

Message of the Day

При подключении к локальной консоли или по ssh вы можете увидеть приветственное оповещение, которое содержит различную полезную информацию о состоянии системы и ссылки на документацию (Message of the Day).

В Ubuntu MOTD генерируется при помощи скриптов, размещенных в каталоге /etc/update-motd.d. Очередность выводимого текста определяется последовательностью именования файлов скриптов.

Для примера удалим существующие скрипты и создадим новый скрипт, который выводит приветствие, информацию о названии апплайнса и его IP адрес.
sudo rm -f /etc/update-motd.d/*
cat << 'EOF' | sudo tee /etc/update-motd.d/01-welcome
#!/bin/sh
printf "Welcome to Appliance OS\n"
printf "Hostname: %s\n" "$(hostname)"
printf "IP Address: %s\n" "$(hostname -I)"
EOF
sudo chmod +x /etc/update-motd.d/01-welcome

Посмотреть сгенерированный MOTD можно, открыв файл /var/run/motd.dynamic.

Псевдографический интерфейс

Многие виртуальные апплайнсы позволяют выполнять базовые настройки без ввода команд в консоли, используя псевдографический интерфейс. Сделать такой интерфейс не сложно, если использовать bash и whiptail. Whiptail позволяет отрисовывать различные виды окон для отображения текстовой информации, создания форм для ввода текста или меню для выбора действий: https://en.wikibooks.org/wiki/Bash_Shell_Scripting/Whiptail

Для примера я подготовил скрипт, который отрисовывает меню выбора типовых действий, вроде настройки сетевых интерфейсов через Network Manager UI, смены номера порта для сервера Nginx или перезапуска ОС.

Чтобы добавить меню сохраните скрипт show-appliance-menu.sh в каталоге /usr/bin/ и разрешите его выполнение:
sudo chmod +x /usr/bin/show-appliance-menu.sh
Для настройки Nginx я подготовил еще два скрипта load-app-config.sh и save-app-config.sh. Сохраните их в каталоге /usr/sbin/ и разрешите выполнение:
sudo chmod +x /usr/sbin/load-app-config.sh
sudo chmod +x /usr/sbin/save-app-config.sh
Эти же скрипты будут использоваться для настройки Nginx через VAMI интерфейс в следующем разделе.

Если вы хотите, чтобы меню show-appliance-menu.sh автоматически запускалось при входе пользователя в консоль или подключении по ssh, то просто добавьте в конец файла ~/.profile в домашней директории пользователя путь к скрипту:
echo /usr/bin/show-appliance-menu.sh >> ~/.profile

Virtual Appliance Management Interface

Cockpit

Многие виртуальные апплайнсы предоставляют специализированный интерфейс управления, доступный при подключении с помощью веб-браузера. Через такой интерфейс можно выполнить базовые настройки и посмотреть статус работы ОС и сервисов. В качестве примера можно привести VAMI интерфейс в vCenter Server и других виртуальных апплайнсах VMware. 

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

Установите Cockpit и зависимости, если не сделали этого ранее:
sudo apt install pvm-dev cockpit -y
Интерфейс Cockpit по умолчанию доступен при подключении через веб-браузер на адрес: https://<server_ip>:9090. Для измененая номера порта можете воспользоваться инструкцией: https://cockpit-project.org/guide/latest/listen.html

Для безопасного подключения при установке в каталоге /etc/cockpit/ws-certs.d создается самозаверенный сертификат, который при необходимости можно заменить на сертификат от доверенного УЦ.

Cockpit поддерживает аутентификацию с помощью локальных учетных записей пользователей.

Cockpit из коробки предоставляет множество возможностей по настройке сервера, включая конфигурирование сетевых интерфейсов, дисков, сервисов, установку обновлений, доступ к консольному интерфейсу.

Для настройки сетевых интерфейсов через Cockpit требуется, чтобы в настройках netplan был указан renderer: NetworkManager. Также при использовании Network Manager отключите сервис /lib/systemd/system/systemd-networkd-wait-online.service, чтобы избежать ошибки timeout'а при попытке запустить сервис networkd для настройки интерфейсов:
sudo systemctl disable /lib/systemd/system/systemd-networkd-wait-online.service

Плагин Cockpit для настройки приложения

Огромным плюсом Cockpit является возможность расширения за счет использования плагинов. Посмотреть список установленных плагинов можно с помощью команды:
cockpit-bridge --packages
Предустановленные плагины по умолчанию размещаются в дочерних директориях в каталоге /usr/share/cockpit/. Каждый плагин содержит файл манифеста, веб-страницы и js скрипты, с помощью которых можно выполнять действия в системе.

Описание файла манифеста доступно по ссылке: https://cockpit-project.org/guide/latest/packages.html#package-manifest

Для оформления интерфейса встроенные плагины используют дизайн модель Patternfly (https://www.patternfly.org/), но вам ничто не мешает использовать собственные CSS шаблоны и ресурсы для оформления страницы плагина.

Для примера я подготовил простой плагин на базе статического html документа, с помощью которого можно настроить порта для сервиса Nginx.

Для добавления плагина создайте каталог myapp в /usr/share/cockpit/:
sudo mkdir /usr/share/cockpit/myapp
Скопируйте в данный каталог три файла: manifest.json, myapp.html и myapp.js.

Также  скопируйте файлы load-app-config.sh и save-app-config.sh в каталог /usr/sbin и разрешите их выполнение, если не сделали этого ранее.

Перезагрузите страницу Cockpit в браузере, теперь на панели навигации появится новый раздел MyApp, в котором можно будет посмотреть и изменить номер порта Nginx.

Подготовка к автоматизированному развертыванию

Как я говорил в начале статьи, одним из плюсов формата OVF в vSphere является поддержка передачи параметров в гостевую ОС при развертывании ВМ из шаблона. Это позволяет администраторам задать настройки, используя мастер импорта, и получать ВМ, готовую к работе сразу после развертывания.

Схожие возможности можно реализовать при помощи сценариев Cloud-init. Например, в oVirt при кастомизации ОС через Cloud-init можно запускать произвольные команды и скрипты внутри гостевой ОС.

Давайте добавим в гостевую ОС еще один скрипт для первоначальной настройки: init-appliance.sh, с помощью которого можно будет настроить сетевой интерфейс ВМ, имя хоста и порт для сервера Nginx.

Скопируйте файл init-appliance.sh в каталог /usr/sbin/ и настройте разрешение на выполнение:
chmod +x /usr/sbin/init-appliance.sh
Скрипт поддерживает следующие опции при запуске:
  • -n, --hostname - имя хоста
  • -m, --mode - режим настройки сети на интерфейсе: dhcp | static
  • -a, --address - сетевой адрес в CIDR формате при статической настройке
  • -g, --gateway - адрес маршрутизатора по умолчанию
  • -d, --dnsservers - список dns серверов, разделенных запятой
  • -p, --port - порт для Nginx сервера
Теперь при первом запуске ВМ достаточно будет запустить Cloud-init, добавив в поле Custom Scripts дополнительную команду для запуска скрипта с нужными параметрами, например:
runcmd:
  - init-appliance.sh -n app02a -m static -a 192.168.1.228/24 -g 192.168.1.1 -d 192.168.1.2,192.168.1.3 -p 8080
Задаст имя хоста app02a, настроит статический IP адрес 192.168.1.228 с 24 маской на сетевом интерфейсе enp1s0 и поменяет порт Nginx на 8080.

Очистка апплайнса от артефактов

Перед тем как приступить к тестированию развертывание апплайнса потребуется очистить его от временных файлов, ключей безопасности и подготовить к запуску Cloud-init.

Существует два вариант как это можно сделать:
  • Скриптом перед финальным выключением ВМ.
  • Функцией запечатывания (Seal Template), встроенной в oVirt.
Вариант со скриптом удобен тем, что не требует выполнения дополнительных шагов по клонированию ВМ в шаблон для запечатывания, но какие-то файлы и записи в журналах событий на машине могут остаться.

Вот пример скрипта, который удаляет временные файлы и устаревшие пакеты, обнуляет machine-id, а также удаляет SSH существующие ключи.
# Удаление временных файлов
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*

# Пересоздание SSH ключей
rm -f /etc/ssh/ssh_host_*

# Очистка локального репозитория
sudo apt clean

# Очистка артефактов cloud-init
sudo cloud-init clean --logs --seed

# Удаление machine-id
cat /dev/null | sudo tee /etc/machine-id
sudo rm /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id

# Очистка истории bash
history -w && cat /dev/null > ~/.bash_history
history -c
Примечание: если вы удаляете SSH ключи с помощью скрипта, то важно, чтобы при развертывании ВМ была выбрана опция Regenerate SSH Keys, либо в скрипт init-appliance.sh добавлена строчка dpkg-reconfigure openssh-server, иначе сервис ssh не сможет корректно стартовать.

После выполнения скрипта просто выключите ВМ и шаблон готов.

Второй вариант - создать из ВМ шаблон и запечатать его. Для этого выключите ВМ и в консоли oVirt выберите действие Make Template.

В окне настроек шаблона выберите опцию Seal Template (Linux only). 

При создании шаблона oVirt запустит утилиту virt-sysprep, которая удалит с диска ВМ все артефакты, включая ssh ключи, machine-id, историю bash и прочие артефакты.

Примечание: в oVirt 4.5.5 есть баг из-за которого при создании Sealed шаблона у всех ВМ, создаваемых из данного шаблона остается установленным флаг Sealed, что приводит к ошибке при развертывания. Для решение данной проблемы просто откройте созданный шаблон на редактирование, на вкладке General проверьте, что флажок Sealed находится в выключенном положении и нажмите OK для применения настроек. После этого ВМ будут создаваться без флага Sealed.

На этом подготовку шаблона апплайнса можно считать завершенной.

Тестовое развертывание

Настало время протестировать автоматическую настройку нового апплайнса.

В зависимости от того, какой выбор очистки от артефактов вы выбрали, создайте новую тестовую машину из существующей ВМ или из созданного шаблона.

После завершения создания выберите опцию Run One и укажите настройки Cloud-init, которые требуется передать в новую ВМ:
  • Cloud-init - установите флаг для инициализации Cloud-init при следующем запуске ВМ.
  • VM Hostname - имя хоста в гостевой ОС. Данный параметр является опциональным, т.к. скрипт init-appliance.sh также может менять имя хоста.
  • Configure Time Zone - установка временной зоны в гостевой ОС.
  • Authentication - позволяет создать пользователя по умолчанию или поменять пароль, если пользователь уже существует (например, если указать User Name: user, Password и Verify Password), а также добавить разрешенные ключи для доступа по SSH.
  • Regenerate SSH Keys - пересоздать приватные и публичные ключи SSH сервера в гостевой ОС.
  • Network - позволяет настроить сетевые интерфейсы. Данный раздел является опцпиональным, т.к. скрипт init-appliance.sh также может менять сетевые настройки интерфейса.
  • Custom Script - может содержать дополнительные операции, которые должен выполнить Cloud-init. Например:
runcmd:
  - init-appliance.sh -n app02a -m static -a 192.168.1.228/24 -g 192.168.1.1 -d 192.168.1.2,192.168.1.3 -p 8080

Дождитесь завершения загрузки ВМ и работы Cloud-init. После запуска гостевая ОС будет автоматически настроена в соответствии с параметрами, которые были переданы в Custom Script.

На этом наш шаблон виртуального апплайнса готов. Вы можете экспортировать файл виртуального диска .qcow2 или весь шаблон в виде .OVA архива для развертывания на целевых платформах виртуализации.

В следующей части мы погорим о том, как можно упростить передачу параметров Cloud-init с помощью собственного мастера развертывания виртуального апплайнса.
Share:

0 коммент.:

Отправить комментарий