vagrant + chef-solo provisioningが初めて動くまで

あるいは Kanazawa.rb meetup #9 は「意識高いもくもく会」です。

はい、まぁ最近じゃ今さらの話ですね。

Chef って興味あったんですよというか正確には Puppet に興味があって、でも大げさだなと思ってたんですよね。あと当時は Puppet は外部DSLだったので、「Rubyの文法でもなんでもない設定って、どうやってエディタでハイライトするの?」というのが最大の心理的ハードルでした。

で、時は流れて Software Design の Chef 特集を読んでやる気になったけど、本家のリファレンスと格闘しているうちに仕組みの大掛かり感が増長されて挫折。その後ビッグウェーブに乗って達人出版会で買った『入門Chef Solo』を読み、そこでようやく

「サーバの状態を管理し収束させるためのフレームワーク」

という表現がグサッと刺さって、分かった気がしたのでもう一度やってみました。で、一応動くところまで来たので、今回改めて感じたことをまとめておこうと思います。

Vagrantのメリットよく分かってなかった

VirtualBox は以前から使っていたのでなんでわざわざ Vagrant なんか使うの?ってずっと思っていたんです。今も自分で使う分には Vagrant である必要はないよなーと思いつつ、以下のようなところがメリットかなと今は思っています。

  • 手作業での設定を必要としないので VirtualBox をよく分かっていない人にも同じように VM を配布することができる
  • ある程度設定の完了した VM を box として package して共有しやすい
    • 生の VirtualBox で VM の使い回しをやろうとするともっと手間が掛かる

※ vagrant 1.1 から単なる VirtualBox の wrapper ではなくなったのでそこにメリットがある人はぜひ使いましょう。

Vagrantの扱いにくさをよく分かってなかった

  • Vagrant は gem install もできるが基本的には配布パッケージが最新
  • 特に今(2013年初夏)は 1.0/1.1/1.2 の過渡期で設定ファイルのフォーマットが違ったりいろいろややこしい
    • Windows で動かすことを思うと1.2がよいが gem の最新は 1.0.x
    • でも Bundler で扱えた方が周辺ツールも含めて管理できるので本当はそっちがよい

org-binbab/gem-vagrant-wrapper · GitHub

という神 gem があります。これを入れると最新の package 版 Vagrant を使いつつ Bundler 管理できるようになって超絶便利。

Chef Solo + Knife Soloという構成はWindowsに厳しすぎる

Chef を使うにあたって『入門Chef Solo』を参考にしたので当然のように全体の作業は Knife Solo ベースでやっていました。

Knife は慣れてくると cookbook を作り実行するというサイクルの中心に置いたときにすごく使いやすいことが分かってきます。それは間違いないんですが、いかんせん

ssh + rsync で cookbook を転送する

というその仕組み上、Unix 系の開発者でない人が使っている(いわゆる普通の)Windows とは相性が悪すぎます。

結局WindowsではVagrant + chef-solo provisoningに落ち着いた

knife solo で cookbook を練っていって、最後は

config.vm.provision :chef_solo do
  ...
end

に反映されるようにしました。まだこの部分の Vagrantfile の生成やバージョンの管理方法はきれいにまとまってないのですが、方針としてはそういう形で行こうと思ってます。 Windows 用の手順をまとめると

  1. VirtualBox をインストール
  2. Vagrant をインストール
  3. vagrant plugin install vagrant-vbguest
  4. Putty + vagrant-multi-putty plugin の準備
  5. vagrant box add <BOX URI>
  6. vagrant up

といった感じ。実際には

  • Putty 周りの設定が慣れてない人はやや面倒(PATH が通ってなきゃいけない)
  • vagrant putty でなぜかパスワードを聞かれる(なんでかよく分かってない)
  • 例えば Rails の環境を作るためには vagrant putty したあとに bundle install とかお約束の作業は必要
    • そのうえで rails server 立ち上げるなども必要

てな感じで2回コマンド叩いたら何もかも完了、みたいなことは実現できないんですが、初回の待ち時間はともかく、サーバの設定が全自動で済んでいるというのはやはり大きいと思います。少なくともサーバ構築とかまったく目的ではない人にとっては書かれた通りに作業するだけでいいというのは魅力的なんじゃないかな。

