Ansible + Packer で AMI を作る

## バージョン

| version | 
|:---|
| ansible 1.9.4 |
| packer 0.8.6 |


## 概要

Ansible + Packer で AMI を作ります。

Packer を使うと簡単に AMI を作ることができ、Ansible は簡単にサーバーの構成を作ることができます。
これを組み合わせると EC2 インスタンスの運用を自動化する第一歩を踏み出せます。

Ansible と Packer をインストールした EC2 インスタンスを作って、そこで実行し AMI を作成します。

## IAM ロールの作成

EC2 インスタンスに結びつける IAM ロールを作成します。
EC2 インスタンスに結びつけると access_key_id, secret_access_key を指定しなくても AWS の各サービスを操作することができます。

AWS コンソール > サービス「IAM」 > 左メニュー「ロール」 > 「新しいロールの作成」ボタンをクリックします。

ロール名の設定で適切な「ロール名」を設定し「次のステップ」をクリック。
ロールタイプの選択では「AWS サービスロール」 > 「Amazon EC2」を選択 > 「AdministratorAccess」にチェックをつけ「次のステップ」をクリックし、ロールを作成します。

今回は「AdministratorAccess」にしていますが、実際の運用では適切な権限を設定してください。

## EC2 インスタンスの作成

AWS コンソール > サービス「EC2」 > 左メニュー「インスタンス」 > 「インスタンスの作成」ボタンをクリックします。

AMI は「Amazon Linux AMI」を選択します。
手順に従い進めて EC2 インスタンスを作成しますが、「ステップ 3: インスタンスの詳細の設定」の「IAM ロール」で作成した IAM ロールを指定してください。

EC2 インスタンスを作成したら SSH で接続します。

```
$ ssh -i xxxxx.pem ec2-user@xxx.xxx.xxx
```


## Ansible のインストール

pip を使って Ansible をインストールします。

```
$ sudo pip install ansible
```


## Packer のインストール

ZIP ファイルを解凍してインストールします。

```
$ wget -O /tmp/packer.zip https://releases.hashicorp.com/packer/0.8.6/packer_0.8.6_linux_amd64.zip
$ sudo unzip /tmp/packer.zip -d /usr/local/bin/
```


## サンプルとなる Nginx をインストールする Playbook の作成

nginx をインストールする単純な Playbook を作成します。
yum で nginx をインストールし、service へ登録します。

```yaml:~/sample.yml
- hosts: all
  sudo: yes
  tasks:
    - name: Install nginx
      yum: name=nginx state=latest

    - name: Set nginx service to start on boot
      service: name=nginx enabled=true
```

## Packer の準備

Packer を実行するための JSON ファイルを作成します。

builders.source_ami には、本日(2015/12/12)時点で最新となる「Amazon Linux AMI 2015.09.1 (HVM), SSD Volume Type」を指定しています。

builders.instance_type には、注意点があります。
EC2-Classic を使える AWS アカウントの人（昔に AWS アカウントを作った人）は t2系のインスタンスタイプを指定すると VPC に関連したエラーが発生するかもしれません。
m3 系など、デフォルトVPCを必要としないインスタンスタイプを指定すればエラーは発生しません。

最近作った人は、デフォルトVPC が設定されているので t2系のインスタンスタイプを指定しても問題なく動作します。

```json:~/sample.json
{
  "variables": {
    "ami_name"      : "sample"
  },
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "ap-northeast-1",
      "source_ami": "ami-383c1956",
      "instance_type": "m3.medium",
      "ssh_pty" : "true",
      "availability_zone" : "ap-northeast-1a",
      "ssh_username": "ec2-user",
      "ssh_timeout": "5m",
      "tags" : {
        "PackerRole" : "{{user `ami_name`}}-base"
      },
      "ami_name": "{{user `ami_name`}}_{{isotime | clean_ami_name}}"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "sudo pip install ansible"
      ]
    },
    {
      "type": "ansible-local",
      "playbook_dir" : "./",
      "playbook_file" : "./sample.yml"
    }
  ]
}
```

## Packer の実行

ここまえ準備ができればあとは実行するだけです。

```
$ packer build sample.json
```

* EC2 インスタンスの起動
* Ansible の実行・適用
* EC2 インスタンスの停止
* AMI の作成
* EC2 インスタンスの削除

上記の流れで処理が実行されます。
EC2 インスタンスの削除までやってくれるのでゴミが残りません。

処理が終わったら
AWS コンソール > サービス「EC2」 > 左メニュー「AMI」 をクリックすると

* sample_2015-12-11T16-52-25Z

のような名前で AMI が作成されていることを確認できます。


## まとめ

AMI を作る流れは以上です。
あとは、いかに Ansible を作って行くかだけです。

今回は簡単なサンプルでしたが、ぼくの github へ何個か playbook を置いています。
Rails 環境を作りたい場合、参考にしてください。

* https://github.com/katsuhiko/ec2-playbooks