Chef memo4


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

# 4 クックブックの活用

## 4.1 コミュニティクックブックを活用する

* [Opscode Community](http://cookbooks.opscode.com/)に、コミュニティクックブックと呼ばれる誰でもダウンロード可能なChefクックブックがある。

### コミュニティクックブックを探す

#### クックブックを検索する

* knife cookbook site serach <キーワード> でコマンドラインから探すこともできる。

```
$ knife cookbook site search apache2

apache:
  cookbook:             http://cookbooks.opscode.com/api/v1/cookbooks/apache
  cookbook_description: various apache server related resource provides (LWRP)
  cookbook_maintainer:  melezhik
  cookbook_name:        apache
apache-mirrors:
  cookbook:             http://cookbooks.opscode.com/api/v1/cookbooks/apache-mirrors
  cookbook_description: Download files from Apache mirrors
  cookbook_maintainer:  ericcitaire
  cookbook_name:        apache-mirrors
apache2:
  cookbook:             http://cookbooks.opscode.com/api/v1/cookbooks/apache2
  cookbook_description: Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions
  cookbook_maintainer:  viverae
  cookbook_name:        apache2
```

#### クックブックの詳細を見る

*　knife cookbook site show <キーワード> でクックブック詳細を表示する

```
$ knife cookbook site show apache2 | head -20
WARNING: No knife configuration file found
average_rating:     
category:           Other
created_at:         2009-10-25T23:47:55.000Z
deprecated:         false
description:        Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions
external_url:       https://github.com/viverae-cookbooks/apache2
foodcritic_failure: true
latest_version:     http://cookbooks.opscode.com/api/v1/cookbooks/apache2/versions/3.0.0
maintainer:         viverae
metrics:
  downloads:
    total:    34525298
    versions:
      0.10.0: 652952
      0.10.1: 653060
      0.11.0: 652945
      0.12.0: 652944
      0.12.1: 652979
      0.12.2: 652984
      0.12.3: 653137

```

#### クックブックの一覧を取得する

* knife cookbook site listコマンドはすべてのクックブックの一覧を取得できる。

### Berkshelfでクックブックをインポートする

* knife cookbook site install <クックブック名> でリポジトリからcookobooksディレクトリ内にコードがダウンロードされる。
* ただし、knife-soloを使う場合は、Berkshelfという外部クックブック管理ツールでインポートすることが前提となっている。
* knife solo initコマンドで生成されたファイルに、Berksfileというファイルがある。これがBerkshelfの設定ファイルとなる。
* Berkshelf3からBerksfileの記述方法が変更されている。

```
// Berkshelfによるクックブックのインポート(Berkshelf3)
source "https://supermarket.getchef.com"

cookbook 'yum-epel', '~> 0.5.3'
cookbook 'apache2', '~> 3.0.0'
cookbook 'mysql', '~> 5.6.1'
```

```
# berksコマンドの実行
$ berks

Resolving cookbook dependencies...
Fetching cookbook index from https://supermarket.getchef.com...
Installing apache2 (3.0.0)
Installing logrotate (1.7.0)
Installing iptables (0.14.0)
Installing mysql (5.6.1)
Installing yum (3.5.1)
Installing yum-epel (0.5.3)
Installing yum-mysql-community (0.1.10)
```

```
# インストールされてるCookbook表示
$ berks list

Cookbooks installed by your Berksfile:
  * apache2 (3.0.0)
  * iptables (0.14.0)
  * logrotate (1.7.0)
  * mysql (5.6.1)
  * yum (3.5.1)
  * yum-epel (0.5.3)
  * yum-mysql-community (0.1.10)
```

* berksコマンドを実行するとBerksfile.lockというファイルが更新される。
* 中身はクックブック名と利用しているバージョン。

``` Berksfile.lock
DEPENDENCIES
  apache2 (~> 3.0.0)
  mysql (~> 5.6.1)
  yum-epel (~> 0.5.3)

GRAPH
  apache2 (3.0.0)
    iptables (>= 0.0.0)
    logrotate (>= 0.0.0)
  iptables (0.14.0)
  logrotate (1.7.0)
  mysql (5.6.1)
    yum-mysql-community (>= 0.0.0)
  yum (3.5.1)
  yum-epel (0.5.3)
    yum (~> 3.0)
  yum-mysql-community (0.1.10)
    yum (>= 3.0)
```

* berksコマンドはこのBerksfile.lockをもとに、利用するクックブックのバージョンを判断している。
* これで以降同リポジトリで利用するクックブックのバージョンが固定される。
* knife-soloはknife solo cookコマンド実行時にBerkshelfを実行し外部クックブックを取り込んだ上でそれらのクックブックをすべてリモートのノードに転送します。
* コミュニティクックブックをインポートする手順
  1. Berksfileに必用なクックブックを列挙する。
  2. ノードの欄リストに追加する。
  3. knife solo cookでノードにレシピを適用する。

### コミュニティクックブックを使う

* コミュニティクックブックはインポートしただけではノードに適用されない。
* Nodeオブジェクトのランリストに当該クックブックを適用するように設定する必用がある。

#### yum-epalクックブックを使う

```
{
  "run_list":[
    "recipe[yum-epal]",
    略
  ]
}
```

#### default.rb以外のレシピ

* recipe[apache2::mod_deflate]はこのmod_deflate.rbを個別に指定するための記法。

#### クックブック名が衝突した場合

* 自作のクックブックとコミュニティクックブックの名前が同じものをつかっていた場合、Chefがもっているクックブックの優先度によってどちらが採用されるかが決まる。あとに定義したクックブックの内容で上書きされる。
* クックブックパスはリポジトリ内の.chef/knife.rbに記載されている。

```
cookbook_path    ["cookbooks", "site-cookbooks"]
node_path        "nodes"
role_path        "roles"
environment_path "environments"
data_bag_path    "data_bags"
#encrypted_data_bag_secret "data_bag_key"

knife[:berkshelf_path] = "cookbooks"
```

#### apache2のクックブックを使う

* NodeオブジェクトでAttrbuteの値を上書きすることで細かい調整が可能

```
{
  "apache": {
    "listen_ports": [ 8080 ],
    "keepalive": "Off",
    "docroot_dir": "/home/vagrant/htdocs"
  },
  "run_list":[
    "recipe[apache2]"
  ]
}
```

## 4.2 Chef Soloで複数ノードを管理する

### VagrantのマルチVM機能

* VagrantのマルチVM機能の設定(Vagrantfile)

``` Vagrantfile
  config.vm.define :node01
  config.vm.define :node02
```

* vagrant up コマンドを実行すると、node01 node02という名前のノードが二つ起動します。

```
$ vagrant up
Bringing machine 'node01' up with 'virtualbox' provider...
Bringing machine 'node02' up with 'virtualbox' provider...
==> node01: Importing base box 'centos65'...
Progress: 40%
```

* 各ノード毎にVMの設定を施したい場合。

``` Vagrantfile
config.vm.define :node01 do |node01|
  node01.vm.box = "opscode-centos-65"
end
```

* マルチVMでvagrant sshその他のコマンドを実行する場合、引数に仮想サーバ名を指定する必用がある。
* 引数を省略するとVagrantfileから生成した仮想サーバすべてが対象となる。

```
$ vagrant ssh node01
$ vagrant ssh-config node01 >> ~/.ssh/config
$ vagrant halt node01
$ vagrant destroy node01
$ vagrant up node01
```

### Nodeオブジェクト

* 複数のノードを対象とする場合、ノードの数と同じ分、Nodeオブジェクトを用意することになる。

```
├─ nodes
   ├─ node01.json
   ├─ ndoe02.json
```

### ロール

* ロールはノードの一つ上の抽象度で、名前のとおりノードの「役割」を定義するもの。
* RoleオブジェクトはNodeオブジェクト同じくJSONで記述する。

### ロールを設定する

* webサーバーをの役割をするwebというロールを定義する。
* gitとapache2のレシピをランリストに設定した。
* chef_typeとjson_classはroleの固定値

``` roles/web.json
{
   "name": "web",
   "chef_type": "role",
   "json_class": "Chef::Role",
   "run_list": [
     "recipe[git]",
     "recipe[apache2]"
   ]
}
```

### ロールを適用する

* webロールの適用例
* これでChefを適用すると、web.jsonに記載されたランリストが両ノードに適用される。

``` nodes/node01.json&nodes/node02.json
{
  "run_list":[
    "role[web]"
  ]
}
```

### 複数のロールを割り当てる

* 一つのノードに複数のロールを割り当てることも可能。
* gitのレシピは個別に用意してwebとdbのロールを割り振っている。

```
{
  "run_list":[
    "role[git]"
    "role[web]"
    "role[db]"
  ]
}
```

### ロールでAttrbuteを管理する

* ロールではAttrbuteも利用できる。
* default_attributesはこのロールを割り当てた側にそのAttrbuteが定義されていなかったら利用される値。
* override_attributesは上書きする値。

```
{
  "name": "web",
  "chef_type": "role",
  "json_class": "Chef::Role",
  "default_attributes": {
      "apache": {
          "listen_ports": [
            "80",
            "443"
          ]
      }
  },
  "override_attributes": {
      "apache": {
          "max_children" : "50"
      }
  },
  "run_list": [
      "recipe[git]",
      "recipe[apache2]"
  ]
}
```


### Environments

* 開発、ステージング、プロダクションといったノードの環境に応じて状態を定義する機能。

* Environmentsの定義ファイルはリポジトリのenviromentsディレクトリ以下に置く。
* たとえばenviroments/development.jsonという開発環境の定義ファイルを作る。

``` enviroments/development.json
{
  "name": "development",
  "description":"Development environment",
  "chef_type": "environment",
  "json_class": "Chef::Environment",
  "default_attributes": {
    "apache": {
      "max_children": "10"
    }
  },
  "override_attributes": {}
}
```

* そして、Nodeオブジェクト側でこのdevelopment環境であることを宣言する。

```
{
  "environment": "development",
  "run_list":[ 
    "role[web]"
  ]
}
```

* これで、このNodeオブジェクトで定義されているノードに対しては、development.jsonのAttrbuteが適用される。
* プロダクション環境を追加する場合、production.jsonを用意して同様に定義する。

### Attrbuteの優先度

* 以下の順で、上から下へ優先度が高くなっている。
  1. クックブック内のAttrbuteファイル
  2. レシピ内で定義されたAttrbute
  3. Environments
  4. ロール
  5. Nodeオブジェクト


### 複数ノードへChef Soloを実行する

* knife solo cookコマンドを都度実行するのは大変なので、複数サーバへの一括適用を考える。

#### xargs

* ノードの台数がそれほど多くなく、Chefの適用が逐次でいい場合など。

```
$ echo node01 node02 node03 | xargs -n 1 knife solo cook
```


#### 外部ツールと連携する

* 規模が大きくなってきた場合、
  * Capistrano、MCollective、Fabricなどほかのツールを利用しChfe Soloを実行する。
  * Chef Serverに移行する。