knife-soloによるChefの実行


##前提

### knifeとは

Chefレポジトリを操作するためのツール。

chef solo環境で利用するのは主に以下の二つ
・knife cookbook（クックブックの作成）
・knife solo

前者は生のchef soloを利用する場合に用いる。
詳しくは以下。

Chefの基本
http://qiita.com/kidachi_/items/9d569b8673e70ef93f0e

### knife-soloとは

今回のトピックはこちら。
それ単体でリポジトリやクックブックの作成、実行まで一括して行ってくれる。
基本はchef soloを利用したい場合はこのknife soloに頼ればok。


##knifeの初期設定

```
$ knife configure
```
諸々の質問事項は全てデフォルトでok。
初期化が完了すると
~/.chef/knife.rbに設定ファイルが保存される。

##knife-solo
knifeのプラグイン（gem）。
chef solo利用にあたり便利な機能をknifeに追加する。
手元（ホストOS）のレシピをリモートにrsyncでゲストOS側に転送した後
chef-soloを実行し、その出力を送り返してくれる便利機能などが付属。

chef-soloだとchefを流す対象（リモートのサーバ）にログインして
そこでchef-soloする必要があるが、
knife-soloならローカルからホストを指定して流せば良いので手軽。

###インストール

```
$ gem install knife-solo
```
ver0.3.0の場合は、knifeの設定ファイル~/.chef/knife.rbに
knife-soloが利用するテンポラリディレクトリのパスを設定する。

```knife.rb
knife[:solo_path] = '/tmp/chef-solo'
```


##knifeによるリポジトリの生成
```
$ knife solo init chef-repo
```
chef-soloに最適なレイアウトでChefリポジトリを作ってくれる。

構成

```
$ ls -1 chef-repo
cookbooks/
data_bags/
nodes/
roles/
site-cookbooks/
```

## site-cookbooks配下に新たなcookbookを作成する

```sh
$ knife cookbook create <cookbook_name> -o site-cookbooks
```

※chef-repo/cookbooksとchef-repo/site-cookbooksの違い（推奨の使い方）
前者はダウンロードしてきたサードパーティのcookbooksを、
後者には自分で作成したcookbooksを入れる。

## knifeの各設定

プロジェクト直下の`.chef/knife.rb`で設定する。
※knife configureの際生成される`~/.chef/knife.rb`とは別なので注意！

```.chef/knife.rb
log_level                :info
log_location             STDOUT
node_name                'taniguchidaiki'
client_key               '/work/OPServer/.chef/hoge.pem'
validation_client_name   'chef-validator'
validation_key           '/etc/chef-server/chef-validator.pem'
chef_server_url          'https://kidachi.local:443'
syntax_check_cache_path  '/work/OPServer/.chef/syntax_check_cache'

role_path '/work/OPServer/roles'
# 上記の通り、cookbooksでなくsite-cookbooks
cookbook_path  '/work/OPServer/site-cookbooks'
data_bag_path '/work/OPServer/data_bags'

knife[:solo_path] = '/tmp/chef-solo'

```




##レシピ転送&リモート実行コマンド一覧

```

# 指定hostに対してchef-soloをインストール
# 以後リモートホスト上でchef-soloが通るように、いい感じに調整してくれる。
$ knife solo prepare <host>
$ knife solo prepare <user>@<host>

# <host>でchef-soloを実行させる
$ knife solo cook <host>

# run_listを個別に指定（ver0.3.0以降）
$ knife solo cook <host> -o hello::default, nginx::default

# <host>に転送したレシピ群を削除
$ knife solo clean <host>

# 新規Chefリポジトリを作成
$ knife solo init chef-repo

```
※knife-soloがssh経由でchef-soloを実行する際、sshに使われるログインユーザはsudoかつパスワードなしでchef-soloを実行できる権限を持っている必要あり（VagrantやEC2は初期状態でOK）。

※複数サーバにknife-soloしたい場合は、

```
$ echo node1 node2 node3 | xargs -n 1 knife solo cook
```



##指定hostにchef-soloをインストール

実際にやってみる。


```
$ knife solo prepare 192.168.33.10
Bootstrapping Chef...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
101  6790  101  6790    0     0    944      0  0:00:07  0:00:07 --:--:-- 17146
Downloading Chef 11.6.2 for el...
Installing Chef 11.6.2
警告: /tmp/tmp.1zXqJZ9U/chef-11.6.2.x86_64.rpm: ヘッダ V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
準備中...                ########################################### [100%]
   1:chef                   ########################################### [100%]
Thank you for installing Chef!
Generating node config 'nodes/192.168.33.10.json'...
```
成功。

###ホストOSからknife-soloする際の注意
通常の方法でssh出来るようにしておく。
→knife-soloの際、ホストからゲストへ通常のsshアクセス、つまり

```
$ ssh 192.168.33.10
```
でsshできるようになっている必要がある。

~/.ssh/configに以下追記。

```
# ~/.ssh/config
Host 192.168.33.*
IdentityFile ~/.vagrant.d/insecure_private_key
User vagrant
```

##run_listの設定
chef-repos内のnodesディレクトリ内jsonファイル（今回は192.168.33.10.json）に
run_list（実行したいレシピ名）を記述する。

```102.168.33.10.json
{
    "run_list":[
      "recipe[apache]",
      "recipe[build-essential]",
      "recipe[chef_handler]",
      "recipe[git]",
      "recipe[iptables]",
      "recipe[mysql55]",
      "recipe[php54]",
      "recipe[postfix]",
      "recipe[runit]",
      "recipe[yum]"
    ]
}

```



##knife-solo実行

※レシピは既成とする。

