okochangの馬鹿でありがとう

ふらふら適当に世間を生きる日々でございます

Packerを使ってAmazon EC2のAMIを作る(2)

こんにちは@oko_cangです。
前回のブログでPackerをとりあえず使ってみましたが、今回はもう少し作成するAMIに手を加える部分をまとめておきます。

前回の内容に付け加えるもの

  • ルートデバイスのEBSを拡張してAMIを作る
  • Amazon Linuxに簡単な初期設定を加える

公式で提供されているAmazon Linuxはルートボリュームのサイズが8GBのEBSを使用するので、これをもっと大きなEBSにします。
また、拡張したEBSをファイルシステムからも認識させたり、タイムゾーンを設定したりなど簡単な初期設定もした状態でAMIにします。

設定ファイル

実際に出来上がった、設定ファイルは以下の通りです。
作成するAMI名が前回と同じもにになっているので、適宜書き換えます。
※access_keyとsecret_keyはそれぞれ自分のものに置き換えて下さい。

$ cat ~/.packer/my_second_template.json 
{
  "builders": [{
    "type": "amazon-ebs",
    "access_key": "XXXXXXXXXXXXXXX",
    "secret_key": "YYYYYYYYYYYYYYYYYYYYYYYYYY",
    "region": "ap-northeast-1",
    "source_ami": "ami-39b23d38",
    "instance_type": "m1.small",
    "ssh_username": "ec2-user",
    "ssh_timeout": "15m",
    "ami_name": "okochang-packer-quick-start",
    "launch_block_device_mappings": [
      {
        "device_name": "/dev/sda1",
        "volume_size": 100,
        "delete_on_termination": true
      }
    ],
    "ami_block_device_mappings": [
      {
        "device_name": "/dev/sdb",
        "virtual_name": "ephemeral0"
      }
    ],
    "tags": {
      "OS_Version": "Amazon Linux",
      "Release": "Latest"
    }
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "sudo yum -y update",
      "sudo resize2fs /dev/xvda1",
      "sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime"
    ]
  }]
}

前回との差分

前回の設定ファイルとの差分は以下となります。
拡張したEBSをファイルシステム側からも認識させるために、launch_block_device_mappingsオプションを使ってAMI作成用のインスタンスを起動するタイミングでルートボリュームのEBSを拡張します。
※起動後にresize2fsが実行され、AMI作成となります
また、初期設定などもするのでSSHのタイムアウトも少し伸ばしています。
SSHのタイムアウトは初期設定とは関係ないです

$ diff -u ~/.packer/my_first_template.json ~/.packer/my_second_template.json 
--- /Users/yanase/.packer/my_first_template.json        2013-09-14 05:54:24.000000000 +0900
+++ /Users/yanase/.packer/my_second_template.json       2013-09-15 17:08:44.000000000 +0900
@@ -7,8 +7,15 @@
     "source_ami": "ami-39b23d38",
     "instance_type": "m1.small",
     "ssh_username": "ec2-user",
-    "ssh_timeout": "5m",
+    "ssh_timeout": "15m",
     "ami_name": "okochang-packer-quick-start",
+    "launch_block_device_mappings": [
+      {
+        "device_name": "/dev/sda1",
+        "volume_size": 100,
+        "delete_on_termination": true
+      }
+    ],
     "ami_block_device_mappings": [
       {
         "device_name": "/dev/sdb",
@@ -19,5 +26,13 @@
       "OS_Version": "Amazon Linux",
       "Release": "Latest"
     }
+  }],
+  "provisioners": [{
+    "type": "shell",
+    "inline": [
+      "sudo yum -y update",
+      "sudo resize2fs /dev/xvda1",
+      "sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime"
+    ]
   }]
 }

実行

以下のように実行しました。

$ packer build ~/.packer/my_second_template.json 
amazon-ebs output will be in this color.

==> amazon-ebs: Creating temporary keypair: packer 02a605903bfa4a3d2f3daed421c7ec2a
==> amazon-ebs: Creating temporary security group for this instance...
==> amazon-ebs: Authorizing SSH access on the temporary security group...
==> amazon-ebs: Launching a source AWS instance...
==> amazon-ebs: Waiting for instance (i-02e87207) to become ready...
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Provisioning with shell script: /var/folders/r1/52kcr4ws1xd6d37t4szy9rk40000gn/T/packer-shell986860561
    amazon-ebs: Loaded plugins: priorities, security,
    amazon-ebs: : update-motd, upgrade-
    amazon-ebs: : helper
    amazon-ebs: Setting up Update Process
    amazon-ebs: Resolving Dependencies
    amazon-ebs: --> Running transaction check
    amazon-ebs: ---> Package aws-apitools-ec2.noarch 0:1.6.7.3-1.0.amzn1 will be updated
    amazon-ebs: ---> Package aws-apitools-ec2.noarch 0:1.6.8.1-1.0.amzn1 will be an update
    amazon-ebs: ---> Package aws-apitools-rds.noarch 0:1.13.002-1.0.amzn1 will be updated
    amazon-ebs: ---> Package aws-apitools-rds.noarch 0:1.14.001-1.1.amzn1 will be an update

