Введение
Packer – утилита для сборки образов виртуальных машин для различных платформ из одного файла конфигурации.
Packer не является заменой таких средств как Chef или Ansible, и может использовать их для конфигрирования системы перед сборкой образа.
Образ, создаваемый Packer, включает в себя настроенную операционную систему, необходимый набор ПО, который позволяет быстро развернуть новую машину. Packer умеет создавать образы AMI для EC2, VMDK/VMX файлы для VMware, OVF для VirtualBox и т.д.
Полный список поддерживаемых платформ можно найти тут>>>.
Пример использования Packer с другими системами, входящими в Atlas:
Установка Packer
Выбираем подходящий пакет на странице загрузок Packer, загружаем архив:
$ wget https://releases.hashicorp.com/packer/0.10.2/packer_0.10.2_linux_amd64.zip
Устанавливаем:
$ unzip packer_0.10.2_linux_amd64.zip $ sudo cp packer /usr/local/bin/ [sudo] password for setevoy: $ packer --version 0.10.2
Сборка образа
Файл конфигурации, в котором описывается создаваемый образ, в терминологии Packer называется шаблоном и представляет собой JSON-файл.
Создаём первый шаблон – ec2_example.json
:
{ "variables": { "aws_access_key": "", "aws_secret_key": "" }, "builders": [{ "type": "amazon-ebs", "access_key": "{{user `aws_access_key`}}", "secret_key": "{{user `aws_secret_key`}}", "region": "us-east-1", "source_ami": "ami-fce3c696", "instance_type": "t2.micro", "ssh_username": "ubuntu", "ami_name": "packer-example {{timestamp}}" }] }
Variables
Во время сборки – вы передаёте значения для aws_access_key
и aws_secret_key
в пользовательских переменных, которые могут быть заданы в файле, в переменных окружения или переданы через командную строку.
Это позволяет убрать некоторые параметры из шаблона, такие как данные для авториазации.
Подробее о user variables – тут>>>.
Builders
Шаблон включает в себя секцию builders
(“сборщики“), которая состоит из массива JSON-объектов, описывающий конкретный сборщик. builder
является компонентом Packer для создания машины и затем – её образа.
В примере выше используется только один такой сборщик – amazon-ebs
, который является сборщиком образов Amazon EC2 AMI. Он создаёт виртуальную машину из исходного образа, выполняет её настройку, устанавливая и настраивая необходимое ПО, а затем – создаёт из этой машины новый AMI. Описание других сборщиков для Amazon можно найти тут>>>, а больше про builders
– тут>>>.
Валидация шаблона
Прежде, чем запустить сборку нового образа – выполним проверку шаблона с помощью validate:
$ packer validate --help Usage: packer validate [options] TEMPLATE Checks the template is valid by parsing the template and also checking the configuration with the various builders, provisioners, etc. If it is not valid, the errors will be shown and the command will exit with a non-zero exit status. If it is valid, it will exit with a zero exit status. Options: -syntax-only Only check syntax. Do not verify config of the template. -except=foo,bar,baz Validate all builds other than these -only=foo,bar,baz Validate only these builds ...
Проверяем:
$ packer validate ec2_example.json Template validated successfully.
Сборка
Если валидация прошла успешно – выполняем сборку образа с помощью build
:
$ packer build ec2_example.json amazon-ebs output will be in this color. ==> amazon-ebs: Prevalidating AMI Name... ==> amazon-ebs: Inspecting the source AMI... ==> amazon-ebs: Creating temporary keypair: packer 5807496d-7d0c-9ad9-f3d4-1bf0a1b7173e ==> amazon-ebs: Creating temporary security group for this instance... ==> amazon-ebs: Authorizing access to port 22 the temporary security group... ==> amazon-ebs: Launching a source AWS instance... amazon-ebs: Instance ID: i-8aac67ba ==> amazon-ebs: Waiting for instance (i-8aac67ba) to become ready... ==> amazon-ebs: Waiting for SSH to become available... ==> amazon-ebs: Connected to SSH! ==> amazon-ebs: Stopping the source instance... ==> amazon-ebs: Waiting for the instance to stop... ==> amazon-ebs: Creating the AMI: packer-example 1476872556 amazon-ebs: AMI: ami-82194995 ==> amazon-ebs: Waiting for AMI to become ready... ==> amazon-ebs: Terminating the source AWS instance... ==> amazon-ebs: Cleaning up any extra volumes... ==> amazon-ebs: No volumes to clean up, skipping ==> amazon-ebs: Deleting temporary security group... ==> amazon-ebs: Deleting temporary keypair... Build 'amazon-ebs' finished. ==> Builds finished. The artifacts of successful builds are: --> amazon-ebs: AMIs were created: us-east-1: ami-82194995
EC2, запущенный Packer-ом для создания AMI:
И собранный AMI:
$ aws --region us-east-1 ec2 describe-images --image-ids ami-82194995 { "Images": [ { "VirtualizationType": "hvm", "Name": "packer-example 1476872556", "Hypervisor": "xen", "SriovNetSupport": "simple", "ImageId": "ami-82194995", "State": "available", "BlockDeviceMappings": [ { "DeviceName": "/dev/sda1", "Ebs": { "DeleteOnTermination": true, "SnapshotId": "snap-148d7e0b", "VolumeSize": 8, "VolumeType": "gp2", "Encrypted": false } }, { "DeviceName": "/dev/sdb", "VirtualName": "ephemeral0" }, { "DeviceName": "/dev/sdc", "VirtualName": "ephemeral1" } ], "Architecture": "x86_64", "ImageLocation": "264418146286/packer-example 1476872556", "RootDeviceType": "ebs", "OwnerId": "264418146286", "RootDeviceName": "/dev/sda1", "CreationDate": "2016-10-19T10:24:43.000Z", "Public": false, "ImageType": "machine" } ] }
Примечание: так как данные авторизации не были указаны – то Packer использует профиль по умолчанию из файла ~/.aws/credentials
. Подробнее про авторизацию Packer в AWS – см. тут>>>.
Provisioners
В предыдущем примере – мы просто перепаковали уже существующий образ, не внеся никаких изменений в систему.
Для того, что бы установить необходимые сервисы и выполнить другие настройки системы – используем provisioners
.
Изменим предыдущий шаблон, и добавим установку NGINX:
{ "variables": { "aws_access_key": "", "aws_secret_key": "" }, "builders": [{ "type": "amazon-ebs", "access_key": "{{user `aws_access_key`}}", "secret_key": "{{user `aws_secret_key`}}", "region": "us-east-1", "source_ami": "ami-fce3c696", "instance_type": "t2.micro", "ssh_username": "ubuntu", "ami_name": "packer-example {{timestamp}}" }], "provisioners": [{ "type": "shell", "inline": [ "sleep 30", "sudo apt-get update", "sudo apt-get install -y nginx" ] }] }
Проверяем:
$ packer validate ec2_example.json Template validated successfully.
И запускаем сборку:
$ packer build ec2_example.json amazon-ebs output will be in this color. ==> amazon-ebs: Prevalidating AMI Name... ... ==> amazon-ebs: Connected to SSH! ... ==> amazon-ebs: Provisioning with shell script: /tmp/packer-shell973438975 amazon-ebs: Ign http://us-east-1.ec2.archive.ubuntu.com trusty InRelease amazon-ebs: Get:1 http://us-east-1.ec2.archive.ubuntu.com trusty-updates InRelease [65.9 kB] amazon-ebs: Get:2 http://us-east-1.ec2.archive.ubuntu.com trusty-backports InRelease [65.9 kB] ... ==> amazon-ebs: Deleting temporary keypair... Build 'amazon-ebs' finished. ==> Builds finished. The artifacts of successful builds are: --> amazon-ebs: AMIs were created: us-east-1: ami-8d19499a
Параллельные сборки
Packer может выполнить сборку нескольких образов для нескольких платформ одновременно, из единого шаблона.
В примерах выше – мы собирали AMI для AWS EC2. Теперь добавим сборщик Docker-образа – docker builder.
В блок builders
добавляем:
... "instance_type": "t2.micro", "ssh_username": "ubuntu", "ami_name": "packer-example {{timestamp}}" },{ "type": "docker", "image": "ubuntu", "commit": true }], "provisioners": [{ ...
Т.к. Docker base образ ("image": "ubuntu"
) не имеет sudo
– немного извратимся в блоке provisioners
:
... "provisioners": [{ "type": "shell", "inline": [ "sleep 30", "if which sudo; then sudo apt-get update && sudo apt-get install -y nginx; else apt-get update && apt-get install -y nginx; fi" ] }] ...
Проверяем и запускаем:
$ packer validate ec2_example.json Template validated successfully.
$ sudo packer build ec2_example.json [sudo] password for setevoy: amazon-ebs output will be in this color. docker output will be in this color. ==> amazon-ebs: Prevalidating AMI Name... ==> docker: Creating a temporary directory for sharing data... ==> docker: Pulling Docker image: ubuntu docker: latest: Pulling from ubuntu docker: 58488e45273c: Already exists docker: 25810b66099e: Already exists ... ==> amazon-ebs: Deleting temporary keypair... Build 'amazon-ebs' finished. ==> Builds finished. The artifacts of successful builds are: --> amazon-ebs: AMIs were created: us-east-1: ami-12065605 --> docker: Imported Docker image: e64b553b8cb6ac39c2b00e27708bd9972ab91e2ec43aad52b2420ee297fa2aae
Проверяем наличие образа:
$ sudo docker images | grep e64b553b8cb <none> <none> e64b553b8cb6 14 minutes ago 223.1 MB
Проверяем NGINX:
$ sudo docker run e64b553b8cb6 which nginx /usr/sbin/nginx
Что бы собрать только определённый образ одним из сборщиков – используйте -only
, например – сбилдить только Docker образ и не создавать AWS AMI можно так:
$ sudo packer build -only docker ec2_example.json docker output will be in this color. ==> docker: Creating a temporary directory for sharing data... ==> docker: Pulling Docker image: ubuntu docker: latest: Pulling from ubuntu docker: 58488e45273c: Already exists ...
Post-Processor
post-processor
шаблона определяет действия, которые должны быть выполнены после сборки образа сборщиками. Например – заархивировать образ, загрузить артефакт (образ) в удалённое хранилище и т.д.
Имеется три варианта добавления post-processor
в шаблон – simple definitions, detailed definitions и sequence definitions.
simple definition – является строкой и включает в себя только имя постпроцессора, например:
{ "post-processors": ["compress"] }
detailed definition является JSON-объектом, и схож с builders
и provisioners
.
Он включает в себя поле type
, в котором указывается имя постпроцессор для выполнения и может содержать дополнительные настройки для него, например:
{ "post-processors": [ { "type": "compress", "format": "tar.gz" } ] }
sequence definition – является JSON-массивом, состоящем из simple- или detailed definitions, например:
{ "post-processors": [ [ "compress", { "type": "upload", "endpoint": "http://example.com" } ] ] }
Учтите, что постпроцессоры выполняются в том порядке, в котором они описаны в шаблоне.
Добавляем docker-tag
post-processor
в шаблон:
... "if which sudo; then sudo apt-get update && sudo apt-get install -y nginx; else apt-get update && apt-get install -y nginx; fi" ] }], "post-processors": [{ "type": "docker-tag", "repository": "setevoy/ubuntu_nginx", "tag": "1.0" }] }
Запускаем сборку, перенаправив STDIN
и STDOUT
в файл packer.log
:
$ sudo packer build -only docker ec2_example.json 2>&1 | tee packer.log docker output will be in this color. ==> docker: Creating a temporary directory for sharing data... ==> docker: Pulling Docker image: ubuntu docker: latest: Pulling from ubuntu ... docker (docker-tag): Tagging image: ba7fe714720f6457d812d76ca4a222fb8dbaea8549decd4d9a119b43ef9b8d67 docker (docker-tag): Repository: setevoy/ubuntu_nginx:1.0 Build 'docker' finished. ==> Builds finished. The artifacts of successful builds are: --> docker: Imported Docker image: ba7fe714720f6457d812d76ca4a222fb8dbaea8549decd4d9a119b43ef9b8d67 --> docker: Imported Docker image: setevoy/ubuntu_nginx:1.0
Готово.