hitcounter
  • April 27, 2018
  • Yuriy Medvedev

Packer и что нам нужно для начала

Packer — это инструмент для создания одинаковых образов ОС для различных платформ из одного описания. Packer отличная утилита для использовании в ваших ci/cd pipelines.

Что потребуется? Packer VirtualBox Vagrant

Установка packer

Osx

Установка в osx через brew


Теперь проверяем версию


packer -v 1.1.3


### Установка в любой Unix-like os

Для простоты установки Packer вы можете воспользоваться скриптом

bash #!/usr/bin/env bash cd ~

Prerequisites

if [ “$(uname)” == “Darwin” ]; then brew install jq > /dev/null 2>&1

For Linux

elif [ “$(expr substr $(uname -s) 1 5)” == “Linux” ]; then sudo apt-get update sudo apt-get install -q –assume-yes jq software-properties-common prometheus-node-exporter fi #check terraform and packer local archives

if [ -f ~/packer.zip ]; then rm -f ~/packer.zip fi

Get URLs for most recent versions

For OS-X

if [ “$(uname)” == “Darwin” ]; then terraform_url=$(curl -s https://releases.hashicorp.com/index.json | jq ‘{terraform}’ | egrep “darwin.*64” | sort -r | head -1 | awk -F[\“] ‘{print $4}’) packer_url=$(curl -s https://releases.hashicorp.com/index.json | jq ‘{packer}’ | egrep “darwin.*64” | sort -r | head -1 | awk -F[\“] ‘{print $4}’ )

For Linux

elif [ “$(expr substr $(uname -s) 1 5)” == “Linux” ]; then terraform_url=$(curl -s https://releases.hashicorp.com/index.json | jq ‘{terraform}’ | egrep “linux.*amd64” | sort -r | head -1 | awk -F[\“] ‘{print $4}’) packer_url=$(curl -s https://releases.hashicorp.com/index.json | jq ‘{packer}’ | egrep “linux.*amd64” | sort -r | head -1 | awk -F[\“] ‘{print $4}’)

fi

Create a move into directory.

cd mkdir packer > /dev/null 2>&1 mkdir -p terraform && cd $_

Download Terraform. URI: https://www.terraform.io/downloads.html

echo “Downloading $terraform_url.” curl -o terraform.zip $terraform_url > /dev/null 2>&1

Unzip and install

echo “Install terraform” unzip -o terraform.zip > /dev/null 2>&1 echo “done”

Change directory to Packer

cd ~/packer

Download Packer. URI: https://www.packer.io/downloads.html

echo “Downloading $packer_url.” curl -o packer.zip $packer_url > /dev/null 2>&1

Unzip and install

echo “Install packer” unzip -o packer.zip > /dev/null 2>&1 echo “Installed packer”

#check terraform and packer local archives if [ -f ~/terraform.zip ]; then chattr -i -a ~/terraform* > /dev/null 2>&1 chmod ugo+w ~/terraform* > /dev/null 2>&1 rm -f ~/terraform* > /dev/null 2>&1 fi if [ -f ~/terraform/terraform.zip ]; then chattr -i -a ~/terraform/terraform* > /dev/null 2>&1 chmod ugo+w ~/terraform/terraform* > /dev/null 2>&1 rm -f ~/terraform/terraform* > /dev/null 2>&1 fi if [ -f ~/packer.zip ]; then rm -f ~/packer.zip fi if [ -f ~/packer/packer.zip ]; then rm -f ~/packer/packer.zip fi

echo “Add packer and terraform to user path” if [ “$(uname)” == “Darwin” ]; then echo ‘ # Terraform & Packer Paths. export PATH=~/terraform/:~/packer/:$PATH ‘ >>~/.bash_profile

source ~/.bash_profile

For Linux

elif [ “$(expr substr $(uname -s) 1 5)” == “Linux” ]; then echo ‘ # Terraform & Packer Paths. export PATH=~/terraform/:~/packer/:$PATH ‘ >>~/.bashrc

source ~/.bashrc fi echo “All done. Local path” which packer which terraform

 Как бонус этот скрипт скачивает последню версию Packer и Terrraform с официального сайта, прописывают нужные пути в переменные среды.


### Установка из исходных кодов

Чтобы установить Packer из исходных кодов, необходимо установить [Golang](https://golang.org/) и склонировать исходные коды с официально [github](https://github.com/hashicorp/packer)  репозитория


$ mkdir -p $GOPATH/src/github.com/hashicorp && cd $_ $ git clone https://github.com/hashicorp/packer.git $ cd packer


После кланирования компилируем

make dev


## Ваше первый packer шаблон

После установки мы можем приступить к сборки образа, давайте смоделируем ситуацию. Есть какой-то веб сервер, на него мы хотим установить ubuntu,nginx,php
Шаг первый создаем json файл для соборки в нашем примере назовем его template.json

mkdir ubuntu-packer && cd $_ vi template.json

Далее опишем все стадии сборки будущего образа.

json

{ “provisioners”:[ { “type”:“shell”, “execute_command”:“echo ‘vagrant’|sudo -S sh ‘{{.Path}}’”, “override”:{ “virtualbox-iso”:{ “scripts”:[ “scripts/base.sh”, “scripts/vagrant.sh”, “scripts/virtualbox.sh”, “scripts/cleanup.sh”, “scripts/zerodisk.sh”, “scripts/nginx.sh” ] } } } ], “post-processors”:[ { “type”:“vagrant”, “override”:{ “virtualbox”:{ “output”:“ubuntu-14-04-x64-virtualbox.box” } } } ], “builders”:[ { “type”:“virtualbox-iso”, “boot_command”:[ “”, “”, “”, “/install/vmlinuz”, “ auto”, “ console-setup/ask_detect=false”, “ console-setup/layoutcode=us”, “ console-setup/modelcode=pc105”, “ debian-installer=en_US”, “ fb=false”, “ initrd=/install/initrd.gz”, “ kbd-chooser/method=us”, “ keyboard-configuration/layout=USA”, “ keyboard-configuration/variant=USA”, “ locale=en_US”, “ netcfg/get_hostname=ubuntu-1404”, “ netcfg/get_domain=vagrantup.com”, “ noapic”, “ preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg”, “ – “, “” ], “boot_wait”:“10s”, “disk_size”:40960, “guest_os_type”:“Ubuntu_64”, “http_directory”:“http”, “iso_checksum”:“dd54dc8cfc2a655053d19813c2f9aa9f”, “iso_checksum_type”:“md5”, “iso_url”:“http://releases.ubuntu.com/14.04/ubuntu-14.04.5-server-amd64.iso", “ssh_username”:“vagrant”, “ssh_password”:“vagrant”, “ssh_port”:22, “ssh_wait_timeout”:“10000s”, “shutdown_command”:“echo ‘shutdown -P now’ > /tmp/shutdown.sh; echo ‘vagrant’|sudo -S sh ‘/tmp/shutdown.sh’“, “vboxmanage”:[ [ “modifyvm”, “{{.Name}}”, “–memory”, “512” ], [ “modifyvm”, “{{.Name}}”, “–cpus”, “1” ] ] } ] }



Минимальный шаблон мы создали, давайте рассмотрим, что он в себе содержит:
### Builder
В качестве билдера я использую virtualbox

“builders”:[ { “type”:“virtualbox-iso”, “boot_command”:[ “”, “”, “”, “/install/vmlinuz”, “ auto”, “ console-setup/ask_detect=false”, “ console-setup/layoutcode=us”, “ console-setup/modelcode=pc105”, “ debian-installer=en_US”, “ fb=false”, “ initrd=/install/initrd.gz”, “ kbd-chooser/method=us”, “ keyboard-configuration/layout=USA”, “ keyboard-configuration/variant=USA”, “ locale=en_US”, “ netcfg/get_hostname=ubuntu-1404”, “ netcfg/get_domain=vagrantup.com”, “ noapic”, “ preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg”, “ – “, “” ], “boot_wait”:“10s”, “disk_size”:40960, “guest_os_type”:“Ubuntu_64”, “http_directory”:“http”, “iso_checksum”:“dd54dc8cfc2a655053d19813c2f9aa9f”, “iso_checksum_type”:“md5”, “iso_url”:“http://releases.ubuntu.com/14.04/ubuntu-14.04.5-server-amd64.iso", “ssh_username”:“vagrant”, “ssh_password”:“vagrant”, “ssh_port”:22, “ssh_wait_timeout”:“10000s”, “shutdown_command”:“echo ‘shutdown -P now’ > /tmp/shutdown.sh; echo ‘vagrant’|sudo -S sh ‘/tmp/shutdown.sh’“, “vboxmanage”:[ [ “modifyvm”, “{{.Name}}”, “–memory”, “512” ], [ “modifyvm”, “{{.Name}}”, “–cpus”, “1” ] ] } ]

В билдере у меня указаны следующие параметры:

- type -- тип билдера могут быть следующими 

	* Alicloud ECS

	* Amazon EC2

	* Azure

	* CloudStack

	* DigitalOcean

	* Docker

	* File

	* Google Cloud

	* Hyper-V

	* LXC

	* LXD

	* NAVER Cloud

	* Null
	
	* 1&1
	
	* OpenStack
	
	* Oracle
	
	* Parallels
	
	* ProfitBricks
	
	* QEMU
	
	* Scaleway
	
	* Triton
	
	* VirtualBox
	
	* VMware
Cписок постоянно изменятеся

- boot_command - команды которые выполняются, при зашрузки с cd 

- boot_wait - время которое, packer будет ожидать загрузку

- disk_size - разрмер диска, в создаваемой виртальной машины

- guest_os_type - тип устанавливаемой операционной системы

- iso_checksum - чек сумма для проверки iso образа

- iso_checksum_type - тип чек-суммы, могут быть md5, sha1, sha256, или sha512

- iso_url - источник откуда мы будем выкачивать iso образ, может быть либо локальным, либо ссылка на образ или все вместе

- ssh_username, ssh_password, ssh_port, ssh_wait_timeout - параметры для работы по sshб пользователь,пароль, порт и таймаут после, которого пакер будет считать, что сервер недоступен

- shutdown_command - команда/команды для выключение 

- vboxmanage - данный параметр служит для изменения параметров виртуальной машины через Virtualbox manager, вы можете изменить количество ядер, оперативной памати и тд

### Provisioners

json “provisioners”:[ { “type”:“shell”, “execute_command”:“echo ‘vagrant’|sudo -S sh ‘{{.Path}}’”, “override”:{ “virtualbox-iso”:{ “scripts”:[ “scripts/base.sh”, “scripts/vagrant.sh”, “scripts/virtualbox.sh”, “scripts/cleanup.sh”, “scripts/zerodisk.sh”, “scripts/nginx.sh” ] }

В моем примере я использую только bash скрипты, но настройка и установка ПО в процессе сборки не ограничивается скриптами, вы можете использовать любые другие ci/cd инструменты и утилиты.

Все мои скрипты раположены в отдельной папке для простоты

### Post-processors

json ], “post-processors”:[ { “type”:“vagrant”, “override”:{ “virtualbox”:{ “output”:“ubuntu-14-04-x64-virtualbox.box” } } } ],


В моем случае, после сборки я хочу получить vagrant box.

### Подготовка 	preseed

> Технология preseed позволяет заранее указать ответы на вопросы, задаваемые при установке, убрав таким образом необходимость отвечать на них вручную. Это позволяет создать полностью автоматические сценарии со всеми необходимыми настройками.

> Если копнуть чуть глубже, то можно выяснить, что Debian Installer использует систему debconf для управления процессом установки, а технология preseed просто заранее добавляет нужные ответы в базу данных debconf. Таким образом с помощью preseed можно настроить не только установщик, но и другие приложения, использующие debconf, хотя эта особенность вам вряд ли пригодится.

> Каждая инструкция preseed состоит обычно из четырёх частей: владельца, названия параметра, типа параметра и значения. Между частями обязательно должен быть ровно один пробел. Установщик носит имя d-i, и именно это значение будет стоять в первом поле в большинстве инструкций

Приступим, вначале создаем папку где будем хранить файл с preseed

mkdir http


Теперь создаем файл который будет использоваться для автомотизации установки ubuntu с iso образа, ``` vi http/preseed.cfg ```

Содержание достаточно простое:

debconf debconf/frontend select Noninteractive choose-mirror-bin mirror/http/proxy string d-i base-installer/kernel/override-image string linux-server d-i clock-setup/utc boolean true d-i clock-setup/utc-auto boolean true d-i finish-install/reboot_in_progress note d-i grub-installer/only_debian boolean true d-i grub-installer/with_other_os boolean true d-i partman-auto-lvm/guided_size string max d-i partman-auto/choose_recipe select atomic d-i partman-auto/method string lvm d-i partman-lvm/confirm boolean true d-i partman-lvm/confirm_nooverwrite boolean true d-i partman-lvm/device_remove_lvm boolean true d-i partman/choose_partition select finish d-i partman/confirm boolean true d-i partman/confirm_nooverwrite boolean true d-i partman/confirm_write_new_label boolean true

Default user

d-i passwd/user-fullname string vagrant d-i passwd/username string vagrant d-i passwd/user-password password vagrant d-i passwd/user-password-again password vagrant d-i passwd/username string vagrant

Minimum packages (see postinstall.sh)

d-i pkgsel/include string openssh-server d-i pkgsel/install-language-support boolean false d-i pkgsel/update-policy select none d-i pkgsel/upgrade select none

d-i time/zone string UTC d-i user-setup/allow-password-weak boolean true d-i user-setup/encrypt-home boolean false tasksel tasksel/first multiselect standard, ubuntu-server

После этого, создаем директорию со скриптами и сами скрипты

### Скрипты для Packer(ci/cd на коленки)

mkdir scripts

scripts kenny$ tree . ├── base.sh ├── cleanup.sh ├── nginx.sh ├── vagrant.sh ├── virtualbox.sh └── zerodisk.sh

Теперь можно и начинать писать скрипты, мои примеры ниже

#### base.sh

apt-get update apt-get -y upgrade apt-get -y install linux-headers-$(uname -r)

sed -i -e ‘/Defaultss+env_reset/a Defaultstexempt_group=sudo’ /etc/sudoers sed -i -e ’s/%sudo ALL=(ALL:ALL) ALL/%sudo ALL=NOPASSWD:ALL/g’ /etc/sudoers

echo “UseDNS no” >> /etc/ssh/sshd_config


#### cleanup.sh

apt-get -y autoremove apt-get -y clean

echo “cleaning up guest additions” rm -rf VBoxGuestAdditions*.iso VBoxGuestAdditions*.iso.?

echo “cleaning up dhcp leases” rm /var/lib/dhcp/*

echo “cleaning up udev rules” rm /etc/udev/rules.d/70-persistent-net.rules mkdir /etc/udev/rules.d/70-persistent-net.rules rm -rf /dev/.udev/ rm /lib/udev/rules.d/75-persistent-net-generator.rules


#### vagrant.sh

date > /etc/vagrant_box_build_time

mkdir /home/vagrant/.ssh wget –no-check-certificate ‘https://github.com/mitchellh/vagrant/raw/master/keys/vagrant.pub' -O /home/vagrant/.ssh/authorized_keys chown -R vagrant /home/vagrant/.ssh chmod -R go-rwsx /home/vagrant/.ssh


#### virtualbox.sh

apt-get -y install virtualbox-guest-utils


#### zerodisk.sh

dd if=/dev/zero of=/EMPTY bs=1M rm -f /EMPTY

#### nginx.sh

export DEBIAN_FRONTEND=noninteractive

mv /tmp/sources.list /etc/apt/sources.list wget http://www.dotdeb.org/dotdeb.gpg -O - | apt-key add -

apt-get update

apt-get -qy install nginx cp /tmp/nginx.conf /etc/nginx/sites-available/default

apt-get -qy install php5-fpm php5-cli php5-intl php5-xhprof

curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer apt-get -qy install mysql-client mysql-server php5-mysqlnd



### Валидация темплейта и сборка с помощью Packer
Для валидации нашего темплейта достаточно выполнить команду:

packer validate template.json

 
После выполнения команды мы должны увидеть следующее сообщение

Template validated successfully.


После проверки мы можем приступать к сборке:

packer build ubuntu.json

 
После сборки мы получим Vagrant box c именем   ubuntu-14-04-x64-virtualbox.box, который уже можно использовать,

## Использование Amazon Web services(aws) для сборки Packer'ом
При использование aws в качестве билдера, шаблон упроститься и сократиться, примерный вид шаблона ниже 

template_aws.json


json { “provisioners”: [ { “type”: “shell”, “execute_command”: “echo ‘vagrant’|sudo -S sh ‘{{.Path}}’”, “override”: { “amazon-ebs”: { “scripts”: [ “scripts/base.sh”, “scripts/cleanup.sh”, “scripts/nginx.sh” ] } } } ], “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-2d39803a”, “instance_type”: “t2.micro”, “ssh_username”: “ubuntu”, “ami_name”: “my-template-{{timestamp}}”, “associate_public_ip_address”: “true”, “force_deregister”: “true”, “vpc_id”: “vpc-80090ae7”, “launch_block_device_mappings”: [ { “device_name”: “/dev/sda1”, “volume_type”: “gp2”, “volume_size”: “50”, “delete_on_termination”: “true” }] } ] }


Как вы можете видеть, я изменил тип билдера и добавил переменные для подключения к aws

- access_key - access ключ для aws  

- secret_key - sercret ключ для aws

- region - AWS регион где будет запущен инстанс

- source_ami - исходная ami(Amazon Machine Images), которую мы будем использовать как базу

- instance_type - тип aws инстанса

- ssh_username - пользователь для подключения по ssh

- ami_name - имя будушей ami, которая будет доступна после сборки

- associate_public_ip_address - Будет ли у временного инстанса внешний  ip адрес, если вы собираете со своей машины, то бесусловно нужен, если из сети aws, то можно и не использовать

-  force_deregister - иногда нужно использоать чтобы не остовались не нужные инстансы

- vpc_id - в какой vpc сети мы будем запускать наш инстанс

- launch_block_device_mappings - Какого размера будет EBS(Elastic Block Storage) и каике у него будут параметры

Так же не забываем задать переменные для подключения к aws, вы можете либо добавить их в шаблон либо вводить с консоли.

### Валидация и сборка 

Валидируем наш новый шаблон

packer validate template_aws.json


 Если валидация прошла успешно, то начинаем сборку будущей ami

packer build template_aws.json

```

После сборки вы можете использовать новую ami для ваших будущих инстансов