Vagrant

先日 Vagrant を触ってみたら便利すぎて鼻血が出ました。しばらく見ないうちに色々進んでるもんですねえ、いやはや参っちゃいました。

Vagrant仮想マシンVirtualBox のフロントエンドに相当する、ruby で書かれたツールです。vagrant コマンドなどを使ってコマンドラインから簡単に新しい VM を作れる。

% gem install vagrant
% vagrant box add centos http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.3-x86_64-v20130101.box
% vagrant init centos
% vagrant up

これだけで CentOSLinux box をローカルマシン内に立ち上げることができる。*1 *2 なにこれすごい。

% vagrant ssh

で、ゲストOSにログイン。

Vagrant は chef や puppet などの自動化ツールとの連携もしやすくなってて、VM 立ち上げのから OS、アプリケーションの環境構築までを一気通関で自動化することが想定されてます。

ちょっとしたテストのために壊してもいい環境が欲しいというのにももちろん使えますし、方々を見ていると組織の中で標準化された開発環境を全開発者に配布するときなんかにも使われているようですね。自分は EC2 でホストしているステージングサーバーへ chef-solo を流す前に vagrant で調整して、問題なければステージングにも chef を適用するのに使ってます。

より詳しい導入方法は Vagrantで簡単仮想マシン構築 | Ryuzee.com あたりをどうぞ。

vagrant sandbox とか

Vagrant == プログラマブルでポータブルな VM。その辺が垣間見える例を。

Sahara というサードパーティライブラリは Vagrant に commit & rollback ができる機能を追加します。vagrant 上であれこれ作業していまいちだな、とおもったら vagrant sandbox roollback すると環境を巻き戻すことができる。これまたすごい。

# sandbox モードに入る
% vagrant sandbox on

# sandbox モード on に入った時点まで巻き戻す!
% vagrant sandbox rollback

# 変更を確定
% vagrant sandbox commit

vagrant sahara は以下で入ります。

% vagrant gem install sahara

Amazon EC2 のスナップショットのように、任意のタイミングの OS のスナップショットを取得して、そこから別のインスタンスを複製するなんてこともできる。vagrant package を使う。

% vagrant package
% ls -la package.box
-rw-r--r-- 1 naoya staff 545475584 2 5 04:33 package.box
% vagrant box add my_box package.box
% vagrant init my_box
% vagrant up

こんな感じで、単に VM を簡単に起動できるよー以上の便利さが、vagrant には備わっています。

Vagrant + chef-solo で環境構築の自動化

ワンストップで VM を立ち上げられるなら、その後のソフトウェアの環境構築も chef-solo で自動化したいというのは当然のこと。試してみた感じ、直近だと以下の二つの方法のいずれかが良さそう。

knife-solo は 開発メモ#5 : Amazon Linux で knife-solo を使って chef-solo 実行 - naoyaのはてなダイアリー でも紹介した chef-solo のフロントエンドツール。vagrant でも無理なくスムーズに使える。Berkshelf は chef 用の Bundlr みたいなものに Vagrant との連携機能がついたもの。

knife-solo

knife-solo で vagrant に chef-solo する手順を記しておきましょう。

% gem install knife-solo

で knife-solo をインストール。

% vagrant up

VM を立ち上げたら引き続きローカルマシンで

% knife solo init chef-repo
% cd chef-repo
% knife solo prepare vagrant@192.168.50.2

を実行する。192.168.50.2 は VM のアドレス。事前に ssh が通るように ~/.ssh/config に

Host 192.168.50.*
    IdentityFile ~/.vagrant.d/insecure_private_key

vagrant の private key を指定しておくとスムーズ。

knife solo prepare を実行すると、VM 上の OS で chef-solo が実行できるように調整してくれる。面倒なインストール作業や設定は一切必要ない。

あとはいつも通り json ファイルやレシピの編集を行って

% knife solo cook vagrant@192.168.50.2

で ok。rsync でレシピがゲストOSに転送されて chef-solo が実行される。ここまで VM 上の OS には一切ログインしてないところがポイントですね。

Berkshelf

knife-solo を使う場合は、Vagrant とは独立した knife という別のツールを巧く使ってやる感じで先のエントリでも書いたように EC2 でも同じ方法が使えるなど環境を選ばない。

一方、次は Berkshelf の方。こちらはより Vagrant と密に連携できるツール。Bundlr 的にレシピを列挙しておくとリモートから取ってきてセットアップしてくれつつ VM 立ち上げ時にそれらを chef-solo してくれる。

% gem install berkshelf

でインストール。berks コマンドが使えるようになる。berks cookbook すると

