Виртуальное приватное облако: подготовка образов
![Тирекс](https://selectel.ru/blog/wp-content/uploads/2023/05/T-Rex_Autor-3-400x400.png)
В сервисе «Виртуальное приватное облако» имеется большой набор готовых образов операционных систем для создания виртуальных машин. Однако многим пользователям необходимы образы, которые отсутствуют в нашем сервисе, например это может быть менее распространенный тип или версия требуемой операционной системы. Иногда возникает необходимость изменить набор предустановленных пакетов или конфигурационные файлы системы в готовом образе — например, у пользователей, которые разворачивают кластер однотипных серверов. Чтобы не производить одинаковую настройку каждый раз после установки сервера, можно подготовить образ с требуемыми изменениями и таким способом ускорить установку большого количества однотипных виртуальных машин.
![Изображение записи](https://selectel.ru/blog/wp-content/uploads/2016/09/PR-2831.png)
В сервисе «Виртуальное приватное облако» имеется большой набор готовых образов операционных систем для создания виртуальных машин.
Однако многим пользователям необходимы образы, которые отсутствуют в нашем сервисе, например это может быть менее распространенный тип или версия требуемой операционной системы.
Иногда возникает необходимость изменить набор предустановленных пакетов или конфигурационные файлы системы в готовом образе — например, у пользователей, которые разворачивают кластер однотипных серверов.
Чтобы не производить одинаковую настройку каждый раз после установки сервера, можно подготовить образ с требуемыми изменениями и таким способом ускорить установку большого количества однотипных виртуальных машин. В этой статье мы покажем, как это делается.
В качестве примера будет использован образ Ubuntu 16.04: подготовка рабочего окружения, настройка необходимых параметров, сборка и загрузка образа в облачный сервис.
Также будут рассмотрены необходимые шаги для подготовки образа с полной совместимостью со всеми дополнительными возможностями сервиса «Виртуальное приватное облако».
В качестве инструмента для сборки образа мы будем использовать diskimage-builder. Это набор компонентов для подготовки образов операционных систем, файловых систем, RAM-дисков с открытым исходным кодом, поддерживаемый сообществом OpenStack.
Инструмент поддерживает создание образов большинства распространенных дистрибутивов GNU/Linux:
- Centos
- Debian
- Fedora
- RHEL
- Ubuntu
- Gentoo
- OpenSUSE
По умолчанию diskimage-builder подготавливает образ cloud-версии операционной системы, поэтому в образе будут присутствовать пакеты cloud-init и cloud-utils, необходимые для автоматической настройки системы в облаке.
Создание образа Ubuntu 16.04
Мы будем готовить образ на машине с ОС Ubuntu 14.04.
Для начала установим необходимые зависимости:
sudo apt update
sudo apt -y install python-pip curl
Затем установим diskimage-builder:
sudo pip install diskimage-builder
Создадим базовые директории для работы:
mkdir -p ~/diskimage-builder/{images,elements}
Для настройки diskimage-builder нам необходимо указать несколько дополнительных параметров, значение которых хранится непосредственно в переменных окружения командной оболочки (таким образом, вы можете указывать их в командной строке):
- ARCH=”amd_64″ — архитектура образа.
- BASE_ELEMENTS=”ubuntu bootloader cloud-init-datasources” — здесь мы укажем используемые элементы diskimage-builder. Элементы представляют собой набор bash-скриптов, которые выполняют все рутинные действия по подготовке и изменению образа. Наиболее важным для нас является элемент ubuntu, который скачает и распакует стандартный официальный образ дистрибутива, проведет установку требуемых пакетов и обновления системы до актуального состояния внутри образа при помощи утилиты chroot, и соберет все обратно в образ, готовый к использованию. Элемент bootloader устанавливает загрузчик (в нашем случае GRUB2) в подготавливаемый образ системы, а cloud-init-datasources передаёт список источников данных для утилиты cloud-init, которая необходима для первоначальной настройки операционной системы при запуске. Для того, чтобы выбрать GPT-разметку замените устанавливаемый по умолчанию параметр block-device-mbr на block-device-gpt.
- DIB_CLOUD_INIT_DATASOURCES=”ConfigDrive, Ec2″ — источники данных для элемента cloud-init-datasources.
- DIB_RELEASE=”xenial” — версия операционной системы, на базе которой мы будем создавать образ.
- IMAGE_PATH=”~/diskimage-builder/images/ubuntu-16.04″ — имя и путь для образа.
Сборка образа осуществляется с помощью команды:
disk-image-create vm $BASE_ELEMENTS -t raw -o $IMAGE_PATH
После ключа -t указываем нужный формат образа. Поддерживаются образы: qcow2, tar, vhd, docker, raw.
Перед непосредственной сборкой образа вам скорее всего понадобится внести дополнительные настройки в систему, например:
- установить дополнительные пакеты в систему;
- отключить механизм predictable_interface_naming, который переименовывает привычные имена интерфейсов eth0, eth1, … в имена вида enp0s3, ens3 и т.д;
- отключить создание пользователя «ubuntu» и разрешить доступ пользователю «root» по протоколу SSH;
- регенерировать SSH-ключи для каждой созданной из данного образа виртуальной машины;
- изменить предустановленную временную зону.
Для этого нам потребуется создать дополнительный элемент в директории ~/diskimage-builder/elements.
Создадим директории:
mkdir -p ~/diskimage-builder/elements/ubuntu-16-custom/{install.d,post-install.d,finalise.d}
Внутри директории ~/diskimage-builder/elements/ubuntu-16-custom создадим файл README.rst с описанием нового элемента:
================
ubuntu-16-custom
================
Customize Ubuntu 16.04 (Xenial)
В директории ~/diskimage-builder/elements/ubuntu-16-custom/install.d создадим скрипт 50-install-additional-packages:
#!/bin/bash
packages="python2.7
python
python-minimal"
apt -y install $packages
Скрипты в директории install.d выполняются при сборке образа во время установки основных пакетов. Созданный нами скрипт 50-install-additional-packages установит в систему python версии 2.7, который все еще необходим для работы многих приложений. По умолчанию в образе Ubuntu 16.04 присутствует только python версии 3.5.
Вы также можете дополнить этот список необходимыми вам пакетами, которые потребуется установить в образ.
Далее в директории ~/diskimage-builder/elements/ubuntu-16-custom/post-install.d необходимо создать скрипт 50-configure-system для изменения конфигурации системы:
#!/bin/bash
# Permit password auth via SSH
echo 'ssh_pwauth: true' >> /etc/cloud/cloud.cfg.d/50_remote_access.cfg
# Generate new keys in first boot
echo 'ssh_deletekeys: true' >> /etc/cloud/cloud.cfg.d/50_remote_access.cfg
# Don’t disable root access via SSH
echo 'disable_root: false' >> /etc/cloud/cloud.cfg.d/50_remote_access.cfg
# Don’t create "ubuntu" user
echo 'users: []' >> /etc/cloud/cloud.cfg.d/50_remote_access.cfg
# Change default timezone to MSK
echo 'timezone: Europe/Moscow' >> /etc/cloud/cloud.cfg.d/50_timezone.cfg
# Change PermitRootLogin value to "yes"
sed -i 's/PermitRootLogin .*/PermitRootLogin yes/g' /etc/ssh/sshd_config
# Set root password to empty
passwd -d root
Скрипты в директории post-install.d выполняются сразу после скриптов в директории install.d.
Также нам потребуется изменить настройки GRUB для добавления параметра запуска «net.ifnames=0», который сохранит имена интерфейсов в привычном формате ethN.
Добавим скрипт 50-configure-grub в директории ~/diskimage-builder/elements/ubuntu-16-custom/finalise.d:
#!/bin/bash
sed -i 's/\(^GRUB_CMDLINE_LINUX.*\)"$/\1 net.ifnames=0"/' /etc/default/grub
update-grub
Скрипты в директории finalise.d выполняются после всех основных этапов подготовки образа.
После создания описанных скриптов нам необходимо изменить их атрибуты, для этого выполним команду chmod:
chmod 0755 ~/diskimage-builder/elements/ubuntu-16-custom/*d/*
Теперь перед созданием образа нам необходимо указать путь для нашего нового элемента. Это можно сделать при помощи параметра ELEMENTS_PATH.
Чтобы не указывать параметры каждый раз напрямую в командной строке, в директории ~/diskimage-builder/ создадим скрипт build-ubuntu-16.04, который задаст параметры diskimage-builder и выполнит сборку образа:
#!/bin/bash
export ARCH="amd64"
export BASE_ELEMENTS="bootloader cloud-init-datasources ubuntu ubuntu-16-custom"
export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive, Ec2"
export DIB_RELEASE="xenial"
export ELEMENTS_PATH="./elements/:/usr/share/diskimage-builder/elements/"
export IMAGE_PATH="./images/ubuntu-16.04"
disk-image-create vm $BASE_ELEMENTS -t raw -o $IMAGE_PATH
Для GPT-разметки:
#!/bin/bash
export ARCH="amd64"
export BASE_ELEMENTS="bootloader cloud-init-datasources block-device-gpt ubuntu ubuntu-16-custom ubuntu-16-selectel"
export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive, Ec2"
export DIB_RELEASE="xenial"
export ELEMENTS_PATH="./elements/:/usr/local/lib/python3.6/dist-packages/diskimage_builder/elements"
export IMAGE_PATH="./images/ubuntu-16.04"
disk-image-create vm $BASE_ELEMENTS -t raw -o $IMAGE_PATH
Изменим атрибуты этого файла:
chmod 0755 ~/diskimage-builder/build-ubuntu-16.04
После этого должна получится вот такая иерархия файлов:
$tree -p ~/diskimage-builder
/home/user/diskimage-builder
├── [-rwxr-xr-x] build-ubuntu-16.04
├── [drwxr-xr-x] elements
│ └── [drwxr-xr-x] ubuntu-16-custom
│ ├── [drwxr-xr-x] finalise.d
│ │ └── [-rwxr-xr-x] 50-configure-grub
│ ├── [drwxr-xr-x] install.d
│ │ └── [-rwxr-xr-x] 50-install-additional-packages
│ ├── [drwxr-xr-x] post-install.d
│ │ └── [-rwxr-xr-x] 50-configure-cloud-init
│ └── [-rw-r--r--] README.rst
└── [drwxr-xr-x] images
Запустим скрипт build-ubuntu-16.04:
cd ~/diskimage-builder
sudo ./build-ubuntu-16.04
Утилита sudo при вызове нужна для того, чтобы предложение ввести пароль не появилось посередине процесса подготовки образа. Данное поведение объясняется тем, что некоторые предустановленные элементы diskimage-builder содержат вызов sudo (например, скрипт 01-ccache от элемента base, который выполняется при сборке большинства дистрибутивов).
По окончании работы нашего скрипта новый образ будет находиться в директории ~/diskimage-builder/images/ubuntu-16.04.raw.
Вы можете использовать созданный образ в сервисе Selectel «Виртуальное приватное облако», загрузив его через веб-интерфейс панели VPC, либо через glance API.
Обратите внимание, что пароль для root был удален на этапе сборки образа, поэтому доступ к виртуальной машине по SSH изначально будет возможен только по ключу. Вы можете добавить ключ SSH при создании машины в панели VPC. Доступ к серверу возможен и через виртуальную консоль no-VNC в панели управления, в этом случае вам не потребуется вводить пароль root, если он не был установлен.
Пароль root устанавливается стандартным способом с помощью утилиты passwd.
Если вы попытаетесь использовать образ, созданный при помощи описанных выше процедур, в нашем сервисе «Виртуальное приватное облако» (VPC), то столкнётесь с рядом ограничений. Для вас не будут доступны следующие возможности VPC:
- установка исходного пароля, сгенерированного сервисом VPC;
- смена пароля root из веб-панели VPC;
- смена пароля root с помощью nova API;
- смена интерфейса для маршрута по умолчанию из веб-панели VPC;
- автоматическое изменение настроек сетевых интерфейсов внутри системы, в том случае, если они были изменены в панели управления сервером.
В следующем разделе мы покажем, как сделать полностью совместимый с VPC образ.
Создание образа для сервиса «Виртуальное приватное облако»
Чтобы создаваемый образ был полностью совместим с сервисом VPC, на этапе сборки потребуется добавить дополнительные свойства свойств для образа и установить в систему дополнительные пакеты.
Добавим еще один элемент ubuntu-16-selectel, для этого создадим директорию:
mkdir -p ~/diskimage-builder/elements/ubuntu-16-selectel/
Внутри данной директории добавим описание элемента в файле README.rst:
====================
ubuntu-16-selectel
====================
Build ubuntu image for Virtual Private Cloud
Создадим требуемые директории для нового элемента:
mkdir -p ~/diskimage-builder/elements/ubuntu-16-selectel/{pre-install.d,install.d,post-install.d}
Изменим список репозиториев скриптом ~/diskimage-builder/elements/ubuntu-16-selectel/pre-install.d/50-add-mirrors:
#!/bin/bash
# Add key for Selectel OpenStack repository
apt-key adv --fetch-keys http://repo.os.selectel.org/selectel-openstack.key
cat <<EOF > /etc/apt/sources.list
## Selectel OpenStack repository
deb http://repo.os.selectel.org xenial main
## Selectel mirrors
deb http://mirror.selectel.ru/ubuntu xenial main restricted universe multiverse
deb http://mirror.selectel.ru/ubuntu xenial-updates main restricted universe multiverse
deb http://mirror.selectel.ru/ubuntu xenial-backports main restricted universe multiverse
## Security updates
deb http://security.ubuntu.com/ubuntu xenial-security main restricted universe multiverse
EOF
Добавим дополнительные пакеты скриптом ~/diskimage-builder/elements/ubuntu-16-selectel/install.d/50-add-selectel-packages:
#!/bin/bash
packages="crontab-randomizer
fstrim-blocks
qemu-guest-agent
set-root-pw"
apt -y install $packages
Будут установлены следующие утилиты:
- crontab-randomizer — простой скрипт, который рандомизирует временные интервалы в /etc/crontab, далее мы добавим вызов данного скрипта при первом запуске системы;
- fstrim-blocks — обертка для предустановленной утилиты fstrim, позволяет проводить TRIM файловой системы на быстрых дисках поблочно через небольшие интервалы, при установке добавит вызов в cron.weekly;
- qemu-guest-agent — утилита, которая позволит передавать команды QMP для управления системой в виртуальную машину, в нашем случае данная утилита нужна для смены пароля виртуальной машины через панель VPC и nova API;
- set-root-pw — скрипт для изначальной установки в виртуальной машине пароля, полученного из метаданных OpenStack, далее мы также добавим вызов этого скрипта при первом запуске системы.
Также во время сборки образа пакет cloud-init будет автоматически обновлен на версию, которая находится в зеркале Selectel OpenStack. Эта версия содержит патчи, которые обеспечивают консистентность настроек сети между виртуальной машиной и сервисом VPC.
Автоматическое обновление пакетов при сборке образа происходит при помощи предустановленного скрипта 00-up-to-date, во время стадии install.d.
Далее нам понадобится добавить дополнительные конфигурационные файлы для cloud-init, создадим в директории ~/diskimage-builder/elements/ubuntu-16-selectel/post-install.d скрипт 50-configure-cloud-init:
#!/bin/bash
# Prevent cloud-init to change custom apt mirrors
echo 'apt_preserve_sources_list: true' > /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
echo 'system_info:' >> /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
echo '- arches: [i386, amd64]' >> /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
echo 'search:' >> /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
echo 'primary:' >> /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
echo '- http://mirror.selectel.ru/ubuntu' >> /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
echo 'failsafe:' >> /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
echo '- http://archive.ubuntu.com/ubuntu/' >> /etc/cloud/cloud.cfg.d/50_selectel_mirror.cfg
# Prevent cloud-init to disable EC2-style metadata
echo 'disable_ec2_metadata: false' > /etc/cloud/cloud.cfg.d/50_enable_ec2.cfg
# Perform some commands in boot time
# 'runcmd' only runs during the first boot
echo 'runcmd:' > /etc/cloud/cloud.cfg.d/50_first_boot_routines.cfg
echo '- set-root-pw 2> /dev/null' >> /etc/cloud/cloud.cfg.d/50_first_boot_routines.cfg
echo '- crontab-randomizer' >> /etc/cloud/cloud.cfg.d/50_first_boot_routines.cfg
Также рекомендуется удалить предустановленный скрипт /etc/cron.weekly/fstrim в случае использования fstrim-blocks, так как предустановленный вариант не содержит параметров поблочного запуска, что повлечет дополнительную нагрузку на систему при запуске fstrim .
Удалим данный файл простым скриптом ~/diskimage-builder/elements/ubuntu-16-selectel/post-install.d/51-remove-fstrim-weekly:
#!/bin/bash
rm -f /etc/cron.weekly/fstrim
Изменим атрибуты новых скриптов:
chmod 755 ~/diskimage-builder/elements/ubuntu-16-selectel/*d/*
Добавим новый элемент ubuntu-16-selectel в скрипт ~/diskimage-builder/build-ubuntu-16.04:
#!/bin/bash
export ARCH="amd64"
export BASE_ELEMENTS="bootloader cloud-init-datasources ubuntu ubuntu-16-custom ubuntu-16-selectel"
export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive, Ec2"
export DIB_RELEASE="xenial"
export ELEMENTS_PATH="./elements/:/usr/share/diskimage-builder/elements/"
export IMAGE_PATH="./images/ubuntu-16.04"
disk-image-create vm $BASE_ELEMENTS -t raw -o $IMAGE_PATH
Иерархия файлов должна иметь такой вид:
$ tree -p diskimage-builder
diskimage-builder
├── [-rw-r--r--] build-ubuntu-16.04
└── [drwxr-xr-x] elements
├── [drwxr-xr-x] ubuntu-16-custom
│ ├── [drwxr-xr-x] finalise.d
│ │ └── [-rwxr-xr-x] 50-configure-grub
│ ├── [drwxr-xr-x] install.d
│ │ └── [-rwxr-xr-x] 50-install-additional-packages
│ ├── [drwxr-xr-x] post-install.d
│ │ └── [-rwxr-xr-x] 50-configure-system
│ └── [-rw-r--r--] README.rst
└── [drwxr-xr-x] ubuntu-16-selectel
├── [drwxr-xr-x] install.d
│ └── [-rwxr-xr-x] 50-add-selectel-packages
├── [drwxr-xr-x] post-install.d
│ └── [-rwxr-xr-x] 50-configure-cloud-init
├── [drwxr-xr-x] pre-install.d
│ └── [-rwxr-xr-x] 50-add-selectel-openstack-mirror
└── [-rw-r--r--] README.rst
Запустим сборку образа:
cd ~/diskimage-builder
sudo ./build-ubuntu-16.04
Для загрузки образа со всеми необходимыми свойствами вам потребуется утилита glance и RC-файл доступа к проекту (его можно скачать в нашей панели управления; все необходимые инструкции опубликованы там же) https://support.selectel.ru/vpc/access/.
Команда для загрузки будет выглядеть так:
glance image-create --name Ubuntu-16.04-VPC \
--disk-format raw \
--container-format bare \
--property hw_disk_bus=scsi \
--property hw_scsi_model=virtio-scsi \
--property x_sel_image_owner=Selectel \
--property hw_qemu_guest_agent=yes \
--file ~/diskimage-builder/images/ubuntu-16.04.raw \
--progress
При загрузке будут добавлены свойства:
- hw_qemu_guest_agent=yes — необходимо для поддержки механизма смены пароля сервера через панель VPC или через nova API; данное свойство будет работать только в том случае, если в образе присутствует утилита qemu-guest-agent не ниже версии 2.3 (в Ubuntu 16.04 используется версия 2.5);
- x_sel_image_owner=Selectel — необходимо для поддержки отображения пароля в панели VPC;
- hw_disk_bus=scsi, hw_scsi_model=virtio-scsi — данные свойства разрешат использование более современной и производительной шины virtio-scsi, одно из преимуществ которой это возможность использования TRIM.
После загрузки образ будет отображаться на вкладке «Образы» в вашем проекте VPC с именем Ubuntu-16.04-VPC.
При первом запуске сервера пароль для пользователя root будет сгенерирован и установлен автоматически. Он будет отображаться на вкладке «Консоль», там же при необходимости можно сгенерировать новый пароль.
Помимо этого вам не придется производить настройки сетевых интерфейсов на сервере вручную, если вы изменили их в панели управления на вкладке «Порты». Чтобы cloud-init перенастроил сетевые интерфейсы, потребуется произвести перезагрузку сервера по питанию. После этого будут сгенерированы новые метаданные OpenStack c новыми настройками сети.
Вы можете запретить утилите cloud-init изменять настройки сети при каждой перезагрузке сервера. Для этого в установленной системе добавьте файл /etc/cloud/cloud.cfg.d/99_disable_network_config.cfg:
network:
config: disabled
В ближайшем будущем мы добавим возможность запрета автоматической перенастройки сети через веб-интерфейс панели VPC без необходимости редактирования конфигурации системы.
Заключение
В этой статье мы рассмотрели базовые возможности diskimage-builder, изучили способы добавления своих скриптов для изменения конфигурации образа, основные этапы сборки и пример загрузки готового образа в облачное окружение.
Если у вас остались вопросы по основным способам использования данного инструмента или же для вас непонятны какие-либо моменты в управлении образами и виртуальными машинами в сервисе VPC, пожалуйста, укажите об этом в комментариях.
Будем также рады, если вы поделитесь собственными способами использования diskimage-builder.