ここまで4回、Itamaeのレシピの書き方やプラグインの作り方などを説明してきました。最終回となる今回は複数サーバに対してItamaeを利用する場合の活用方法を3つ紹介します。
Capistranoを使ってItamaeを複数ホストに対して実行する
CapistranoはRubyで書かれたデプロイツールで、アプリケーションのデプロイによく使われています。Capistranoを使ってSSH経由で複数台にItamaeを実行することで、手軽に並列でItamaeを実行することができます。ここではCapistranoのデプロイ機能を使ってレシピなどをデプロイし、デプロイ後にItamaeを実行する例を紹介します。
まず、Bundlerを使ってCapistranoをインストールし、cap install
で初期ファイルを生成します。
$ cd itamae - repo
$ bundle init # Gemfileがない場合
$ echo 'gem "capistrano"' >> Gemfile
$ bundle install
$ bundle exec cap install STAGES = production
config/deploy.rb
を以下のように修正します。itamae:apply
タスクでitamae local
が実行されるようにしています。また、itamae:apply
の前にdeploy
を実行するように指定しているので、実行前に/tmp/itamae-repo
にコードがデプロイされます。
set : application , ‘ itamae ’
set : repo_url , 'git@github.com:your/itamae-repo.git'
set : deploy_to , '/tmp/itamae-repo'
# この部分はAWS EC2のAPIを呼ぶなどして、動的に定義すると良いかもしれません
role : app , [‘ app - 1 ’]
namespace : itamae do
# apply前にdeployを実行します
task : apply => [: deploy ] do
# bootstrap.rbを実行します
recipe = File . join ( fetch (: release_path ), 'bootstrap.rb' )
on roles ( ENV [ 'ROLES' ]. split ( ',' )) do
# 対象ホスト側にItamaeがインストールされている必要があります
execute "itamae" , "local" , recipe
end
end
end
itamae:apply
タスクでItamaeを実行できます。
$ bundle exec cap production itamae : apply ROLES = app
(中略)
DEBUG [ ed621171 ] Command : /usr/ bin / env itamae local / tmp / itamae - repo / releases / 20150927150652 / bootstrap . rb
DEBUG [ ed621171 ] [ 0m INFO : Starting Itamae ...
DEBUG [ ed621171 ] [ 0m
DEBUG [ ed621171 ] [ 0m INFO : Recipe : /tmp/ itamae - repo / releases / 20150927150652 / bootstrap . rb
DEBUG [ ed621171 ] [ 0m [ 32m INFO : execute [ echo Hello ] executed will change from 'false' to 'true'
DEBUG [ ed621171 ] [ 0m
INFO [ ed621171 ] Finished in 0.317 seconds with exit status 0 ( successful ).
このように非常に簡単に複数台へのItamaeの実行が実現できます。上記の例ではitamae ssh
を使わずitamae local
を利用しています。itamae ssh
はitamae local
に比べ速度が遅いため、ある程度の規模になったらlocalを使うのがお勧めです。itamae local
は対象ホストにitamae
がインストールされている必要があるので、パッケージ などでインストールしましょう。
もちろん、itamae ssh
を使うことも可能です。その場合はrun_locally
内でItamaeを実行しましょう。詳しくはCapistranoのドキュメントを参照してください。
PackerとItamaeを使ってAWS EC2用のイメージを作成する
Packer とItamaeを使ってAWS EC2のイメージ(AMI)を作る例を紹介します。Packerは各種VMのマシンイメージをつくるためのツールで、EC2やDigitalOceanなどのIaaS用のイメージ作成やVirtualBoxやVMwareなどの仮想マシンイメージの作成に対応しています。Packerでは任意のコマンドを実行しイメージを作成することができるので、その機能を使ってItamaeを実行します。
まず、Packerをダウンロードします。
$ wget https : //dl.bintray.com/mitchellh/packer/packer_0.8.6_darwin_amd64.zip
$ unzip packer_0 . 8.6 _darwin_amd64 . zip
Packerの設定ファイルを書きます。以下をubuntu.json
として保存します(vpc_id
、subnet_id
、/path/to/itamae-repo
は環境に合わせて書き換えます) 。
{
"builders" : [{
"type" : "amazon-ebs" ,
"region" : "ap-northeast-1" ,
"source_ami" : "ami-46990446" ,
"instance_type" : "t2.micro" ,
"ssh_username" : "ubuntu" ,
"ssh_timeout" : "5m" ,
"ami_name" : "ubuntu-trusty-hvm" ,
"vpc_id" : "vpc-abcdef" ,
"availability_zone" : "ap-northeast-1c" ,
"subnet_id" : "subnet-abcdef" ,
"associate_public_ip_address" : true ,
"run_tags" : {
"Name" : "packer-tmp-ubuntu-trusty-hvm"
}
}],
"provisioners" : [
{
"type" : "file" ,
"source" : "/path/to/itamae-repo" ,
"destination" : "/tmp/itamae-repo"
},
{
"type" : "shell" ,
"inline" : [
"curl -s https://packagecloud.io/install/repositories/ryotarai/itamae/script.deb.sh | sudo bash" ,
"sudo apt-get install itamae" ,
"sudo /opt/itamae/embedded/bin/itamae local /tmp/itamae-repo/bootstrap.rb" ,
"sudo rm -rf /tmp/itamae-repo"
]
}
]
}
Packerの設定ファイルにはbuilders
とprovisioner
を指定する必要があり、ここではBuilderにamazon-ebs
(AMI)を、ProvisionerにItamaeの実行コマンドを指定します。file
Provisionerを使って、Itamaeのレシピなどを転送し(以下では/path/to/itamae-repo
を転送しています) 、itamae
コマンドを実行しています。
あとはpacker build
コマンドに上記の設定ファイルを与えれば、全自動でインスタンスを作成し、Itamaeを実行し、イメージを作成してくれます。
$ AWS_ACCESS_KEY_ID = foo AWS_SECRET_ACCESS_KEY = bar ./ packer build ubuntu . json
amazon - ebs output will be in this color .
==> amazon - ebs : Prevalidating AMI Name ...
==> amazon - ebs : Inspecting the source AMI ...
(中略)
==> amazon - ebs : Provisioning with shell script : /var/ folders / tj / 0g3ny7c94mq9s _2dtbzk0hbr0000gn / T / packer - shell612616353
(中略)
amazon - ebs : INFO : Starting Itamae ...
amazon - ebs : INFO : Recipe : /tmp/ itamae - repo / bootstrap . rb
amazon - ebs : INFO : execute [ echo Hello ] executed will change from 'false' to 'true'
amazon - ebs :
==> amazon - ebs : Stopping the source instance ...
==> amazon - ebs : Waiting for the instance to stop ...
==> amazon - ebs : Creating the AMI : ubuntu - trusty - hvm
amazon - ebs : AMI : ami - abcdef
==> amazon - ebs : Waiting for AMI to become ready ...
==> amazon - ebs : Terminating the source AWS instance ...
==> amazon - ebs : Cleaning up any extra volumes ...
==> 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 - abcdef
ConsulのWatch機能を使ってItamaeを実行する
Capistranoを使った方法は手軽である反面、サーバ台数が増えるとSSHのオーバヘッドが気になったり、接続が切れたり、ストレスを感じることがあります。そのような問題を解決するため、Consul のEvent機能を利用して、Itamaeを実行する例を紹介します。Consulはサービスディスカバリ、障害検知、KVSなどの機能を提供するソフトウェアですが、その中の機能の一つとしてEventの発火と監視があります。Itamae実行用のEventを監視し、Eventを受けてItamaeを実行することができます。
ここでは説明を簡略化するため、1台構成で解説しますが、実際に利用する場合はConsulクラスタを構築する必要があります。詳しくはConsulのドキュメントを参照してください。
まず、Consulをダウンロードします。
$ wget https : //dl.bintray.com/mitchellh/consul/0.5.2_linux_amd64.zip
$ unzip 0.5 . 2 _linux_amd64 . zip
eventを受け取ったときに実行されるスクリプトを書きます。細かい仕様などについてはドキュメント を参照してください。以下のスクリプトをitamae-apply-handler
として保存します。
#!/usr/bin/env ruby
require 'pathname'
require 'json'
require 'base64'
require 'tmpdir'
# 同じeventを2度以上処理しないように最後のeventのindexを保存しておく
index = ENV [ 'CONSUL_INDEX' ]
index_file = Pathname . new ( '/tmp/itamae-apply-handler-last-index' )
if index_file . exist ? && index_file . read == index
puts "This is not a new event"
exit
end
index_file . write ( index )
input = JSON . parse ( $stdin . read ). last
payload = JSON . parse ( Base64 . decode64 ( input [ 'Payload' ]))
Dir . mktmpdir do | tmpdir |
Dir . chdir ( tmpdir ) do
# RecipeURLで指定されたgzipped tarballをダウンロードし実行する
system ( "wget" , "-O" , "recipe.tar.gz" , payload [ 'RecipeURL' ]) || raise
system ( "tar" , "xf" , "recipe.tar.gz" ) || raise
system ( "/opt/itamae/embedded/bin/itamae" , "local" , "bootstrap.rb" ) || raise
end
end
上記のスクリプトでやっていることは非常にシンプルでeventで指定されたURLからレシピをダウンロードし、itamae local
を実行しています。
このスクリプトを実行可能にします。
$ chmod + x itamae - apply - handler
スクリプト内でItamaeを実行しているので、事前にインストールしておく必要があります。以下ではDebianパッケージを使ってインストールしていますが、Rubygemでインストールすることも可能です。
$ curl - s https : //packagecloud.io/install/repositories/ryotarai/itamae/script.deb.sh | sudo bash
$ sudo apt - get install itamae
最後にevent名とhandlerのひも付ける設定ファイルを書きます。以下をconsul.json
として保存します。
{
"watches" : [{
"type" : "event" ,
"name" : "itamae-apply" ,
"handler" : "/path/to/itamae-apply-handler"
}]
}
そして、Consulをサーバモードで起動します。
$ ./ consul agent - data - dir = /tmp/ consul - server - bootstrap - config - file = consul . json
(中略)
2015 / 09 / 28 08 : 25 : 15 [ INFO ] consul : New leader elected : vagrant - ubuntu - trusty - 64
2015 / 09 / 28 08 : 25 : 15 [ INFO ] raft : Disabling EnableSingleNode ( bootstrap )
2015 / 09 / 28 08 : 25 : 15 [ INFO ] consul : member 'vagrant-ubuntu-trusty-64' joined , marking health alive
2015 / 09 / 28 08 : 25 : 16 [ INFO ] agent : Synced service 'consul'
この状態でeventを発行すると、Itamaeが自動的に実行されます。
$ ./ consul event - name itamae - apply '{"RecipeURL": "https://gist.github.com/ryotarai/b5e6a356145faeac55da/raw/recipes.tar.gz"}'
consul monitor
コマンドでログが見られます。
$ ./ consul monitor - log - level = debug
2015 / 09 / 28 09 : 16 : 05 [ DEBUG ] consul : user event : itamae - apply
2015 / 09 / 28 09 : 16 : 05 [ DEBUG ] agent : new event : itamae - apply ( b99e3de8 - a0f7 - a74a - e8b9 - 4b2d48b97ef2 )
2015 / 09 / 28 09 : 16 : 05 [ DEBUG ] http : Request / v1 / event / list ? index = 9906610952174680195 & name = itamae - apply ( 5.003298219s )
2015 / 09 / 28 09 : 16 : 06 [ DEBUG ] agent : watch handler '/home/vagrant/itamae-apply-handler' output : -- 2015 - 09 - 28 09 : 16 : 05 -- https : //gist.github.com/ryotarai/b5e6a356145faeac55da/raw/recipes.tar.gz
Resolving gist . github . com ( gist . github . com )... 192.30 . 252.143
Connecting to gist . github . com ( gist . github . com )| 192.30 . 252.143 |: 443. .. connected .
HTTP request sent , awaiting response ... 301 Moved Permanently
Location : https : //gist.githubusercontent.com/ryotarai/b5e6a356145faeac55da/raw/recipes.tar.gz [following]
-- 2015 - 09 - 28 09 : 16 : 06 -- https : //gist.githubusercontent.com/ryotarai/b5e6a356145faeac55da/raw/recipes.tar.gz
Resolving gist . githubusercontent . com ( gist . githubusercontent . com )... 103.245 . 222.133
Connecting to gist . githubusercontent . com ( gist . githubusercontent . com )| 103.245 . 222.133 |: 443. .. connected .
HTTP request sent , awaiting response ... 200 OK
Length : 167 [ application / octet - stream ]
Saving to : ‘ recipe . tar . gz ’
0K 100 % 32.2M = 0s
2015 - 09 - 28 09 : 16 : 06 ( 32.2 MB / s ) - ‘ recipe . tar . gz ’ saved [ 167 / 167 ]
INFO : Starting Itamae ...
INFO : Recipe : /tmp/ d20150928 - 2975 - 1a7tza3 / bootstrap . rb
INFO : execute [ echo Hello Itamae ] executed will change from 'false' to 'true'
このように非常に簡単にスケーラブルなItamae実行環境が用意できます。この例はあくまで大枠を解説したものなので、実際に運用する際には考慮すべき点がいくつかあります。いくつか挙げると、
Abort機能
途中で中止できるほうが心の平穏が保たれそうです。
同時実行数の制限
全台で同時に実行されると困る場合や、リスクが大きい場合、同時に実行できる数を制限すると良いかもしれません。
consul lock
で同時に実行できる数を制限することもできます。
ログの集約
いちいちサーバにログインする必要があるのでログを集約する必要があります。
eventの発行元の検証
誰でもeventを発行出来てしまうので、例えばHMACをPayloadに付加すると良いかもしれません。
レシピをCIなどでアップロードする
Gitなどで管理しているレシピをどこかにアップロードする必要があるので、Jenkinsなどでアップロードする必要があります。
上記の例ではHTTPのURLを指定してダウンロードしていましたが、AWSであればS3からダウンロードするのもよいでしょう。
といったところでしょうか。規模が大きい場合このような方法も試してみてはいかがでしょうか。
まとめ
今回紹介した方法以外にもItamaeを使う手段はいろいろあります。Itamaeは非常にシンプルなツールなので環境に合わせてカスタマイズして使っていただけるかと思います。
これまで全5回、Itamaeについて紹介してきましたが、Itamaeの機能や使い方などすべて紹介しました。Itamaeは全5回の連載で全貌を解説できるぐらい、軽量でシンプルだということをおわかりいただけたでしょうか。Itamaeをコンポーネントの一つとして様々なツールと組み合わせ、Infrastructure as Codeを推し進めていただければ幸いです。