開発環境の構築は、アプリを作る上で重要ですが、楽をしたい作業です。
ただし、開発環境構築で手を抜き、チームメンバー間で環境の差異がでてしまった場合、問題があった時の切り分けが困難になってしまいます。
そこで、チームのメンバーが同じ環境を簡単に作れるように、vagrant と chef-solo を使った開発環境の構築についてご紹介したいと思います。
vagrant は、仮想マシン (バーチャルマシン、以降は VM とします) をプログラマブルに作成/破棄できるツールです。
vagrant はプラグイン機構をもっており、プラグインにより vagrant を拡張することができます。
操作出来る VM は VirtualBox が基本なのですが、有料ですが VMware をサポートしている vagrant も公開されています (VMware Vagrant Environments)。
その他にも色々なプラットフォームが操作できるようなプラグインが配布されています
(Available Vagrant Plugins)。
chef-solo は chef というツールに同梱されている、プロビジョニングツールです。
プロビジョニングツールとは、サーバー構築・管理を自動化するツールです。
chefはサーバークライント構成をとって、サーバーの構成管理をおこなっていますが、chef-soloはサーバークライント構成を使わず、単体でプロビジョニングを行うことができるツールです。
プロビジョニングツールには、chef以外にも、puppetなどが挙げられます。
上記でも紹介したとおり、プロビジョニングツールはchef以外にも色々ありますが、その中でchefを選んだ理由は、
くらいです。
ですので、特にchefを勧めるわけではありません。
chef以外に慣れているプロビジョニングツールがあれば、それを採用することをおすすめします。
ただし、vagrantと連携できるプラグインがあるかどうかは確認しておいて下さい。(もしなければ、自分でプラグインを書くことになるでしょう)
vagrantには、chefとpuppetを実行するためにプラグインが予め同梱されています。
Berkshelfは、chefで使うクックブックを管理するgemです。
必要なクックブックを、設定に従って集めて来てくれます。
設定はBerksfileというファイルに下記のように書きます。
cookbook 'sudo', git: 'git@github.com:opscode-cookbooks/sudo.git'
cookbook 'hoge', git: 'git@github.com:SpringMT/hoge.git'
bundlerとGemfileと同じような関係ですね。
ここに、使用するクックブックを列挙しておくと、プライベートgit、chef server、ローカルのファイルなどからBerkshelfが自動的にクックブックを集めてきてくれます。
Berkshelfを使うことによって、クックブックを分割して管理することができ、再利用性が高まるので、chefを使う際はオススメです。
まず、vagrantとchef-soloを使う前に、これらツールを使う理由を整理しましょう。
開発環境を構築するために、なぜvagrant、chef-soloを使うのでしょうか。
vagrantを使うということは、自分のマシンにVMを立ち上げることになり、もう一台マシンが走っていることになります。
その分だけ、ホストマシンに負荷がかかり動作が重くなるのは明白です。
ですので、私個人の意見としては、開発環境構築にvagrantを使ってVMを立ち上げるよりは、ホストマシンだけで開発環境を構築できるのであれば、そうするべきだと思っています。
現在、Macを使っていれば、Homebrewなどを使って様々なミドルウェアをインストールすることができます。
また、Macであればローカルマシンの環境構築にはboxenを使うこともできます。
ではなぜ、今回vagrantを使ってVMを立ち上げることを選択したのでしょうか。
それには、下記のようなローカルの環境では設定しにくい要因があったためです。
上記のようなことをローカルマシンで実現できないわけではないのですが、ローカルマシンへの影響が大きすぎるため、vagrantとchef-soloを使ってVM上に環境構築することにしました。
vagrantは、Mac、windows、Linuxの環境全て動きます。
ただし、今回私が試した環境はMacのみなので、それ以外のOSでは動作確認をしていません。
まず、vagrantとchef-soloを動かす設定を作ります。
ここではRubyのインストールの仕方については細かく説明しません。
rbenvやrvmを使ってインストールすることをおすすめします。
るびまでも紹介されているので参考になると思います。
gemで配布されているvagrantは__使ってはいけません__。(rubygemsに登録されているvagrantはバージョンがかなり古いです)
vagrantは、下記ページからOSにあったファイルをダウンロードしてインストールして下さい。
Macの場合はdmgですね。
vagrantのインストールが完了すれば、vagrantコマンドが使えます。
vagrantコマンドを使って、Berkshelfと連携するプラグインをインストールしておきましょう。
vagrant plugin install vagrant-berkshelf
chef-soloと連携するプラグインはvagrantに同梱されているので、特にプラグインのインストールは不要です。
他にも使いたいプラグインがあれば、各々インストールしてください。
boxファイルは、vagrantでVMを立ち上げるためのベースとなるファイルです。
vagrantのサイトで公開されているものもありますが、その中に自分が使いたいboxファイルがない場合や、個人で公開している野良boxファイルしか見つからず、自前でboxファイルを用意する必要がある場合があるかと思います。
boxファイルを作ることになる場合、veeweeというツールを使うことがお勧めです。
boxファイルを作る際は、boxファイルは極力シンプルにしておくと良いと思います。
多くの人が使える状態にしておき、あとで、chef-soloで自分の好きな状態にするのが良いでしょう。
さて、作ってboxファイルの共有はどうしましょう。
コピーして渡すには容量がそれなりに大きく、会社によってはUSBを使った共有もできない場合もあります。
実は、ここが結構困ったところですが、結局自分はチームの全員がアクセスできるファイルサーバーにおいて、そこからダウンロードしてもらっています。
vagrantがインストールできていれば、vagrantコマンドが使えると思います。
まず、vagrantの設定ファイルを格納するディレクトリを作って、そこでvagrant initを行います。
更に、boxファイルをvagrantに登録します。
mkdir [vagrant dir]
cd [vagrant dir]
vagrant init
vagrant box add 'vagrantに登録する名前' 'boxファイルのパス'
ここで、_Vagrantfile_というファイルができていることを確認してください。
Vagrantfileのサンプルは下記のとおりです。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "vagrant box addで登録したboxファイルの名前"
# berkshelfを使うのでtrue
config.berkshelf.enabled = true
# hostnameの設定が必要であれば設定可能
config.vm.hostname = 'test'
# chefの設定
config.vm.provision :chef_solo do |chef|
chef.run_list = [
# 使うクックブックを列挙しておく
"sample",
]
end
end
他にも、私の場合は、ネットワークの設定やsynced_folderの設定をしていますが、上記の設定だけでも十分に稼働可能です。
まず、chefを使うための準備を行います。 chef本体と、chefのクックブックを作るためのツールknife-soloをインストールします。
gem install chef
gem install knife-solo
もちろん、bundler経由からインストールしても問題ありません。
インストールが完了したら、vagrant initしたディレクトリで下記コマンドを実行します。
knife solo init .
そうすると、
.
├── Berksfile
├── Vagrantfile
├── cookbooks
├── data_bags
├── environments
├── nodes
├── roles
└── site-cookbooks
こんな感じにディレクトリが作られると思います。
それぞれの説明はchefを解説しているブログ等に譲りますが、ここで幾つか自分が取った方針について紹介しようと思います。
クックブックの再利用が困難になるため、site-cookbooksの中にはクックブックをほとんど入れませんでした。
なるべく最小の単位でクックブックで作り、クックブックはそれぞれレポジトリを作って管理しました。
それらを、Berkshelfでまとめて使えるようにしています。
クックブックは、誰でも使える場所に公開しておき、再利用可能な状態にしておくことで、他に使いたい人が再発明しなくてすみます。
site-cookbooksに入れたクックブックは、作りたい環境特有の設定を行うためのクックブックのみになっています。(このクックブックも、あとでシェアできるようになるべく分割しています)
chefには、data_bagという仕組みを使って、公開したくないデータを暗号化して配布する方法があります。(パスワードなど) しかし、今回はその方法を採用しませんでした。 その理由としては、下記二点がありました。
鍵の配布は特に手間になるので暗号化したい場合は、鍵の配布の方法も合わせて考える必要があります。
しかし、チームのほとんどが同じ鍵を持つことになるので、特に暗号化する必要がないと思い、今回は特に暗号化をしませんでした。
ほとんどのクックブックは出回ってるクックブックと同じ書き方をしていますが、GH:EのリポジトリやGitHubのプライベートリポジトリをcloneしてくる部分が大分ハマったので、ここで紹介できればと思います。
これは、ローカルマシンとvagrantとの連携技になります。
まず、Vagrantfileの設定で、sshのforward_agentをtrueにしてください。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
.
config.ssh.forward_agent = true
.
end
次に、ローカルマシンのssh/config
の設定を行ってください。
Host [GH:Eのhostやgithub.com]
ForwardAgent yes
ローカルマシンで、ssh-agentにGH:EもしくはGitHubで使ってる鍵を登録してください。
ssh-add ~/.ssh/id_rsa
# 登録できているか確認
ssh-add -l
この設定で、VMから__vagrantユーザー__が、ローカルマシンのssh agent経由でGH:EやGitHubのプライベートリポジトリからgit cloneすることができます。
ただし、このままだとVMからcloneするときにwarnningメッセージがでて実行が止まってしまうので、vagrantユーザーの.ssh/configに下記の設定を反映できるようなクックブックを書いて実行できるようにしておいてください。
サンプルはこちらです。
directory "#{node['vagrant']['tmp_vagrant_path']}" do
owner "vagrant"
group "vagrant"
mode "2775"
recursive true
end
template "/home/vagrant/.ssh/config" do
source "ssh.config.erb"
mode "0600"
owner "vagrant"
group "vagrant"
end
Host [GH:Eのhostやgithub.com]
StrictHostKeyChecking no
ここまで行うと、vagrantユーザーでgit cloneすることができます。
ただ、このままでは、cloneしたディレクトリがvagrantユーザーになってしまうので、一旦git cloneした後に、cloneしてきたリポジトリをmvで移動したり、ユーザーを変えたりする必要があります。
クックブックで表現すると下記のようになるかと思います。
git "#{tmp_vagrant_path}/test" do
repository "git@github.hoge.jp:test/test.git"
revision "master"
user "vagrant"
group "vagrant"
action :checkout
not_if "test -d /home/user/test"
end
execute "chown hoge at test" do
command "chown -R hoge:hoge #{tmp_vagrant_path}/test"
not_if "test -d /home/user/test"
end
execute "mv test" do
command "mv #{tmp_vagrant_path}/test /home/hoge/"
not_if "test -d /home/user/test"
end
この他に方法が無いかと色々試したのですが、この方法以外しか見つからず。。。
他にいい方法があれば、ぜひご教授頂きたいです!!
ここまで、準備ができたら、Berksfileに作成したクックブックを設定し、berks install
を実行してください。
その後に、
vagrant up
を行えば、VMが立ち上がります。
ここまでできたら、他に人にも使ってもらえる準備が整いました。
以下には、使ってもらったときに起きたトラブルとその解消方法を紹介します。
vagrant upを実行中、結構な頻度でSEGVで落ちます。
この場合は、vagrant provisionを実行して再度chefを実行しましょう。
(クックブックは冪等性を担保していることが前提となります。)
環境を更新するために、クックブックを修正することが多々あると思います。
クックブックを修正したら、vagrantを管理しているディレクトリでberks update
を実行してBerksfile.lockを更新しましょう(よく忘れます。。。。)。
Berksfile.lockを更新したら、使ってる人たちに連絡してberks installしてもらい、vagrant provisionを実行してもらい新しいクックブックを適用しましょう。
vagrant haltすると、VMがsymbol lookup errorがでて立ち上がらなくなることがあります。一旦止めたいときはvagrant suspendで行うことを推奨します。
また、いきなりホストマシンを落とすと恐らくvagrant haltと同じ現象が起こり、立ち上がらなくなる場合があります。
ホストマシンを落とすときは、一旦vagrant suspendしてからホストマシンを落とすとよいでしょう。
ウンGレベルまで肥大化した深淵なリポジトリをcloneする場合、timeoutすることがあります(デフォルトは300 sec)。
この場合、boot_timeoutの値を伸ばしてあげましょう。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
.
config.vm.boot_timeout = 3600
.
end
もともとはssh.timeoutだったのですが、名前が変わってハマりました。。。
開発環境構築はチームで開発を行う上で重要ではありますが、あまり時間を掛けたくないものです。
この記事で、少しでも開発環境構築が楽になればと思います。
春山 誠 (@Spring_MT)
Fukuoka.rb所属(だったんですが、東京に引っ越したので現在は不定)
Perlがメインの会社にいますが、今は主にRuby書いてます。