Knife-ZeroでInfrastructure as Codeを始めよう #getchef
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本稿はChef Advent Calendar 2014の24日目の記事です。
Chefとは
Chefとは、インフラの情報を集中管理するツールです。An Overview of Chefでは次のように述べられています。
Chef is a powerful automation platform that transforms complex infrastructure into code, bringing your servers and services to life. (略)
Chef is built around simple concepts: achieving desired state, centralized modeling of IT infrastructure, and resource primitives that serve as building blocks. (略)
[和訳] Chefは複雑なインフラをコードに変換し、サーバやサービスを生きた状態とする、強力な自動化プラットフォームです。(略)
Chefは単純な概念で成り立っています: 望ましい状態に到達させる。ITインフラの中央集権的なモデルとなる。リソースの根源的要素を組み立てブロックのように扱う。(略)
インフラの情報を集中管理し、インフラの各要素を細かい部品に分けて再利用できるようにし、各要素をあるべき状態に収束させることがChefの真価です。
Chefで見逃されがちなのが インフラの情報を集中管理 の部分です。ここを見ずに単なる自動セットアップツールとしてChefを用いてもよいけれど、それはもったないでしょう。
Chefのインストール
では、さっそくChefをインストールしてみましょう。今回はChef Serverは必要ありません。Ubuntu 12.04 LTSをワークステーションとして、クライアントパッケージのみをインストールします。
また、管理する対象のリモートノードもUbuntu 12.04 LTSとします。
Chef Development Kitのインストール
ワークステーション用のクライアントパッケージはChef Development Kit、通称Chef DKと呼ばれています。Chefのクライアントプログラムだけでなく、Chefで開発を行うための各種ツールや、Chefを動作させるためのRubyまで同梱しています。そのため、別途Rubyをインストールしたり、RubyGemsでChefをインストールする必要はまったくありません。
Chef DKはChef Development Kit | Chef Downloads | Chefからダウンロードできます。OS、Chef DKのバージョン、OSのバージョンを選択し、ダウンロードしましょう。今回は chefdk_0.3.5-1_amd64.deb をダウンロードしました。早速インストールしましょう。
ubuntu@ws:~$ sudo dpkg -i chefdk_0.3.5-1_amd64.deb 以前に未選択のパッケージ chefdk を選択しています。 (データベースを読み込んでいます ... 現在 49102 個のファイルとディレクトリがインストールされています。) (chefdk_0.3.5-1_amd64.deb から) chefdk を展開しています... chefdk (0.3.5-1) を設定しています ... Thank you for installing Chef Development Kit! ubuntu@ws:~$
Knife-Zeroのインストール
ChefクライアントプログラムはChef DK付属のものではなく、Knife-Zeroを利用します。
ubuntu@ws:~$ chef gem install knife-zero --no-document Fetching: knife-zero-1.1.0.gem (100%) WARNING: You don't have /home/ubuntu/.chefdk/gem/ruby/2.1.0/bin in your PATH, gem executables will not run. Successfully installed knife-zero-1.1.0 1 gem installed ubuntu@ws:~$
警告はKnife-Zeroには関係ないので無視してかまいません。
SSHキーペアの作成など下準備
Knife-ZeroはSSHを利用してリモートノードの操作を行うので、SSH秘密鍵・公開鍵のペアを作成しておきます。ここではパスフレーズなしの鍵ペアを作成しています。
ubuntu@ws:~$ ssh-keygen -N '' Generating public/private rsa key pair. Enter file in which to save the key (/home/ubuntu/.ssh/id_rsa): Created directory '/home/ubuntu/.ssh'. Your identification has been saved in /home/ubuntu/.ssh/id_rsa. Your public key has been saved in /home/ubuntu/.ssh/id_rsa.pub. The key fingerprint is: 9a:72:67:23:3a:5c:2e:e9:74:03:44:0f:5e:87:0e:67 ubuntu@ws.example.jp The key's randomart image is: +--[ RSA 2048]----+ | o ... | | o.+E. | | o=. | | . . | | . S | | ..o | | .o+B + | | .==.= . | | .oo | +-----------------+ ubuntu@ws:~$
当然ながら、対象のリモートノードはSSHデーモンが動作している必要があるので起動しておきます。また、先に作成した公開鍵をリモートノードにあらかじめ配置します。
ubuntu@node:~$ mkdir .ssh ubuntu@node:~$ cat > .ssh/authorized_keys ssh-rsa (省略) ubuntu@ws.example.jp ubuntu@node:~$
加えて簡便のために、パスワードなしでsudoを実行してroot権限を得られるように、ログインアカウントに設定しておきましょう。
作業環境を作る
Knife-Zeroを実行する環境とするディレクトリツリーを作り、gitの管理下に置いておきます。このディレクトリツリーはchef-repoと呼ばれ、インフラをコード化したものとなります。
ubuntu@ws:~$ chef generate repo chef-repo
Compiling Cookbooks...
Recipe: code_generator::repo
* directory[/home/ubuntu/chef-repo] action create
- create new directory /home/ubuntu/chef-repo
:
(diff output suppressed by config)
ubuntu@ws:~$
ubuntu@ws:~$ cd chef-repo
ubuntu@ws:~/chef-repo$ tree
.
├── LICENSE
├── README.md
├── Rakefile
├── certificates
│ └── README.md
├── chefignore
├── config
│ └── rake.rb
├── cookbooks
│ └── README.md
├── data_bags
│ └── README.md
├── environments
│ └── README.md
└── roles
└── README.md
6 directories, 10 files
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ git init
Initialized empty Git repository in /home/ubuntu/chef-repo/.git/
ubuntu@ws:~/chef-repo$
これからKnife-Zeroで管理すると示す設定ファイルを準備しておきます。
ubuntu@ws:~/chef-repo$ mkdir .chef ubuntu@ws:~/chef-repo$ echo 'local_mode true' > .chef/knife.rb ubuntu@ws:~/chef-repo$ cat .chef/knife.rb local_mode true ubuntu@ws:~/chef-repo$
ノードへChefクライアントのインストール
リモートノードへChefクライアントをインストールし、Chefの管理対象とします。
knife zero bootstrapがコマンド、node.example.jpがノードのホスト名、-x ubuntuがログインユーザ名の指定、--sudoがsudoコマンドにてroot権限を取得するという意味となります。
ubuntu@ws:~/chef-repo$ knife zero bootstrap node.example.jp -x ubuntu --sudo Connecting to node.example.jp node.example.jp Installing Chef Client... node.example.jp --2014-12-19 12:06:20-- https://www.opscode.com/chef/install.sh node.example.jp www.opscode.com (www.opscode.com) をDNSに問いあわせています... 184.106.28.90 node.example.jp www.opscode.com (www.opscode.com)|184.106.28.90|:443 に接続しています... 接続しました。 node.example.jp HTTP による接続要求を送信しました、応答を待っています... 200 OK node.example.jp 長さ: 18285 (18K) [application/x-sh] node.example.jp `STDOUT' に保存中 node.example.jp 100%[======================================>] 18,285 --.-K/s 時間 0.002s node.example.jp node.example.jp 2014-12-19 12:06:21 (7.52 MB/s) - stdout へ出力完了 [18285/18285] node.example.jp node.example.jp Downloading Chef 11 for ubuntu... node.example.jp downloading https://www.opscode.com/chef/metadata?v=11&prerelease=false&nightlies=false&p=ubuntu&pv=12.04&m=x86_64 node.example.jp to file /tmp/install.sh.1100/metadata.txt node.example.jp trying wget... node.example.jp url https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/12.04/x86_64/chef_11.16.4-1_amd64.deb node.example.jp md5 2ffff5b4d80e4dcffc917f8eb2003a31 node.example.jp sha256 28b08975e7e33ac46c888616ec7fa232a0c624aeeda81e58a6047d2c6b62edfb node.example.jp downloaded metadata file looks valid... node.example.jp downloading https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/12.04/x86_64/chef_11.16.4-1_amd64.deb node.example.jp to file /tmp/install.sh.1100/chef_11.16.4-1_amd64.deb node.example.jp trying wget... node.example.jp Comparing checksum with sha256sum... node.example.jp Installing Chef 11 node.example.jp installing with dpkg... node.example.jp 以前に未選択のパッケージ chef を選択しています。 (データベースを読み込んでいます ... 現在 49102 個のファイルとディレクトリがインストールされています。) node.example.jp (.../chef_11.16.4-1_amd64.deb から) chef を展開しています... node.example.jp chef (11.16.4-1) を設定しています ... node.example.jp Thank you for installing Chef! node.example.jp Starting first Chef Client run... : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp Creating a new client identity for node.example.jp using the validator key. node.example.jp resolving cookbooks for run list: [] node.example.jp Synchronizing Cookbooks: node.example.jp Compiling Cookbooks... node.example.jp [2014-12-19T12:06:48+09:00] WARN: Node node.example.jp has an empty run list. node.example.jp Converging 0 resources node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 0/0 resources updated in 1.443860973 seconds ubuntu@ws:~/chef-repo$
自動的にChefクライアントをダウンロードし、ノードにインストールされました。
そして、ノードをChef管理対象に置きました。Chef Serverではなく、ワークステーションのChef-Repoディレクトリ内に管理情報が格納される形となっています。
ubuntu@ws:~/chef-repo$ cat clients/node.example.jp.json | cat
{
"name": "node.example.jp",
"public_key": "-----BEGIN PUBLIC KEY-----\n(省略)\n-----END PUBLIC KEY-----\n"
}
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ cat nodes/node.example.jp.json
{
"name": "node.example.jp",
"normal": {
"tags": [
]
},
"automatic": {
"network": {
"interfaces": {
"lo": {
"mtu": "16436",
"flags": [
"LOOPBACK",
"UP",
"LOWER_UP"
],
"encapsulation": "Loopback",
"addresses": {
"127.0.0.1": {
"family": "inet",
"prefixlen": "8",
"netmask": "255.0.0.0",
"scope": "Node"
},
"::1": {
"family": "inet6",
"prefixlen": "128",
"scope": "Node"
}
},
"state": "unknown"
},
"eth0": {
"type": "eth",
"number": "0",
"mtu": "1500",
"flags": [
"BROADCAST",
"MULTICAST",
"UP",
"LOWER_UP"
],
"encapsulation": "Ethernet",
"addresses": {
"52:54:00:8E:F7:2A": {
"family": "lladdr"
},
"192.168.122.67": {
"family": "inet",
"prefixlen": "24",
"netmask": "255.255.255.0",
"broadcast": "192.168.122.255",
"scope": "Global"
},
"fe80::5054:ff:fe8e:f72a": {
"family": "inet6",
"prefixlen": "64",
"scope": "Link"
}
},
"state": "up",
"arp": {
"192.168.122.209": "52:54:00:62:c3:07"
},
:
"recipes": [
],
"roles": [
]
}
}
ubuntu@ws:~/chef-repo$
ついでにワークステーション自体も登録してしまいましょう。
ubuntu@ws:~/chef-repo$ knife zero bootstrap ws.example.jp -x ubuntu --sudo Connecting to ws.example.jp ws.example.jp Starting first Chef Client run... : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp Creating a new client identity for ws.example.jp using the validator key. ws.example.jp resolving cookbooks for run list: [] ws.example.jp Synchronizing Cookbooks: ws.example.jp Compiling Cookbooks... ws.example.jp [2014-12-19T12:33:12+09:00] WARN: Node ws.example.jp has an empty run list. ws.example.jp Converging 0 resources ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 0/0 resources updated in 1.627046827 seconds ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ ls -l clients 合計 8 -rw-rw-r-- 1 ubuntu ubuntu 511 12月 19 12:06 node.example.jp.json -rw-rw-r-- 1 ubuntu ubuntu 509 12月 19 12:33 ws.example.jp.json ubuntu@ws:~/chef-repo$ ls -l nodes 合計 64 -rw-rw-r-- 1 ubuntu ubuntu 31169 12月 19 12:23 node.example.jp.json -rw-rw-r-- 1 ubuntu ubuntu 31157 12月 19 12:33 ws.example.jp.json ubuntu@ws:~/chef-repo$
以降、Knife-Zeroによって、ノードを管理していきます。
knifeコマンドでノードを管理する
knifeコマンドで登録した情報の取得を行ってみます。knife searchを用います。次はノードのIPアドレスを取得する例です。
ubuntu@ws:~/chef-repo$ knife search 'name:*' --attribute ipaddress 2 items found node.example.jp: ipaddress: 192.168.122.67 ws.example.jp: ipaddress: 192.168.122.209 ubuntu@ws:~/chef-repo$
これらはChef-Repoに格納されらデータから表示しています。
引数を操作することで、個々のノードの情報も表示ができます。
ubuntu@ws:~/chef-repo$ knife search 'name:node*' --attribute fqdn 1 items found node.example.jp: fqdn: node.example.jp ubuntu@ws:~/chef-repo$ knife search 'name:ws*' --attribute fqdn 1 items found ws.example.jp: fqdn: ws.example.jp ubuntu@ws:~/chef-repo$
knife sshで各ノードに対してリモートからコマンドを実行できます。
ubuntu@ws:~/chef-repo$ knife ssh 'name:*' 'uname -a' node.example.jp Linux node.example.jp 3.2.0-74-generic #109-Ubuntu SMP Tue Dec 9 16:45:49 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux ws.example.jp Linux ws.example.jp 3.2.0-74-generic #109-Ubuntu SMP Tue Dec 9 16:45:49 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux ubuntu@ws:~/chef-repo$
クックブックを作る
インフラをコード化してあるべき状態を記述したChefのファイルをクックブックと呼びます。クックブックはRubyを知らなくても書けます。クックブックがRubyの内部DSLというのは一旦忘れましょう。知るべきことはクックブックの書き方だけでいいのです。
パッケージを1つインストールする
ntpパッケージをインストールするクックブックを作ってみましょう。
chef generate cookbookコマンドを使うと、クックブックの雛形を用意してくれます。クックブックの名前は「ntp」とします。
ubuntu@ws:~/chef-repo$ chef generate cookbook cookbooks/ntp
Compiling Cookbooks...
Recipe: code_generator::cookbook
* directory[/home/ubuntu/chef-repo/cookbooks/ntp] action create
- create new directory /home/ubuntu/chef-repo/cookbooks/ntp
:
(diff output suppressed by config)
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ tree cookbooks/ntp
cookbooks/ntp
├── Berksfile
├── README.md
├── chefignore
├── metadata.rb
└── recipes
└── default.rb
1 directory, 5 files
ubuntu@ws:~/chef-repo$
cookbooks/ntp/recipes/default.rbは「ntpクックブック」の「defaultレシピ」と言います。通常、クックブックとはレシピ以外を含めたさまざまなデータの集合体を表すものですが、おおざっぱに同一視してしまってもだいたい通じます。
では編集してntpパッケージをインストールするようにしましょう。
# # Cookbook Name:: ntp # Recipe:: default # # Copyright (c) 2014 The Authors, All Rights Reserved. package 'ntp'
これだけです。元々あるコメントを除けば1行付け足しただけです。Ruby要素はどこにもありません。
このレシピを適用したいノードに登録します。
ubuntu@ws:~/chef-repo$ knife node run_list add node.example.jp 'recipe[ntp]' node.example.jp: run_list: recipe[ntp] ubuntu@ws:~/chef-repo$ knife node run_list add ws.example.jp 'recipe[ntp]' ws.example.jp: run_list: recipe[ntp] ubuntu@ws:~/chef-repo$
ノードでChefクライアントを実行して実際に適用する前に**-W**オプションでwhy-run (dry-runのようなもの)してみます。
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo -W node.example.jp [2014-12-22T13:09:25+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp"] node.example.jp Synchronizing Cookbooks: node.example.jp - ntp node.example.jp Compiling Cookbooks... node.example.jp Converging 1 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install node.example.jp - Would install version 1:4.2.6.p3+dfsg-1ubuntu3.1 of package ntp node.example.jp [2014-12-22T13:09:26+09:00] WARN: In whyrun mode, so NOT performing node save. node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 1/1 resources would have been updated ws.example.jp [2014-12-22T13:09:27+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp Compiling Cookbooks... ws.example.jp Converging 1 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install ws.example.jp - Would install version 1:4.2.6.p3+dfsg-1ubuntu3.1 of package ntp ws.example.jp [2014-12-22T13:09:28+09:00] WARN: In whyrun mode, so NOT performing node save. ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 1/1 resources would have been updated ubuntu@ws:~/chef-repo$
ntpパッケージがインストールされることがわかります。では-Wオプションを取り除いて実際にレシピを適用し、ノードをあるべき状態に収束します。
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T13:14:00+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp"] node.example.jp Synchronizing Cookbooks: node.example.jp - ntp node.example.jp Compiling Cookbooks... node.example.jp Converging 1 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install node.example.jp - install version 1:4.2.6.p3+dfsg-1ubuntu3.1 of package ntp node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 1/1 resources updated in 9.409252235 seconds ws.example.jp [2014-12-22T13:14:11+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp Compiling Cookbooks... ws.example.jp Converging 1 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install ws.example.jp - install version 1:4.2.6.p3+dfsg-1ubuntu3.1 of package ntp ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 1/1 resources updated in 10.834032539 seconds ubuntu@ws:~/chef-repo$
レシピの適用が成功し、1/1 resources updatedで表されている通り、ノードの1リソース中1つのリソースに変更があったことを示しています。べき等性の確認のためもう1回適用してみます。
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T13:18:52+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp"] node.example.jp Synchronizing Cookbooks: node.example.jp - ntp node.example.jp Compiling Cookbooks... node.example.jp Converging 1 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install (up to date) node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 0/1 resources updated in 0.991954497 seconds ws.example.jp [2014-12-22T13:18:55+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp Compiling Cookbooks... ws.example.jp Converging 1 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install (up to date) ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 0/1 resources updated in 1.050684551 seconds ubuntu@ws:~/chef-repo$
0/1 resources updatedで表されている通り、ノードの1リソース中どのリソースにも変更がなかったことを示しています。
さらにべき等性の確認のため、パッケージをアンインストールしてもう1回実行してみます。
ubuntu@ws:~/chef-repo$ knife ssh 'name:*' 'sudo apt-get purge -y ntp' -x ubuntu パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 ws.example.jp 以下のパッケージが自動でインストールされましたが、もう必要とされていません: ws.example.jp libopts25 libcap2 ws.example.jp これらを削除するには 'apt-get autoremove' を利用してください。 ws.example.jp 以下のパッケージは「削除」されます: ws.example.jp ntp* ws.example.jp アップグレード: 0 個、新規インストール: 0 個、削除: 1 個、保留: 1 個。 ws.example.jp この操作後に 1,511 kB のディスク容量が解放されます。 (データベースを読み込んでいます ... 現在 100642 個のファイルとディレクトリがインストールされています。) ws.example.jp ntp を削除しています ... ws.example.jp * Stopping NTP server ntpd [ OK ] ws.example.jp ntp の設定ファイルを削除しています ... ws.example.jp man-db のトリガを処理しています ... ws.example.jp ureadahead のトリガを処理しています ... パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 node.example.jp 以下のパッケージが自動でインストールされましたが、もう必要とされていません: node.example.jp libopts25 libcap2 node.example.jp これらを削除するには 'apt-get autoremove' を利用してください。 node.example.jp 以下のパッケージは「削除」されます: node.example.jp ntp* node.example.jp アップグレード: 0 個、新規インストール: 0 個、削除: 1 個、保留: 1 個。 node.example.jp この操作後に 1,511 kB のディスク容量が解放されます。 (データベースを読み込んでいます ... 現在 61224 個のファイルとディレクトリがインストールされています。) node.example.jp ntp を削除しています ... node.example.jp * Stopping NTP server ntpd [ OK ] node.example.jp ntp の設定ファイルを削除しています ... node.example.jp man-db のトリガを処理しています ... node.example.jp ureadahead のトリガを処理しています ... ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T13:25:47+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp"] node.example.jp Synchronizing Cookbooks: node.example.jp - ntp node.example.jp Compiling Cookbooks... node.example.jp Converging 1 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install node.example.jp - install version 1:4.2.6.p3+dfsg-1ubuntu3.1 of package ntp node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 1/1 resources updated in 5.015853954 seconds ws.example.jp [2014-12-22T13:25:54+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp Compiling Cookbooks... ws.example.jp Converging 1 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install ws.example.jp - install version 1:4.2.6.p3+dfsg-1ubuntu3.1 of package ntp ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 1/1 resources updated in 5.624764122 seconds ubuntu@ws:~/chef-repo$
1/1 resources updatedで表されている通り、再びレシピの適用に成功してリソースの更新が行われました。
なお、Chef-Repoディレクトリの**nodes/**ディレクトリの情報は、Chefクライアントの実行などで更新が行われています。
ubuntu@ws:~/chef-repo$ git diff
diff --git a/nodes/node.example.jp.json b/nodes/node.example.jp.json
index d90e315..03bea39 100644
--- a/nodes/node.example.jp.json
+++ b/nodes/node.example.jp.json
:
@@ -1207,11 +1208,11 @@
},
"current_user": "ubuntu",
"root_group": "root",
- "ohai_time": 1418959381.048563,
- "uptime_seconds": 2566,
- "uptime": "42 minutes 46 seconds",
- "idletime_seconds": 2528,
- "idletime": "42 minutes 08 seconds",
+ "ohai_time": 1419222348.6213446,
+ "uptime_seconds": 5229,
+ "uptime": "1 hours 27 minutes 09 seconds",
+ "idletime_seconds": 5154,
+ "idletime": "1 hours 25 minutes 54 seconds",
"block_device": {
"ram0": {
"size": "131072",
@@ -1316,10 +1317,14 @@
}
},
"recipes": [
-
+ "ntp",
+ "ntp::default"
],
"roles": [
]
- }
+ },
+ "run_list": [
+ "recipe[ntp]"
+ ]
}
diff --git a/nodes/ws.example.jp.json b/nodes/ws.example.jp.json
index 09b10d6..099b1af 100644
--- a/nodes/ws.example.jp.json
+++ b/nodes/ws.example.jp.json
:
@@ -1207,11 +1208,11 @@
},
"current_user": "ubuntu",
"root_group": "root",
- "ohai_time": 1418959992.8692613,
- "uptime_seconds": 3175,
- "uptime": "52 minutes 55 seconds",
- "idletime_seconds": 3127,
- "idletime": "52 minutes 07 seconds",
+ "ohai_time": 1419222354.9337227,
+ "uptime_seconds": 5235,
+ "uptime": "1 hours 27 minutes 15 seconds",
+ "idletime_seconds": 5117,
+ "idletime": "1 hours 25 minutes 17 seconds",
"block_device": {
"ram0": {
"size": "131072",
@@ -1316,10 +1317,14 @@
}
},
"recipes": [
-
+ "ntp",
+ "ntp::default"
],
"roles": [
]
- }
+ },
+ "run_list": [
+ "recipe[ntp]"
+ ]
}
ubuntu@ws:~/chef-repo$
パッケージを複数インストールする
nginxパッケージとredis-serverパッケージをインストールするクックブックを作ってみましょう。
ubuntu@ws:~/chef-repo$ chef generate cookbook cookbooks/multi_pkgs
Compiling Cookbooks...
Recipe: code_generator::cookbook
* directory[/home/ubuntu/chef-repo/cookbooks/multi_pkgs] action create
- create new directory /home/ubuntu/chef-repo/cookbooks/multi_pkgs
:
(diff output suppressed by config)
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ vi cookbooks/multi_pkgs/recipes/default.rb # # Cookbook Name:: multi_pkgs # Recipe:: default # # Copyright (c) 2014 The Authors, All Rights Reserved. package 'nginx' package 'redis-server' ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ knife node run_list add node.example.jp 'recipe[multi_pkgs]'
node.example.jp:
run_list:
recipe[ntp]
recipe[multi_pkgs]
ubuntu@ws:~/chef-repo$ knife node run_list add ws.example.jp 'recipe[multi_pkgs]'
ws.example.jp:
run_list:
recipe[ntp]
recipe[multi_pkgs]
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T16:23:51+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs"] node.example.jp Synchronizing Cookbooks: node.example.jp - ntp node.example.jp - multi_pkgs node.example.jp Compiling Cookbooks... node.example.jp Converging 3 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install (up to date) node.example.jp Recipe: multi_pkgs::default node.example.jp * package[nginx] action install node.example.jp - install version 1.1.19-1ubuntu0.6 of package nginx node.example.jp * package[redis-server] action install node.example.jp - install version 2:2.2.12-1build1 of package redis-server node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 2/3 resources updated in 14.823459658 seconds ws.example.jp [2014-12-22T16:24:07+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp - multi_pkgs ws.example.jp Compiling Cookbooks... ws.example.jp Converging 3 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install (up to date) ws.example.jp Recipe: multi_pkgs::default ws.example.jp * package[nginx] action install ws.example.jp - install version 1.1.19-1ubuntu0.6 of package nginx ws.example.jp * package[redis-server] action install ws.example.jp - install version 2:2.2.12-1build1 of package redis-server ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 2/3 resources updated in 15.721211671 seconds ubuntu@ws:~/chef-repo$
インストールできました。ここで一旦アンインストールしておきます。
ubuntu@ws:~/chef-repo$ knife ssh 'name:*' 'sudo apt-get purge -y nginx redis-server' -x ubuntu パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 ws.example.jp 以下のパッケージが自動でインストールされましたが、もう必要とされていません: ws.example.jp libjpeg-turbo8 libjpeg8 libxslt1.1 nginx-full nginx-common libgd2-noxpm ws.example.jp これらを削除するには 'apt-get autoremove' を利用してください。 ws.example.jp 以下のパッケージは「削除」されます: ws.example.jp nginx* redis-server* ws.example.jp アップグレード: 0 個、新規インストール: 0 個、削除: 2 個、保留: 1 個。 ws.example.jp この操作後に 610 kB のディスク容量が解放されます。 (データベースを読み込んでいます ... 現在 100734 個のファイルとディレクトリがインストールされています。) ws.example.jp nginx を削除しています ... ws.example.jp redis-server を削除しています ... ws.example.jp Stopping redis-server: redis-server. ws.example.jp redis-server の設定ファイルを削除しています ... ws.example.jp dpkg: 警告: redis-server の削除中、ディレクトリ '/var/log/redis' が空でないため削除できませんでした。 ws.example.jp man-db のトリガを処理しています ... ws.example.jp ureadahead のトリガを処理しています ... パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 node.example.jp 以下のパッケージが自動でインストールされましたが、もう必要とされていません: node.example.jp libjpeg-turbo8 libjpeg8 libxslt1.1 nginx-full nginx-common libgd2-noxpm node.example.jp これらを削除するには 'apt-get autoremove' を利用してください。 node.example.jp 以下のパッケージは「削除」されます: node.example.jp nginx* redis-server* node.example.jp アップグレード: 0 個、新規インストール: 0 個、削除: 2 個、保留: 1 個。 node.example.jp この操作後に 610 kB のディスク容量が解放されます。 (データベースを読み込んでいます ... 現在 61316 個のファイルとディレクトリがインストールされています。) node.example.jp nginx を削除しています ... node.example.jp redis-server を削除しています ... node.example.jp Stopping redis-server: redis-server. node.example.jp redis-server の設定ファイルを削除しています ... node.example.jp dpkg: 警告: redis-server の削除中、ディレクトリ '/var/log/redis' が空でないため削除できませんでした。 node.example.jp man-db のトリガを処理しています ... node.example.jp ureadahead のトリガを処理しています ... ubuntu@ws:~/chef-repo$
ループを用いてレシピを書き直してみます。
ubuntu@ws:~/chef-repo$ vi cookbooks/multi_pkgs/recipes/default.rb
#
# Cookbook Name:: multi_pkgs
# Recipe:: default
#
# Copyright (c) 2014 The Authors, All Rights Reserved.
%w{ nginx redis-server }.each do |pkg|
package pkg
end
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T16:28:00+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs"] node.example.jp Synchronizing Cookbooks: node.example.jp - ntp node.example.jp - multi_pkgs node.example.jp Compiling Cookbooks... node.example.jp Converging 3 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install (up to date) node.example.jp Recipe: multi_pkgs::default node.example.jp * package[nginx] action install node.example.jp - install version 1.1.19-1ubuntu0.6 of package nginx node.example.jp * package[redis-server] action install node.example.jp - install version 2:2.2.12-1build1 of package redis-server node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 2/3 resources updated in 6.903009063 seconds ws.example.jp [2014-12-22T16:28:08+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp - multi_pkgs ws.example.jp Compiling Cookbooks... ws.example.jp Converging 3 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install (up to date) ws.example.jp Recipe: multi_pkgs::default ws.example.jp * package[nginx] action install ws.example.jp - install version 1.1.19-1ubuntu0.6 of package nginx ws.example.jp * package[redis-server] action install ws.example.jp - install version 2:2.2.12-1build1 of package redis-server ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 2/3 resources updated in 7.603140636 seconds ubuntu@ws:~/chef-repo$
packageを数並べた場合と同じようにインストールできました。resourcesの数が変わっていないことに注目してください。つまり、同じ結果を得るための書き方はさまざまにできるということです。
テンプレートを用いる
ChefはエンジンにERBを用いたテンプレートが利用できます。
変数から得た値(Hello, World!)をテンプレート(tmpl.hello.erb)中に埋め込み、ファイル(/tmp/hello.txt)として出力するクックブックを作成します。
雛形を作成します。
まずはデータの集合体であるクックブックです。tmplクックブックと命名しています。
ubuntu@ws:~/chef-repo$ chef generate cookbook cookbooks/tmpl
Compiling Cookbooks...
Recipe: code_generator::cookbook
* directory[/home/ubuntu/chef-repo/cookbooks/tmpl] action create
- create new directory /home/ubuntu/chef-repo/cookbooks/tmpl
:
(diff output suppressed by config)
ubuntu@ws:~/chef-repo$
変数であるアトリビュートファイルです。デフォルト値を入れるので、defaultアトリビュートと命名しています。
ubuntu@ws:~/chef-repo$ chef generate attribute cookbooks/tmpl default
Compiling Cookbooks...
Recipe: code_generator::attribute
* directory[cookbooks/tmpl/attributes] action create
- create new directory cookbooks/tmpl/attributes
* template[cookbooks/tmpl/attributes/default.rb] action create
- create new file cookbooks/tmpl/attributes/default.rb
- update content in file cookbooks/tmpl/attributes/default.rb from none to e3b0c4
(diff output suppressed by config)
ubuntu@ws:~/chef-repo$
テンプレートファイルです。前述の通りtmpl.hello.erbファイルと命名しています。
ubuntu@ws:~/chef-repo$ chef generate template cookbooks/tmpl tmpl.hello.erb
Compiling Cookbooks...
Recipe: code_generator::template
* directory[cookbooks/tmpl/templates/default] action create
- create new directory cookbooks/tmpl/templates/default
* template[cookbooks/tmpl/templates/default/tmpl.hello.erb] action create
- create new file cookbooks/tmpl/templates/default/tmpl.hello.erb
- update content in file cookbooks/tmpl/templates/default/tmpl.hello.erb from none to e3b0c4
(diff output suppressed by config)
ubuntu@ws:~/chef-repo$
tmplクックブックの雛形が準備できました。
ubuntu@ws:~/chef-repo$ tree cookbooks/tmpl/
cookbooks/tmpl/
├── Berksfile
├── README.md
├── attributes
│ └── default.rb
├── chefignore
├── metadata.rb
├── recipes
│ └── default.rb
└── templates
└── default
└── tmpl.hello.erb
4 directories, 7 files
ubuntu@ws:~/chef-repo$
各雛形からクックブックを作っていきましょう。
ubuntu@ws:~/chef-repo$ vi cookbooks/tmpl/attributes/default.rb default['tmpl']['message'] = 'Hello, World!' ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ vi cookbooks/tmpl/templates/default/tmpl.hello.erb "<%= node['tmpl']['message'] %>" ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ vi cookbooks/tmpl/recipes/default.rb # # Cookbook Name:: tmpl # Recipe:: default # # Copyright (c) 2014 The Authors, All Rights Reserved. template '/tmp/hello.txt' do source 'tmpl.hello.erb' end ubuntu@ws:~/chef-repo$
ノードに適用します。
ubuntu@ws:~/chef-repo$ knife node run_list add node.example.jp 'recipe[tmpl]'
node.example.jp:
run_list:
recipe[ntp]
recipe[multi_pkgs]
recipe[tmpl]
ubuntu@ws:~/chef-repo$ knife node run_list add ws.example.jp 'recipe[tmpl]'
ws.example.jp:
run_list:
recipe[ntp]
recipe[multi_pkgs]
recipe[tmpl]
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T17:25:29+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl"] node.example.jp Synchronizing Cookbooks: node.example.jp - multi_pkgs node.example.jp - ntp node.example.jp - tmpl node.example.jp Compiling Cookbooks... node.example.jp Converging 4 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install (up to date) node.example.jp Recipe: multi_pkgs::default node.example.jp * package[nginx] action install (up to date) node.example.jp * package[redis-server] action install (up to date) node.example.jp Recipe: tmpl::default node.example.jp * template[/tmp/hello.txt] action create node.example.jp - create new file /tmp/hello.txt node.example.jp - update content in file /tmp/hello.txt from none to 3d06fb node.example.jp --- /tmp/hello.txt 2014-12-22 17:25:30.600670333 +0900 node.example.jp +++ /tmp/chef-rendered-template20141222-9137-1tt4lvn 2014-12-22 17:25:30.600670333 +0900 node.example.jp @@ -1 +1,2 @@ node.example.jp +"Hello, World!" node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 1/4 resources updated in 1.531860219 seconds ws.example.jp [2014-12-22T17:25:31+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp - multi_pkgs ws.example.jp - tmpl ws.example.jp Compiling Cookbooks... ws.example.jp Converging 4 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install (up to date) ws.example.jp Recipe: multi_pkgs::default ws.example.jp * package[nginx] action install (up to date) ws.example.jp * package[redis-server] action install (up to date) ws.example.jp Recipe: tmpl::default ws.example.jp * template[/tmp/hello.txt] action create ws.example.jp - create new file /tmp/hello.txt ws.example.jp - update content in file /tmp/hello.txt from none to 3d06fb ws.example.jp --- /tmp/hello.txt 2014-12-22 17:25:33.028000026 +0900 ws.example.jp +++ /tmp/chef-rendered-template20141222-9405-1e5lqms 2014-12-22 17:25:33.028000026 +0900 ws.example.jp @@ -1 +1,2 @@ ws.example.jp +"Hello, World!" ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 1/4 resources updated in 1.301652536 seconds ubuntu@ws:~/chef-repo$
ファイルが作成できたことを確認します。
ubuntu@ws:~/chef-repo$ knife ssh 'name:*' 'cat /tmp/hello.txt' -x ubuntu ws.example.jp "Hello, World!" node.example.jp "Hello, World!" ubuntu@ws:~/chef-repo$
テンプレートにはOhaiで収集した値を埋め込むこともできます。ここではfqdnを埋め込みます。
ubuntu@ws:~/chef-repo$ git diff cookbooks diff --git a/cookbooks/tmpl/templates/default/tmpl.hello.erb b/cookbooks/tmpl/templates/default/tmpl.hello.erb index 1c1ac75..b8087c4 100644 --- a/cookbooks/tmpl/templates/default/tmpl.hello.erb +++ b/cookbooks/tmpl/templates/default/tmpl.hello.erb @@ -1 +1 @@ -"<%= node['tmpl']['message'] %>" +<%= node['fqdn'] %> says "<%= node['tmpl']['message'] %>" ubuntu@ws:~/chef-repo$
ノードに適用します。
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T17:29:34+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl"] node.example.jp Synchronizing Cookbooks: node.example.jp - multi_pkgs node.example.jp - tmpl node.example.jp - ntp node.example.jp Compiling Cookbooks... node.example.jp Converging 4 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install (up to date) node.example.jp Recipe: multi_pkgs::default node.example.jp * package[nginx] action install (up to date) node.example.jp * package[redis-server] action install (up to date) node.example.jp Recipe: tmpl::default node.example.jp * template[/tmp/hello.txt] action create node.example.jp - update content in file /tmp/hello.txt from 3d06fb to f3a09e node.example.jp --- /tmp/hello.txt 2014-12-22 17:25:30.600670333 +0900 node.example.jp +++ /tmp/chef-rendered-template20141222-9637-g2wd8o 2014-12-22 17:29:35.516354291 +0900 node.example.jp @@ -1,2 +1,2 @@ node.example.jp -"Hello, World!" node.example.jp +node.example.jp says "Hello, World!" node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 1/4 resources updated in 1.291272443 seconds ws.example.jp [2014-12-22T17:29:36+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp - multi_pkgs ws.example.jp - tmpl ws.example.jp Compiling Cookbooks... ws.example.jp Converging 4 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install (up to date) ws.example.jp Recipe: multi_pkgs::default ws.example.jp * package[nginx] action install (up to date) ws.example.jp * package[redis-server] action install (up to date) ws.example.jp Recipe: tmpl::default ws.example.jp * template[/tmp/hello.txt] action create ws.example.jp - update content in file /tmp/hello.txt from 3d06fb to 053da1 ws.example.jp --- /tmp/hello.txt 2014-12-22 17:25:33.028000026 +0900 ws.example.jp +++ /tmp/chef-rendered-template20141222-10088-1kk0bd5 2014-12-22 17:29:37.982553342 +0900 ws.example.jp @@ -1,2 +1,2 @@ ws.example.jp -"Hello, World!" ws.example.jp +ws.example.jp says "Hello, World!" ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 1/4 resources updated in 1.348914275 seconds ubuntu@ws:~/chef-repo$
ファイルを変更できたことを確認します。
ubuntu@ws:~/chef-repo$ knife ssh 'name:*' 'cat /tmp/hello.txt' -x ubuntu ws.example.jp ws.example.jp says "Hello, World!" node.example.jp node.example.jp says "Hello, World!" ubuntu@ws:~/chef-repo$
リソース間の通信
notifiesまたはsubscribesを用いることで、設定ファイルに変更があったらサービスを再起動するといった動作を実現できます。
nginxパッケージをインストールし、待ち受けポート番号(listen_port)のみが変更できる設定ファイル(/etc/nginx/sites-available/default)を設置するクックブックを作成します。
まずnginxクックブックの雛形を作成します。
ubuntu@ws:~/chef-repo$ chef generate cookbook cookbooks/nginx
Compiling Cookbooks...
Recipe: code_generator::cookbook
* directory[/home/ubuntu/chef-repo/cookbooks/nginx] action create
- create new directory /home/ubuntu/chef-repo/cookbooks/nginx
:
ubuntu@ws:~/chef-repo$ chef generate attribute cookbooks/nginx default
Compiling Cookbooks...
Recipe: code_generator::attribute
* directory[cookbooks/nginx/attributes] action create
- create new directory cookbooks/nginx/attributes
* template[cookbooks/nginx/attributes/default.rb] action create
- create new file cookbooks/nginx/attributes/default.rb
- update content in file cookbooks/nginx/attributes/default.rb from none to e3b0c4
(diff output suppressed by config)
ubuntu@ws:~/chef-repo$ chef generate template cookbooks/nginx nginx.default.erb
Compiling Cookbooks...
Recipe: code_generator::template
* directory[cookbooks/nginx/templates/default] action create
- create new directory cookbooks/nginx/templates/default
* template[cookbooks/nginx/templates/default/nginx.default.erb] action create
- create new file cookbooks/nginx/templates/default/nginx.default.erb
- update content in file cookbooks/nginx/templates/default/nginx.default.erb from none to e3b0c4
(diff output suppressed by config)
ubuntu@ws:~/chef-repo$
実際にクックブックを作成していきます。ここではnotifiesを使用します。subscribesでも同じことが実現できますが、ここでは説明およびコード例は省略します。各自の宿題としてください。
ubuntu@ws:~/chef-repo$ vi cookbooks/nginx/attributes/default.rb default['nginx']['listen_port'] = 80 ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ vi cookbooks/nginx/templates/default/nginx.default.erb
#
# Generated by Chef for <%= node['fqdn'] %>
#
server {
listen <%= node['nginx']['listen_port'] %> default_server;
listen [::]:<%= node['nginx']['listen_port'] %> default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ =404;
}
}
ubuntu@ws:~/chef-repo$ vi cookbooks/nginx/recipes/default.rb # # Cookbook Name:: nginx # Recipe:: default # # Copyright (c) 2014 The Authors, All Rights Reserved. package 'nginx' template '/etc/nginx/sites-available/default' do source 'nginx.default.erb' notifies :restart, 'service[nginx]' end service 'nginx' do supports :restart => true action :enable end ubuntu@ws:~/chef-repo$
ノードに適用します。
ubuntu@ws:~/chef-repo$ knife node run_list add node.example.jp 'recipe[nginx]'
node.example.jp:
run_list:
recipe[ntp]
recipe[multi_pkgs]
recipe[tmpl]
recipe[nginx]
ubuntu@ws:~/chef-repo$ knife node run_list add ws.example.jp 'recipe[nginx]'
ws.example.jp:
run_list:
recipe[ntp]
recipe[multi_pkgs]
recipe[tmpl]
recipe[nginx]
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo node.example.jp [2014-12-22T18:17:40+09:00] WARN: : node.example.jp Starting Chef Client, version 11.16.4 node.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl", "nginx"] node.example.jp Synchronizing Cookbooks: node.example.jp - tmpl node.example.jp - ntp node.example.jp - multi_pkgs node.example.jp - nginx node.example.jp Compiling Cookbooks... node.example.jp [2014-12-22T18:17:41+09:00] WARN: Cloning resource attributes for package[nginx] from prior resource (CHEF-3694) node.example.jp [2014-12-22T18:17:41+09:00] WARN: Previous package[nginx]: /var/chef/cache/cookbooks/multi_pkgs/recipes/default.rb:8:in `block in from_file' node.example.jp [2014-12-22T18:17:41+09:00] WARN: Current package[nginx]: /var/chef/cache/cookbooks/nginx/recipes/default.rb:7:in `from_file' node.example.jp Converging 7 resources node.example.jp Recipe: ntp::default node.example.jp * package[ntp] action install (up to date) node.example.jp Recipe: multi_pkgs::default node.example.jp * package[nginx] action install (up to date) node.example.jp * package[redis-server] action install (up to date) node.example.jp Recipe: tmpl::default node.example.jp * template[/tmp/hello.txt] action create (up to date) node.example.jp Recipe: nginx::default node.example.jp * package[nginx] action install (up to date) node.example.jp * template[/etc/nginx/sites-available/default] action create node.example.jp - update content in file /etc/nginx/sites-available/default from 7fe53b to 97aa27 node.example.jp --- /etc/nginx/sites-available/default 2012-03-29 11:50:24.000000000 +0900 node.example.jp +++ /tmp/chef-rendered-template20141222-10157-1n5zvby 2014-12-22 18:17:42.116304044 +0900 node.example.jp @@ -1,121 +1,18 @@ : node.example.jp * service[nginx] action enable (up to date) node.example.jp * service[nginx] action restart node.example.jp - restart service service[nginx] node.example.jp node.example.jp Running handlers: node.example.jp Running handlers complete node.example.jp Chef Client finished, 2/8 resources updated in 2.850105057 seconds ws.example.jp [2014-12-22T18:17:44+09:00] WARN: : ws.example.jp Starting Chef Client, version 11.18.0.rc.1 ws.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl", "nginx"] ws.example.jp Synchronizing Cookbooks: ws.example.jp - ntp ws.example.jp - tmpl ws.example.jp - multi_pkgs ws.example.jp - nginx ws.example.jp Compiling Cookbooks... ws.example.jp [2014-12-22T18:17:45+09:00] WARN: Cloning resource attributes for package[nginx] from prior resource (CHEF-3694) ws.example.jp [2014-12-22T18:17:45+09:00] WARN: Previous package[nginx]: /var/chef/cache/cookbooks/multi_pkgs/recipes/default.rb:8:in `block in from_file' ws.example.jp [2014-12-22T18:17:45+09:00] WARN: Current package[nginx]: /var/chef/cache/cookbooks/nginx/recipes/default.rb:7:in `from_file' ws.example.jp Converging 7 resources ws.example.jp Recipe: ntp::default ws.example.jp * package[ntp] action install (up to date) ws.example.jp Recipe: multi_pkgs::default ws.example.jp * package[nginx] action install (up to date) ws.example.jp * package[redis-server] action install (up to date) ws.example.jp Recipe: tmpl::default ws.example.jp * template[/tmp/hello.txt] action create (up to date) ws.example.jp Recipe: nginx::default ws.example.jp * package[nginx] action install (up to date) ws.example.jp * template[/etc/nginx/sites-available/default] action create ws.example.jp - update content in file /etc/nginx/sites-available/default from 7fe53b to 223390 ws.example.jp --- /etc/nginx/sites-available/default 2012-03-29 11:50:24.000000000 +0900 ws.example.jp +++ /tmp/chef-rendered-template20141222-10819-d944p2 2014-12-22 18:17:45.884371929 +0900 ws.example.jp @@ -1,121 +1,18 @@ : ws.example.jp * service[nginx] action enable (up to date) ws.example.jp * service[nginx] action restart ws.example.jp - restart service service[nginx] ws.example.jp ws.example.jp Running handlers: ws.example.jp Running handlers complete ws.example.jp Chef Client finished, 2/8 resources updated in 2.687193341 seconds ubuntu@ws:~/chef-repo$
設定通りの80番ポートにアクセスできることを確認します。
ubuntu@ws:~/chef-repo$ curl http://node.example.jp <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.1.19</center> </body> </html> ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ curl http://ws.example.jp <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.1.19</center> </body> </html> ubuntu@ws:~/chef-repo$
ポート番号を8080に変更します。クックブックのアトリビュートを変更してもかまいませんが、Chef-Repoに格納してあるノード情報を編集します。
ubuntu@ws:~/chef-repo$ knife node edit node.example.jp
{
"name": "node.example.jp",
"chef_environment": "_default",
"normal": {
"nginx": {
"listen_port": 8080
},
"tags": [
]
},
"run_list": [
"recipe[ntp]",
"recipe[multi_pkgs]",
"recipe[tmpl]",
"recipe[nginx]"
]
}
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ knife node edit ws.example.jp
{
"name": "ws.example.jp",
"chef_environment": "_default",
"normal": {
"nginx": {
"listen_port": 8080
},
"tags": [
]
},
"run_list": [
"recipe[ntp]",
"recipe[multi_pkgs]",
"recipe[tmpl]",
"recipe[nginx]"
]
}
ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ git diff
diff --git a/nodes/node.example.jp.json b/nodes/node.example.jp.json
index c4c6fb5..09e752e 100644
--- a/nodes/node.example.jp.json
+++ b/nodes/node.example.jp.json
@@ -1,6 +1,9 @@
{
"name": "node.example.jp",
"normal": {
+ "nginx": {
+ "listen_port": 8080
+ },
"tags": [
]
diff --git a/nodes/ws.example.jp.json b/nodes/ws.example.jp.json
index 9043d68..76bf9b4 100644
--- a/nodes/ws.example.jp.json
+++ b/nodes/ws.example.jp.json
@@ -1,6 +1,9 @@
{
"name": "ws.example.jp",
"normal": {
+ "nginx": {
+ "listen_port": 8080
+ },
"tags": [
]
ubuntu@ws:~/chef-repo$
変更したノード情報をノードに適用します。
ubuntu@ws:~/chef-repo$ knife zero chef_client 'name:*' -x ubuntu --sudo -C 1
node.example.jp [2014-12-22T18:26:40+09:00] WARN:
:
node.example.jp Starting Chef Client, version 11.16.4
node.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl", "nginx"]
node.example.jp Synchronizing Cookbooks:
node.example.jp - multi_pkgs
node.example.jp - tmpl
node.example.jp - ntp
node.example.jp - nginx
node.example.jp Compiling Cookbooks...
node.example.jp [2014-12-22T18:26:41+09:00] WARN: Cloning resource attributes for package[nginx] from prior resource (CHEF-3694)
node.example.jp [2014-12-22T18:26:41+09:00] WARN: Previous package[nginx]: /var/chef/cache/cookbooks/multi_pkgs/recipes/default.rb:8:in `block in from_file'
node.example.jp [2014-12-22T18:26:41+09:00] WARN: Current package[nginx]: /var/chef/cache/cookbooks/nginx/recipes/default.rb:7:in `from_file'
node.example.jp Converging 7 resources
node.example.jp Recipe: ntp::default
node.example.jp * package[ntp] action install (up to date)
node.example.jp Recipe: multi_pkgs::default
node.example.jp * package[nginx] action install (up to date)
node.example.jp * package[redis-server] action install (up to date)
node.example.jp Recipe: tmpl::default
node.example.jp * template[/tmp/hello.txt] action create (up to date)
node.example.jp Recipe: nginx::default
node.example.jp * package[nginx] action install (up to date)
node.example.jp * template[/etc/nginx/sites-available/default] action create
node.example.jp - update content in file /etc/nginx/sites-available/default from 97aa27 to 3960f9
node.example.jp --- /etc/nginx/sites-available/default 2014-12-22 18:17:42.116304044 +0900
node.example.jp +++ /tmp/chef-rendered-template20141222-10563-2yu0aq 2014-12-22 18:26:41.266762936 +0900
node.example.jp @@ -3,8 +3,8 @@
node.example.jp #
node.example.jp
node.example.jp server {
node.example.jp - listen 80 default_server;
node.example.jp - listen [::]:80 default_server ipv6only=on;
node.example.jp + listen 8080 default_server;
node.example.jp + listen [::]:8080 default_server ipv6only=on;
node.example.jp
node.example.jp root /usr/share/nginx/html;
node.example.jp index index.html index.htm;
node.example.jp * service[nginx] action enable (up to date)
node.example.jp * service[nginx] action restart
node.example.jp - restart service service[nginx]
node.example.jp
node.example.jp Running handlers:
node.example.jp Running handlers complete
node.example.jp Chef Client finished, 2/8 resources updated in 2.28401369 seconds
ws.example.jp [2014-12-22T18:26:43+09:00] WARN:
:
ws.example.jp Starting Chef Client, version 11.18.0.rc.1
ws.example.jp resolving cookbooks for run list: ["ntp", "multi_pkgs", "tmpl", "nginx"]
ws.example.jp Synchronizing Cookbooks:
ws.example.jp - ntp
ws.example.jp - nginx
ws.example.jp - multi_pkgs
ws.example.jp - tmpl
ws.example.jp Compiling Cookbooks...
ws.example.jp [2014-12-22T18:26:44+09:00] WARN: Cloning resource attributes for package[nginx] from prior resource (CHEF-3694)
ws.example.jp [2014-12-22T18:26:44+09:00] WARN: Previous package[nginx]: /var/chef/cache/cookbooks/multi_pkgs/recipes/default.rb:8:in `block in from_file'
ws.example.jp [2014-12-22T18:26:44+09:00] WARN: Current package[nginx]: /var/chef/cache/cookbooks/nginx/recipes/default.rb:7:in `from_file'
ws.example.jp Converging 7 resources
ws.example.jp Recipe: ntp::default
ws.example.jp * package[ntp] action install (up to date)
ws.example.jp Recipe: multi_pkgs::default
ws.example.jp * package[nginx] action install (up to date)
ws.example.jp * package[redis-server] action install (up to date)
ws.example.jp Recipe: tmpl::default
ws.example.jp * template[/tmp/hello.txt] action create (up to date)
ws.example.jp Recipe: nginx::default
ws.example.jp * package[nginx] action install (up to date)
ws.example.jp * template[/etc/nginx/sites-available/default] action create
ws.example.jp - update content in file /etc/nginx/sites-available/default from 223390 to f0e3c4
ws.example.jp --- /etc/nginx/sites-available/default 2014-12-22 18:17:45.884371929 +0900
ws.example.jp +++ /tmp/chef-rendered-template20141222-11323-n203be 2014-12-22 18:26:44.702071618 +0900
ws.example.jp @@ -3,8 +3,8 @@
ws.example.jp #
ws.example.jp
ws.example.jp server {
ws.example.jp - listen 80 default_server;
ws.example.jp - listen [::]:80 default_server ipv6only=on;
ws.example.jp + listen 8080 default_server;
ws.example.jp + listen [::]:8080 default_server ipv6only=on;
ws.example.jp
ws.example.jp root /usr/share/nginx/html;
ws.example.jp index index.html index.htm;
ws.example.jp * service[nginx] action enable (up to date)
ws.example.jp * service[nginx] action restart
ws.example.jp - restart service service[nginx]
ws.example.jp
ws.example.jp Running handlers:
ws.example.jp Running handlers complete
ws.example.jp Chef Client finished, 2/8 resources updated in 2.440957849 seconds
ubuntu@ws:~/chef-repo$
設定ファイルの変更とnginxの再起動が行われました。設定通りの8080番ポートにアクセスできることを確認します。
ubuntu@ws:~/chef-repo$ curl http://node.example.jp curl: (7) couldn't connect to host ubuntu@ws:~/chef-repo$ curl http://node.example.jp:8080 <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.1.19</center> </body> </html> ubuntu@ws:~/chef-repo$
ubuntu@ws:~/chef-repo$ curl http://ws.example.jp curl: (7) couldn't connect to host ubuntu@ws:~/chef-repo$ curl http://ws.example.jp:8080 <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.1.19</center> </body> </html> ubuntu@ws:~/chef-repo$
まとめ
Knife-ZeroはChef Serverを用いずに、手軽にChefによるInfrastructure as Codeを実践できる大変有用なツールです。Chef Serverによる使い勝手とまったく変わらない上に、管理規模が大きくなったらChef Serverへの移行も簡単に行えるという利点もあります。
Infrastructure as CodeをやってみたいけれどChef Serverはちょっと手に余るな、という方は、Knife-Zeroから始めてみてはいかがでしょう。本稿はなるべく平易となるように心掛けて記述したつもりです。是非その便利さを実感してみてください。
