Packer: мультисборка, пост-процессоры и пользовательские плагины

от автора

Привет, Хабр!

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 — один из параметров, которые определили в его конфигурации.

Далее можно лить на гит свое сокровище или же оставить у себя на хранение.


С официальными плагинами пакер можно ознакомить здесь. А больше про инфраструктуру вы можете узнать в рамках практических онлайн-курсов от экспертов отрасли.


ссылка на оригинал статьи https://habr.com/ru/articles/796135/