はじめてのChef Server環境構築 (Linux/オフライン環境)

#はじめに
Chefなるものについて右も左も分からない状態からお勉強しつつ、Chef Serverの環境構築してみたので、備忘録としてまとめます。
実環境としては外部のネットワークには繋げられない閉じた環境(オフライン)で実施しなければならないケースも多いと思いますが、世にあるドキュメントでは外部のWebにつながる環境が前提となっている記述が多く、Chefのドキュメントもその辺りが結構不親切な気がします。当記事は外部ネットワークに直接は繋がらない環境で実施した作業をベースにしていますので、その辺参考になれば幸いです。

参考:
[Install the Chef Server](https://docs.chef.io/install_server.html)
[Install the Chef DK (Workstation)](https://docs.chef.io/install_dk.html)
[Bootstrap a Node](https://docs.chef.io/install_bootstrap.html)

#前提知識: Chef Server構成概要

小規模環境向けに、Chef Zeroという単体構成も可能なようですが、ここではChef Serverの構成を行うことを目標とします。
Chef Serverの構成を行う場合、主なコンポーネントとしては以下の3つがあります。

* Chef Server: クックブックやノードの管理を行う
* Chef Workstation: クックブックの開発やChef Serverに対する各種指示を実行する
* Chef Node: 管理対象のノード(環境を構築したい対象のマシン)

![image01.JPG](https://qiita-image-store.s3.amazonaws.com/0/132331/73224f0b-48d7-f3bd-0c83-3c9e8fd0623e.jpeg)



#環境
Chef Workstation, Chef Server, Chef Nodeはそれぞれ別マシンとして構成できますが、簡略化のため、今回サンプルとして作成する環境はChef WorkstationとChef Serverは同一マシン上に構成し、管理対象のChef Nodeは1台とします。
![image02.JPG](https://qiita-image-store.s3.amazonaws.com/0/132331/f749f9c6-2460-7ebd-91bc-1294b958af2b.jpeg)



RedHat Enterprise Linux V6.5 x 2台
Chef V12 / Chefサーバー構成 
- Chef Server 12.7
- Chef Workstation 0.19.6



#Chef Server環境構築手順
Chef Serverの導入/構成を行い、単純なCookbook/レシピを作成して実行するまでの手順を追ってみます。
(公式ドキュメント等を参考にしてはいますが、正確性は保障できません。あしからず。)

##yum設定

足りないOSのパッケージを適宜追加でインストールしやすいようにyumの設定をしておく。(Chefとは関係ないけど念のため書いておきます)

/Inst_Imate/RHEL/に以下のisoイメージを配置
rhel-server-6.5-x86_64-dvd.iso  
rhel-server-supplementary-6.5-x86_64-dvd.iso

以下のようにマウントポイント(ディレクトリ)を作成しておく

```
[root@vmx-007-013 /mnt]# ls -la
total 18
drwxr-xr-x.  4 root root 4096 Nov  7 09:58 .
dr-xr-xr-x. 28 root root 4096 Nov  7 09:55 ..
dr-xr-xr-x  12 root root 8192 Nov 12  2013 rhel65
dr-xr-xr-x   6 root root 2048 Nov 14  2013 rhel65supplementary
```

isoイメージのマウント

```
mount -t iso9660 -o loop /Inst_Image/RHEL/rhel-server-6.5-x86_64-dvd.iso /mnt/rhel65
mount -t iso9660 -o loop /Inst_Image/RHEL/rhel-server-supplementary-6.5-x86_64-dvd.iso /mnt/rhel65supplementary
```

yumリポジトリ作成

```xxx:dvd1.repo
[dvd1]
name=dvd1
baseurl=file:///mnt/rhel65
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
```

```xxx:dvd2:repo
[dvd2]
name=dvd2
baseurl=file:///mnt/rhel65supplementary
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
```

```
# yum repolist
Loaded plugins: product-id, refresh-packagekit, security, subscription-manager
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
repo id                                                                           repo name                                                                      status
dvd1                                                                              dvd1                                                                           3,690
dvd2                                                                              dvd2                                                                              41
repolist: 3,731                                                                            dvd2
```

##Chef Serverセットアップ

###パッケージの入手
以下のサイトから対象プラットフォームのパッケージをダウンロードする。
[Chef Downloads - Chef Server](https://downloads.chef.io/chef-server/)

訳あって最新版ではないですが、ここではV12.7.0.1のRHEL6(64bit)版をダウンロードして使用します。

###rpmによるChef Serverのインストール

```
# rpm -ivh chef-server-core-12.7.0-1.el6.x86_64.rpm
warning: chef-server-core-12.7.0-1.el6.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
Preparing...                ########################################### [100%]
   1:chef-server-core       ########################################### [100%]

```

###Chef Server導入後の追加設定
####共用メモリの上限の確認
共有メモリの設定が小さいと後続タスク(chef-server-ctl reconfigure)でエラーになるケースがあるらしい。
以下のコマンドで確認してみるとそこそこでかいのでとりあえずそのままとする。

```
[root@vmx-007-018 /Inst_Image/Chef]# sysctl kernel.shmmax
kernel.shmmax = 68719476736
```

####ファイアーウォールの設定
443番ポートは許可するよう設定しておく必要があるらしい。

```
# iptables -I INPUT -m state --state NEW -p tcp --destination-port 443 -j ACCEPT
# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]
```

###Chef Server構成

参考: [chef-server-ctl](https://docs.chef.io/ctl_chef_server.html)

####chef-server-ctl reconfigureコマンド実行

```
# chef-server-ctl reconfigure
Starting Chef Client, version 12.12.3
resolving cookbooks for run list: ["private-chef::default"]
Synchronizing Cookbooks:
  - private-chef (0.1.0)
  - enterprise (0.10.1)
  - apt (2.9.2)
  - yum (3.10.0)
  - openssl (4.4.0)
  - runit (1.6.0)
  - chef-sugar (3.3.0)
  - packagecloud (0.0.18)
Installing Cookbook Gems:
Compiling Cookbooks...

... 略 ...

Chef Client finished, 392/463 resources updated in 02 minutes 55 seconds
Chef Server Reconfigured!
```

####administratorの作成

```
# chef-server-ctl user-create admin User Admin admin@chef.io 'abc123' --filename /root/Chef_Keys/admin.pem
# ls -la /root/Chef_Keys/
total 12
drwxr-xr-x   2 root root 4096 Nov 10 16:24 .
dr-xr-x---. 26 root root 4096 Nov 10 16:21 ..
-rw-r--r--   1 root root 1678 Nov 10 16:24 admin.pem
```

####organizationの作成

```
# chef-server-ctl org-create xxxxx 'xxxxxxxxxx' --association_user admin --filename /root/Chef_Keys/org.pem
# ls -la /root/Chef_Keys/
total 16
drwxr-xr-x   2 root root 4096 Nov 10 16:25 .
dr-xr-x---. 26 root root 4096 Nov 10 16:21 ..
-rw-r--r--   1 root root 1678 Nov 10 16:24 admin.pem
-rw-r--r--   1 root root 1678 Nov 10 16:25 org.pem
```

####追加フィーチャー: Chef Manageの設定
GUIでChef Serverを管理するためのChef Manageというのが追加フィーチャーとして用意されています。Webブラウザベースでの管理が色々とできるらしいですが、 このフィーチャーは有償のようです。(これはWorkstationの構成でもちょっと関係してきます。)


[Chef Manage](https://docs.chef.io/manage.html)より抜粋
>This feature is included as part of the Chef Automate license agreement and is [available via subscription](https://www.chef.io/pricing/).

[Install the Chef Server](https://docs.chef.io/install_server.html#standalone)より抜粋
>Starting with the Chef management console 2.3.0, the [Chef MLSA](https://docs.chef.io/chef_license.html) must be accepted when reconfiguring the product. If the Chef MLSA has not already been accepted, the reconfigure process will prompt for a yes to accept it. Or run chef-manage-ctl reconfigure --accept-license to automatically accept the license.


以下のサイトからパッケージをダウンロード (とりあえず最新版を選択すればよさそう？)
[Cehf Downloads - Chef Manage](https://downloads.chef.io/chef-manage/redhat/)

ダウンロードしたxxx.rpmを適当なディレクトリ(ex. /Inst_Image/Chef)に配置して、以下のコマンドでインストールすればOKぽい。

```
# chef-server-ctl install chef-manage --path /Inst_Image/Chef
```

###Chef Serverの起動
chef-server-ctl startコマンド実行

```
# chef-server-ctl start
ok: run: bookshelf: (pid 1755) 281s
ok: run: nginx: (pid 1618) 285s
ok: run: oc_bifrost: (pid 1544) 287s
ok: run: oc_id: (pid 1601) 286s
ok: run: opscode-chef-mover: (pid 2139) 0s
ok: run: opscode-erchef: (pid 1857) 278s
ok: run: opscode-expander: (pid 1703) 282s
ok: run: opscode-solr4: (pid 1633) 283s
ok: run: postgresql: (pid 1458) 288s
ok: run: rabbitmq: (pid 1406) 288s
ok: run: redis_lb: (pid 1348) 320s
```

##Chef Workstationセットアップ

###パッケージの入手
以下のサイトからChef-DKのRHEL版をダウンロード。とりあえず(当時)最新だった0.19.6を選択
[Chef Downloads - Chef Development Kit](http://downloads.chef.io/chef-dk/)

※WorkstationのセットアップをするのにChef-DKというものをインストールしなければならない、というのが分かりにくい(なんで名前が違うんだ！)。しかもChef Serverとのバージョニングも違うしバージョンの整合性をどう考えればよいのか不明。

###rpmによるChef-DKのインストール

```
# rpm -ivh chefdk-0.19.6-1.el6.x86_64.rpm
warning: chefdk-0.19.6-1.el6.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
Preparing...                ########################################### [100%]
   1:chefdk                 ########################################### [100%]
Thank you for installing Chef Development Kit!
```

インストールチェック用のコマンドを打ってみる。

```
# chef verify
Running verification for component 'berkshelf'
Running verification for component 'test-kitchen'
Running verification for component 'tk-policyfile-provisioner'
Running verification for component 'chef-client'
Running verification for component 'chef-dk'
Running verification for component 'chef-provisioning'
Running verification for component 'chefspec'
Running verification for component 'generated-cookbooks-pass-chefspec'
Running verification for component 'rubocop'
Running verification for component 'fauxhai'
Running verification for component 'knife-spork'
Running verification for component 'kitchen-vagrant'
Running verification for component 'package installation'
Running verification for component 'openssl'
Running verification for component 'inspec'
Running verification for component 'delivery-cli'
Running verification for component 'git'
Running verification for component 'opscode-pushy-client'
Running verification for component 'chef-sugar'
................................................................................................................................./opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/mixlib-shellout-2.2.7/lib/mixlib/shellout.rb:289:in `invalid!': Expected process to exit with [0], but received '128' (Mixlib::ShellOut::ShellCommandFailed)
---- Begin output of /opt/chefdk/gitbin/git clone https://github.com/chef/chef-provisioning ----
STDOUT:
STDERR: Cloning into 'chef-provisioning'...
fatal: unable to access 'https://github.com/chef/chef-provisioning/': Failed to connect to github.com port 443: Connection timed out
---- End output of /opt/chefdk/gitbin/git clone https://github.com/chef/chef-provisioning ----
Ran /opt/chefdk/gitbin/git clone https://github.com/chef/chef-provisioning returned 128
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/mixlib-shellout-2.2.7/lib/mixlib/shellout.rb:276:in `error!'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/component_test.rb:128:in `block in sh!'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/component_test.rb:128:in `tap'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/component_test.rb:128:in `sh!'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/command/verify.rb:482:in `block (3 levels) in <class:Verify>'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/component_test.rb:165:in `block in tmpdir'
        from /opt/chefdk/embedded/lib/ruby/2.3.0/tmpdir.rb:89:in `mktmpdir'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/component_test.rb:164:in `tmpdir'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/command/verify.rb:480:in `block (2 levels) in <class:Verify>'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/component_test.rb:99:in `instance_eval'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/component_test.rb:99:in `run_smoke_test'
        from /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-dk-0.19.6/lib/chef-dk/command/verify.rb:585:in `block (2 levels) in invoke_tests'
```

=>エラーになる！
なんかgithubへアクセスしようとして失敗しているらしい。外部のネットワークにつながらない環境なので...
ううむ。オフラインでの方法はどこに書いてあるんだろうか？？？
よく分からないが失敗しているのは「verify」コマンドなので無視してもよいようだ。

###Chef開発用ユーザー作成
Chef開発用ユーザー(chefdev)を作成し、それで作業することにする 

```
# useradd chefdev
# passwd xxxxxxxx
Changing password for user chefdev.
New password:
BAD PASSWORD: it is based on a dictionary word
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updated successfully.
```

以降、su - chefdevして作業

###Rubyのパス指定

```
$ echo 'eval "$(chef shell-init bash)"' >> ~/.bash_profile
```

ログインし直して確認

```
$ which ruby
/opt/chefdk/embedded/bin/ruby
```

=> chefdk以下のものが参照されているのでOK

###Chefリポジトリの構成
先に紹介したChef-manageという有償フィーチャーを使っていると、WebのインターフェースからStarter Kitというのを入手して楽に構成ができるようです。
もしくは手動でChefリポジトリを構成します。
ちょっとここは横着して...
[Install the Chef DK](https://docs.chef.io/install_dk.html) の
「Set up the chef-repo - Manually (w/o Webui)」あたりの手順に従って構成！

###ユーザーのプロファイル設定
$PATHにRubyのパス追加

```
$ echo 'export PATH="/opt/chefdk/embedded/bin:$PATH"' >> ~/.bash_profile && source ~/.bash_profile
```

###SSL設定
Chefリポジトリのディレクトリ(ex. /home/chefdev/chef-repo)に移動して、knife ssl fetchコマンド実行。(実行するディレクトリに注意！)
参考: [knife ssl fetch](https://docs.chef.io/knife_ssl_fetch.html)

```
$ knife ssl fetch
WARNING: Certificates from vmx-007-018.vmware.cloud.ise.com will be fetched and placed in your trusted_cert
directory (/home/chefdev/chef-repo/.chef/trusted_certs).

Knife has no means to verify these are the correct certificates. You should
verify the authenticity of these certificates after downloading.

Adding certificate for vmx-007-018.vmware.cloud.ise.com in /home/chefdev/chef-repo/.chef/trusted_certs/vmx-007-018_vmware_cloud_ise_com.crt

```

=> chef-repo/.chef/trusted_certs/に証明書が作成される

###インストール確認

knife client listコマンドでxxx-validatorがリストされればOK

参考: [knife client](https://docs.chef.io/knife_client.html)

###Nodeセットアップを行うためのCookbookの準備
githubから以下のクックブックを入手
[chef-client](https://github.com/chef-cookbooks/chef-client)
[compat_resource](https://github.com/chef-cookbooks/compat_resource)
[cron](https://github.com/chef-cookbooks/cron)
[ohai](https://github.com/chef-cookbooks/ohai)
[windows](https://github.com/chef-cookbooks/windows)
[logrotate](https://github.com/cookbooks/logrotate)

zipをダウンロードし、Chef Workstationマシンの、chef-repo/cookbooks/以下に展開します。
ディレクトリ名がxxx-masterとなるので、ディレクトリ名を変更して"-master"は削除します。

```
$ cd ~/chef-repo/cookbooks
$ ls -la
...
drwxrwxr-x 10 chefdev chefdev 4096 Oct 26 02:18 chef-client
drwxrwxr-x  8 chefdev chefdev 4096 Nov 26 05:06 compat_resource
drwxrwxr-x 13 chefdev chefdev 4096 Oct  7 06:20 cron
drwxrwxr-x  9 chefdev chefdev 4096 Jul 22 04:01 logrotate
drwxrwxr-x  9 chefdev chefdev 4096 Nov 18 15:09 ohai
drwxrwxr-x 12 chefdev chefdev 4096 Nov 17 02:48 windows

```

Chef ServerにCookbookをアップロードする
参考: [knife cookbook](https://docs.chef.io/knife_cookbook.html)

```
$ knife cookbook upload chef-client --include-dependencies
Uploading chef-client    [7.0.0]
Uploading cron           [3.0.0]
Uploading logrotate      [2.1.0]
Uploading windows        [2.0.2]
Uploading compat_resource [12.16.2]
Uploading ohai           [4.2.2]
Uploaded 6 cookbooks.
```

##Chef Nodeセットアップ

###Chef用ユーザーを作成する
Chef Nodeのマシンにchefclientユーザーを作成

```
# useradd chefclient
# passwd chefclient
Changing password for user chefclient.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
```

chefclientユーザーでsudoが使えるようにする。
visudoを実行し、/etc/sudoersを編集 (以下の文を追加)
```chefclient ALL=(ALL) ALL```

###SSH設定
Chef WorkstationからChef Nodeに対してSSH経由でリモートで操作できるようにSSH公開鍵認証の設定をしておく。

---
(1) chef Nodeでの操作 (SSHサーバー側)
chefclientユーザーのホームに.sshディレクトリ作成し、パーミッションを設定

```
$ cd ~
$ mkdir .ssh
$ chmod 755 .ssh
$ ls -la | grep .ssh
drwxr-xr-x  2 chefclient chefclient 4096 Nov 24 16:02 .ssh
```

---
(2) Chef Workstationでの操作 (SSHクライアント側)
chefdevユーザーでkeyペア作成

```
$ cd ~
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/chefdev/.ssh/id_rsa):
Created directory '/home/chefdev/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/chefdev/.ssh/id_rsa.
Your public key has been saved in /home/chefdev/.ssh/id_rsa.pub.
The key fingerprint is:
55:6b:cd:62:df:72:eb:06:a2:e7:ba:2c:c2:46:04:a8 chefdev@vmx-007-018
The key's randomart image is:
+--[ RSA 2048]----+
|  .         .    |
| . .       . +   |
|.   .     . = o  |
|E    .   . o o . |
|    .   S     o o|
|     .     . . o.|
|    o     . . .. |
|     + ... .  .. |
|    . . .+=.  .. |
+-----------------+

$ ls .ssh/
id_rsa  id_rsa.pub
```

生成された公開鍵(id_rsa.pub)をChef Clientに転送

```
$ scp id_rsa.pub chefclient@xxxxx:~/.ssh/
The authenticity of host 'xxxxx (xxxxx)' can't be established.
RSA key fingerprint is 90:65:fb:07:92:d1:4e:27:d5:98:3d:32:72:bc:c2:72.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'xxxxx' (RSA) to the list of known hosts.
chefclient@xxxxx's password:
id_rsa.pub
```

(xxxxxはChef Nodeのホスト名/IPアドレス)

---
(3) Chef Nodeでの操作 (SSHサーバー側)
公開鍵をauthorized_keysファイルに追加し、パーミッションを設定

```
$ cd ~/.ssh
$ cat id_rsa.pub > authorized_keys
$ chmod 644 authorized_keys
$ ls -la
total 16
drwxr-xr-x 2 chefclient chefclient 4096 Nov 24 16:06 .
drwx------ 5 chefclient chefclient 4096 Nov 24 15:58 ..
-rw-r--r-- 1 chefclient chefclient  401 Nov 24 16:06 authorized_keys
-rw-r--r-- 1 chefclient chefclient  401 Nov 24 16:02 id_rsa.pub
```

---
(4) Chef Workstationでの操作 (SSHクライアント側)
SSH接続確認

```
$ ssh chefclient@xxxxx pwd
/home/chefclient
```

=>パスワードを聞かれずに結果(Chef Node側のchefclientユーザーのホームディレクトリ)が返されればOK

###knife bootstrapによるChef Clientの導入 & ノードセットアップ
Chef Node用マシンの/Inst_Image/Chefに、Chef Clientパッケージを配置しておきます。(Nodeが大量にある場合はNFSサーバーなどを立ててNFSマウントしたりしておくことを想定)

Chef Workstationから、以下のコマンドでノードのセットアップを行います。
参考: [knife bootstrap](https://docs.chef.io/knife_bootstrap.html)

```
$ knife bootstrap xxxxx --ssh-user chefclient --ssh-identity-file ~/.ssh/id_rsa --sudo --node-name chefnode00 --run-list 'recipe[chef-client::delete_validation]' --bootstrap-install-command "rpm -i /Inst_Image/Chef/chef-12.11.18-1.el6.x86_64.rpm"
Creating new client for chefnode00
Creating new node for chefnode00
Connecting to xxxxx
xxxxx knife sudo password:
Enter your password:
xxxxx
xxxxx warning: /Inst_Image/Chef/chef-12.11.18-1.el6.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
xxxxx   package chef-12.11.18-1.el6.x86_64 is already installed
xxxxx Starting the first Chef Client run...
xxxxx Starting Chef Client, version 12.11.18
xxxxx resolving cookbooks for run list: ["chef-client::delete_validation"]
xxxxx Synchronizing Cookbooks:
xxxxx   - chef-client (7.0.0)
xxxxx   - cron (3.0.0)
xxxxx   - logrotate (2.1.0)
xxxxx   - compat_resource (12.16.2)
xxxxx   - windows (2.0.2)
xxxxx   - ohai (4.2.2)
xxxxx Installing Cookbook Gems:
xxxxx Compiling Cookbooks...
xxxxx Converging 1 resources
xxxxx Recipe: chef-client::delete_validation
xxxxx   * file[/etc/chef/validation.pem] action delete (up to date)
xxxxx
xxxxx Running handlers:
xxxxx Running handlers complete
xxxxx Chef Client finished, 0/1 resources updated in 13 seconds
```

(xxxxxはChef Nodeのホスト名/IPアドレス)

確認
参考: [knife node list](https://docs.chef.io/knife_node.html#list)

```
$ knife node list
chefnode00
```

これで、Chef NodeマシンにChef Clientが導入され、chefnode00という名前でChef Serverの管理対象として認識されました。

##シンプルなcookbokの作成/実行

Chef Server, Chef Workstation, Chef Nodeの構成が完了したので、Cookbookを作成してChef Nodeに適用してみます。
以下の操作はChef Workstationから実行します(chefdevユーザー)。

###Cookbook作成
Chef Workstationから、knife cookbook createコマンドを実行 => deprecated?
参考: [knife cookbook create](https://docs.chef.io/knife_cookbook.html#create)

```
$ cd ~/chef-repo
$ knife cookbook create test01
WARN: This command is being deprecated in favor of `chef generate cookbook` and will soon return an error.
Please use `chef generate cookbook` instead of this command.
 at /opt/chefdk/embedded/lib/ruby/gems/2.3.0/gems/chef-12.15.19/lib/chef/knife.rb:429:in `block in run_with_pretty_exceptions'
** Creating cookbook test01 in /home/chefdev/chef-repo/cookbooks
** Creating README for cookbook: test01
** Creating CHANGELOG for cookbook: test01
** Creating metadata for cookbook: test01
```

このコマンドは古いからchef generate cookbook使えと言われた。
chef generate cookbookも実行してみる。
参考: [chef generate cookbook](https://docs.chef.io/ctl_chef.html#chef-generate-cookbook)

```
$ cd ~/chef-repo
$ chef generate cookbook cookbooks/test02
Generating cookbook test02
- Ensuring correct cookbook file content
- Ensuring delivery configuration
- Ensuring correct delivery build cookbook content

Your cookbook is ready. Type `cd cookbooks/test02` to enter it.

There are several commands you can run to get started locally developing and testing your cookbook.
Type `delivery local --help` to see a full list.

Why not start by writing a test? Tests for the default recipe are stored at:

test/recipes/default_test.rb

If you'd prefer to dive right in, the default recipe can be found at:

recipes/default.rb
```

ふむ、今後はchef generate cookbookコマンドを使いましょう。
とりあえずtest01の方を使って進めます。

###レシピ作成

ファイルをテンプレートからコピーするだけのレシピを作ってみます。(一応Attributeも使ってみる)

Attributes

```rb:~/chef-repo/cookbooks/test01/attributes/default.rb
default['test01']['var01'] = "aaaaa"
default['test01']['var02'] = "bbbbb"
```

Templates

```xxx:~/chef-repo/cookbooks/test01/templates/default/template01.txt.erb
*** test01 - template01 ***

var01: <%= node['test01']['var01']%>

var02: <%= node['test01']['var02']%>

```

Recipes

```rb:~/chef-repo/cookbooks/test01/recipes/recipe01.rb
template "/tmp/template01.txt" do
        source "template01.txt.erb"
        owner "root"
        group "root"
        mode 0644
end
```

このレシピでは、Cookbookにテンプレートとして用意したtemplate01.txt.erbファイルを元にして、Attributesに指定した変数に内容を置き換えて、それをChef Nodeの/tmp/template01.txtに配置する、ということを行う想定です。

>補足: Cookbookとレシピの関係
>Cookbookの中にはレシピを複数保持することができます。各ノードに適用するのはレシピの単位で制御します。例えばDBサーバー構成用のCookbook作って、レシピとして製品インストール用、インスタンス作成用のレシピを作る、という感じで管理するとよさそうです。

###ノード定義のrun_listにレシピを設定

Chef Serverでは、管理対象のノードの定義内にrun-listという属性を持っています。run-listはそのノードを構成するのに必要な情報を保持するためのものです。ノードの構成を行う際に適用したいレシピは、まず、当該ノードのrun-listに登録します。
run-listには、複数のレシピや、"ロール"(複数のレシピをまとめて管理できるオブジェクト)を指定できます。

knife nodeコマンドを使用して、先に作成したレシピ(cookbook "test01"のレシピ"recipe01")を対象のノードのrun-listに設定します。
参考: [knife node run_list set](https://docs.chef.io/knife_node.html#run-list-set)
参考: [knife node run_list add](https://docs.chef.io/knife_node.html#run-list-add)

```
$ knife node run_list set chefnode00 'recipe[test01::recipe01]'
chefnode00:
  run_list: recipe[test01::recipe01]

$ knife node show chefnode00
Node Name:   chefnode00
Environment: _default
FQDN:        vmx-007-013.vmware.cloud.ise.com
IP:          xxxxx
Run List:    recipe[test01::recipe01]
Roles:
Recipes:     chef-client::delete_validation
Platform:    redhat 6.5
Tags:
```

これで、管理対象ノードとレシピの関連付けができました。

※補足
上の例はrun_list setコマンドなので、run_listにレシピを新たに「セット」するコマンドです。既存のリストがあって、「追加」する場合はrun_list addを使います。また、コンマ区切りで複数のレシピをrun_listに追加することができます。
例:

```
knife node run_list add chefnode00 'recipe[test01::recipe01], recipe[test01::recipe02]'
```

###CookbookをChef Serverへアップロード

先に作成したCookbookをChef Serverにアップロードします。
参考: [knife cookbook upload](https://docs.chef.io/knife_cookbook.html#upload)

```
$ knife cookbook upload test01
Uploading test01         [0.1.0]
Uploaded 1 cookbook.

$ knife cookbook show test01
test01   0.1.0
```

これで実行の準備が整いました。

###ノードの構成(レシピの実行)

knife sshコマンドで、chefnode00の構成を行います。
参考: [knife ssh](https://docs.chef.io/knife_ssh.html)

```
$ knife ssh name:chefnode00 "sudo chef-client" --identity-file ~/.ssh/id_rsa --ssh-user chefclient
vmx-007-013.vmware.cloud.ise.com knife sudo password:
Enter your password:
vmx-007-013.vmware.cloud.ise.com
vmx-007-013.vmware.cloud.ise.com Starting Chef Client, version 12.11.18
vmx-007-013.vmware.cloud.ise.com resolving cookbooks for run list: ["test01::recipe01"]
vmx-007-013.vmware.cloud.ise.com Synchronizing Cookbooks:
vmx-007-013.vmware.cloud.ise.com   - test01 (0.1.0)
vmx-007-013.vmware.cloud.ise.com Installing Cookbook Gems:
vmx-007-013.vmware.cloud.ise.com Compiling Cookbooks...
vmx-007-013.vmware.cloud.ise.com Converging 1 resources
vmx-007-013.vmware.cloud.ise.com Recipe: test01::recipe01
vmx-007-013.vmware.cloud.ise.com   * template[/tmp/template01.txt] action create
vmx-007-013.vmware.cloud.ise.com     - create new file /tmp/template01.txt
vmx-007-013.vmware.cloud.ise.com     - update content in file /tmp/template01.txt from none to a17f31
vmx-007-013.vmware.cloud.ise.com     --- /tmp/template01.txt    2016-12-06 20:07:34.132886037 +0900
vmx-007-013.vmware.cloud.ise.com     +++ /tmp/.chef-template01.txt20161206-8595-1a9xk7o 2016-12-06 20:07:34.132886037 +0900
vmx-007-013.vmware.cloud.ise.com     @@ -1 +1,6 @@
vmx-007-013.vmware.cloud.ise.com     +*** test01 - template01 ***
vmx-007-013.vmware.cloud.ise.com     +
vmx-007-013.vmware.cloud.ise.com     +var01: aaaaa
vmx-007-013.vmware.cloud.ise.com     +
vmx-007-013.vmware.cloud.ise.com     +var02: bbbbb
vmx-007-013.vmware.cloud.ise.com     - change mode from '' to '0644'
vmx-007-013.vmware.cloud.ise.com     - change owner from '' to 'root'
vmx-007-013.vmware.cloud.ise.com     - change group from '' to 'root'
vmx-007-013.vmware.cloud.ise.com
vmx-007-013.vmware.cloud.ise.com Running handlers:
vmx-007-013.vmware.cloud.ise.com Running handlers complete
vmx-007-013.vmware.cloud.ise.com Chef Client finished, 1/1 resources updated in 08 seconds
```

###対象のChef Nodeに接続して、ファイルが作成されているか確認します。

```
# cd /tmp
# ls -la | grep template
-rw-r--r--   1 root root   56 Dec  6 20:07 template01.txt

# cat template01.txt
*** test01 - template01 ***

var01: aaaaa

var02: bbbbb
```

=> OK! 意図したとおりにファイルが作成されました！！！

##シンプルなcookbokの作成/実行 その2

以下の辺りの機能を試すために、上のレシピにもう少しコードを追加してみます。

* 複数パッケージの導入(64bit/32bit)
* ディレクトリ作成
* 判定ロジック追加(not_if)
* 環境変数の適用 (個別指定とprofile読み込み)
* レシピ中でのAttributeの使用


```rb:~/chef-repo/cookbooks/test01/recipes/recipe01.rb
template "/tmp/template01.txt" do
        source "template01.txt.erb"
        owner "root"
        group "root"
        mode 0644
end

%w{libstdc++ libstdc++-devel}.each do |pkg64|
        package pkg64 do
                action :install
        end
end

%w{glibc}.each do |pkg32|
        yum_package pkg32 do
                arch 'i686'
                action :install
        end
end

directory "/tmp/chef_test01" do
  owner "root"
  group "root"
  mode 00755
  action :create
  not_if { File.exists?("/tmp/chef_test01") }
end

execute "test02" do
        cwd "/root/Shell"
        user "root"
        group "root"
        command "./test.sh #{node['test01']['var01']} #{node['test01']['var02']} > test02.txt"
        not_if { File.exists?("/tmp/chef_test01") }
end
```

ノード側でもテスト用に単純なシェル・スクリプト(/root/Shell/test.sh)を用意しておきます。

```sh:test.sh
#!/bin/bash

date
echo arg1: $1
echo arg2: $2
```

レシピを修正したら、```knife cookbook upload test01```コマンドでcookbookをアップロードしなおして、再度実行する、という流れになります。
(実行結果は省略)


#おわりに
やってみた率直な感想としては、Chef Server構成だと特に仕組みが大掛かりすぎ！
マニュアル分かりにくいし、バージョンが変わって色々変更が入っているいるせいか、世の中に出回っているドキュメントや本の情報が古くて混乱しがちでなかなか大変でした。

"インストールや構成作業を簡素化/自動化する"という目的のためだけであればあまり労力に見合わなそうな気がします。"構成作業の効率化"という目的であれば、よく比較されているAnsibleというやつの方がよさそうです(Ansibleもよく知らないのだけど、基本環境としてはSSHがつながれば良く、あとは作業端末からスクリプトを流し込むだけ、みたいな。Chefのようにサーバーとかの鬱陶しい構成は無くていいらしい。それを聞いたらAnsibleの方が断然魅力的に思えた...)。

Chefを使うのであれば、単に構築だけでなく、その後のバージョン管理なども含めてChef使って実現する、みたいな使い方じゃないと効果ないのではないかな。ちなみに上の手順では端折ってますが、chefのリポジトリはgitできちんとバージョン管理しましょうというのが作法のようです(そこが肝になるので)。

また、Chefでよく言われている"べき等性"(何度実行しても同じ状態になることを保証する)というのが結構眉唾な気がします。べき等性を保つためにはそれを意識したレシピ作りが必要になるので(すなわち、レシピの書き方でその辺はグダグダになるので)、何を前提としてどこまでChefで管理するのか、というのを事前にカッチリと固めた上でそのガバナンスを利かせた上でレシピの設計/実装をしないといけないように思える。そこまでやるなら有償サポート契約とかも必要になってくるだろうし...

ということで、相当しっかりやらないと個別に自動化のスクリプト書くのと比較してメリット出すのが難しい気がする。うーん、これ、本当に普及していくのかなぁ。
(とりあえず初めて環境触ってみただけで言ってる戯言ですけど...)