VagrantとChefでチームの開発環境を共通化する

インフラ構築のテストに遅まきながらVagrantを使おうと色々調べていたが、チーム開発の開発環境を共通化したい、という声がメンバーがから上がったのでそっちの方もVagrantでやることにした。

Vagrantで仮想マシンを作ってChefで環境構築できるようにしたものをメンバーに配布する流れ。

概要

VagrantはVirtualBoxのような仮想マシンのフロントエンドツールでAmazon EC2やVM Wareに対しても使うことができる。
コマンド一発で仮想マシンを立ち上げたり落としたりできて便利。エディタで設定ファイルを編集して仮想マシンの設定を変更することも簡単。プラグインでの機能拡張もでき、仮想マシンを一時的にSandbox化できるSaharaなどが有名。

詳しくは以下。

大いに参考になる。
ただしVagrantfileの書き方が最新のものとは違うので、それらに関しては公式のドキュメントを参照のこと。

導入

実際に導入してみる。
環境はMacのOSはMountain LionでRubyは2.0.0-p247。

VirtualBoxを入れる

Download VirtualBox

先述したように他の仮想化環境でも行けるがとりあえずVirtualBoxで。

Vagrantを入れる

Vagrant

上記からパッケージをダウンロードしてきて入れる。
gem install vagrantでも入るが現在は非推奨の方法となっており、入るバージョンも古い。

Boxを探して来てaddする

Vagrantbox.es

手頃なBoxを上記から探してvagrant box addする。
例えばニフティクラウドのCentOS 6.3を使いたいので以下のようにするなど。

$ vagrant box add centos63 https://dl.dropbox.com/u/7225008/Vagrant/CentOS-6.3-x86_64-minimal.box

centos63は任意に付けられる名前。分かりやすいものを付けておくとよい。
こうしたコマンドの結果は~/.vagrant.d以下に保存される。

Vagrantfileの作成
$ vagrant init centos63

Vagrantfileが作られてvagrant upの準備ができる。

なお後々ローカルと仮想マシンのファイルの同期を何も考えずに行うために、Vagrantfileはプロジェクトのルートに置く。つまりRailsならRAILS_ROOTに置く。

とりあえず起動
$ vagrant up

仮想マシン初期化。少し待てばOK。
場合によってエラーメッセージが出たりするけど気にしない。

そして落とす
$ vagrant halt

なんでこんなことするかと言うと、いったん起動してからじゃないとプラグインの導入がうまくいかないっぽいので。

プラグインの導入

Vagrantを便利にしてくれるプラグインを入れておく。

$ vagrant plugin install sahara
$ vagrant plugin install vagrant-vbguest
$ vagrant plugin install vagrant-berkshelf

それぞれの詳細は後述。

再び起動
$ vagrant up

vagrant-vbguestが動いていろいろインストールされたりする。
先ほどの起動でエラーメッセージが出ていた場合は解消されたはず。

使いこなしのための予備知識

  • ssh
  • 同期ディレクトリ
  • 環境構築 Provisioning
  • ポートフォワーディング

といったいくつかのことを理解しておく。

ssh

立ち上げた仮想マシンへのssh接続は以下のようにする。仮想マシン上のvagrantユーザーでの接続となる。

$ vagrant ssh

通常のsshコマンドでログインするには.ssh/configに設定を追加する。

Windowsでvagrant upした後にsshログインする方法

vagrant ssh-configを使えば簡単。

$ vagrant ssh-config >> .ssh/config

これで以下のように接続できるようになる。

$ ssh default

defaultの部分を変更したければ.ssh/configを修正。
自分の場合はssh centos63で接続できるように変更した。

.ssh/configに関しては以下がわかりやすい。

~/.ssh/config で簡単に複数ホストへのSSH接続を管理する – – すぱぶろ

同期ディレクトリ

ローカルのVagrantfileがあるディレクトリと仮想マシン上の/vagrantが同期するようになっている。
つまりプロジェクトのルートにVagrantfileを置いておけば、編集したファイルがすぐに仮想マシンに反映されるため開発が捗る。

設定で変更することもできるが、他の開発メンバーが何も考えずに利用できるようにするにはデフォルトのこの状態がベストではないかと思う。

