Chef-Solo + Berkshelf による自動環境構築

# Chef
[https://www.chef.io](https://www.chef.io)
インフラ環境の構成管理ツール。Ruby製。
アプリケーションのインストールや各種設定を全自動で行える。

かつては皆インフラ環境構築を手動で行ってきたが、
スクリプトや設定ファイル等に記述することで
インフラ環境をプログラミング (Infrastructure as a Code) するのが最近のはやり。

似たようなツールとして、Puppet、Ansible 等がある。

# Berkshelf
[http://berkshelf.com](http://berkshelf.com)
Cookbook の管理ソフト。Ruby でいうところの Bundler に該当するもの。
Cookbook 同士の依存関係を解消してくれる。

他の人が作ってくれた Cookbook は下記URLから検索できる。
[https://supermarket.chef.io/cookbooks-directory](https://supermarket.chef.io/cookbooks-directory)

# Chef の用語説明
* Resource
  * 1つのアプリケーションのインストール・設定などの最小単位。
* Recipe
  * Resource をまとめたもの。
* Cookbook
  * Recipe をまとめたもの。
* Role
  * Cookbook の適用設定を記述したもの。
* リポジトリ
  * Cookbook の保存先。
* Knife
  * Chef 関連の操作を行う際に実行するコマンド。
* knife-Solo
  * knifeのプラグイン。Chef-Solo 関連の操作を実行する際はこちらのコマンド。
 
リポジトリ -> Cookbook -> Recipe -> Resource の階層構造となる。

# Chef の構成
## Chef-Soloを用いる場合
スタンドアロン版の Chef 環境。今回はこちらの構成で作業を行う。
がっつりサーバーを立てるような規模でないような場合はこの構成。

* Chef-Solo:
  * Cookbookの開発・管理、Nodeの管理などを行う。
  * 管理する側のマシン。
* Node:
  * Chef で構成管理されるマシン。
  * 管理される側のマシン。

※ Chef-Solo は今後は非推奨になるっぽい? ([公式ブログより](https://www.chef.io/blog/2014/06/24/from-solo-to-zero-migrating-to-chef-client-local-mode/))。
が、まだ情報が錯綜しているぽいので、今回は Chef-Solo でいく。

## Chef Server を用いる場合
サーバー/クライアント版。一応参考までに記載。
比較的大規模なシステムを管理する場合こちらの構成で用いる。
詳しくは他の資料を探してください。

* Chef Server:
  * Cookbookの管理、Nodeの管理を行うマシン。
* Nodes:
  * Chef で構成管理されるマシン。
* Workstation:
  * Cookbook等の開発・アップロードを行うマシン。

# Chef 環境の構築
今回はローカルマシンの MacBook Pro (Retina, 13-inch, Late 2013) に環境を構築する。
OS は Yosemite にアップデート済み。

## リポジトリの作成
```
$ mkdir ~/chef_repo # 任意の場所に作成
$ cd ~/chef_repo
```

## Chef・Knife-Solo・Berkshelf のインストール
Ruby 1.9 以上が必要。OSX Yosemite の場合デフォルトで入っているRubyでOK。
以下の Gemfile を `~/chef_repo` 以下に作成。

```ruby:Gemfile
source "https://rubygems.org"

gem 'chef'
gem 'knife-solo'
gem 'berkshelf'
```

BundlerでGemをインストール。

```
$ bundle install --path vendor/bundle
```

これでインストール完了。

# Vagrant でテスト用サーバー構築
Vagrant 自体のインストールの説明は割愛。

今回は CentOS6.5 の イメージファイルを使う。
また、仮想環境の作成先ディレクトリは `~/projects/chef_zero_test` とした。

```
$ vagrant box add centos6.5 https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
$ mkdir ~/projects
$ mkdir ~/projects/chef_zero_test
$ cd ~/projects/chef_zero_test
$ vagrant init centos6.5
```

作成された `Vagrantfile` の中を下記のように編集する。

```ruby:Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "centos6.5"
  config.vm.box_url = "https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box"
  config.vm.network "private_network", ip: "192.168.33.10"
  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", "4096"]
  end
end
```

これでローカルから 192.168.33.10 で仮想マシンにアクセスできるようになる。

```
$ vagrant up
```

で仮想マシンを立ち上げておく。

# 仮想マシンへのChef環境導入
下記コマンドを実行。
`[sudo 権限のあるユーザー]@[IPアドレス]` を引数に、
`-i [秘密鍵の場所]` をオプションで指定してやると動いた。

```
$ bundle exec knife solo prepare vagrant@192.168.33.10 -i ~/.vagrant.d/insecure_private_key
Bootstrapping Chef...
...
Preparing... ########################################### [100%]
1:chef ########################################### [100%]
Thank you for installing Chef!
Generating node config 'nodes/192.168.33.10.json'...
```

Node の確認。

```
$ bundle exec knife node list -z
192.168.33.10
$ bundle exec knife node show 192.168.33.10 -z
Node Name: 192.168.33.10
Environment: _default
FQDN:
IP: 192.168.33.10
Run List:
Roles:
Recipes:
Platform:
Tags:
```

無事登録された模様。

# Cookbook の適用
## Cookbook の取得
今回は Berkshelf を利用してクックブックを管理する。
試しに Chef のコミュニティで作成された Emacs の Cookbook を取得してみる。

以下の内容の Berksfile を `~/chef_repo` に作成。

```ruby:Berksfile
source "https://api.berkshelf.com"

cookbook 'emacs'
```

Cookbook を取得する。

```
$ bundle exec berks vendor cookbooks
```

## Run List の設定
対象の Node の json ファイルの run_list に Cookbook 名を追加。

```json:nodes/192.168.33.10.json
{
  "run_list": [
    "recipe[emacs]"
  ],
  "automatic": {
    "ipaddress": "192.168.33.10"
  }
}
```

Run List が更新されたか確認。

```
$ bundle exec knife node show 192.168.33.10 -z
WARNING: No knife configuration file found
Node Name:   192.168.33.10
Environment: _default
FQDN:        
IP:          192.168.33.10
Run List:    recipe[emacs]
Roles:       
Recipes:     
Platform:     
Tags:  
```

## Cookbook の設定反映
下記コマンドを実行してNodeにCookbookを適用する。

```
$ bundle exec knife solo cook vagrant@192.168.33.10 -i ~/.vagrant.d/insecure_private_key
Running Chef on 192.168.33.10...
Checking Chef version...
Installing Berkshelf cookbooks to 'cookbooks'...
Resolving cookbook dependencies...
Using emacs (0.9.0)
Vendoring emacs (0.9.0) to cookbooks/emacs
Uploading the kitchen...
Generating solo config...
Running Chef...
Starting Chef Client, version 12.0.3
Compiling Cookbooks...
Converging 1 resources
Recipe: emacs::default
* yum_package[emacs-nox] action install
- install version 23.1-25.el6 of package emacs-nox

Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources updated in 24.896140136 seconds
```

## 結果の確認

```
$ cd ~/projects/chef_zero_test
$ vagrant ssh
```

上記のコマンドを実行し、仮想環境にログイン。
Emacsを起動してみる。

```
$ emacs
```

これで Emacs が起動すればOK。

# さいごに
ここまでで他人が書いた Cookbook を取得し、
対象のマシンにインストールするところまではコード化できた。

つまり Vagrantfile、Gemfile、Berksfile があれば、
同一環境が簡単に再現可能となった。

次は自作の Cookbook の作成 & 適用か。