knife-soloによるITインフラ構築


#1.はじめに
[前回の記事](http://qiita.com/_daisuke0802/items/14788e55eacbee49e93e)では対象となるサーバーにSSHで接続して直接クックブックを書いたり、レシピを書いたり、
chef-soloを実行したり、といったことをやりました。
ですが、いちいち対象となるサーバーに接続してあれやこれやと作業をするのは面倒くさいものです。
対象となるサーバーが1台や2台ならよいかもしれません。
しかし、同じような内容のWEBサーバーの構築対象が10台、20台になると、、、やはり面倒です。
手元の作業用端末でローカルに置いてあるクックブックやレシピを使ってリモートで対象となるサーバーの
構築ができた方が断然便利でしょう。

というわけで、今回はknife-soloを使用したリモートでのITインフラ構築を行なってゆきます。

* 本稿の範囲：knife-soloを使用してのApacheセットアップ。
* 対象読者：Chefに興味があるものの未だ使用経験の無い方
* 検証環境：OS X Meverics

それでは、行きましょう。

#2.knife-soloとは
knife-soloとは、Chef Soloをより強化するためのプラグインです。
例えば対象となるサーバーに対してChefのインストールをしてくれたり、また、手元にあるキッチン（リポジトリ）を
対象となるサーバーへアップロードしchef-soloを実行してくれたり、といったことができるようになります。

#2.1.Knife Soloを使って幸せになる
では、knife-soloを使用することで私たちはどのように幸せになれるのでしょうか。
既に触れたとおり、1台や2台のサーバー構築であれば前回の記事でやったように対象となるサーバーにログインし、
クックブックやらレシピやらを設置し、chef-soloを実行、というようなやり方でもよいでしょう。
ですが、対象となるサーバーが10台、20台と増えてきた場合、それぞれのサーバーにログインして同様の作業を行うとなると、、、
想像しただけでも非常に面倒で嫌になります。

こんな面倒な作業から我々を救ってくれるのが、knife-soloです。
knife-soloを使用すれば手元の作業端末からローカルに置いてあるリポジトリを使用してリモートで対象サーバーの環境構築を
行なうことができます。
なんと、chef-soloのインストール自体もknife-soloを使用して行なうことが可能です。

いちいち対象となる個々のサーバーにログインすることなく、このリポジトリをどこのサーバーへ適用すればよいのか、
ということを指示するだけで問題を解決することが出来ます。ありがたや。

それでは早速、knife-soloを使用したITインフラ構築に挑んでみましょう。

#2.2.knife-soloのインストール
`gem install knife-solo`でknife-soloのインストールができます。
ターミナルで実行します。

```ターミナル
$ sudo gem install knife-solo
Fetching: knife-solo-0.4.2.gem (100%)
Thanks for installing knife-solo!

If you run into any issues please let us know at:
  https://github.com/matschaffer/knife-solo/issues

If you are upgrading knife-solo please uninstall any old versions by
running `gem clean knife-solo` to avoid any errors.

See http://bit.ly/CHEF-3255 for more information on the knife bug
that causes this.
Successfully installed knife-solo-0.4.2
Parsing documentation for knife-solo-0.4.2
Installing ri documentation for knife-solo-0.4.2
1 gem installed

```

インストールに成功しました。

#2.3.BerkshelfとLibrarian-Chef
Berkshelfとは、クックブックの依存関係を管理してくれるツールです。
一方のLibrarian-Chefというのも、同じようにChefリポジトリの依存関係の管理を助けてくれるツールなようです。
（Librarian-Chefについては、まだ調査不足。。）

knife-soloでは、両方のgemがインストールされていればBerkshelfを優先して使用します。
どちらを使用するかにより、knife-soloの挙動（リポジトリを作成する、手元のリポジトリを使用して対象となる
サーバーの環境を構築するといった）に違いが生じます。

#3.リポジトリを作る
手元の作業端末にリポジトリを作ります。
`knife solo init {リポジトリ名}`でリポジトリを作ります。
ターミナルにて実行して下さい。
なお、`{リポジトリ名}`を"."とするとカレントディレクトリにリポジトリが作られます。
今回は"mychefrepo"という名前でリポジトリを作成します。

```ターミナル
$ knife solo init mychefrepo
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...
```

何やら作られました。このようなディレクトリが作られています。

```
cookbooks
data_bags
environments
nodes
roles
site-cookbooks
```

本稿で関係してくるのは、"nodes"と"site-cookbooks"のみです。
その他のディレクトリについては稿を改めて触れたいと思います。


#4.仮想環境構築
今回もVagrant+VirtualBoxで仮想環境を構築します。
ゲストマシンのOSはCentOSです。前回の記事で`add`したboxを使います。

```ターミナル
$ cd mychefrepo
$ vagrant init github-centos-6.5
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
```

そして、Vagrantfileを編集します。コメントの部分は省略しています。

```Vagrantfile
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "github-centos-6.5"
  config.vm.network "private_network", ip: "192.168.33.10"
end
```

そして、ゲストマシンを起動します。

```ターミナル
$ vagrant up
```

ゲストマシンにホスト名でssh接続できるように~/.ssh/configの設定をします。
ホスト名は"web"とします。
`vagrant ssh-config`と入力するとOpenSSHでマシンに接続する為の設定が出力されます。
これを~/.ssh/configへリダイレクトします。

```ターミナル
$ vagrant ssh-config --host web >> ~/.ssh/config
```

#5.ゲストマシンへChefをインストール
knife-soloを使用してリモートで対象となるサーバーへChefのインストールを行ないます。
使用するコマンドは`knife solo prepare {ホスト名}`です。

```ターミナル
$ knife solo prepare web
：
（省略）
：
Thank you for installing Chef!
Generating node config 'nodes/web.json'...
```

待つこと数分、、、chefのインストールに成功しました。
と同時に、nodesディレクトリにweb.jsonというファイルが作られました。

#6.クックブックを作る
それでは、Apacheをセットアップする為のクックブックを作成します。
クックブックの作成は前回のchef-soloと同じように`knife cookbook create {COOKBOOK_NAME} {option}`コマンドを使用します。
`-o`オプションで出力先を"site-cookbooks"にします。
（cookbooksディレクトリは、BerkshelfやLibrarian-Chefといったツールを使用して取得するクックブックの為に予約されています。）

```ターミナル
$ sudo knife cookbook create apache -o site-cookbooks
** Creating cookbook apache
** Creating README for cookbook: apache
** Creating CHANGELOG for cookbook: apache
** Creating metadata for cookbook: apache
```

site-cookbooksディレクトリにapacheディレクトリが作られました。

#7.レシピを作る
前回と同様にレシピを作ります。
`site-cookbooks/apache/recipes/default.rb`をお好きなエディタで以下のように編集します。
コメントの部分は省略しています。

```default.rb
package "httpd" do
  action :install
end

service "httpd" do
  action [ :enable, :start ]
end
```

#8.ノードを作る
先程の手順「5.ゲストマシンへChefをインストール」で`knife solo prepare {ホスト名}`とした際に
nodesディレクトリに`{ホスト名}.json`というファイルが作られました。
ChefではChefでメンテナンスする対象のマシンを"ノード"と呼びます。
（その対象が物理、仮想、クラウドのいずれでも同様の呼び方をします。）
nodesディレクトリ配下に作られるこれらのJSON（ノードオブジェクトという）は、ノードの重要な２つの要素
（Attributeとrun-list）をコード化したものです。

本稿ではAttributeには触れず、run-listに先程作ったレシピを使用するように記述するに留めます。
（Attributeについては稿を改めたいと思います。）

webノードに対して、先程作ったレシピを使うようにコードを記述します。

```nodes/web.json
{
  "run_list": [
    "recipe[apache]"
  ]
}
```

#9.Knife Solo実行
それでは、knife-soloを使用し、手元にあるリポジトリを使用してリモートで対象となるサーバー（ノード）のITインフラ構築を行ないます。
リポジトリの直下（mychefrepo）へ戻り`knife solo cook {ホスト名}`コマンドを使います。
ターミナルから実行します。

```ターミナル
$ knife solo cook web
Running Chef on web...
Checking Chef version...
Uploading the kitchen...
Generating solo config...
Running Chef...
[2014-06-16T14:26:16+00:00] WARN: 
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
SSL validation of HTTPS requests is disabled. HTTPS connections are still
encrypted, but chef is not able to detect forged replies or man in the middle
attacks.

To fix this issue add an entry like this to your configuration file:

\```
  # Verify all HTTPS connections (recommended)
  ssl_verify_mode :verify_peer

  # OR, Verify only connections to chef-server
  verify_api_cert true
\```

To check your SSL configuration, or troubleshoot errors, you can use the
`knife ssl check` command like so:

\```
  knife ssl check -c /home/vagrant/chef-solo/solo.rb
\```

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 

Starting Chef Client, version 11.12.4
Compiling Cookbooks...
Converging 2 resources
Recipe: apache::default
  * package[httpd] action install
    - install version 2.2.15-30.el6.centos of package httpd

  * service[httpd] action enable
    - enable service service[httpd]

  * service[httpd] action start
    - start service service[httpd]


Running handlers:
Running handlers complete

Chef Client finished, 3/3 resources updated in 38.720525997 seconds
```

無事に成功したようです。

#10.動作確認
それでは前回同様、適当なWEBブラウザからApacheの画面が出るか確認してみます。
WEBブラウザから`http://192.168.33.10`へアクセスしてみましょう。
前回の記事と同様、Apacheの画面が表示されれば成功です。

#11.再構築する
無事に動作確認までできました。お疲れ様でした。
ここで試しに構築したゲストマシンを破棄して再構築を試してみましょう。
ゲストマシンの破棄は`vagrant destroy`でした。

```ターミナル
$ vagrant destroy
    default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Forcing shutdown of VM...
==> default: Destroying VM and associated drives...
```

破棄できました。
次に`vagrant up`してゲストマシンを再び起動します。

```ターミナル
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'github-centos-6.5'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: mychefrepo_default_1402929295486_89641
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: hostonly
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
    default: /vagrant => /Users/nakagawadaisuke/mychefrepo
```

まっさらの状態でゲストマシンが起動しました。ChefもApacheもインストールされていない状態です。
先程の動作確認をしたWEBブラウザで同じURLへアクセスすると真っ白い画面が返ってきます。

それでは、knife-soloを使用して環境を再構築してみましょう。
今回は既に作ったリポジトリが手元にありますのでコマンド一発で済みます。

`knife solo bootstrap {ホスト名}`と入力します。
先程は使用していないコマンドです。
これは`knife solo prepare`によるChefのインストールと`knife solo cook`によるカレントリポジトリのアップロードとchef-soloの実行を
一緒に実行してくれます。

```ターミナル
$ knife solo bootstrap web
```

少し時間がかかりますがChefのインストール、カレントリポジトリのアップロードとchef-soloの実行まで進めてくれます。
もう一度、WEBブラウザから動作確認をしてみましょう。
再びApacheの画面が出れば成功です。

#12.まとめ
`knife solo`プラグインにより追加される５つのコマンドについてまとめます。

| command | description | 
|:-----------|:------------|
| knife solo init | Chefリポジトリの作成 |
| knife solo prepare | 対象ホストにChefをインストール |
| knife solo cook | カレントリポジトリを対象ホストへアップロードしchef-soloを実行 |
| knife solo bootstrap | prepareとcookを実行 |
| knife solo clean | 対象ホストからアップロードしたリポジトリを削除 |


本稿では[前回の記事](http://qiita.com/_daisuke0802/items/14788e55eacbee49e93e)と同様にAacheをインストールしましたが、その手段が異なりました。
前回は、対象となるホストに直接ログインして、リポジトリ、クックブック、レシピを作成してchef-soloを実行しました。
今回は、knife-soloというプラグインを使用して手元にある端末からのChefインストールとリポジトリを使用してのリモートな環境構築を行ないました。
手元にある端末から対象となるサーバーに対してリモートなITインフラ構築を行うことのメリットについて掴んでいただければ幸いです。