Содержание

Proxmox & packer: автоматизация подготовки VM

Зачем всё это нужно

Полный ответ на этот вопрос лежит в подходе IaC, что заслуживает отдельной статьи. В рамках же данного материала будет продемонстрирован пример создания шаблона ВМ через packer. Наличие такого образа позволяет заранее установить внутрь всё необходимое единожды, тем самым сократить время развертывания целевой системы.

Packer

Hashicorp разработала packer для возможности создания универсального образа операционной системы (golden image), в который заранее упаковывается всё необходимое. На основе этого образа далее уже развёртываются виртуальные машины с нужным набором софта. В терминологии packer так называемый builder выполняет непосредственно сборку, а с помощью плагинов билдера указывается целевая платформа: в основном это облачные провайдеры типа AWS, Yandex, но есть и локальные QEMU, Proxmox и даже Docker или Ansible. Все дальнейшие инструкции будут применимы к плагину Proxmox.

Packer подключается к облаку или локальному гипервизору, создаёт ВМ с указанными параметрами и выполняет установку ОС на основе файла автоматической установки (например, для rpm-based используется kickstart, для deb-based – Subiquity в случае с Ubuntu). А после установки формирует эталонный шаблон из которого клонируются ВМ.

cloud-init

Казалось бы, packer позволил автоматизировать ручной этап. Но при этом добавил новых ручных действий, которые придётся выполнить. Например, какой IP-адрес, хостнейм или ssh-key назначать ВМ, создаваемой из шаблона? Ведь при создании каждой новой ВМ придётся это как-то вручную указывать и менять “эталонный” образ… Или же другой случай: после установки ОС необходимо каждый раз накатывать какой-то типовой софт через ansible, что тоже отнимает время на ручные действия. Тут в игру вступает cloud-init – разработка от компании Canonical.

С помощью cloud-init можно выполнить инициализацию ОС до её финальной загрузки. Такое часто можно встретить в облаках. После создания ВМ из подготовленного шаблона с помощью packer запускается cloud-init, который считывает конфигурационный файл и выполняет указанные там действия. Это может быть как создание нужных юзеров, ключей, установка софта или запуск плейбуков и т.д.

Как это работает

<blockquote>Все действия выполнены на Proxmox 7 и Ubuntu 22.04, в которой используется установщик Subiquity.</blockquote> 1. Packer.

Конфигурационные файлы могут быть в формате HCL или JSON. В рамках данной статьи будет использоваться HCL. В секции source описывается ВМ с нужными параметрами. Тут есть важный параметр boot_command: в нём указывается, как запустить операционную систему. Причём в boot_command указаны комбинации, эмулирующие нажатие физических клавиш, как если бы это делалось вручную в консоли гипервизора. В данном случае packer переключается в консоль grub, указывает ядро для загрузки и добавляет параметры, которые необходимо выкачать по http. Веб-сервером выступает сам packer – установщик ОС подключается к машине, с которой packer был запущен. С помощью этих параметров, полученных через http, будет произведена автоустановка Ubuntu.

<blockquote>Про wsl и сеть. Если packer запущен в WSL, то в идеале он должен получать адрес из той же подсети, в которой создаются VM в Proxmox, чтобы они могли подключиться к веб-серверу Packer. В противном случае будет возникать ошибка на этапе “Reached target Host and Network Name Lookups” или на этапе загрузки AppArmor. Ещё подойдет как вариант portproxy.</blockquote> 2. cloud-init.

Для работы cloud-init потребуется два YAML файла: user-data и meta-data. В user-data указываются необходимые модули, с помощью которых можно выполнить те или иные действия – создать файлы, пользователей и т.д. Примеры различных конфигов user-data можно посмотреть в документации.

Для автоматической установки Ubuntu используется также конфигурация cloud-init:

То есть проще говоря, конфиг для автоустановки Ubuntu такой же, как и для cloud-init, но в начале файла используется специфичная конструкция autoinstall для инсталлятора subiquity, а далее уже используются нативные модули cloud-init.

Разбор конфигурационных файлов

Чтобы безмолвно не выкладывать весь конфиг целиком, стоит разобрать некоторые моменты.

.
├── README.md
└── ubuntu-server-jammy
    ├── http
    │  ├── meta-data
    │   └── user-data
    ├── ubuntu-server-jammy.pkr.hcl
    └── variables.pkr.hcl

Теперь что касается самого конфигурационного файла ubuntu-server-jammy.pkr.hcl. Для его понимания стоит изучить HCL, тем кто работал с terraform будет проще, т.к. там по сути тоже самое. Основные моменты, на которые стоит обратить внимание:

Также стоит пробежаться по файлу cloud-init, на основе которого выполняется автоматическая установка ОС:

И самый главный момент – создание пользователей. Здесь уже будут создаваться юзеры и пароли как для packer (с помощью которого он будет выполнять shell-команды из своего конфига), а также конечный пользователь для подключения по SSH после клонирования и запуска ВМ. Здесь важно указать хеш пароля (создав командой mkpasswd –method=SHA-512 –rounds=4096 например). Также можно указать публичный ключ, что будет намного удобнее. Примеры можно посмотреть тут.

Как это запустить

Для сборки и установки шаблона необходимо:

export PROXMOX_API_TOKEN_ID='root@pam!packer'
export PROXMOX_API_TOKEN_SECRET="7bf07389-db62-4985-aef3-58640dff3beb"
export PROXMOX_API_URL="https://192.168.3.100:8006/api2/json"

packer build ubuntu-server-jammy.pkr.hcl

После того, как шаблон появится в гипервизоре, для быстрого создания новой ВМ необходимо выполнить клонирование:

После указать имя ВМ:

Теперь важно указать корректные значения для новой ВМ. Для этого надо скорректировать в разделе cloud-init IP-адрес, маску и шлюз + остальные параметры при необходимости и перегенировать образ уже клонированной ВМ, после чего выполнить запуск:

Подключиться к запущенной ВМ можно по указанному выше IP-адресу (если он задан статически) и с логином\паролем или ssh-ключом, который указан в файле user-data