chef-zeroで行こう！


## 更新内容
- 2015/4/21 - レシピの適用に-a nameを追加
- 2015/5/09 - レシピの適用が何故か実行できなくなってたので、EC2で実行できるよう修正

## はじめに

Chefを導入するに当たって、Chef HostingかChef On-premisesかChef Zeroか色々考えた末、Chef Zeroを選定。

## 選定理由

- Chef Hosting: 管理画面あり。無料で5ノードまで管理できる。Chefを運用しなくてもいいのは楽だが、サーバが不安定。Provisionしたい時に出来ないリスクを抱えたくないので却下。
- Chef On-premises: 管理画面あり。無料で25ノードまで使える。但し、冗長化等自分で運用しなきゃいけない。一部不安定なAPIサーバを呼び出したり・・・却下！
- Chef Zero: 管理画面なし。ノード数無制限、サーバ不要。簡単導入。採用！

## Berkshelfは使わない

Berkshelfは、ChefのCookbookとその依存関係を管理するツール。
１からCookbookを書かなくても利用できるが、リポジトリ変わったり内容が手元で管理できないのは安定を目指すインフラとしては使わない事とする。

## 作成したリポジトリはgitで管理

gitについてはここでは書かない。

## インストール

下記URLからパッケージをダウンロード
https://opscode-omnibus-packages.s3.amazonaws.com/mac_os_x/10.8/x86_64/chefdk-0.4.0-1.dmg
ダウンロード後にインストーラの指示に従いインストールし、ターミナルを起動して下記コマンドを実行

```
sudo chef gem install knife-zero
```

# さぁ、はじめよう！

## 手順

1. Repositoryの作成
2. Repositoryの初期設定
3. Cookbookの作成
4. Recipeの作成
5. Roleの作成
6. RoleにRecipeを追加
7. Nodeの初期化
8. NodeにRecipeを追加
9. Nodeのrun_listからRecipeを削除
10. NodeにRoleを割り当て
11. レシピの適用

## 概要

### 完成するディレクトリ階層（抜粋）

```
chef-repo <<Repository>>
+- cookbooks
|  +- iptables <<Cookbook>>
|     +- recipes
|        +- disabled.rb <<Recipe>>
|
+- nodes
|  +- webserver01.json <<Node>>
|
+- roles
   +- linux-servers.json <<Role>>
```

### 完成するRoleとRecipeの関係

```
linux-servers <<Role>>
+- run_list:
   +- recipe[iptables::disabled]
```

### 完成するNodeとRoleの関係

```
webserver01 <<Node>>
+- run_list:
   +- role[linux-servers]
```


## 1.Repositoryの作成

Repository[chef-repo]を作成する。

```:コマンド形式
chef generate repo <<epository-name>>
```

```:実際の実行
chef generate repo chef-repo
```

## 2.Repositoryの初期設定

.chef/knife.rbにローカルモードの設定と、cookbook_path, node_path, role_pathを指定。

```
cd chef-repo
mkdir .chef
vi .chef/knife.rb
```

```:.chef/knife.rb
local_mode true

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

## 3.Cookbookの作成

Cookbook[iptables]を作成する。

```:コマンド形式
knife cookbook create <<cookbook-name>>
```

```:実際の実行
knife cookbook create iptables
```

## 4.Recipeの作成

Recipe[iptables::disabled]を作成する。
iptablesの自動起動OFFとサービスの停止を定義。

```
vim cookbooks/iptables/recipes/disabled.rb
```

```:cookbooks/iptables/recipes/disabled.rb
service 'iptables' do
  only_if { File.exist?("/etc/init.d/iptables") }
  supports :status => true, :start => true, :stop => true, :restart => true
  action [ :disable, :stop ]
end
```

## 5.Roleの作成

Role[linux-servers]を作成する。
環境変数EDITORが開くので、そのまま保存する。
※環境変数EDITORが指定されていない場合はエラーとなる

```:コマンド形式
EDITOR=vim knife role create <<role-name>>
```

```:実際の実行
EDITOR=vim knife role create linux-servers
```

## 6.RoleにRecipeを追加

Role[linux-servers]にrecipe[iptables::disabled]を追加する。

```:コマンド形式
knife role run_list add <<role-name>> <<recipe-name>>
```

```:実際の実行
knife role run_list add linux-servers 'recipe[iptables::disabled]'
```

## 7.Nodeの初期化

Nodeの初期化は、NodeにChef ClientのインストールとNodeをRepositoryのNode一覧に追加する。

```:コマンド形式
knife zero bootstrap <<hostname or ip-address>> -x <<ssh-user>> --sudo --hint ec2 --node-name <<nodename>>
```

```:実際の実行
knife zero bootstrap webserver01 -x root --ssh-password PASSWORD --node-name webserver01
```

```:実際の実行(AWSの場合)
knife zero bootstrap webserver01 -x ec2-user --sudo --hint ec2 --node-name webserver01
```

※.ssh/configを参照できる
※-x ec2-userはSSH接続ユーザを指定
※--hint ec2はOhaiに渡される。
※既にnodes/webserver01.jsonが存在する場合は上書きされて設定が吹き飛ぶので注意

### 参考

```:~/.ssh/config
Host webserver01
  Hostname XXX.XXX.XXX.XXX
  Port 22
  IdentityFile ~/.ssh/webserver01.pem
  User ec2-user
```

## 8.NodeにRecipeを追加

NodeにRecipeを追加する場合はこうする。

```:コマンド形式
knife node run_list add <<node-name>> <<recipe-name>>
```

```:実際の実行
knife node run_list add webserver01 'recipe[iptables::disabled]'
```

## 9.Nodeのrun_listからRecipeを削除

Nodeに直接Recipeを割り当てるのは後々レシピの管理が面倒になるので、RecipeはすべてRoleに割り当てるルールとする。なので削除。

```:コマンド形式
knife node run_list remove <<node-name>> <<recipe-name>>
```

```:実際の実行
knife node run_list remove webserver01 'recipe[iptables::disabled]'
```

## 10.NodeにRoleを割り当て

Node[webserver01]にRole[linux-servers]を割り当てる。

```:コマンド形式
knife node run_list add <<node-name>> <<role-name>>
```

```:実際の実行
knife node run_list add webserver01 'role[linux-servers]'
```

## 11.レシピの適用

```:コマンド形式
knife zero chef_client QUERY -x <<ssh-user>> --sudo -i <<private-key>> -a name
```

```:実際の実行（2015/05/09、何故か実行できなくなった）
knife zero chef_client 'name:webserver01' -x ec2-user --sudo -i ~/.ssh/webserver01.pem -a name
```
※.ssh/configを参照できないので秘密鍵を指定する必要がある


```:実際の実行（ローカル環境等）
knife zero chef_client 'name:webserver01' -x root --ssh-password PASSWORD -a ipaddress
```

※-aオプションで接続先をアドレスを示す属性を指定

```:実際の実行（EC2インスタンスの場合）
knife zero chef_client 'name:webserver01' -x ec2-user --sudo -i ~/.ssh/webserver01.pem -a ec2.public_ipv4
```
※Ohaiが収集した構成情報を参照する

# -

とりあえず簡単だが、これでInfrastructure as a codeの第一歩として。
随時更新していきたいと思います。