Posted at

10分で理解するPacker

More than 1 year has passed since last update.


Packer とは

サーバーイメージを作成するためのツールです

AWSであればAMI、Azureであれば arm を作成します

Vagrant を開発している HashiCorp社 が開発しているツールなので使用感は Vagrant と同じような感じです

構築済みのサーバーイメージをAMIとして作成しておき、これをベースとしてインスタンスを立ち上げるのはよくあるパターンだと思います

"ゴールデンイメージ" というインフラパターンらしいです

ただ、このAMIがどうやって作られたか?がわからなくなりがちなのですが、Packerを使うことでAMI構築手順を全てコード化することができます


TL;DR

json ファイルに定義内容を記述し、$ packer build hoge.json を実行するだけで定義内容の通りに自動でサーバーイメージを作成してくれます


インストール

以下に従って OS 毎のビルド済みバイナリをダウンロードしてきてパスを通すだけです

https://www.packer.io/downloads.html


Mac の場合

Mac の場合は Homebrew でインストールできます


Homebrewでpackerインストール

$ brew update

$ brew install packer


AWS での使い方


事前準備


IAM ユーザーを作る

aws cli を利用するための アクセスキーを取得します

管理者に依頼して IAM ユーザーを作成してもらってください

https://console.aws.amazon.com/iam/home?#/home

利用したい AWS サービス(EC2だけかな?)に対しての操作権限をつけてもらう必要があります


AWS CLI をセットアップする

以下を参考に aws コマンドを使えるように設定する

http://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html

$ aws configure で認証情報をセットした後であれば、Pakcer からはこのAWS認証情報を参照してくれます

~/.aws/credentials にAWSの認証情報が保存されます


AMIを作成する


1. json ファイルを作成する

例として以下の AMI を作成する定義を見てみましょう

項目
設定値
メモ

リージョン
ap-northeast-1 (東京)

ベースのAMI
公式 ubuntu 16.04 の最新版

インスタンスタイプ
t2.micro

ssh ユーザー名
ubuntu

AMIの名前
Packer test YYYY-MM-DDThh-mm-ssZ
作成時のタイムスタンプがセットされる

ディスク
30GB、gp2 の EBS を /dev/sda1 として接続

初期化コマンド
apt update を実行してから python-simplejson をインストール

この AMI 定義は以下のように json ファイルで書きます

定義できる項目は packer のドキュメントを参照のこと

https://www.packer.io/docs/builders/amazon.html


packer-example.json

{

"builders": [{
"type": "amazon-ebs",
"region": "ap-northeast-1",
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "*ubuntu-xenial-16.04-amd64-server-*",
"root-device-type": "ebs"
},
"owners": ["099720109477"],
"most_recent": true
},
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "Packer Test {{isotime | clean_ami_name}}",
"launch_block_device_mappings": [{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"volume_size": 10,
"volume_type": "gp2"
}]
}],
"provisioners": [{
"type": "shell",
"inline": [
"sudo apt update",
"sudo apt install -y python-simplejson",
"sudo echo `date`' - packer provisioned this AMI' > /home/ubuntu/packer_provisioners"
]
}]
}



2. 構文チェック

$ packer validate を実行すると構文チェックされます

$ packer validate packer-example.json

以下のメッセージが出力されれば構文チェックはOKです

Template validated successfully.

もしエラーがある場合はエラーメッセージが出力されます

$ packer build packer-example.json 

Failed to parse template: Error parsing JSON: invalid character '"' after object key:value pair
At line 4, column 6 (offset 49):
3: "type": "amazon-ebs"
4: "
^


3. ビルド実行

$ packer build を実行して AMI をビルドします

$ packer build packer-example.json

初期化タスクの内容にもよりますが AMI ビルドには数分かかります

以下のように AMIs were created と出力されればビルド成功です

・・・

Build 'amazon-ebs' finished.

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
ap-northeast-1: ami-c5f49528

ビルド中 EC2 のコンソールを開くと "Packer Builder" というインスタンスが起動されて、このインスタンス内で処理が実行され定義した内容の AMI が作成されます

ビルドが完了すると以下のように AMI が追加されていることが確認できます


[Advanced] イメージの初期化処理を Ansible でやる

packer で provisioners で設定したタスクによりイメージの初期化を行うことができます

https://www.packer.io/docs/provisioners/index.html

↑のサンプルでは Shell Provisioner を使うことで、イメージとなるインスタンスの内部で指定されたシェルコマンドが実行されていたということです

Ansible Provisioner というのを使うと、初期化タスクを ansible に任せることができます

先ほどの packer-example.json を修正し Provisioner に ansible を指定します

playbook_file に指定された playbook に沿って ansible が実行されます

※playbook の書き方はここでは割愛します


packer-ansible.json

{

"builders": [{
"type": "amazon-ebs",
"region": "ap-northeast-1",
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "*ubuntu-xenial-16.04-amd64-server-*",
"root-device-type": "ebs"
},
"owners": ["099720109477"],
"most_recent": true
},
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "Packer Ansible Example {{isotime | clean_ami_name}}",
"launch_block_device_mappings": [{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"volume_size": 30,
"volume_type": "gp2"
}]
}],
"provisioners": [{
"type": "shell",
"inline": [
"sudo apt update",
"sudo apt install -y python-simplejson"
]
}, {
"type": "ansible",
"playbook_file": "./ansible/playbook.yml"
}]
}