Chef memo2


[Chef実践入門 ~コードによるインフラ構成の自動化](http://www.amazon.co.jp/dp/477416500X) のまとめノート

# 2 ローカル開発環境構築

## 2.1 Chef Soloとは

* Chefには以下二つの利用形態がある。
  - Chef Server/Chef Client
  - Chef Solo 

* Chef Server/Chef Clientは中規模以上のシステム向けで、中央集権のサーバーやDBが必用
* Chef Solo はサーバーもクライアントも必要ないコマンド形式。

## 2.2 検証環境を構築する

* [Vagrant setup 参照](http://qiita.com/watanayu19700101/items/d4efc02007a62a3bdca5)

## 2.3 Chef Soloをインストールする

* ゲスト側でオムニバスインストーラーを使ってChefをインストールする

```
$ curl -L http://www.opscode.com/chef/install.sh | sudo bash

$ chef-solo -v
Chef: 11.16.4
```

## 2.4 Chefを動かしてみる

### Chefの用語

#### レシピ
* コードで書いたサーバ設定の手順

```ruby:example.rb
package "git" do
  action :install
end
```

#### クックブック
* 特定のレシピに必用なデータやファイルをまとめた入れもの

#### リポジトリ(キッチン)
* クックブック郡を含む、Chefの実行に必用な一連のファイルをまとめる入れもの
* リポジトリ　> クックブック > レシピ という階層でレシピ群が管理される

#### ナイフ
* リポジトリを操作するためのツール。

### 1. ナイフコマンドでクックブックを作成する
* デフォルトではChefのリポジトリは /var/chef が使われる

ゲスト側でナイフコマンドによるクックブックの作成

```
# $ sudo knife cookbook create <クックブック名> -o <出力先ディレクトリ>
$ sudo knife cookbook create hello -o /var/chef/cookbooks
```

### 2. レシピを編集する
* クックブックを作った時点でレシピファイルのひな型がrecipiesディレクトリの中にdefault.rbという名前で作成されているので、それを編集する。

```
$ sudo vim /var/chef/cookbooks/hello/recipes/default.rb
```

```ruby:default.rb
#
# Cookbook Name:: hello
# Recipe:: default
#
# Copyright 2014, YOUR_COMPANY_NAME
#
# All rights reserved - Do Not Redistribute
#
log "Hello world."
```

### 3. Chef Soloを実行する

ゲスト側でchef-soloコマンドによるhelloクックブックの実行

```
$ sudo chef-solo -o hello

[2014-11-23T15:41:38+00:00] WARN: *****************************************
[2014-11-23T15:41:38+00:00] WARN: Did not find config file: /etc/chef/solo.rb, using command line options.
[2014-11-23T15:41:38+00:00] WARN: *****************************************
[2014-11-23T15:41:38+00:00] WARN: 

## 略 ##

Starting Chef Client, version 11.16.4
[2014-11-23T15:41:40+00:00] WARN: Run List override has been provided.
[2014-11-23T15:41:40+00:00] WARN: Original Run List: []
[2014-11-23T15:41:40+00:00] WARN: Overridden Run List: [recipe[hello]]
Compiling Cookbooks...
Converging 1 resources
Recipe: hello::default
  * log[Hello world.] action write
  

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

### まとめ
1. クックブックを作る
2. レシピを書く
3. chef-soloコマンドを実行する

という手順。

## 2.5 Chef Soloでパッケージをインストールする

### dstatパッケージをインストールする

* サーバーモニタリングツールのdstatをインストールする

#### 1. ゲスト側でknifeコマンドを使ってdstatクックブックを新規作成

```
$ sudo knife cookbook create dstat -o /var/chef/cookbooks
```

dstatをインストールするレシピ

``` ruby:default.rb
package "dstat" do
   action:install
end
```

#### 2. ゲスト側でchef-soloによるhelloクックブックとdstatクックブックの実行

```
$ sudo chef-solo -o hello,dstat

Starting Chef Client, version 11.16.4
[2014-11-24T01:09:22+00:00] WARN: Run List override has been provided.
[2014-11-24T01:09:22+00:00] WARN: Original Run List: []
[2014-11-24T01:09:22+00:00] WARN: Overridden Run List: [recipe[hello], recipe[dstat]]
Compiling Cookbooks...
Converging 2 resources
Recipe: hello::default
  * log[Hello world.] action write
  
Recipe: dstat::default
  * package[dstat] action install
    - install version 0.7.0-1.el6 of package dstat

Running handlers:
Running handlers complete
Chef Client finished, 2/2 resources updated in 24.554105287 seconds
```

#### 3. ゲスト側でrpmコマンドによるインストール確認

```
$ rpm -q dstat

dstat-0.7.0-1.el6.noar
ch
```


### Chefのレシピはクロスプラットフォーム
* 先のレシピにはrpmやyum、apt-get, portsなどパッケージ管理ツールの名称をなにも記述していないが、このあたりのOSごとの違いをChefが裏で吸収している。

### Chefは冪等性を持つ
* 既に対象のパッケージがインストールされている状態で、同パッケージをインストールするレシピを実行してもした場合、そのパッケージのインストールは行われずに全体のプロセスが正常終了する。Chefが当該パッケージの有無をよしなに判断してくれている。
* これは、何度実行してもサーバの状態に同じ結果をもたらす事を意味する。
* このような何度実行しても同じ結果になる性質を、冪等性と呼ぶ。

```
$ sudo chef-solo -o hello,dstat

Starting Chef Client, version 11.16.4
[2014-11-24T01:33:01+00:00] WARN: Run List override has been provided.
[2014-11-24T01:33:01+00:00] WARN: Original Run List: []
[2014-11-24T01:33:01+00:00] WARN: Overridden Run List: [recipe[hello], recipe[dstat]]
Compiling Cookbooks...
Converging 2 resources
Recipe: hello::default
  * log[Hello world.] action write
  
Recipe: dstat::default
  * package[dstat] action install (up to date)

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

## 2.6 knife-soloでchef-soloをリモート実行する

* 手元の作業マシンでクックブックを作成してChef Soloの実行も作業マシンからリモートのサーバーに命令するだけで完結させる

### knife-soloとは
* ChefでChef Solo環境を構築するためのユーティリティツール
* 手元の作業マシンで作ったクックブックをリモートサーバーに転送してchef-soloコマンドを実行するといった一連の作業を自動化できる
* knife-soloはRubyGemsとして公開されている

#### 1. knife-soloのインストール
* knife-soloをインストールするとknife-soloに依存関係のあるChefを同時にインストールされる
* それに伴いknifeコマンドもインストールされる
* そしてknifeのサブコマンドとしてknife soloコマンドが実行できるようになる

```
# 環境を汚したくないのでオムニバスを利用する
$ curl -L http://www.opscode.com/chef/install.sh | sudo bash

$ chef-solo -v
Chef: 11.16.4

# オムニバスのgemを使う
$ sudo /opt/chef/embedded/bin/gem install knife-solo
```

#### 2. Berkshelfのインストール
* クックブックの依存関係を管理するツール

```
$ sudo /opt/chef/embedded/bin/gem install berkshelf
```

### knife-soloでリポジトリを作る
* いったん先にリモートで作ったクックブックは忘れる
* Chefリポジトリを新規ローカルに作成する
* knife solo initコマンドをVagrantfileがある同じディレクトリで実行する

```
$ knife solo init .

# Chefに必用な各種ファイル・ディレクトリが展開される
$ ls -la
total 32
drwxr-xr-x  13 novo  staff   442 11 24 11:26 .
drwxr-xr-x   4 novo  staff   136 11 23 22:17 ..
drwxr-xr-x   3 novo  staff   102 11 24 11:26 .chef
-rw-r--r--   1 novo  staff    12 11 24 11:26 .gitignore
drwxr-xr-x   3 novo  staff   102 11 23 23:25 .vagrant
-rw-r--r--   1 novo  staff    14 11 24 11:26 Berksfile
-rw-r--r--   1 novo  staff  4826 11 23 23:25 Vagrantfile
drwxr-xr-x   3 novo  staff   102 11 24 11:26 cookbooks
drwxr-xr-x   3 novo  staff   102 11 24 11:26 data_bags
drwxr-xr-x   3 novo  staff   102 11 24 11:26 environments
drwxr-xr-x   3 novo  staff   102 11 24 11:26 nodes
drwxr-xr-x   3 novo  staff   102 11 24 11:26 rtoles
drwxr-xr-x   3 novo  staff   102 11 24 11:26 site-cookbooks
```

### knife-soloでChef Soloをインストールする
* knife solo bootstrap ＜hostName or ipAdress＞ で作業マシンからほかのサーバに対してChef Soloのインストールが可能。厳密にはインストール後に一度Chefを実行している。
* knife solo prepare ＜hostName or ipAdress＞ でインストールのみを行う。
* 今回はChefはインストール済みなので再度インストールされ上書きされる。
* 

```
$ knife solo bootstrap 192.168.33.10

# エラー
Bootstrapping Chef...
Enter the password for novo@192.168.33.10: 
ERROR: Net::SSH::AuthenticationFailed: Authentication failed for user novo@192.168.33.10

# sshの設定を追加する
$ vagrant ssh-config --host webdb >> ~/.ssh/config

# 再度挑戦
$ knife solo bootstrap webdb

# 成功
Starting Chef Client, version 11.12.8
Compiling Cookbooks...
Converging 0 resources

Running handlers:
Running handlers complete

Chef Client finished, 0/0 resources updated in 4.326981289 seconds
```

### クックブックを作成する
* クックブックの作成はknife-soloではなく、先ほどと同じくknifeで作る。
* knifeはChef付属のツール。$ knife ~ で実行。
* knife-soloはChef Solo用にknifeを拡張するプラグイン。　$ knife solo ~ のようにサブコマンドとして実行。
* Chefにおいて自作のクックブックはsite-cookbooksに作るのが慣習。

```
# dstatクックブックを作成
$ knife cookbook create dstat -o site-cookbooks
```

### レシピを編集する
* ローカルなのでサブライムでもなんでも好きなエディタが使える

```
$ vim /Users/example/vagrant/opscode-centos-6.5/site-cookbooks/dstat/recipes 
```

dstatをインストールするレシピ

``` ruby:default.rb
package "dstat" do
   action:install
end
```

### Nodeオブジェクトでサーバーの状態を記述する

#### Nodeとは
* Chefの文脈ではChefで管理するサーバーを指す

#### Nodeオブジェクトとは
* 任意のノードの状態を記述するための設定ファイル。
* json形式でできている。
* knife solo bootstarp時にnodesディレクトリの中に.jsonが作成される。

デフォルトのNodeオブジェクト設定ファイル

```webdb.json
{"run_list":[]}
```

編集後のNodeオブジェクト設定ファイル

```webdb.json
// webdbノードにはdstatのレシピが適用されることを表す
// run_listはそのノードに適用されるレシピのリスト
// $ sudo chef-solo -o hello,dstat をjsonで表現
{
  "run_list":["recipe[dstat]"]
}
```

### knife-soloでChef Soloを実行する

* 作業マシンからリモートのノードをプロビジョニングする。
* プロビジョニングを走らせるには、knife solo cook ＜hostName＞ を実行する。
* knife solo cookコマンド の裏側では、rsyncでローカルからリモートにクックブックが転送され、SSH経由でsudo付きでchef-soloコマンドが実行される。その際に先に作ったNodeオブシェクとからノードの状態が読み込まれる。

```
$ knife solo cook webdb

Starting Chef Client, version 11.12.8
Compiling Cookbooks...
Converging 1 resources
Recipe: dstat::default
  * package[dstat] action install (up to date)

Running handlers:
Running handlers complete

Chef Client finished, 0/1 resources updated in 3.797419136 seconds
```

## 2.7 Chef SoloでApache、MySQlをセットアップする

### 1. クックブックを作成する
* ApacheとMySQLのクックブックを作成する

```
$ knife cookbook create apache -o site-cookbooks
$ knife cookbook create mysql -o site-cookbooks
```

### 2. Nodeオブジェクトを設定する
* Nodeオブジェクト設定ファイルにApacheとMySQLのレシピを追加する。

```webdb.json
{
  "run_list": {
    "recipe[dstat]",
    "recipe[apache]",
    "recipe[mysql]"
  }
}
```

### 3. Apacheのレシピを書く

* Apache用レシピ(site-cookbooks/apache/recipes/default.rb)

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

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

* package はパッケージを扱うためのシンタックス
* service はサービス(バックグラウンドに常駐して稼動し続けるプログラム)を扱うためのシンタックス
  * :enable はOS起動時のサービス有効化(chkconfig httpd on)
  * :start はサービスの起動(service httpd start)

* packageやserviceといったキーワードはリソースと呼ばれる。

### 4. MySQLのレシピを書く

* MySQL用レシピ(site-cookbooks/mysql/recipes/default.rb)

```
package "mysql-server" do
  action :install
end

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

* mysqlのサービス名はmysqld

### 5. Chef Soloを実行する

* knife-soloでChef Soloを実行する

```
$ knife solo cook webdb
```


* ゲスト側で実行結果の確認

```
$ ssh webdb
$ ps -ef | egrep "(httpd|mysql)"
```

### 5. ブラウザから動作確認する

* http://192.168.33.10 にブラウザからアクセス
* apacheのデフォルト画面が表示されればOK.

### 6. Apacheの設定ファイルをChefで取り扱う

* httpd.confもChefで管理してみる
* クックブック内で設定ファイルを扱う場合、
  * クックブックのtemplateディレクトリ内に設定ファイルを置く
  * templateリソースで、その設定ファイルをChef実行時に望んだパスに配置するように記述する。

#### もとになる設定ファイルをVagrantの共有ディレクトリ経由でコピーする。
```
$ ssh webdb

$ cp /etc/httpd/conf/httpd.conf /vagrant/site-cookbooks/apache/templates/default/httpd.conf.erb
```

#### 設定ファイルを編集する

```
$ vim /vagrant/site-cookbooks/apache/templates/default/httpd.conf.erb
```

```httpd.conf.erb
# サーバー名を設定
ServerName webdb:80
```

#### レシピにtemplateリソースを記述する

* Apache用レシピ(site-cookbooks/apache/recipes/default.rb)

```default.rb
template "httpd.conf" do
  path "/etc/httpd/conf/httpd.conf"
  owner "root"
  group "root"
  mode 0644
  notifies :reload, 'service[httpd]'
end
```

#### knife-soloでChef Soloを実行する

```
$ knife solo cook webdb
```


### 7. 仮想サーバーを破棄して再度Chef Soloを実行してみる。

```
$ vagrant destroy -f

$ vagrant up

$ vagrant ssh

$ rpm -qa | grep dstat

$ knife solo bootstrap webdb
```

### まとめ
* 一度レシピを書いてしまえばたとえサーバーがなくなったとしてもまったく同じ状態にサーバーを戻すことができる。これがプロビジョニングツールを使う醍醐味。
* [ここまでのコードはこちら](https://github.com/watanayu19700101/example-chef-repos)

## 2.8 Chefリポジトリの扱い

### リポジトリはGitで管理する。

### リポジトリのディレクトリレイアウト

* knife-soloで作成したリポジトリのレイアウトを見ていく。

├─ Berksfile
├─ Vagrantfile
├─ cookbooks
├─ data_bags
├─ environments
├─ nodes
├─ roles
├─ site-cookbooks

#### Berksfile
* 外部から取得するクックブックの依存管理用設定ファイル

#### Vagrantfile
* Vagrantで仮想サーバーを起動する時の設定ファイル

#### cookbooks (dir)
* 外部から取得したクックブックの置き場

#### data_bags (dir)
* DataBagと呼ばれるクックブックで利用したい任意のデータの置き場 
* データベースてきな

#### environments (dir)
* Environments機能を使う際にその環境に応じた変数等を格納する場所

#### nodes (dir)
* Nodeオブジェクト設定ファイルの格納場所

#### rorles (dir)
* ロール機能の設定ファイルを置く場所

#### site-cookbooks (dir)
* 自分で作ったクックブックを置く場所

## 2.9 Vagrant以外のサーバへChefを実行する

* ノードにSSHでログインできてパスワードなしでsudoできるアカウントであれば、knife solo cook でいける

```
# example
$ knife solo cook <name>@<host> -i <key path> 
```

## 2.10 Chefの考え方

### 冪等性
### 手順ではなく状態を定義
### 状態を収束させる
### すべての状態はクックブックで管理
### アプリケーション領域との切り分け