
Привет, Хабр!
Packer — это open-source инструмент для создания идентичных машинных образов для множества платформ из одного исходного файла конфигурации. Т.е с пакером можно автоматизировать создание образов для Amazon EC2, VMware, Docker и т.д, используя единый процесс сборки.
Рассмотрим его возможности мультисборки, пост-процессоров и пользовательских плагинов.
Установка и конфиг. файл
Довольно интуитивная установка здесь.
Конфигурационный файл Packer в HCL2 организован в блоки, аргументы и выражения, которые вместе описывают, как должен быть создан каждый образ.
Блоки — это основные контейнеры для конфигурации в HCL2. Они имеют тип, который определяет их функцию, и тело, содержащее аргументы или даже другие блоки, есть такие блоки:
sourceопределяет базовый образ и настройки для создания нового образа.buildсодержит настройки сборки, включая источники и провайдеры.variableобъявляет переменные для параметризации конфигураций.localsпозволяет определять локальные переменные для удобства.
Аргументы внутри блоков присваивают значения определенным свойствам. Например, в блоке source аргумент ami_name может использоваться для определения имени AMI.
Выражения используются для динамического вычисления значений аргументов. HCL2 поддерживает различные типы выражений, включая использование переменных, арифметические операции и вызов функций.
Пример конфигурационного файла на HCL2 для Packer:
variable "region" { type = string default = "us-west-2" } source "amazon-ebs" "example" { ami_name = "packer-example-${var.region}" instance_type = "t2.micro" region = var.region source_ami_filter { filters = { name = "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*" root-device-type = "ebs" virtualization-type = "hvm" } owners = ["099720109477"] most_recent = true } } build { sources = [ "source.amazon-ebs.example" ] }
Здесь мы объявили переменную region, источник amazon-ebs с именем example, который определяет параметры для создания AMI на базе Ubuntu Xenial 16.04. Затем, в блоке build, указывается, что источником для сборки является source.amazon-ebs.example.
Краткий обзор синтаксиса
Язык HCL основной инструмент для работы в Packer.
HCL включает базовые арифм. функции add, subtract, multiply, и divide:
variable "count" { type = number default = 5 } locals { count_plus_one = add(var.count, 1) count_double = multiply(var.count, 2) }
format, join, split, и replace позволяют манипулировать текстовыми данными:
locals { formatted_string = format("This is a %s", "string") joined_string = join(", ", ["Hello", "World"]) splitted_array = split(", ", "Hello, World") replaced_string = replace("Hello, World", "World", "Packer") }
Для работы с коллекциями можно использовать length, element, sort, и merge:
locals { list_example = ["one", "two", "three"] list_length = length(local.list_example) second_element = element(local.list_example, 1) sorted_list = sort(local.list_example) }
file и templatefile, позволяют включать содержимое файлов непосредственно в конфигурацию:
locals { user_data = file("${path.module}/user-data.sh") rendered_template = templatefile("${path.module}/config.tpl", { name = "world" }) }
timestamp возвращает текущую метку времени:
locals { current_timestamp = timestamp() }
md5, sha1, и bcrypt позволяют исполнять криптографические операции для создания хешей строк:
locals { md5_hash = md5("Hello, World") }
uuid генерирует уникальный идентификатор, а cidrsubnet и cidrhost используются для работы с сетевыми адресами:
locals { unique_id = uuid() subnet_address = cidrsubnet("10.0.0.0/16", 8, 0) }
Мультисборка
Мультисборка осуществляется через определение нескольких источников сборки в конфиг файле Packer. Каждый источник сборки указывает на конкретную платформу и содержит необходимые параметры для создания образа для этой платформы.
В процессе сборки пакер запускает каждый источник сборки параллельно или последовательно, в зависимости от конфигурации, создавая образы для каждой целевой платформы.
Мультисборка для Amazon EC2 и Docker:
source "amazon-ebs" "amazon-linux" { ami_name = "packer-example-{{timestamp}}" instance_type = "t2.micro" region = "us-west-2" source_ami_filter { filters = { name = "amzn2-ami-hvm-*-x86_64-gp2" root-device-type = "ebs" virtualization-type = "hvm" } owners = ["137112412989"] most_recent = true } } source "docker" "ubuntu" { image = "ubuntu:18.04" commit = true } build { sources = [ "source.amazon-ebs.amazon-linux", "source.docker.ubuntu", ] }
Оба образа создаются параллельно, используя общую конфигурацию сборки.
Мультисборка для VirtualBox и VMware:
source "virtualbox-iso" "windows-10" { iso_url = "http://example.com/windows-10.iso" iso_checksum = "abc123" // доп. параметры для VirtualBox } source "vmware-iso" "windows-10" { iso_url = "http://example.com/windows-10.iso" iso_checksum = "abc123" // доп. параметры для VMware } build { sources = [ "source.virtualbox-iso.windows-10", "source.vmware-iso.windows-10", ] }
Используя один и тот же исходный ISO-образ, Packer создает два отдельных образа, каждый из которых оптимизирован для своей платформы виртуализации.
Пост-процессоры
Пост-процессоры в Packer конфигурируются в блоке post-processors и могут быть заданы как одиночные задачи или как цепочки задач. Packer выполнит эти пост-процессоры в указанном порядке после успешного создания всех образов.
Загрузка образа в Amazon S3:
post-processors { type = "amazon-s3" only = ["amazon-ebs.ubuntu"] bucket = "my-packer-images" region = "us-west-2" key = "packer/{{user `version`}}/{{.BuildName}}.ami" acl = "private" }
Пост-процессор amazon-s3 используется для загрузки созданного образа для Amazon EBS в заданный S3 bucket. Параметры конфигурации указывают целевой bucket, регион, путь и ключ доступа.
Создание Vagrant box:
post-processors { type = "vagrant" only = ["virtualbox-iso.ubuntu"] output = "builds/ubuntu-{{user `version`}}.box" }
Пост-процессор vagrant преобразует образ, созданный для VirtualBox, в формат Vagrant box, сохраняя его в указанной директории.
Минификация образа Docker:
post-processors { type = "docker-tag" repository = "user/ubuntu" tag = "latest" } post-processors { type = "docker-push" only = ["docker.ubuntu"] }
Пост-процессоры docker-tag и docker-push юзаются для тегирования и последующей загрузки созданного Docker образа в Docker Hub.
Использование цепочек пост-процессоров:
post-processors { sequence { post-processors { type = "vagrant" } post-processors { type = "vagrant-cloud" box_tag = "myusername/mybox" access_token = "{{user `vagrant_cloud_token`}}" } } }
Каждый пост-процессор имеет свой набор конфигурационных параметров:
type: тип пост-процессора (например,vagrant,amazon-s3).only: определяет, для каких сборок должен быть применен пост-процессор.except: исключает определенные сборки из использования пост-процессора.keep_input_artifact: указывает, следует ли сохранять исходный образ после применения пост-процессора.
Пользовательские плагины
Packer предоставляет утилиту packer-sdc для генерации шаблона кода плагина:
packer-sdc plugin new -name=my-custom-plugin -type=[builder|provisioner|post-processor]
Разработка плагина включает реализацию определенного интерфейса в зависимости от типа плагина. Например, для создания нового провайдера вы должны реализовать интерфейс Builder. Packer использует RPC для взаимодействия с плагинами, но большая часть этой работы абстрагирована, т.е можно сфокуситься на бизнес-logic:
package main import ( "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/plugin" ) type MyCustomBuilder struct { // интерфейс Builder } func (b *MyCustomBuilder) Prepare(raws ...interface{}) ([]string, []string, error) { // логика подготовки } // остальная реализация func main() { server, err := plugin.Server() if err != nil { panic(err) } server.RegisterBuilder(new(MyCustomBuilder)) server.Serve() }
Можно использовать стандартные инструменты Go для написания модульных тестов.
func TestMyCustomBuilder_Prepare(t *testing.T) { // тест метода Prepare вашего плагина }
После разработки и тестирования плагина его нужно собрать и установить в локал директорию Packer.
go build -o packer-plugin-my-custom-plugin . mkdir -p ~/.packer.d/plugins mv packer-plugin-my-custom-plugin ~/.packer.d/plugins/
После установки плагина можно использовать его в своих Packer шаблонах, указав его имя в конфигурации:
{ "builders": [ { "type": "my-custom-plugin", "some_parameter": "value" } ] }
my-custom-plugin - это тип плагина, а some_parameter - один из параметров, которые определили в его конфигурации.
Далее можно лить на гит свое сокровище или же оставить у себя на хранение.
С официальными плагинами пакер можно ознакомить здесь. А больше про инфраструктуру вы можете узнать в рамках практических онлайн-курсов от экспертов отрасли.