===  中略  ===


    amazon-ebs:
    amazon-ebs: Updated:
    amazon-ebs: aws-apitools-ec2.noarch 0:1.6.8.1-1.0.amzn1
    amazon-ebs: aws-apitools-rds.noarch 0:1.14.001-1.1.amzn1
    amazon-ebs: curl.x86_64 0:7.27.0-11.34.amzn1
    amazon-ebs: iptables.i686 0:1.4.18-1.21.amzn1
    amazon-ebs: iptables.x86_64 0:1.4.18-1.21.amzn1
    amazon-ebs: krb5-libs.i686 0:1.10.3-10.26.amzn1
    amazon-ebs: krb5-libs.x86_64 0:1.10.3-10.26.amzn1
    amazon-ebs: krb5-workstation.x86_64 0:1.10.3-10.26.amzn1
    amazon-ebs: libcurl.x86_64 0:7.27.0-11.34.amzn1
    amazon-ebs: nspr.x86_64 0:4.9.5-2.17.amzn1
    amazon-ebs: nss.x86_64 0:3.14.3-4.29.amzn1
    amazon-ebs: nss-softokn.x86_64 0:3.14.3-3.14.amzn1
    amazon-ebs: nss-softokn-freebl.i686 0:3.14.3-3.14.amzn1
    amazon-ebs: nss-softokn-freebl.x86_64 0:3.14.3-3.14.amzn1
    amazon-ebs: nss-sysinit.x86_64 0:3.14.3-4.29.amzn1
    amazon-ebs: nss-tools.x86_64 0:3.14.3-4.29.amzn1
    amazon-ebs: nss-util.x86_64 0:3.14.3-3.16.amzn1
    amazon-ebs: python-boto.noarch 0:2.9.9-1.0.amzn1
    amazon-ebs: ruby.x86_64 0:1.8.7.374-1.0.amzn1
    amazon-ebs: ruby-libs.x86_64 0:1.8.7.374-1.0.amzn1
    amazon-ebs:
    amazon-ebs: Complete!
    amazon-ebs: resize2fs 1.42.3 (14-May-2012)
    amazon-ebs: Filesystem at /dev/xvda1 is mounted on /; on-line resizing required
    amazon-ebs: old_desc_blocks = 1, new_desc_blocks = 7
    amazon-ebs: The filesystem on /dev/xvda1 is now 26214400 blocks long.
    amazon-ebs:
==> amazon-ebs: Stopping the source instance...
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating the AMI: okochang-packer-quick-start
==> amazon-ebs: AMI: ami-eb58c4ea
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Adding tags to AMI (ami-eb58c4ea)...
    amazon-ebs: Adding tag: "OS_Version": "Amazon Linux"
    amazon-ebs: Adding tag: "Release": "Latest"
==> amazon-ebs: Terminating the source AWS instance...
==> 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:

ap-northeast-1: ami-eb58c4ea

確認

念のため作成後のAMIを確認します。

$ aws ec2 describe-images --region ap-northeast-1 --image-ids ami-eb58c4ea | jq '.'
{
  "Images": [
    {
      "ImageType": "machine",
      "Public": false,
      "RootDeviceName": "/dev/sda1",
      "OwnerId": "975450034499",
      "KernelId": "aki-44992845",
      "ImageLocation": "975450034499/okochang-packer-quick-start",
      "Architecture": "x86_64",
      "VirtualizationType": "paravirtual",
      "Name": "okochang-packer-quick-start",
      "Tags": [
        {
          "Key": "OS_Version",
          "Value": "Amazon Linux"
        },
        {
          "Key": "Release",
          "Value": "Latest"
        }
      ],
      "Hypervisor": "xen",
      "ImageId": "ami-eb58c4ea",
      "RootDeviceType": "ebs",
      "State": "available",
      "BlockDeviceMappings": [
        {
          "Ebs": {
            "VolumeType": "standard",
            "VolumeSize": 100,
            "SnapshotId": "snap-37f15412",
            "DeleteOnTermination": true
          },
          "DeviceName": "/dev/sda1"
        },
        {
          "VirtualName": "ephemeral0",
          "DeviceName": "/dev/sdb"
        }
      ]
    }
  ]
}

まとめ

これだけの事が出来れば、あとは応用でシステムのベースとなるAMI作成には十分そうです。
初期設定が複雑になるようであればスクリプトを作ったり、Chefのレシピを使うようにしたら良いみたいです。