Chef Provisioningのすすめ

2013年、伊藤直也さんが書かれた「入門Chef Solo」から、Chefを使ったサーバープロビジョニングのコード化が注目されましたが、その当時日本ではスタンダードだったChef Solo(+ Knife Solo)が引退していくことになってしまいました。
その難民がKnife Zeroに移行したり、Chef特有の仕様に挫折してAnsibleへと移行していった人も多いかと思いますが、それ以外の選択肢として、Chef社がコミットしている「Chef Provisioning」（旧名:Chef Metal）もなかなか使い勝手のよいツールに仕上がってきているので、紹介してみたいと思います！

（記事後半で実際にプロビジョニングをする例を挙げていますが、シンプルにCookbookを適用するだけなら本当に簡単です！）

# Chef Provisioningとは
- 従来のChef Solo + Knife Soloの代わりとなりえる、公式のプロビジョニングツール
 - ssh経由でプロビジョニング（Cookbookを適用）できる
 - AWSのEC2やDokcerイメージを作ってCookbookを適用することも可能
- 複数サーバーの構成をテキストファイルで管理できる
 - Master-Slave構成やクラスタを組むようなアプリケーション設定も
- 作業マシン上にChef Zero（簡易Chef Server）を動的に立ち上げ、プロビジョニング対象マシンがそこに接続する

### Chef Solo(Knife Solo)と比べて
- Chef Soloは引退…
 - Chef SoloとChef Serverは機能が異なっていたが、Chef ProvisioningはChef Zeroを利用してるため、Chef Serverと同等の機能が利用可能
- スタンドアローンなChef Soloを、Knife Soloを利用することで複数サーバーへの適用ができたが、あくまで1サーバーへのプロビジョニングが基本

### Chef Serverと比べて
- 導入が容易
- 構成をブラウザで管理しないのであれば

### Knife Zeroと比べて
- 同じくChef Zeroを利用しているが、何をするでも（gitのように）knifeコマンドを多用するため、覚えることが多い
- Chef ProvisioningはChef社公式ツールなので、今後もメンテナンスされていきそう

### Ansibleと比べて
- DSLがRubyそのものなので、Rubyになれてればyamlで記述するより利便性が高いコードが書ける
 - ifやループはもちろん、rubyでできることならなんでも
- Chef Supermarketで様々なコミュニティCookbookが公開されている
 - https://www.chef.io/blog/2015/03/16/using-chef-supermarket-a-guided-tour/
- Chefと違って対象サーバーに特定のソフトウェアをインストールする必要はない
 - Chefのインストール作業はコマンド一発でできる

# Chef Provisioning実行環境のセットアップ
※なるべく手数が少なくわかりやすい方法で案内します

## Chef Provisioningのインストール
Chef社提供のパッケージ Chef Development Kit (ChefDK) からインストールすれば、Chef実行に必要なツールがruby含めて一式そろうので、お勧めです。

※ /opt/chefdk/ 以下にrubyやchefコマンドが配置されるので、すでにrubyがインストール済みでも影響しません

0. ChefDKのダウンロード＆インストール
    https://downloads.chef.io/chef-dk/
    からLinuxやWindows,Mac用パッケージを落としてきて、作業マシンにインストールします

0. chef-provisioning-sshのインストール
    ChefDKにはchef-provisioningも同梱されてますが、ssh経由でセットアップするドライバは無いので、別途インストールします

    ```bash:
$ chef gem install chef-provisioning-ssh --no-ri --no-rdoc
```
    ※`chef gem` とすると、ChefDKでインストールしたruby gemでinstallされます
    ※現状、chef-provisioning-aws, vagrantは同梱されてますが、chef-provisioning-dockerも未同梱でした

## Chef Provisioning実行のための構成
#### Cookbookの取得
※ここでは例としてjavaのインストールをします
※Cookbookの取得には、依存するものも含め取得するBerkshelfを利用します

0. ディレクトリ作成 ＆ その中に入る

1. "Berksfile"という名前のファイルに次の内容で保存

    ```:Berksfile
source "https://supermarket.getchef.com"
cookbook 'java'
```

2. Berkshelfの記載内容を読み取って、"cookbooks"ディレクトリにjavaのcookbookをダウンロード

    ```bash:
$ berks vendor cookbooks
```

#### chef-provisioning-sshの実行ファイル作成
0. 適当なファイル名の（例えばサーバー名の）rubyファイルを作成
    ※各自の環境にあわせて、sshのホスト・ユーザー名・鍵ファイル置き場など変更してください

    ```ruby:server1.rb
require 'chef/provisioning'
require 'chef/provisioning/ssh_driver'
with_driver 'ssh'
machine "server1" do
      machine_options :transport_options => {
        'ip_address' => '111.111.111.111',
        'username' => 'ec2-user',
        'ssh_options' => {
          'port' => 22,
          'keys' => ['~/.ssh/id_rsa']
        }
      }
      add_machine_options :convergence_options => {:chef_version => 'true'}
      run_list ['java']
      action [:converge]
end
```

## chef-provision-sshの実行
1. chef zeroを起動（-zオプション）して、chef-clientコマンドで先ほどのrubyファイルを指定して実行

    ```bash:
$ chef-client -z server1.rb
```

これにて完了です。
Chef実行に必要なものがChefDKのインストール一発でだいたい入ってしまうことも関係しますが、従来よりだいぶ簡単に実行できるようになってますね！

# Chef Provisioning をさらに使いやすくする独自拡張
これだけでも十分簡単にできますが、実際のサーバーに対して使うにあたって、より利便性を高くする改良をしてみました
※Chef Provisioningのソースコードには手は加えていません

- 複数環境（開発・本番等）、複数roleの混在する設定、を1つのテキストファイルで管理
- site-cookbooksのサポート
- ssh接続のアカウント（初回はrootユーザーでセットアップ、次回以降はadminユーザーで）

と・・、このことをきちんと書くとさらに文量が多くなってしまうので、中途半端ですが一旦ここで終わりにします。もしまだまだChefで戦ってくぞ！という方が多ければ、続きを別の記事で書いてみようと思います。