```
$ knife solo cook 192.168.33.10
```

いろいろエラーが出た。

##エラー1

```
WARNING: Local cookbook_path '/var/chef/cookbooks' does not exist
WARNING: Local cookbook_path '/var/chef/site-cookbooks' does not exist
WARNING: Local role_path '/var/chef/roles' does not exist
WARNING: Local data_bag_path '/var/chef/data_bags' does not exist
```

path設定がデフォルトのままだったのでこけた。

Vagrantfileに適切なpathを設定し、vagrant reload。

```Vagrantfile
   config.vm.provision :chef_solo do |chef|
     chef.cookbooks_path = "/work/chef-repo/cookbooks"
     chef.roles_path = "/work/chef-repo/roles"
     chef.data_bags_path = "/work/chef-repo/data_bags"
  #   chef.add_recipe "mysql"
  #   chef.add_role "web"
  #
  #   # You may also specify custom JSON attributes:
  #   chef.json = { :mysql_password => "foo" }
   end
```

※ちなみにこの設定は~/.chef/knife.rbの設定に上書きされる。
※今回は knife solo initを使っていなかったので、rolesとdata_bagsディレクトリがそもそも存在していなかった。chef-repo配下に自分で作成して解決。



##エラー2

```
Recipe: mysql55::default
  * package[mysql-server] action install
================================================================================
Error executing action `install` on resource 'package[mysql-server]'
================================================================================

Chef::Exceptions::Package
-------------------------
Version 5.5.32-1.el5.remi of mysql-server not found. Did you specify both version and release? (version-release, e.g. 1.84-10.fc6)
```
```
Recipe: php54::default
  * package[php] action install
================================================================================
Error executing action `install` on resource 'package[php]'
================================================================================


Chef::Exceptions::Package
-------------------------
Version 5.4.20-1.el5.remi of php not found. Did you specify both version and release? (version-release, e.g. 1.84-10.fc6)

```
mysql、phpそれぞれ、レシピで指定したバージョンが見つからないと。

yumからinstall可能なmysqlをチェック

```
[vagrant@localhost ~]$  yum --enablerepo=epel,remi,rpmforge info mysql
Loaded plugins: fastestmirror
Determining fastest mirrors
 * base: ftp.nara.wide.ad.jp
 * extras: ftp.nara.wide.ad.jp
 * updates: ftp.nara.wide.ad.jp
Available Packages
Name        : mysql
Arch        : x86_64
Version     : 5.1.69
Release     : 1.el6_4
Size        : 907 k
Repo        : updates
Summary     : MySQL client programs and shared libraries
URL         : http://www.mysql.com
License     : GPLv2 with exceptions
Description : MySQL is a multi-user, multi-threaded SQL database server. MySQL is a
            : client/server implementation consisting of a server daemon (mysqld)
            : and many different client programs and libraries. The base package
            : contains the standard MySQL client programs and generic MySQL files.
```

Versionが古い。またRepoがCentOSデフォルト（updates）になっている。
→epel/remiリポジトリを追加する。

##リポジトリを追加/有効化する

CentOSにyumリポジトリを追加
http://qiita.com/kidachi_/items/40f862181050b78b9cc7
//TODO 本当はここもChef化したい。

###mysql,phpそれぞれをリポジトリから落とせるバージョンに最適化する。

```
$ sudo vi chef-repo/cookbooks/mysql55//attributes/default.rb
default['mysql55']['version'] = "5.5.34-1.el6.remi"
default['mysql55']['server-id'] = "0"
```
```
$ sudo vi chef-repo/cookbooks/php54//attributes/default.rb
default['php54']['version'] = "5.4.20-1.el5.remi"
```

###remiを常時有効化（enabled=1）にする。

//TODO 後々依存関係が出たりするので、常時有効はあまり良くないとか？


```/etc/yum.repos.d/remi.repo（ゲスト）
[remi]
name=Les RPM de remi pour Enterprise Linux 5 - $basearch
baseurl=http://rpms.famillecollet.com/el5.$basearch/
http://iut-info.univ-reims.fr/remirpms/el5.$basearch/
enabled=1
priority=1
```
###Vagrantfile上でも各リポジトリを有効化。

```Vagrantfile（ホスト）
vmclient.vm.provision :chef_solo do |chef|
	~
  chef.add_recipe "yum::epel"
  chef.add_recipe "yum::remi"
	~
end
```
参考）
Chef の サードパーティ Cookbook を利用して、yum のリポジトリを追加してみる
http://girigiribauer.com/archives/1095

##再度knife-solo実行

```
$ knife solo cook 192.168.33.10
Running Chef on 192.168.33.10...
Checking Chef version...
Uploading the kitchen...
Generating solo config...
Running Chef...
Starting Chef Client, version 11.6.2
Compiling Cookbooks...
Recipe: chef_handler::default
  * remote_directory[/var/chef/handlers] action create
	~
	~
Chef Client finished, 40 resources updated
```

成功。



```102.168.33.10.json
{
    "run_list":[
      "recipe[apache]",
      "recipe[build-essential]",
      "recipe[chef_handler]",
      "recipe[git]",
      "recipe[iptables]",
      "recipe[mysql55]",
      "recipe[php54]",
      "recipe[postfix]",
      "recipe[runit]",
      "recipe[yum]"
    ]
}

```
これで、今後上記のミドルウェアは全てChefベースで展開できる。


## 補足

vagrant関連記事は以下

Vagrantの基本
http://qiita.com/kidachi_/items/e63c1607705178aa257c


saharaでVagrantの状態管理
http://qiita.com/kidachi_/items/ba365905b2a770c72be1