Packer
https://www.packer.io/docs
https://rtfm.co.ua/packer-vvedenie-primery/
Терминология
- Артефакт - результат одиночной сборки. Обычно это id'шники или файлы для воссоздания ВМ
- Сборка - одиночная задача, которая произведет образ для одной из платформ
- Сборщик - компонент packer'а, который позволяет создать образ
- Post-processor - компонент packer'а, который берет результат работы сборщика или другого пост-обработчика и обрабатывает его для получения новых артефактов
- Provisioner - устанавливает и конфигурирует ПО на запущенной машине
- Шаблоны - json-файлы в которых определяется сборка образа и конфигурирование компонентов packer'а. Packer позволяет читать шаблон и создавать множество образов машин параллельно
CLI
Packer имеет очень человеко-читаемый вывод. Но он также имеет и машино-читаемый режим.
Его можно включить флагом -machine-readable
для любой команды и не важно в каком порядке, команда флаг
или флаг команда
, главное чтобы он присутствовал.
-
packer build - на основе шаблона генерирует набор артефактов. Разные сборки, опреленные в шаблоне, запускаются параллельно
-
packer console - позволяет проверить как накладываются передаваемые переменные на шаблон
Переменные (уже определенные или пустые) можно вызывать так:{{user `aws_access_key`}} # Этот шаблон заменится на значение переменной определенное пользователем в секции __variables__ в темплейте
Также в console можно загонять разный текст через пайплайн и получать на выходе то как он выглядел бы при обработке
-
packer fix - позволяет исправить шаблон в соответствии с новой версией packer'а (если после обновления packer'а шаблон перестал работать)
-
packer inspect - позволяет получить описание содержимого темплейта без погружения в json. Пример:
$ packer inspect main.json Optional variables and their defaults: aws_access_key = aws_secret_key = Builders: amazon-ebs Provisioners: <No provisioners>
-
packer validate - валидирует шаблон и выводит допущенные в шаблоне ошибки
Шаблоны
Шаблоны это json-файлы которые конфигурируют разные компоненты packer'а и описывают создание одного или более образов ВМ
Компоненты шаблона:
- builders - единственный обязательный элемент шаблона. Список из одного или более объектов, которые описывают сборщиков
- description - строка с описанием того что делает шаблон
- min_packer_version - минимальная версия packer'а для этого шаблона
- post-processors - список объектов, которые описывают разные шаги постобработки при сборке образа
- provisioners - описывает какие средства провижининга будут задействованы для установки и конфигурации ПО при сборке образа
- variables - набор key:value строк, которые описывают переменные
-
sensitive-variables - то же что и
variables
, но эти переменные не пишутся в лог и stdout
Так как JSON не предоставляет комментарии, то чтобы оставить комментарий в шаблоне packer нужно добавить корневой элемент, имя которого начинается с подчеркивания. Пример:
{ "_super-comment": "My cool comment", "variables": { "aws_access_key": "", "aws_secret_key": "" ...
Только такие элементы могут быть комментариями. Другие будут вызывать ошибки при валидации
builders
Билдер (сборщик) - это объект, который определяет параметры сборки
Выглядит так:
{
"builders": [
{
"type": "amazon-ebs",
"access_key": "...",
"secret_key": "...",
// еще куча разных аттрибутов
}
]
}
Поле type является обязательным и по умолчанию является именем по которому можно обратиться к билдеру. Имя используется в выводе при сборке, чтобы было видно что сейчас происходит. Если просто типа билдера не достаточно, то можно и явно указать имя билдера через аттрибут name
communicators
Коммуникаторы это механизм используемый packer'ом для загрузки файлов, запуска скриптов и прочего провижининга запущенной машины. Каждый билд ассоциируется с каким-то коммуникатором для связи, обычно это SSH. Коммуникатор конфигурируется в секции builders и может быть трех видов (это значения ключа communicator):
- none - коммуникатор отключен. В таком случае провижининг не возможен
- ssh - будет установлено ssh соединение с машиной (по умолчанию)
- winrm - WinRM
Аттрибут pause_before_connecting позволяет указать паузу перед подключением к собранной машине. На самом деле это время ожидания перед повторным подключением после первого (тестового) успешного подключения.
template engine
В шаблонах используются следующие постановления:
- Все связанное с шаблонизацией происходит в двойных фигурных скобках
{{ }}
(без пробелов между скобкой и словом как в jinja) - Функции вызываются в двойных фигурных скобках
- Переменные префиксируются точкой и начинаются с большой буквы
Функции
Имеется множество разных функций, которые могут быть использованы в шаблоне
post-processors
Секция пост-процессинга в шаблоне определяет какие дополнительные действия должны сделаны билдерами при сборке образа. Например сжатие образа или загрузка его куда-либо
Каждый описанный пост-процессор будет выполнен для каждого описанного билдера. То есть при двух билдерах и одном пост-процессоре, пост-процессор будет выполнен дважды (по одному разу для каждого билдера)
Есть три варианта описания пост-процессора: простой, детализированный и последовательный. Можно представлять, что простой и детализированный варианты это ссылки на последовательный вариант
- Просто это просто строка с именем пост-процессора
{ "post-processors": ["compress"] }
- Детализированный похож на определение билдера или провижинера. Это объект с разными аттрибутами
{ "post-processors": [ { "type": "compress", "format": "tar.gz" } ] }
- Последовательный еще более подробный
Чтобы сохранять промежуточные артефакты во время пост-процессинга нужно указать true
в аттрибуте keep_input_artifact
для нужного пост-проссинга
Провижининг
{
"provisioners": [
// ... one or more provisioner definitions here
]
}
Провизоры будут запускаться для каждой сборки в том порядке в котором они определены в шаблоне
В определение провизора должен содержаться аттрибут type
, оно определяет имя используемого провизора. У разных провизоров разные обязательные поля, например провизор shell
требует аттрибута shell
Можно использовать аттрибуты only
или except
в объекте провизора, чтобы избрать нужные билды. Они принимают в себя список имен билдов (не типов билдеров, нужно указать билдам имена и использовать их тут)
Наравне с обычными провизорами, можно указать провижининг для обработки ошибок обычного провизора. Он сработает при возникновении ошибки в работе провизора
Можно делать переопределения в провизорах. Это может быть нужно когда мы хотим чтобы создаваемые машины отличались
{
"type": "shell",
"script": "script.sh",
"override": {
"vmware-iso": {
"execute_command": "echo 'password' | sudo -S bash {{.Path}}"
}
}
}
Иногда нужно делать паузу при сборке. Например когда ваш скрипт в провизоре делает ребут, тогда нужно подождать некоторое время перед запуском следующего провизора
Это можно сделать с помощью аттрибута pause_before
, он указывается в провизоре который идет после перезагрузки и принимает время в секундах
max_retries
- определяет количество повторных попыток после первой неудачной
timeout
- это таймаут на выполнение провизора прежде чем он будет считаться зафейленым
Пользовательские переменные
Переменные позволяют шаблонам быть параметризированными и не хранить в шаблонах секретные данные (например токены)
Переменные объявляются в секции variables, а также могут быть переданны через файл или флаг -var
Если переменная будет передваться как аргумент, то лучше ее объявить пустой в шаблоне. Тогда будет понятно, что эта переменная будет заменена
Например тут мы сразу видим какие переменные нам нужно передать аргументами
{
"variables": {
"aws_access_key": "",
"aws_secret_key": ""
},
"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}"
// ...
}
]
}
Устанавливать переменные можно из файла или через командную строку
Через командную строку это делается через ключ -var
которому передается строка в формате "var_name=var_value". Ключи -var
может быть передан сколько угодна раз (в зависимости от того как много у вас переменных). Переменные из командной строки переопределяют любые ранее заданные переменные
Чтобы определить переменные в отдельном файле, нужно в нем описать объект variables из шаблона:
{
"aws_access_key": "foo",
"aws_secret_key": "bar"
}
Переменные из файла с переменными указанного в конце переопределят предыдущие
То же и с комбинированием-var-file
и-var
, то что указано позже - важнее. Не важно файл это или параметр команды
Существует секция sensitive-variables
, в ней можно указывать чувствительные переменные, которые не должны быть видно в журналах и прочих местах (например это токены)
{
"variables": {
"my_secret": "{{env `MY_SECRET`}}",
"not_a_secret": "plaintext",
"foo": "bar"
},
"sensitive-variables": ["my_secret", "foo"],
}
На работу приложения это никак не влияет, влияет только на вывод и журналы
Коммуникаторы
Коммуникаторы это механизм для загрузки файлов, выполнения скриптов и прочих действий в созданной машине. Коммуникаторы конфигурируются в секции builders
Поддерживаются три вида коммуникаторов:
- none - никакой
- ssh - ssh (по умолчанию)
- winrm - winrm
Иногда ssh может быть не сконфигурирован в дефолтном образе, тогда нужно использовать файл preseed или kickstart для предконфигурирования
SSH коммуникотор имеет огромное количество опций, которые можно посмотреть здесь https://www.packer.io/docs/communicators/ssh
Builders
Билдеры отвечают за создание машины и генерацию образа из нее для различных платформ. Packer может работать с различными билдерами по умолчанию и может быть расширен для добавления новых билдеров
По умолчанию в packer доступно огромное количество билдеров для огромного количества платформ. Опишу здесь лишь то что интересно мне:
docker
Docker билдер собирает образы для докера. Он стартует докер контейнер, запускает провижининг внутри этого контейнера и экспортирует контейнер в образ
Провижининг в этом случае происходит без использования Dockerfile, это происходит так же как если бы вы настраивали железный или виртуальный сервер
Для работы docker-builder'а требуется docker engine
Обязательные опции:
- commit/discard/export_path - закоммитить контейнер/отменить/экспортировать в указанный tar файл (одновременно может быть указано только одно из трех)
- image - базовый образ для контенера (из которого он будет запущен)
Также есть еще миллион опциональных параметров
https://www.packer.io/docs/builders/docker
Packer умеет добавлять к образу различную информацию (тэги, и прочее) и импортировать его сразу в репозиторий образов
file
file-builder - то не настоящий билдер, он просто создает артефакты из файла и может быть использован для отладки пост-процессоров без длительного ожидания
null
Это тоже не настоящий билдер. Он просто настраивает ssh-подключение и запускает провижининг. Полезно для дебагинга провизоров так как занимает мало времени
Vagrant
Обязательные:
- source_path - URL или имя используемого vagrant-бокса (имя на vagrant-cloud, имя на другом хранилище, имя локального файла). Если используется .box имя (url или локальный файл), то нужно также указать box_name опцию
-
global_id - айдишник уже существующего в системе бокса (посмотреть айдишники можно командой
vagrant global-status
)
Две эти ^ опции - взаимоисключающие, возможна только одна из них
Остальные опции:
-
output_dir - папка в которую будет помещен бокс и прочее. Это нужно для избежания коллизий (чтобы файлы не смешивались). Если не указывать, то папка будет создана все-равно
output-BUILDERNAME
- box_name - нужно при использовании source_path
- provider - нужно при использовании source_path, указывает на используемый провайдер (virtualbox, docker, etc)
- checksum - чексумма .box файла
-
checksum_type - тип указываемой выше чексуммы. Без этого поля чексумма не может быть проверена. Поддерживаемые значения:
- none
- md5
- sha1
- sha256
- sha512
Рекомендуется проверять чексумму, потому что большие файлы могут быть легко повреждены при загрузке
- template - путь до темплейта с vagrantfile'ом. Используется шаблонизация на языке Go
-
skip_add - не вызывать
vagrant add
для добавления бокса в локальное окружение -
teardown_method - что сделать с боксом после сборки, возможные значения:
- halt <- default
- suspend
- destroy
- box_version - версия
-
add_cacert - эквивалент
vagrant box add --cacert
-
add_capath - эквивалент
vagrant box add --capath
-
add_cert - эквивалент
vagrant box add --cert
-
add_clean - эквивалент
vagrant box add --clean
-
add_force - эквивалент
vagrant box add --force
-
add_insecure - эквивалент
vagrant box add --insecure
-
output_vagrantfile - эквивалент
vagrant package --vagrantfile
-
package_include - эквивалент
vagrant package --include
Эквиваленты можно посмотреть здесь https://www.vagrantup.com/docs/cli/box.html#box-add
- skip_package - пакер не будет упаковывать бокс в .box-файл
virtualbox
VirtualBox builder может создавать ВМ и экспортировать их в OVA/OVF формат
- virtualbox-iso - начинает с iso, создает новую ВМ, устанавливает и провижинит ПО и экспортирует машину в образ
- virtualbox-ovf - импортирует существующий OVF/OVA файл, запускает провизоры поверх этой ВМ и экспортирует машину для создания образа
- virtualbox-vm - поверх существующей ВМ запускает провижининг и может сделать снапшот или экспортировать машину
provisioners
Провизоры это встроенное и стороннее ПО для конфигурирования и установки машины после загрузки
Обычно они устанавливают пакеты, патчат ядро, создают юзеров, загружают код приложений
ansible-local
В машину будет закинут плейбук и запущен ансибл в локальном режиме (то есть виртуалка сама себя сконфигурирует [без ssh])
{
"type": "ansible-local",
"playbook_file": "local.yml"
}
ansible-remote
{
"type": "ansible",
"playbook_file": "./playbook.yml"
}
file
В машину будет загружен файл
Для загрузки файла будет использовать пользователь для провижининга (обычно это не рут), поэтому рекомендуется загрузить таким образом файл куда-нибудь, а потом уже с помощью модуля shell делать с ним что надо (установить права, положить в нужно место и тд)
{
"type": "file",
"source": "app.tar.gz",
"destination": "/tmp/app.tar.gz"
}
shell
{
"type": "shell",
"inline": ["echo foo"]
}
Вместо инлайн можно указывать скрипты (которые там уже лежат)
post-proccessors
Пост-процессоры запускаются после сборки и провижининга
Могут загружать собранный образ куда-то (в облако), сжимать, или что угодно еще
No Comments