Данная статья это авторский перевод/русскоязычная версия моей статьи на Medium, и первая из цикла про этот интересный инструмент.

Пожалуй, наиболее адекватным эпиграфом будет перефразированный английский перевод частушки «по реке плывет топор»:

Down the pipeline flows the code
From the towers of London.
Let it setup by itself
On this fancy piece of iron

Как это часто бывает, данный проект появился в результате случайности. Я всего лишь устанавливал Ubuntu на новую Dell rack workstation, когда элементарная задача неожиданно превратилась в «увлекательную». Зато открыло для меня совершенно новый уровень.

Поскольку это не совсем сервер, в машине нет модуля IPMI. Зато у этой модной железки есть 2 порта USB-C/DisplayPort и ни одного простого интерфейса для монитора. К сожалению, в коробке не было фирменного адаптера USB-C/DP – HDMI или в display port. А no-name, который оказался у меня в офисе под рукой, требовал изрядных танцев с бубном, чтобы на экране можно было увидеть хоть что-нибудь, пока к машине нельзя было добраться по SSH.

Поскольку машина предназначалась для тестов и разработки, переустанавливать систему приходилось неоднократно. Мне довольно быстро надоело это занятие, и я задумался, а можно ли как-то без этих альтернативных ощущений с монитором? Воображение рисовало идеальное конечное решение: хотелось вставить флэшку в бездыханную железяку, и на выходе получить вход по SSH. С одной стороны, без IPMI короткий ответ «нет» - нужно хотя бы вручную выбрать загрузочный диск, а лучше настроить boot sequence в BIOS. К сожалению, из коробки железяка мало того, что не загружается с внешнего носителя, так еще требуется сменить настройку RAID, чтобы система увидела внутренний SSD. И сделать это необходимо с едва работающим монитором. Но есть и хорошая новость: достаточно добраться до BIOS хотя бы один раз.

После этого жизнь начинает играть новыми красками. Поиск быстро привел меня к Ubuntu autoinstall https://ubuntu.com/server/docs/install/autoinstall Но если бы все было так просто. Как это часто бывает, качество документации не просто оставляет желать, но иногда может вводить в заблуждение. Например, я долго не мог разобраться с разницей между Ubuntu autoinstall и cloud-init. Позже объясню, почему.

С другой стороны, путешествие по граблям оказалось неожиданно полезным. Разработанные workarounds очень пригодились в дальнейшем, и них я расскажу в следующих статьях. Данный цикл статей это попытка восполнить пробел в документации, и поделиться знанием об очень интересном инструменте Ubuntu, и куда это может завести.

Это первая статья из цикла, и в ней мы реализуем простейший вариант. Мы создадим загрузочный образ ISO, который пока просто накатывает минимальный Ubuntu server. Все настройки по-умолчанию, сеть DHCP, OpenSSH сервер, логин и пароль. Я буду использовать авторизацию SSH по паролю, но ничего не мешает использовать ключи.

Все происходит полностью автоматически, причем без клавиатуры и монитора: вставили флэшку, нажали кнопку «вкл», и получили систему с SSH. И оно правда работает.

Готовим ингредиенты

Autoinstall использует yaml, который должен называться "user-data". Для ISO с автозапуском мы сохраним его в папке “/nocloud”. Вот содержимое /nocloud/user-data:

#cloud-config
autoinstall:
  version: 1
  identity:
     hostname: ubuntu22auto
     username: ubuntulogin
     password: <mkpasswd -m sha-512 ubuntupass>
  ssh:
     install-server: yes
     allow-pw: yes

Это минимально возможный конфиг autoinstall.

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

Человек приходит в патентное бюро регистрировать свое изобретение, универсальную бритвенную машину. Патентный клерк его спрашивает:
- Расскажите пожалуйста немного про свое изобретение? Как работает ваша машина?
- Ну вы вставляете в нее свое лицо, нажимаете на кнопку, и она вас бреет.
- Очень интересно.... Но лица же у людей все разные?
- Первый раз да.

Некоторые гипервизоры и карты IPMI сами отключат загрузочный образ при перезагрузке. Но давайте сделаем гарантированно безопасный вариант. На мой взгляд, наиболее чистой и аккуратной реализацией для автоматической установки без всего является выключение машины после установки системы. Таким образом у нас появляется совершенно четкая индикация, когда нужно извлечь загрузочный носитель, и включить сервер. Это можно сделать, добавив в конфиг bash комманду (об этом позже), но в autoinstall уже есть встроенная функция. Достаточно добавить:

