Как правило, создавать виртуальную машину с нуля — не совсем разумно. Всё-таки процесс долгий. Например, создание с нуля одного билд-сервера в моём мини-зоопарке занимает 40 минут. Это включает в себя установку пары-тройки SDK, всех доступных обновлений и сертификатов. Но в реальности, чтобы добавить новый, полностью сконфигурированный сервер в кластер, мне нужно минуты три. Как же так?
Прикол в том, что большая часть софта уже установлена в базовом образе, из которого машина создаётся. К ней только остаётся добавить свежих настроек, зарегистрировать в кластере, и всё. В результате самая продолжительная часть процесса — это выделение ресурсов под новую машину, а не её настройка.
Так уж исторически сложилось, что мы пользуемся своим, домашним инструментом для подготовки образов, но во вселенной есть и бесплатные и open source. Например, Packer.
Что такое Packer
Packer — это создатель образов виртуальных машин. Он отлично дружит и со всеми крупными облачными провайдерами, вроде AWS, GCE, Azure и Digital Ocean, и даже с локальными гипервизорами, вроде VMWare и VirtualBox. И да, создавать образы можно как для Linux, так и для Windows машин.
На вход Packer требует только файл шаблона для будущего образа. Шаблон идёт в JSON формате и в нём всего три основные секции:
- builders,
- provisioners и
- post-processors
1 2 3 4 5 6 7 8 |
{ "builders": [ ], "provisioners": [ ], "post-processors": [ ] } |
«builders» отвечает, собственно, за создание машины, и поэтому его содержание будет меняться от провайдера к провайдеру. В «provisioners» идут настройки и обычно они одинаковые для всех. Наконец, в «post-processors» можно положить финальные штрихи, вроде архивации образа или его экспорта в Vagrant.
И да, только первая секция шаблона — builders — обязательна.
План на сегодня
У меня есть какая-то мания к переиспользованию примеров из поста в пост, поэтому сегодня мы попробуем упаковать какой-нибудь кусок конфигурации Consul кластера с прошлого поста в образ для Packer. А что, возьмём Ubuntu, установим в ней Consul. Чем не образ?
Чтобы не тратить центы драгоценнейшей валюты на виртуальные машины в AWS или GCE, мы создадим образ для VirtualBox. Не так внушает, конечно, но зато бюджетно.
Установка
Packer можно скачать в виде архива с бинарниками, и его установка сводится к «правый клик -> распаковать». VirtualBox менее дружелюбен, так что там придётся покликать немного больше. Раза три.
Я буду работать в Mac, но на Убунте (проверял) и Windows (не проверял) процесс будет идентичным.
Настраиваем секцию «builders»
Самая неприятная черта Packer-настройщика для VirtualBox состоит в том, что он сложнее всех остальных облачных настройщиков вместе взятых. Так вышло из-за того, что в облаке мы обычно создаём VM уже из готового образа, а в VirtualBox мы делаем VM с нуля: ISO c операционкой, мышка с кнопкой — и пошёл развлекаться. К счастью, в интернетах кроме порно встречаются уже готовые примеры конфигурации VirtualBox для Packer. Этот чувак, например, вообще прекрасен — у него есть примеры билдеров для всего со словом Linux внутри.
Вообще, настройщику VirtualBox для Ubuntu нужно две вещи:
- Собственно, кусок JSON’а в builders, в котором мы опишем, что за провайдер будем использовать (VirtualBox), откуда качать ISO с операционкой и куда кликать в процессе установки;
preseed.cfg
файл, из которого Убунта возьмёт большинство своих настроек. Всемогущий Гугл поможет найти и его.
Вот так выглядит моя начальная версия ubuntu-consul-template.json
файла для Packer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
{ "builders": [{ "type": "virtualbox-iso", "guest_os_type": "Ubuntu_64", "iso_url": "http://releases.ubuntu.com/16.04/ubuntu-16.04.2-server-amd64.iso", "iso_checksum": "737ae7041212c628de5751d15c3016058b0e833fdc32e7420209b76ca3d0a535", "iso_checksum_type": "sha256", "output_directory": "output-ubuntu-consul", "disk_size": 15000, "headless": "true", "http_directory": "http", "boot_wait": "5s", "boot_command": [ "<enter><wait>", "<f6><esc>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs>", "/install/vmlinuz ", "initrd=/install/initrd.gz ", "net.ifnames=0 ", "auto-install/enable=true ", "debconf/priority=critical ", "preseed/url=http://{{.HTTPIP}}:{{.HTTPPort}}/preseed.cfg", "<enter>" ], "ssh_timeout": "60m", "ssh_username": "ubuntu", "ssh_password": "ubuntu", "shutdown_command": "sudo systemctl poweroff", "vboxmanage": [ ["modifyvm", "{{.Name}}", "--memory", 512], ["modifyvm", "{{.Name}}", "--cpus", 1] ] }], "provisioners": [ ] } |
Выглядит стрёмно, по памяти я бы такое точно не воспроизвёл, но содержимое на самом деле очень разумно и понятно. Например, type: virtualbox-iso
явно указывает на тип провайдера. Множество полей начинающихся на iso_*
определённо относятся к ISO с Убунтой. В vboxmanage
можно положить физические параметры для виртуальной машины: количество процессоров и т. п. А в boot_command
идёт последовательность клавиш, которую нужно нажимать во время установки.
Вот эти куски конфигурации особенно интересны:
preseed/url=http://{{.HTTPIP}}{{.HTTPPort}}/preseed.cfg
"http_directory": "http"
Чтобы установка Убунты прошла в автоматическим режиме, ей можно передать файл с инструкциями. Например — через URL — preseed/url=
. Packer запустит свой веб-сервер, через который Убунта может эти инструкции скачать, а опция http_directory
покажет, где лежит контент для скачивания.
В интернетах я нашёл пример настроек, назвал его — preseed.cfg
, положил в локальную папку http,
и этого оказалось достаточно. Как выглядят настройки можно посмотреть на github.
Настраиваем «provisioners»
Добавлять провижинеров (ненавижу это слово) намного проще. Packer умеет работать и с Ansible, и с Chef, но в нашем случае простого шелл-скрипта будет достаточно:
1 2 3 4 5 6 7 8 9 |
{ "builders": [/*...*/] "provisioners": [{ "type": "shell", "scripts": [ "install-consul.sh" ] }] } |
Я взял код для install-consul.sh
практически без изменений из поста про Vagrant и Consul:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#!/bin/bash dpkg -s unzip &>/dev/null || { # update and unzip sudo apt-get -y update && sudo apt-get install -y unzip } # install consul if [ ! -f ~/consul ]; then cd ~ version='0.8.0' wget https://releases.hashicorp.com/consul/${version}/consul_${version}_linux_amd64.zip -O consul.zip unzip consul.zip rm consul.zip # make consul executable chmod +x consul fi |
И всё!
Пробный запуск
Теперь проверим валидность шаблона через Packer и затем соберём из него образ.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ ./packer validate ubuntu-consul-template.json # Template validated successfully. $ ./packer build ubuntu-consul-template.json #... # virtualbox-iso: Downloading or copying: http://releases.ubuntu.com/16.04/ubuntu-16.04.2-server-amd64.iso #... # ==> virtualbox-iso: Starting the virtual machine... #... # virtualbox-iso: Saving to: 'consul.zip' #... # virtualbox-iso: Executing: export packer-virtualbox-iso-1494908412 --output output-ubuntu-consul/packer-virtualbox-iso-1494908412.ovf #... # --> virtualbox-iso: VM files in directory: output-ubuntu-consul |
За ходом процесса реально можно наблюдать. В какой-то момент даже становится понятно, зачем была нужна та дикая последовательность <bs><bs>
. Оказывается , это backspace, удаляющий дефолтные настройки загрузки (в самом низу):
А в остальном — установка, как установка:
Но вообще процесс очень быстрый. Буквально несколько минут. В результате сборки получаются два файла: VMDK и OVF, которые заменяют собой образ для VirtualBox. OVM можно импортировать и получить в результате новую, созданную из образа, машинку:
Теперь запускаем машину (логин и пароль — ubuntu
и ubuntu
) и убеждаемся, что consul действительно уже там:
Готово.
Заключение
Если вам приходится создавать виртуальную машину в единственном экземпляре, то создать её в один этап и с нуля — это вполне нормально (если это проходит автоматически, конечно). Но если приходится иметь дело с кластером похожих машин, которые приходят и уходят, то процесс создания машины стоит разделить на два этапа: создание базового образа и затем клонирование машинок на его основе. Packer как раз и отвечает за первую часть — создание и конфигурацию образов.
Моя самая любимая фича в нём — это возможность переиспользовать один и тот же шаблон для создания образов в разных облачных провайдерах. Всё моё хозяйство живёт в Google Compute Engine, но как приятно всё-таки осознавать, что с минимальными телодвижениями его можно перенести в какой-нибудь AWS. Осталось только адаптировать наши PowerShell виндовых серверов под Packer.
Как обычно, рабочий пример (тестировал на Mac и Ubuntu), я выложил на github.
Крутяк! Спасибо!
Статья устарела, образы не доступны
А как packer определяет, когда машина загрузилась и можно начинать отправлять комбинации клавиш?
Там
boot_wait
параметр был прямо перед комбинацией клавиш, скорее всего это он.Ну и с 2017-го года, когда пост писался, многое изменилось. Формат билдеров уже другой — теперь везде используется HCL вместо JSON. Возможно, virtualbox и установщики убунты тоже поумнели. VB уже сам предлагает конфигурировать машины автоматически, так что может быть появился какой-то внятный стандарт для этого.