Packer

Packerを初めて使ってハマったこと

最近はDockerの環境を運用することが多いので、すっかりEC2に対してAnsibleで環境を構築したりメンテナンスしたりすることが減りました。 それでもAWS上のECSをEC2ベースで運用していて、EC2に監視用のエージェントなどをインストールしているケースなどもあると思います。 例えば自分の場合だとPrometheusの監視モジュール、node exporterを各EC2にインストールしています。

今後もECS OptimizedなEC2はどんどん更新されていくので、これを機にPackerを導入してベースイメージの作成をすることにしました。 ちなみにPackerを導入しようと思ったのは先日発表されたDockerの脆弱性対応のためEC2をアップデートしないといけなかったことがきっかけです。

というわけでPackerは初めて触ったわけですが、ほとんどはまることもなくAnsibleをプロビジョナーとする構成を作ることができました。 それでも何点かつまずいた点があったので、残しておきます。

環境は下記の通りです。

  • Mac OS Mojave 10.14.3
  • Packer 1.3.4
  • Ansible 2.6.5

Packerのインストール

Macを前提とします。brewで簡単にインストールできます。

$ brew install packer

最終的にbuild.jsonは下記のようになりました。 ECS用のEC2の最新版を取ってきてansibleでプロビジョンしています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
    "provisioners": [
	{
	    "type": "ansible",
	    "playbook_file": "./playbook.yml"
	}
    ],
    "builders": [{
	"type": "amazon-ebs",
	"region": "ap-northeast-1",
	"source_ami_filter": {
	    "filters": {
		"virtualization-type": "hvm",
		"name": "amzn-ami-*-amazon-ecs-optimized",
		"root-device-type": "ebs"
	    },
	    "owners": ["591542846629"],
	    "most_recent": true
	},
	"instance_type": "t3.nano",
	"ssh_username": "ec2-user",
	"ami_name": "amzn-ami-amazon-ecs-optimized-20190225",
	"subnet_id": "subnet-xxxxxxxxxx",
	"associate_public_ip_address": true
    }]
}

つまずきを何点か

default subnetが存在しない場合

今回、Ansibleでプロビジョンするにあたり、インターネット上のモジュールをダウンロードする必要がありました。 インターネットにアクセスできない状態だとAnsibleが途中で落ちます。

PackerはPublic IPを取得できるdefault subnet上でAMIを起動しようとします。 default subnetが存在しない環境だとSubnetを指定してあげる必要があります。 そこで上記のようにsubnet_id でsubnetを指定しています。

PublicIPが自動割り当てされないSubnetの場合

Subnetの項目のうち、Auto-assign public IPv4 addressがNoになっている場合、Public IPが自動で割り当てられません。 “associate_public_ip_address”: true としてPublic IPが割り当てられるようにしましょう。

Ansibleを含めたディレクトリ構成

ansibleのPlaybookをどこに設置すれば良いか、一瞬悩みました、 なんのことはない、build.jsonと同じ階層に置けば良いだけでした。 ディレクトリ構成はこんな感じになりました。

├── build.json
├── playbook.yml
└── roles
    └── exporter
        ├── handlers
        │   └── main.yml
        ├── tasks
        │   └── main.yml
        ├── templates
        │   ├── node_exporter.default
        │   └── node_exporter.init.d.amzn.j2
        └── vars
            └── main.yml

まとめ

Packerはやれることも単純なこともあり、そこまで複雑でハマることもないツールです。 何点かつまずきポイントを載せましたが、エラーメッセージを見ればわかるっていうものでした。 単純ですが、OSのバージョンアップに追従したベースイメージを作成する際に非常に重宝しています。