% berks cookbook sandbox
      create  sandbox/files/default
      create  sandbox/templates/default
      create  sandbox/attributes
      create  sandbox/definitions
      create  sandbox/libraries
      create  sandbox/providers
      create  sandbox/recipes
      create  sandbox/resources
      create  sandbox/recipes/default.rb
      create  sandbox/metadata.rb
      create  sandbox/LICENSE
      create  sandbox/README.md
      create  sandbox/Berksfile
      create  sandbox/chefignore
      create  sandbox/.gitignore
         run  git init from "./sandbox"
      create  sandbox/Gemfile
      create  sandbox/Vagrantfile
Using sandbox (0.1.0) at path: '/Users/naoya/work/sandbox/sandbox'

という感じでご丁寧に chef のクックブックを作って git init までしてくれる。vagrant を Bundler で動かす用に、Gemfile も。

% cd sandbox
% bundle

次に Berksfile に、リモートから持ってきたいレシピを列挙する。ここでは例として opscode の yum を持ってきて EPEL を有効にしてみる。

site :opscode

metadata
cookbook 'yum'

次に、ひな形として生成されている Vagrantfile を編集。使う box、ネットワークアドレスの編集の他に chef にまつわる記述がある。これは Berkshelf の機能ではなく Vagrant の chef 連携機能で chef オブジェクトに chef の JSON 相当のデータを渡すことで chef-solo 実行内容を指定することができる。

require 'berkshelf/vagrant'

Vagrant::Config.run do |config|
  config.vm.host_name = "sandbox-berkshelf"
  config.vm.box = "centos"
  config.vm.network :hostonly, "192.168.50.5"
  
  # chef の実行
  config.vm.provision :chef_solo do |chef|
    chef.run_list = [
      "recipe[sandbox::default]",
      "recipe[yum::epel]"
    ]
  end
end

これで準備は完了。

% bundle exec vagrant up

とすると、リモートから yum レポジトリを取ってきて chef-solo が走る

[default] Importing base box 'centos'…
[default] Matching MAC address for NAT networking...
[default] Clearing any previously set forwarded ports...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[Berkshelf] installing cookbooks...
[Berkshelf] Using sandbox (0.1.0) at path: '/Users/naoya/work/sandbox/sandbox'
[Berkshelf] Using yum (2.1.0)
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Configuring and enabling network interfaces...
[default] Setting host name...
[default] Mounting shared folders...
[default] -- v-root: /vagrant
[default] -- v-csc-1: /tmp/vagrant-chef-1/chef-solo-1/cookbooks
[default] Running provisioner: Vagrant::Provisioners::ChefSolo...
[default] Generating chef JSON and uploading...
[default] Running chef-solo...

では vagrant ssh

% bundle exec vagrant ssh
Welcome to your Vagrant-built virtual machine.
[vagrant@sandbox-berkshelf ~]$

お見事。

knife-solo の場合は VM の立ち上げと knife-solo の実行は分離されているけど、こちらは vagrant up 一回でワンストップ。まあそのへんは Berkshelf の機能というよりは Vagrant の chef-solo 連携の部分ですが。

なお、chef-solo をさらに実行する場合はいちいち VM を停めて vagrant up とかしなくても

% bundle exec vagrant provision

で chef-solo だけが走るようになってます。

Berkshelf を単独で使う

Berkshelf は便利ですが、Vagrant とくっついている感じなのが、chef-solo を他環境で実行することを考えたときに若干微妙ではある。Bundlr 的な部分だけを使いたい、という場合は自分で chef レポジトリ内に Berksfile を用意して

% berks install --path vendor/cookbooks

とすると、Berksfile 内に列挙したレシピが vendor/cookbooks 内に入る。

おまけ : rbenv 環境の chef

knife-solo で chef を実行すると knife prepare で入るのは Omibus Chef Packaging の chef。ruby はパッケージに組み込みのもの。Berkshelf の場合は Vagrant box に組み込まれた chef-solo。

初期のセットアップの chef-solo はそれらを使うとして、bootstrap が完了したら rbenv な ruby で chef-solo したい・・・ということもあるかもしれない。その辺りのサンプルと手順を以下にまとめておきました。

knife-solo を使う場合少し hack しないといけないのが、難点。

まとめ

Vagrant ベンリ! (まとまってない)

壊したって全く痛くないホストが10秒で手に入るようになって、あれこれ試行錯誤がしやすくなりました。とりあえず、chef レシピの調整が楽になってとても満足でございます。

*1:VirtualBox をあらかじめインストールしておく必要があります。

*2:その後の update で vagrant を gem から入れるのは非推奨になりました。http://downloads.vagrantup.com/ のパッケージでいれてね、とのこと