Packer & Chef-SoloでAmazon EC2のAMIを簡単に作る方法
全国1000万人のPackerユーザーのみなさんこんにちはこんにちは。
Packerは、Mitchell Hashimotoさんによって開発が進められている様々な環境の仮想マシンのテンプレートを簡単に作れるツールです。例えばVagrantを使っている場合はいままではPatrick Deboisさんが作っていたVeeweeを使うのが定番でしたが、このPackerの登場で主流が移りつつあります。 またPackerでは、Amazon EC2用のAMI (Amazon Machine Image)を作成することもできます(某ドラクエ好きな著名エンジニアのIさんが「PackerはAMI作成ツールだ!」と言っていたのを聞いたような気がw)
今までは、Packerでミドルウェアやパッケージをインストールしたり、細かい設定をする場合にはShellのProvisionerを使っていたのですが、先日登場したバージョン0.3.5から、Chef-Soloに対応しましたので、今日はその使い方を説明します。
下準備
まずはPackerの最新版をインストールしてください。こちらのダウンロードページから環境にあったものをダウンロードします。 ダウンロードしたら適当な場所に配置してください。 僕は/opt/packer 以下に配置してPATHを通していますので、以降のコマンドはPATHが通っている前提となります。Cookbookの準備
Packerから呼び出すCookbookを準備します。ここではBerkshelfを使ってCookbookを管理することにしますので、以下のような形で、今回Packerで使うCookbookをBerkshelfファイルに記述してください。 Berkshelfの使い方はこちらを参照してください。 以下の例では、Opscodeが提供するyumのCookbook、自分のローカルマシンにあるtimezoneとapache2のCookbook、そしてgithubにあげてあるmemcachedのCookbookを使うようになっています。ご自身の環境にあわせて適宜書き換えてください。Berksfile
site :opscode
cookbook 'yum'
cookbook 'timezone', :path => '../../ryuzee-cookbooks/timezone'
cookbook 'apache2', :path => '../../ryuzee-cookbooks/apache2'
cookbook 'memcached', :git => 'git://github.com/ryuzee-cookbooks/memcached.git'
作成が終わったら、Cookbookをローカルのvendor-cookbooksで管理するように以下のコマンドを実行します。
Berks install --path=./vendor-cookbooks
Packer用のJSONファイルの準備
Packerが起動するときに利用するjsonファイルを作成します。とくに名前に決まりはありません。今回はamazonlinux.jsonという名前にしました{
"builders": [{
"type": "amazon-ebs",
"region": "ap-northeast-1",
"source_ami": "ami-39b23d38",
"instance_type": "m1.medium",
"ssh_username": "ec2-user",
"ssh_timeout": "5m",
"ami_name": "amznlinux-{{timestamp}}"
}],
"provisioners": [{
"type": "chef-solo",
"cookbook_paths": ["./vendor-cookbooks/"],
"run_list": ["timezone", "apache2", "memcached"],
"json": {"memcached":{"maxcon":"512","cachesize":"512"}},
"prevent_sudo": false,
"skip_install": false
}]
}
内容は前半半分は、Amazon EC2でEBS AMIを作成するので、それに関連する情報(リージョン、元となるAMI、作業の時に使うインスタンスの種類、SSHで接続する際のユーザー名とタイムアウト、完成したAMIにつける名前)です。 なお、以前のバージョンから現在時刻を取得する項目名が変わっているので、注意してください。 後半半分はProvisionerの設定です。順番に見ていきます。
- typeの箇所はchef-soloを指定します。なおシェルを使いたい場合はshellになります。
- cookbook_pathsは、今回適用するCookbookが置かれている場所を記述します。今回の例ではカレントディレクトリにBerkshelfを使ってvendor-cookbooksディレクトリを用意したのでそちらを指定します。なお項目名は開発ブランチの時と名前が変わっていますので、既に0.3.5以前から開発ブランチを使ってこの機能を使っていた人は変更する必要があります。
- run_listには適用したいCookbookを列挙します。単に依存関係があるだけのCookbookについてはとくに記載する必要はありません。
- jsonの箇所では、Cookbookを適用時にattributesを変更するために使います。たとえば上記の例では、元々memcachedのmaxconを1024、cachesizeを256としてデフォルト値設定していたのを上書きしているということです。
- prevent_sudoは、Chef-Soloを実行する際にsudoをつけずに実行するかどうかのフラグです。元となるインスタンスにrootでログインするのでない限りはfalseとなります。
- skip_installは、クライアント側に必要となるChef Soloを自動でインストールしないようにするフラグです。
実行
実行方法は以前と変わりません。packer build amazonlinux.json
とすればAMIの作成が始まります。なお、ログの出力を強化するには、環境変数にPACKER_LOG=1を設定してください。
実行すると
amazon-ebs output will be in this color.
==> amazon-ebs: Creating temporary keypair for this instance...
==> 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-8cc8f58e) to become ready...
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
amazon-ebs: Installing Chef...
amazon-ebs: % Total % Received % Xferd Average Speed Time Time Time Current
amazon-ebs: Dload Upload Total Spent Left Speed
amazon-ebs: 100 6790 100 6790 0 0 7311 0 --:--:-- --:--:-- --:--:-- 9005
amazon-ebs: Downloading Chef for el...
amazon-ebs: Installing Chef
amazon-ebs: warning: /tmp/tmp.G3MNcjNC/chef-.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
amazon-ebs: Preparing... ########################################### [100%]
amazon-ebs: 1:chef ########################################### [100%]
amazon-ebs: Thank you for installing Chef!
amazon-ebs: Creating directory: /tmp/packer-chef-solo
amazon-ebs: Creating directory: /tmp/packer-chef-solo/cookbooks-0
amazon-ebs: Creating configuration file 'solo.rb'
amazon-ebs: Creating JSON attribute file
amazon-ebs: Executing Chef: sudo chef-solo --no-color -c /tmp/packer-chef-solo/solo.rb -j /tmp/packer-chef-solo/node.json
amazon-ebs: Starting Chef Client, version 11.6.0
amazon-ebs: Compiling Cookbooks...
amazon-ebs: Converging 8 resources
amazon-ebs: Recipe: timezone::default
amazon-ebs: * execute[cp -p /usr/share/zoneinfo/Japan /etc/localtime] action run
amazon-ebs: - execute cp -p /usr/share/zoneinfo/Japan /etc/localtime
amazon-ebs: Recipe: apache2::default
amazon-ebs: * package[httpd] action install
amazon-ebs: - install version 2.2.25-1.0.amzn1 of package httpd
amazon-ebs: * file[/etc/httpd/conf.d/welcome.conf] action delete
amazon-ebs: - delete file /etc/httpd/conf.d/welcome.conf
amazon-ebs: * file[/var/www/html/index.html] action create_if_missing
amazon-ebs: - create new file /var/www/html/index.html
amazon-ebs: - update content in file /var/www/html/index.html from none to b80023
amazon-ebs: --- /var/www/html/index.html 2013-08-31 09:34:07.197018173 +0900
amazon-ebs: +++ /tmp/.index.html20130831-1449-kk5zqc 2013-08-31 09:34:07.201018192 +0900
amazon-ebs: @@ -0,0 +1 @@
amazon-ebs: +It works!
amazon-ebs: * service[httpd] action enable
amazon-ebs: - enable service service[httpd]
amazon-ebs: * service[httpd] action start
amazon-ebs: - start service service[httpd]
amazon-ebs: Recipe: memcached::default
amazon-ebs: * package[memcached] action install
amazon-ebs: - install version 1.4.13-1.11.amzn1 of package memcached
amazon-ebs: * template[/etc/sysconfig/memcached] action create
amazon-ebs: - update content in file /etc/sysconfig/memcached from 320378 to 5fb386
amazon-ebs: --- /etc/sysconfig/memcached 2012-08-15 06:57:16.000000000 +0900
amazon-ebs: +++ /tmp/chef-rendered-template20130831-1449-4fqyhl 2013-08-31 09:34:10.389032083 +0900
amazon-ebs: @@ -1,5 +1,5 @@
amazon-ebs: PORT="11211"
amazon-ebs: USER="memcached"
amazon-ebs: -MAXCONN="1024"
amazon-ebs: -CACHESIZE="64"
amazon-ebs: +MAXCONN="512"
amazon-ebs: +CACHESIZE="512"
amazon-ebs: OPTIONS=""
amazon-ebs: * service[memcached] action enable
amazon-ebs: - enable service service[memcached]
amazon-ebs: * service[memcached] action start
amazon-ebs: - start service service[memcached]
amazon-ebs: * service[memcached] action restart
amazon-ebs: - restart service service[memcached]
amazon-ebs: Chef Client finished, 11 resources updated
==> amazon-ebs: Stopping the source instance...
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating the AMI: amznlinux-1377909138
==> amazon-ebs: AMI: ami-db7eecda
==> amazon-ebs: Waiting for AMI to become ready...
==> 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-db7eecda
のように表示され、AMIの作成が完了します。
まとめ
いままではせっかくCookbookがあっても、別でシェルを書くか、インスタンス起動後にCookbookを適用するしかなかったのですが、今回のChef-Soloへの対応で、既存のものをサクサク組み合わせた形で素早くベースとなる環境を作れることになります。 既にChefまたはChef Soloを使っている人にとってはかなり敷居が低いのでぜひ試してみると良いと思います。なお、今回使ったコードは以下にアップしていますので参考にしてみてください。 https://github.com/ryuzee/sandbox-devops/tree/master/packer-ec2-chef-solo
アジャイルコーチングやトレーニングを提供しています
株式会社アトラクタでは、アジャイル開発に取り組むチーム向けのコーチングや、認定スクラムマスター研修などの各種トレーニングを提供しています。ぜひお気軽にご相談ください。
詳細はこちら