vagrant-awsを利用したイイカンジ(?)のAWS開発フロー
Vagrantでupとdestroy繰り返すのが大好きです。アルパカ大明神です。
DevOps
社内でデブオプスを推進していることもあり、
まず第一歩として進めているのが
といったサーバエンジニア視点での開発フロー改善についての調査/検討です。
そして、ここ数日の間に
「こういう感じで開発を進められたらイイカンジなのでは?」
というフローが固まってきたので共有したいと思います。*1
概要図
リポジトリのVagrantfileを用いてローカルVagrantを構築し、
その環境を使ってアプリケーションを開発。
さらにec2の操作まで全てvagrantコマンド*2で実行します。
今回はknife soloも一切使用していません。
本番環境のクラスタ構築はCloudFormation+AutoScalingを利用するため、
必ずAMIを作成する必要があります。
そのため複数サーバへのデプロイを考えずに
「1台にのみ環境構築しそのままAMIに固める」
という方式をとっています。
対象が1台のみということもあり、デプロイスクリプトもchefレシピに同梱されています。
開発フロー
以下のような流れで行います。
インフラ担当者とアプリケーション開発者は同一人物の場合もあります。
インフラ担当者
必要なプラグインをインストールしておく
vagrant plugin install vagrant-aws vagrant plugin install vagrant-ami vagrant plugin install vagrant-omnibus
vagrant-awsについて
このプラグインを利用すると、vagrantでVMを操作する感覚で以下のような操作を行うことが可能です。
インスタンス起動(Launch Instance)
vagrant up <vm_name> --provider=aws
※インスタンス起動時、生AMIからvagrant upするとsyncがエラーになる
という既知の問題があります。
https://github.com/mitchellh/vagrant-aws/issues/83
こちらのuser_data対応をしても初回だけはどうしてもエラーが発生します。*4
自分は妥協してrequiretty対応済みのAMIから起動しています。
インスタンス削除(Terminate Instance)
vagrant destroy <vm_name>
sshログイン
vagrant ssh <vm_name>
プロビジョニング実行(shell/chef-soloなど)
vagrant provision <vm_name>
AMI保存について
当初はPackerを予定していたのですが、現時点(2013/9/14)の段階では
かゆいところに手が届かない部分もあったので
現在はvagrant-amiを使う方法を取っています。
vagrant-ami
以下のコマンドでvagrantからAMIを作ることが出来ます。
Vagrantfileの設定をそのまま使い回せるのがいいかんじですね。*5
vagrant create_ami --name my-ami --desc "My AMI" --tags name=hoge
chef-solo形式のコンフィグjsonとVagrantのprovision設定の共存について
今回のように、provisionしたい対象サーバが1台であればvagrant provisionでサクッとchef-solo実行したいですね。
ただし、将来的に複数サーバに対して
knife solo や capistrano+chef-soloなど実行したくなるかもしれません。
そのためchef-solo形式のコンフィグjsonとVagrantのprovision設定は極力共存させたいところです。
ちなみにVagrantfileでchef_soloしたい時には以下のような書き方になります。
config.vm.provision :chef_solo do |chef| # cookbook/roleのパスなど chef.cookbooks_path = ["./cookbooks", "./site-cookbooks"] chef.roles_path = "./roles" # レシピ/ロール追加 chef.add_recipe "nginx" chef.add_role "webapp" # custom attribute chef.json = { "nginx" => { "worker_processes" => 16, "worker_rlimit_nofile" => 8096, }, } end
http://docs.vagrantup.com/v2/provisioning/chef_solo.html
上記の設定をchef形式で同じように書くとこんな感じになるでしょうか。
{ "nginx": { "worker_processes": 16, "worker_rlimit_nofile": 8096 }, "recipes":[ "recipe[nginx]", "role[webapp]" ] }
これらをいちいち両方に書くのは面倒なので
chefのjson形式ファイルを正として、それをVagrantfileで読み込むようにしてみました。
# provisioning config.vm.provision :chef_solo do |chef| ## ファイル読み込み fname = ENV["chef_json"] # 環境変数でjsonファイルを受け取る nodes_json = (fname) ? JSON.parse(File.read(fname)) : {'recipes'=>{}} # node.jsonの情報を登録 nodes_json["recipes"].each do |run| case run when /^recipe\[(\w+)\]/ chef.add_recipe($1) when /^role\[(\w+)\]/ chef.add_role($1) else chef.add_recipe(run) end end # delete recipes key nodes_json.delete("recipes") # add attrubute chef.json = nodes_json end
chef_jsonという環境変数にjson名を入れる必要がありますが
これで設定を共有することが出来ました。*6
example
例というか、いま実際利用しているファイルをほぼ流用したものです。
https://github.com/toritori0318/vagrant-aws-sample
VagrantfileとRakefileをご覧頂くと良いかもしれません。
Rakefileは初心者なのでもう少しいい書き方があればご指南下さい。。
rakeタスク使い方の一例
基本的な使い方は rake -T でタスク一覧を確認してみましょう。
ローカルVM起動
rake local:up
ローカルVM chef-solo実行
rake local:provision
ローカルVM destroy
rake local:destroy
aws chef-solo実行(dev環境)
rake aws:provision vm=aws_srv_dev
aws chef-solo デプロイタスクのみ実行(dev環境)
rake aws:provision_deploy vm=aws_srv_dev