shutdown: poweroff

Итак, у нас есть yaml для autoinstall. Теперь нужно объяснить Ubuntu, как его активировать. За это отвечает grub.cfg:

menuentry "Ubuntu autoinstall test" {
 set fgxpayload=keep
 linux /casper/vmlinuz "ds=nocloud;s=/cdrom/nocloud/" debug autoinstall ---
 initrd /casper/initrd.gz
}

Вот, что на самом деле запускает автоматическую установку: “ds=nocloud;s=/cdrom/nocloud/” debug autoinstall Это папка, где лежит наш файл user-data, который мы только что создали. Данная строчка стоила мне изрядного количества седых волос - у меня получилось надежно заставить это работать с кавычками. Желающим не возбраняется поэкспериментировать с escape символами без кавычек. Так же, для прода я бы заменил ‘debug’ на ‘quiet’.

Настраиваем среду разработки

Итак, конфиги готовы. А как их теперь встроить в загрузочный ISO образ Ubuntu?

Документация autoinstall обычно описывает хардкор вариант через боль, и не слишком подробно. К этому мы тоже придем в дальнейших статьях цикла, по мере продвижения в сторону сложных сценариев и сборки образа с помощью CI/CD pipeline. Пока начнем с простого, и будем наращивать сложность постепенно.

Итак, просто и не больно это делается с помощью приложения CUBIC, Custom Ubuntu ISO Creator, https://github.com/PJ-Singh-001/Cubic. Давайте его установим. Начнем с чистой виртуалки Ubuntu 22.04 Desktop в качестве среды для сборки образа. Дальше все просто, как написано в readme:

sudo apt-add-repository universe
sudo apt-add-repository ppa:cubic-wizard/release
sudo apt update
sudo apt install --no-install-recommends cubic

Теперь он откликается на "cubic" в терминале. Создаем папку под наш проект, например U22AutoInstallBuildV0.1:

Стартовый экран CUBIC
Стартовый экран CUBIC

Скачиваем ISO образ Ubuntu server. Я сохраню его в папке "Downloads". Обратите внимание на ссылку, которую я использую. В дальнейшем это пригодится:

wget http://releases.ubuntu.com/22.04/ubuntu-22.04.4-live-server-amd64.iso

Теперь, выбираем его в качестве исходника, и настраиваем проект. CUBIC подтянет метаданные из ISO. Давайте внесем изменения:

CUBIC, метаданные проекта
CUBIC, метаданные проекта

Распаковываем дистрибутив ISO:

CUBIC, распаковка образа
CUBIC, распаковка образа

Теперь мы попадаем в chroot shell, где можно вносить изменения в дистрибутив. В данной статье мы этого делать не будем, поэтому пока пропускаем:

CUBIC chroot shell.
CUBIC chroot shell.
CUBIC image customization progress.
CUBIC image customization progress.

На этом экране мы могли бы изменить версию ядра, если бы у нас были варианты на выбор. Раздел "Preseed", вероятно, наследие старых версий Debian/Ubuntu. Свежие версии Ubuntu устанавливаются с помощью Subiquity, и не используют preseed файлы:

CUBIC kernel options.
CUBIC kernel options.

Редактируем конфиги с помощью VSCode.

Вкладка “Boot” уже более полезна. Помните, нам необходимо внести правки в grub.cfg?

CUBIC boot settings.
CUBIC boot settings.

Это можно сделать здесь, но я предпочитаю VSCode.

Если на нашей чистой виртуалке Ubuntu еще не установлен OpenSSH server, то:

sudo apt install openssh-server

Теперь в нее необходимо скопировать ключ ssh, чтобы VSCode не задолбал запросами пароля 100 раз. В случае Windows я предпочитаю MS Windows Terminal который устанавливается из Microsoft Store. В нем уже есть встроенный клиент ssh:

ssh-keygen

Сгенерированные ключи id_rsa & id_rsa.pub лежат в папке .ssh в домашней директории пользователя. В других операционных системах работает примерно так же.

Если у вас чистая Ubuntu, проверьте наличие хотя бы пустого файла ~/.ssh/authorized_keys в домашней директории пользователя. Если его еще нет, создаем:

