ある日何気なく最新版のvagrant-berkshelf(4.0.4)を入れたところ、

It appears that you are not using the ChefDK. Please note that Vagrant Berkshelf works best when used with the ChefDK, and other installation methods are not officially supported.

Please download and install the latest version of the ChefDK from:

    https://downloads.getchef.com/chef-dk

and follow the installation instructions. Do not forget to add the ChefDK to your PATH.

というメッセージが表示されて vagrant up ができなくなってしまいました。メッセージを読むに、どうやらChefDKを使うようにと指示されています。

このChefDKについては存在は知っていて興味もあったのですが、実際に触れたことはなかったので、これを機に試してみることにしました。

ChefDK(Chef Development Kit)とは

ChefDKとはChefおよびポピュラーな関連ツール一式を簡単にインストールできるようにパッケージングしたソフトウェアになります。加えて新たなコマンドである chef コマンドが含まれていて、ジェネレータとともにChefのワークフローを簡素化する狙いを担うとされています。

執筆時点でMac OSX、RHEL、Windows、Ubuntu、Debianに対応したパッケージが用意されており、[公式サイトのダウンロードページttps://downloads.getchef.com/chef-dk/)よりダウンロード&インストールできます。

最新バージョンである0.6.2では以下のものが含まれています。

  • chefコマンド
  • Berkshelf 3.0
  • Test Kitchen
  • ChefSpec
  • FoodCritic
  • 既存のChefツール全て(Chef Client, Knife, Ohai and Chef Zero)

Chefの実行に必要なRubyやgemなども組み込まれており、従来とは違ってRubyのインストールやgemの準備を気にかける必要はありません。初めてChefを使う人にとってはぐっと導入が簡単になるので、大きな意味をもってくるでしょう。

なおバージョン番号から見るにChefDK自体はまだ正式リリースではないようなので、今後挙動や構成が変わる可能性もあるのでご注意ください。しかしインストールされるツールは chef コマンドを除き今まで通りにgemで入れるのと変わりませんので、ChefDKによって入るknifechef-soloなどの従来のコマンドは問題なく動作すると考えていいでしょう。

ChefDKのインストール

ChefDKのダウンロードページ
ChefDKのダウンロードページ

今回はMac OSXで試します。まず公式サイトのダウンロードページよりMac OSX版をダウンロードしてインストールします。

ChefDKのインストーラー
ChefDKのインストーラー

パッケージからアプリをインストールするだけなので特に説明するようなことはありません。
インストールが完了すると /opt/chefdk 以下にもろもろのファイルが展開され、/usr/bin/ 以下にもシンボリックリンクが作成されています。

まっさらな環境であればこれで問題なくChefDKによるChefが動くようになっていたはずです。
しかしすでにRubyを導入済みの環境では話はそう簡単ではありませんでした。開発者であればrvmやrbenvを使っていることが多いので、その際には以下を参考にしてください。

既存のRuby環境との衝突

インストール後にvagrant upしてみると同じエラーメッセージが表示され、相変わらずうまく動きません。

berksコマンドの場所を確認してみると

$ which berks
/Users/moongift/.rbenv/shims/berks

どうもrbenvでいれた既存のRubyのBerkshelfを使用しているようです。

ちなみに/usr/bin/berksを確認してみると以下のようにChefDKのものを指しています。

$ ls -l /usr/bin/berks
lrwxr-xr-x  1 root  wheel  21 11 25 13:47 /usr/bin/berks -> /opt/chefdk/bin/berks

この時の解決法として、3つのパターンで考えてみたいと思います。

解決策1 ChefDKのパスを優先

ChefDKのパスを優先することでChefDKで入れた方のberksコマンドが有効になります。

chef shell-initを使うと、パス設定のコマンドが表示されるので、これを実行するか.bashrcや.zshrcに追加すればOKです。

$ chef shell-init zsh
export PATH=/Users/moongift/.rbenv/bin:/Users/moongift/bin:/usr/local/bin:/usr/local/sbin:/opt/local/bin:/opt/local/sbin:/Users/moongift/.rbenv/shims:/Users/moongift/.rbenv/bin:/usr/bin:/bin:/usr/sbin:/sbin
export GEM_ROOT="/opt/chefdk/embedded/lib/ruby/gems/2.1.0"
export GEM_HOME=/Users/moongift/.chefdk/gem/ruby/2.1.0
export GEM_PATH=/Users/moongift/.chefdk/gem/ruby/2.1.0:/opt/chefdk/embedded/lib/ruby/gems/2.1.0

ですがこの設定を行うとChefDKで入れたツール一式は使えるようになりますが、逆に既存のRuby環境に影響が出てしまいます。Ruby製のツールを使っていたりRubyで開発している場合、この設定を適用することは難しいでしょう。

解決策2 既存のchefやberkshelfを削除

rbenvで入れているすべてのバージョンのRubyでBerkshelfのgemをアンインストールします。

そして以下のファイルは消えないので手動で消します。

$ rm /Users/moongift/.rbenv/shims/berks

この方法でもChefDKで入れたberksコマンドを有効にすることができます。

しかしこの方法ではインストール済みのRubyのバージョンが多い場合には大変な作業になりますし、何かの拍子(よく使うbundle installなど)でBerkshelfが入ってしまうと問題が再発します。そのため、あまり筋が良い解決法とは言えないでしょう。

解決策3 chef execを使う

chef execを使うことで解決策1で試したchef shell-initで表示される環境変数を適用した状態でコマンドを実行できます。

$ chef exec which berks
/opt/chefdk/bin/berks

しっかりとChefDKのberksを指し示していますね。試しにirbでchef execした時の環境変数を確認してみます。

$ chef exec irb
irb(main):002:0> ENV["PATH"]
=> "PATH=/Users/moongift/.rbenv/bin:/Users/moongift/bin:/usr/local/bin:/usr/local/sbin:/opt/local/bin:/opt/local/sbin:/Users/moongift/.rbenv/shims:/Users/moongift/.rbenv/bin:/usr/bin:/bin:/usr/sbin:/sbin"
irb(main):003:0> ENV["GEM_HOME"]
=> "/Users/moongift/.chefdk/gem/ruby/2.1.0"
irb(main):004:0> ENV["GEM_ROOT"]
=> "\"/opt/chefdk/embedded/lib/ruby/gems/2.1.0\""
irb(main):005:0> ENV["GEM_PATH"]
=> "/Users/moongift/.chefdk/gem/ruby/2.1.0:/opt/chefdk/embedded/lib/ruby/gems/2.1.0"

どうやらこの解決策が最もスマートに思えます。そもそもの問題だった vagrant upについても、

$ chef exec vagrant up

これで解決できます。これでこれまで通り仮想マシンが起動します。

ChefDKの環境にgemを入れる

実際に運用するとなると、Knifeのプラグインなどを入れるためにChefDKの環境にgemを使ったライブラリのインストールが必要になります。それには chef gem を使います。

$ chef gem install knife-zero

または chef exec を使う要領で

$ chef exec gem install knife-zero

でもOKです。ただせっかく用意されていますので chef gem を使った方が良さそうです。

終わりに

今回はvagrant-berkshelfをきっかけにChefDKを軽く試してみました。

Chefを使っていると必要な他のgemとの依存関係の衝突やビルドエラーなどで悩むことがままありますが、ChefDKを使えば全部詰め合わせたChefが簡単に手に入るので、そうした煩わしさから解放されそうです。

chefコマンドによる新たなワークフローの示唆に加え、vagrant-berkshelfのようにChefDKを前提とする周辺ツールが出てきていることもあり、今後はChefを使う上で欠かせないツールになるのではないでしょうか。

Chef Development Kit | Chef Downloads | Chef