VagrantのChef Solo Provisioningで思い込んでいたこと

Chef を実行するのは VM 上なんだからどうにかして VM 内に cookbook 運ばなきゃいけないですよね。で、VirtualBox の共有フォルダに置くとかしなきゃいけないのかなと思ったけど、そんな必要はありませんでした。なんか自動でうまいこといってた。

ChefのCookbookを育てる環境とそうでない環境

上の vagrant-wrapper 頼みで cookbook を育てる環境の Gemfile は以下のようにしました。

# -*- mode: ruby -*-

source 'https://rubygems.org'

gem 'rake'
gem 'vagrant-wrapper'
gem 'chef'
gem 'knife-solo', '> 0.2', :git => 'https://github.com/matschaffer/knife-solo.git', :tag => 'v0.3.0.pre3'
gem 'sahara', :git => 'https://github.com/ryuzee/sahara.git'
gem 'vagrant-vbguest'

これで git と gem と ssh の使える環境では knife solo でもりもり cookbook を作ったり実行したりできます。provisioning にしか興味のない環境では bundle install はしないで package の Vagrant を直接叩いて作業してもらいます。

Chefでようやくつかめてきたこと

すべてはリソースと見つけたり

Chef って語る要素がすごく多いんですが、要は

  • ホストの状態を収束させる
  • そのためにリソースをキーにしてコードブロックを与える
    • その中で only_if, not_if でちゃんと状態をチェックする
    • 楽して execute リソースを選ぶと実行の終了をきちんと待てずに2回実行しないと安定しないといったことも起きるので注意

の大きく2点が大事かなということに気づき始めました。

正直言うと sh script の方が楽じゃないのと思うポイントはまだ多いし、生のコマンドでできることが chef の resource に落とし込んだ段階で制限されて変に手間の多い recipe になるといったことはあります。でもやはりそこは手間と思っても分けておいた方が段階的に実行する/しないをチェックでき、最終的には早く収束される方向に振ってあって、試してるうちにうまいなぁと思うようになってきます。

  • 特に条件分岐を sh script で書き始めるとコードがすぐややこしくなる
  • なにより sh script では再利用しにくい
    • Chefでちゃんとリソースを意識してrecipeを書いていればrecipe単位, cookbook単位での再利用しやすさがある程度自然と確保される

辺りが感心するポイントでした。

recipeの分け方

今のところ以下のような方針でやってます。

  • とりあえず 1アプリ:1 cookbook
  • cookbook には default recipe があるんだけど、とりあえず cookbook と同名の recipe を作って明示的に呼ぶようにしてる
  • 特に何らかの設定が必要だったり事前準備の必要なアプリのインストールの場合はこの分け方がいい
  • 設定が不要でただインストールすればいいものはいくつもまとめてしまっちゃってok
  • cookbook が分かれていなくても recipe が分かれていれば include_recipe で再利用できるので、分けて再利用する

recipe の再利用は

include_recipe "#{cookbook}::#{recipe}"

で記述するんですが、recipe 内では #{cookbook_name} で自身の cookbook の名前を知ることができる1ので、同じ cookbook 内の recipe も違う cookbook 内の recipe も自在に再利用できます。

再利用を前提にあれこれやっているうちに

  • とりあえず何をするときにどこを見ればいいか
  • 何が分かっていないか

がだんだん分かってきたので、以前よりはだいぶ recipe を書くのは早くなってきました。

次の課題

例えば複数の Rails 環境を用意したい場合、『入門Chef Solo』方式で hostonly で IP アドレスを固定していくのがいいのかどうか、迷っています。Vagrantfile を組み立てる rake タスクを用意して2、用途に応じて Vagrantfile を生成したのち vagtant up するのが手間も少ないし、見通しもいいのかなぁという感じのことを考えています。

でもそのうちまた違うこと言ってるかもしれないです。

chef というか vagrant を使ったホスト管理の話ですね、これは。

  1. Ruby 的には instance variable に attr が設定されているだけ 

  2. 一応 Vagrant を入れた環境には必ず Ruby も Rake もあるので 

More