いろいろな方法でvagrantをprovisioningしてみる

vagrantはいくつかの方法で、起動時にいろいろな処理を走らせることができます。
今回は、

  1. shell script
  2. chef
  3. berkshelf

によるprovisioningをそれぞれ試してみました。

shell

まずは、provisionningがどういうタイミングで走るのかを試しがてら、shell scirptでやってみる。

# scripts/setup.sh
[ -f /vagrant/1.txt ] && touch /vagrant/2.txt
touch /vagrant/1.txt

# Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box     = "centos6.4-x86-minimal"
  config.vm.box_url = "http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130309.box"

  config.vm.provision :shell do |shell|
    shell.path = "scripts/setup.sh"
  end
end

初期化に使うscriptを指定できる。pathの指定は、Vagrantfileがあるディレクトリから相対。
このまま、vagrant upするとVMが立ち上がって、起動後に上記のshell scriptが走る。
試してみたところ、

$ vagrant up
$ vagrant reload
$ vagrant provision

をやったときにそれぞれprovisioningが走る。
複数回vagrant upなどをやってみるとわかるけど、起動など上記のタイミングで何度も同じshell scriptが走る。そのため、provisioningは複数回は知らせても大丈夫なものが好ましい。(chefとかででてくる「冪等性」ってやつ)

chef

次はchefでやってみる。
Macにはknife-soloはいってなかったので、いれる。rbenvはboxenで入れたやつ。

$ rbenv global 2.0.0-p0
$ gem install chef --no-ri --no-rdoc

# install knife 0.3.0 from git
$ git clone git://github.com/matschaffer/knife-solo.git
$ cd knife-solo
$ bundle install
$ rake
$ rake install

次に、recipeを書く。とりあえずなんも考えずにpackageから入りそうなmemcached

$ knife cookbook create memcached -o ./cookbooks

# cookbooks/memcached/recipes/default.rb
package "memcached"

service "memcached" do
  action [:enable, :start]
end

# Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box     = "centos6.4-x86-minimal"
  config.vm.box_url = "http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130309.box"

  config.vm.provision :chef_solo do | chef|
    chef.cookbooks_path = "cookbooks"

    chef.add_recipe("memcached")
  end
end

$ vagrant up

これでVMあげると、chefが走ってmemcachedが入ってる。cookbooks_pathはVagrantfileのあるディレクトリから相対パスで指定。
便利。

berkshelf

berkshelfはcookbookの管理ツール。Berksfileを書くとそれをもとに既存のcookbookをとってきて、それを使ってprovisioningできる。
まずpluginのinstallして、

$ vagrant plugin install vagrant-berkshelf

各ファイルを用意してvagrant up

# Berksfile
site :opscode

cookbook 'nginx'

# Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box     = "centos6.4-x86-minimal"
  config.vm.box_url = "http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130309.box"

  config.berkshelf.enabled = true

  config.vm.provision :chef_solo do |chef|
    chef.run_list = [
      "recipe[nginx]"
    ]
  end
end

$ vagrant up

vagrant upされると、Berksfileに書かれたcookbookを~/.berkshelf/cookbooks, ~/.berkshelf/vagrant/{vm名などから作られたpath}以下に持ってこられる。berkshelf.enabled = trueだと、この~/.berkshelf/vagrant/{vm名などから作られたpath}以下がcookbooks_pathとして、セットアップされるみたい。

vagrant-berkshelf使うとほぼ何もせずにprovisioningしたVMたてられてカジュアルだなーって思った。

一方で、cookbookに手を入れたりすると大変そう。自前で書いたり、berkshelfでpath指定してlocalに落としてそれを書き換えたり、cookbookをforkしたり。目的にあわせて、cookbookをどうしていくかが課題。