mkdir -p ~/.ssh
cd ~/.ssh
touch authorized_keys

Теперь копируем публичный ключ с нашей основной машины. В Windows:

scp ~/.ssh/id_rsa.pub ubuntulogin@<remotehost>:~/.ssh/authorized_keys

Проверяем:

ssh ubuntulogin@<remotehost>

Теперь подключаемся из VSCode. Проверьте, что у вас установлен Remote extension pack или хотя бы Remote-SSH:

Не забудьте проверить/поменять логин:

После этого система запросит конфигурацию, и запустит удаленное подключение в новом окне. Чтобы не путаться, я сразу открою непосредственно папку проекта:

Структура папок проекта CUBIC
Структура папок проекта CUBIC

Перед нами структура папок дистрибутива Ubuntu в варианте, как ее распаковал CUBIC. В следующих статьях мы посмотрим на нее более детально, а сейчас нас интересует только custom-disk:

Структура папки custom-disk
Структура папки custom-disk

Первым делом, создаем папку nocloud и yaml файл user-data, который мы уже сформировали выше. Так же необходимо создать пустой файл meta-data. Он нам не понадобится, но система требует наличие заглушки.

Следующий важный элемент это пароль пользователя:

mkpasswd -m sha-512 ubuntupass

полученный хэш необходимо вставить в наш конфиг:

$6$LmPUjxOfMHOMgRlg$pSXXVlcfwSKUSotcoG6ed7DUu7.iOX7kJEylN9V9z3C96uNBIMfCJjtL1tNjLx9dDbKS/kH9W7B8oIMKxmXb70

Если mkpasswd не установлен по-умолчанию,

недостающий mkpasswd
недостающий mkpasswd

добавляем, как указано:

sudo apt install whois

Вот наш рабочий user-data yaml:

файл user-data
файл user-data

Все практически готово. Осталось подредактировать grub.cfg. Он хранится в папке custom-disk/boot/grub:

grub.cfg
grub.cfg

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

Второе изменение это таймаут. Его я изменил с 30 секунд на 10, но можно и меньше, если не планируете вмешиваться в процесс загрузки.

Собираем ISO

На этом все. Остается только запаковать это обратно в ISO образ. Нажимаем "Next", и можно запускать. Лично я предпочитаю паковать образы xz, почему объясню в следующих статьях.

CUBIC, выбор архиваторов для упаковки
CUBIC, выбор архиваторов для упаковки
CUBIC image generation progress
CUBIC image generation progress

Проверяем готовый образ

CUBIC готовый образ с метаданными
CUBIC готовый образ с метаданными

В CUBIC есть функция проверки “Test” готового ISO с помощью QEMU. Она может быть полезной для простых сценариев (убедитесь, что у вас настроена вложенная виртуализация). Пробуем:

CUBIC тестируем образ с помощью QEMU.
CUBIC тестируем образ с помощью QEMU.

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

вылетел
вылетел

Вам может повезти больше. Это зависит от гипервизора, ресурсов, некоторых тонкостей в настройках, фазы луны и т.д. С ESXi мне обычно везет больше, и то на простых образах, а в данном случае я использую Hyper-V. В любом случае, для реальных проектов я от этого способа давно отказался, и использую полноценные виртуалки.

Создадим выделенную виртуальную машину для теста. Проверяем, что в ней есть стандартные настройки под Ubuntu. ESXi, Proxmox, XCP-NG, LXD ничего дополнительно не требуют. Hyper-V, который я использую для данного демо, требует отключить “Enable Secure Boot”:

Hyper-V требует отключить “Enable Secure Boot”
Hyper-V требует отключить “Enable Secure Boot”

Подключаем наш полученный образ.... и оно просто работает:

Успешно установленная Ubuntu
Успешно установленная Ubuntu

Итог

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

В следующих статьях, мы рассмотрим уже более сложные сценарии.

Комментарии (3)


  1. Sanes
    13.05.2024 13:52

    Cloud-init не тоже самое?


    1. Phoenixforge Автор
      13.05.2024 13:52

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


  1. qwertyshka
    13.05.2024 13:52

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

    Не так давно, при работе с Кубиком, именно на этом этапе у меня были проблемы - не смог установить дополнительные программы через apt и snap.