と言うわけで開発用のウェブサーバーのもろもろの設定なども/vagrantにファイルがある前提で行うことになる。(か、シンボリックリンクを使うなど)

参考: Synced Folders – Vagrant Documentation

環境構築 Provisioning

仮想マシンの環境構築をキックスタートスクリプトやChef、Puppetなど好きな手段で行うことができる。

Vagrantfileに構築内容を記述しておけばvagrant upした時点で適用される。

構築内容を更新した場合は

$ vagrant provision

で既存の環境に反映できる。

環境の更新があった場合はメンバー各自にこれを行ってもらう。

ポートフォワーディング

仮想マシン内に立てたウェブサーバーなどにホストOS(今回だとMac)のブラウザからアクセスするための設定。
以下のように書く。

  config.vm.network :forwarded_port, guest: 3030, host: 3030, auto_correct: true

auto_correctはvagrant-vbguestのせいでネットワークがうまくつながらなかったりしたので追加してみた。
他つながらない原因としては仮想マシンのiptablesなどが考えられるので、うまくいかない場合はそちらもチェック。

参考: Forwarded Ports – Networking – Vagrant Documentation

ポートフォワーディングの代わりに仮想マシンにIPを振ることもできるが、ネットワーク環境はメンバーそれぞれなのでポートフォワーディングで済ませた方がスムーズなはず。

プラグイン

プラグインによってVagrantは更に便利になる。

sahara

仮想マシンをSandboxモードにできるプラグイン。超便利。詳細は以下。

Vagrantの必須プラグインSaharaをVagrant 1.1に対応させました

今は1.1以降にもちゃんと対応しているようで、普通にvagrant plugin installでインストールできる。

vagrant-berkshelf

BundlerのCookbook版であるBerkshelfを使うためのプラグイン。
Berkshelfを使う場合は以下のような流れで環境を構築する。

  • Berkfileにcookbookを追加
  • berks install –path vendor/cookbooks
  • vagrant provision

Vagrantfileのchef.cookbooks_pathは無視されるので、site-cookbooks以下に置くようなローカルなcookbookも 必ずBerkfileに登録しなければならない。

Berkfileの書き方はGemfileと似ていて、cookbookには:pathや:gitといったオプションを使うことができる。

それぞれのCookbookはvendor/cookbooksに置いてリポジトリに含める。

vagrant-vbguest

boxのGuestAdditionのバージョンとVirtualBoxの要求するバージョンを合わせるためのプラグイン。詳細は以下。

VagrantのboxのVBoxGuestAdditionsを超簡単に最新版に更新する方法

これがないととてもめんどくさい。

配布

VagrantfileとBerkfileをプロジェクトのルートに置いてコミット。vendor/cookbooksもリポジトリに含める。
そして上記のVagrantの導入を各自でやってもらう。するとvagrant upした時点で環境ができる。

環境の更新は各自リポジトリからpullした後でvagrant provision。
更新のたびにイメージを作って配布するという手もあるが、そのためのタスクが増えてしまうのでひとまずそれは無しで。

開発が進んで運用していくうちに各メンバーそれぞれの仮想マシンに独自設定が入り込んで均一な環境でなくなってしまうことが考えられるので、時々プロジェクトのルートの.vagrant/をまるっと削除して最初から環境を作り直すといったことをやった方がいいかもしれない。

その他

CentOS6でネットワークが遅い

IPv6が悪さをしているらしい。

ここを見て解決。
他の対処法としてこういう情報もある。

  # for CentOS ipv6 issue
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--natdnsproxy1", "off"]
    vb.customize ["modifyvm", :id, "--natdnshostresolver1", "off"]
  end
複数台の仮想マシン

共有の開発環境にはひとまず不要だけど、インフラ構築のテストなどのために複数台の仮想マシンを立てることもできる。

vagrantでVMを一度に複数台立てる – $shibayu36->blog;

大量の仮想マシンを立てたければVirtualBoxの中でLXCを使うなどVagrant以外のアプローチもあるようだ。

2013/10/08追記

こういうの突き詰めると社内PaaSとかになっていくんかな。

2013/10/13追記

ローカルに必要な開発環境だから社内PaaSじゃ代わりにはならないか。

最初のvagrant upとプラグインの導入周りの順序を整理して書き直した。