「構成管理ツールChefを使ってみよう」をやってみよう。

#結論
**出来ひんやんけ！**

#きっかけ
環境構築せな、、
一個一個やるのめんどくさ、、、

そういえば`Chef`とか`Ansible`とかあったな。
プロジェクトは`Ruby on Rails`で作ってるし、`Chef`でやってみるか。

(`Chef`=Ruby製、`Ansible`=Python製)


#手順書探し
Qiitaで一般ユーザが上げてるのより、まずは企業ブログとかで転がってないかな。

[構成管理ツールChefを使ってみよう - Conoha](https://www.conoha.jp/guide/chef.php)

一通り見てみて分かりやすいし、ちょうどConoha使ってるから、これでいいや！
（記事の掲載日が書かれてないので、おそらく古い記事だった。それに気付かなかったのでこれから詰む事になる。悪いのは確認不足だった僕。）


#手順書通りやってみる(解決策も含め)

##chef-zeroのインストール
ここに出てくる以下の文言。

```sh
下記URLからパッケージをダウンロード
https://opscode-omnibus-packages.s3.amazonaws.com/mac_os_x/10.8/x86_64/chefdk-0.3.5-1.dmg
```

・・・これって最新版のdmgファイル？
公式（ [Chef Development Kit](https://downloads.chef.io/chefdk) ）を見てみると、最新版でない事が判明。

なので、最新版持ってこよう！
（別に古いの取ってきてもいいと思うけど、どうなるかは知らん）


##使ってみよう
まずは、chefリポジトリを作成。
次に、conf.rbファイルを作成。

これらどちらも問題なし。手順書の通り実施してOK。

###Cookbook/Recipeの作成

####Cookbookの作成
ここで出てくる以下のコマンド。

```sh
$ knife cookbook -c conf.rb create nginx
```

実行すると以下のエラーメッセージが表示される。
`FATAL: knife cookbook create has been removed. Please use 'chef generate cookbook' from the ChefDK`

どこかのバージョンで`knife cookbook create`が使用不可となり、`chef generate cookbook`を使うようになったらしい。

なので、上記のコマンドを以下に変更する。

```sh
$ chef generate cookbook -c conf.rb cookbooks/nginx
```

ここで、`nginx`ではなく`cookbooks/nginx`としているのは、以下の理由である。

- コマンド実行して作成される`nginx`ディレクトリは、カレントディレクトリを基点とする
- 作成したいのは`cookbooks`ディレクトリ配下である
- 引数を`nginx`とした場合、カレントディレクトリに`nginx`ディレクトリが作成されるため要件を満たさない
- そのため、親ディレクトリである`cookbooks`を含める必要がある


####Recipeの作成
上記の手順「Cookbookの作成」で作成された`nginx`ディレクトリ配下に、レシピを書いていく。

これは問題なし。手順書の通り実施してOK。


###Nodeの登録とChef-clientパッケージのインストール
ここで出てくる以下のコマンド。

```sh
$ knife zero bootstrap XXX.XXX.XXX.XXX -x root -i [VPS Key Pair].key
```

いや、Conoha使ってるけど鍵なんか持ってないし、、
試しにやってるだけだから、Conohaにもssh接続する時にベーシック認証だし、、、

調べてみると、`-z`オプションを使うと鍵を使わなくてもいいらしい。
正確にいうと、手順「使ってみよう」で作成したリポジトリに入ってる鍵を使って接続する=ユーザは意識しなくていい。
([knifeのzオプションについて - Qiita](https://qiita.com/bouzuao/items/be88e96380a835814d82))

今回はそれでいいので、以下のコマンドに変更する。
(「鍵使いたいよー」って人は、本来の手順でOK)

```sh
$ knife zero bootstrap XXX.XXX.XXX.XXX -x root -z
```


###NodeにRecipeを定義する
ここで出てくる以下のコマンド。

```sh
$ knife node -c conf.rb run_list add vXXX-XXX-XXX-XXX.abcde.static.cnode.jp.json 'recipe[nginx]' -z
```

実はこれ、**嘘をついている。**
(ただの記載ミスだとは思うが、このままやるとエラーになる)

何故なら、`run_list add`の後に続く引数は、JSONではなくNode名だからだ。
([公式ドキュメント](https://docs.chef.io/knife_node.html#run-list-add))

なので、上記のコマンドは以下に変更する。

```sh
$ knife node -c conf.rb run_list add vXXX-XXX-XXX-XXX.abcde.static.cnode.jp 'recipe[nginx]' -z
```

###NodeにRecipeを適用する
ここでめちゃめちゃ躓いたorz

ここで出てくる以下のコマンド。

```sh
$ knife zero -c conf.rb chef_client 'name:vXXX-XXX-XXX-XXX.abcde.static.cnode.jp' -x root -i [VPS Key Pair].key
```

まず、先程言った通り、鍵は使わないため、`-i xxx.key`ではなく`-z`にする。

次に、`chef_client`だが、これが使えない。
正確に言うと、以下の警告メッセージが表示される。
`WARN: 'zero chef_client' was renamed. use 'zero converge'.`
つまり、`chef_client`ではなく`converge`を使うべきである。

更に、`-a`オプションでattributeを指定しておかないとエラーが発生する。
おそらくバージョン差異ではあるが、最新版を使うなら抑えておかなければいけなそうだ。
(参考: [Vagrantでknife-zeroを使うためのベストプラクティス](https://chopschips.net/blog/2015/08/25/vagrant-knife-zero-best-practice/#%E3%83%AC%E3%82%B7%E3%83%94%E3%81%AE%E9%81%A9%E7%94%A8))

なので、上記のコマンドは以下に変更する。

```sh
knife zero -c conf.rb converge 'name:*' -x root -a knife_zero.host -z
```

####MySQLの導入
手順的には、`./cookbooks/nginx/recipes/default.rb`に`MySQL`に関するレシピを追記している。

いやいやいやいや。

動作確認するための手順とはいえ、
nginx入れるためのレシピにmysql入ってちゃダメでしょ。
ラーメン作るから炒飯も〜〜って同じレシピには書かないでしょ。

これについては、以下の「まとめ」で記載する。


#まとめ
という事で、新たな手順はこうなるはず。(2018/08/17時点)

まず、公式からChef-Zeroをダウンロード。
[Chef Development Kit](https://downloads.chef.io/chefdk)

次に、ダウンロードしたパッケージを用いてインストール。
インストールが完了したら、ターミナルを起動し、以下を実行していく。

```sh:terminal
# knife-zeroはパッケージに含まれていないため別途インストール
$ chef gem install knife-zero

# 任意のディレクトリに、Chefリポジトリを作成
$ chef generate repo chef-repo
$ cd chef-repo

# chef-zero にchefリポジトリのディレクトリ位置を知らせるため、conf.rbを作成
$ vim conf.rb
```

```txt:conf.rb
current_dir = File.absolute_path( File.dirname(__FILE__) )
cookbook_path ["#{current_dir}/cookbooks"]
node_path     "#{current_dir}/nodes"
role_path     "#{current_dir}/roles"
ssl_verify_mode  :verify_peer
```

```sh:terminal
# nginxとmysqlのCookbookを作成
$ chef generate cookbook -c conf.rb cookbooks/nginx
$ chef generate cookbook -c conf.rb cookbooks/mysql

# nginxとmysqlのレシピを作成
$ vim cookbooks/nginx/recipes/default.rb
$ vim cookbooks/mysql/recipes/default.rb
```

```rb:cookbooks/nginx/recipes/default.rb
package 'nginx' do
  action [ :install ]
  options "--enablerepo=epel"
end

%w{nginx iptables}.each do |svc|
  service svc do
    supports [ :restart, :reload ]
    action [ :enable, :start ]
  end
end

iptables_conf_path = '/etc/sysconfig/iptables'
allow_port = 80
execute "allow port #{allow_port}" do
  not_if "grep '-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port}' #{iptables_conf_path}"
  command "sed -i -e '/:OUTPUT ACCEPT/a-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port} -j ACCEPT' #{iptables_conf_path}"
  action :run
  notifies :restart, "service[iptables]"
end
```

```rb:cookbooks/mysql/recipes/default.rb
%w{mysql mysql-server}.each do |pkg|
  package pkg do
    action :install
  end
end

service 'mysqld' do
  action [:enable, :start]
end
```

```sh:terminal
# Nodeとなるリモートサーバにchef-clientをインストールし、手元にNodeの詳細を残す
$ knife zero bootstrap XXX.XXX.XXX.XXX -x root -z

# Nodeに対して、作成したレシピを定義する
$ knife node -c conf.rb run_list add vXXX-XXX-XXX-XXX.abcde.static.cnode.jp 'recipe[nginx]' -z
$ knife node -c conf.rb run_list add vXXX-XXX-XXX-XXX.abcde.static.cnode.jp 'recipe[mysql]' -z

# Nodeに対して、レシピを適用する
$ knife zero -c conf.rb converge 'name:*' -x root -a knife_zero.host -z
```

##余談
手順書ってちょくちょく修正しないと、かえって面倒な事になるね、、