前回 Chefのローカルモードだけでリモートサーバを運用してみようと、Knife-Zeroを作った。Nodeの構成情報もとれるよ。 - Qiita の続きといえば続きです。
Knife-Zeroのページはこちら。 http://knife-zero.github.io/ja/
Chef11.xからローカルモードというのが加わりました。Chef-Client/Server環境の簡易版であり、Soloの代わりでもあります。
Chef-Soloからの乗り換えとしてChef-Zero(ローカルモード)検索が多いようなので、この追記を先頭に移動
このサンプルではSSH越しにローカルモードを実行していますが、単にサーバ側にChef-Repoを置いてローカルモードをしたい場合、
Chefをインストール後にChef-Repoのディレクトリに移動してchef-client -z
でOKです。
SoloみたいにCookbookPathが無いとかそういうエラーもなく、簡単に実行できます。
ついでに、Knife-Soloは無くならないので、乗り換え必須ではありません。追記1: で、Soloどうなるのよってのはこちらに書いたので合わせてどうぞ。
追記2: 200ストックの通知が来たので、コマンド等を現行(1.8.0時)向けに少し修正
追記3: Knife-Zeroのページ。
概要
今回はローカルモードを主眼において、そのままChef-Serverレスでインフラを管理していこうという試みのチュートリアルです。
本文はだいたいこんな感じですすめます。
- ローカルモードでのChefのインフラ構築ワークフロー
- Knife-Sakuraでサーバ調達 (※ optional)
- Knife-Zero
ちなみに作業後のディレクトリ構成等は higanworks/chef_localmode_tutorial にアップしているので、セットアップ代わりにこちらをクローンしてから始めてもよいです。
セットアップ
Rubyプロジェクトぽく進めます、必要なディレクトリを用意して。
$ mkdir my_chefrepo
$ cd my_chefrepo/
$ bundle init
Writing new Gemfile to /Users/sawanoboriyu/my_chefrepo/Gemfile
Gemfileに使うGemsを記述して。
source "https://rubygems.org"
gem 'chef'
gem 'knife-zero'
gem 'knife-sakura'
Bundleします。
...
Installing chef (11.14.6)
Installing knife-zero (0.1.2)
...
Installing knife-sakura (0.0.2)
Your bundle is complete!
It was installed into ./vendor/bundle
ちなみにknife-zero(0.1.2), knife-sakura(0.0.2)以上が必須です。
--binstubs
しているので、カレントの./bin
に実行ファイルが来ます。
$ tree . -I vendor
.
├── Gemfile
├── Gemfile.lock
└── bin
├── chef-apply
├── chef-client
├── chef-service-manager
├── chef-shell
├── chef-solo
├── chef-zero
├── coderay
├── erubis
├── ffi-yajl-bench
├── fog
├── htmldiff
├── knife
├── ldiff
├── nokogiri
├── ohai
├── pry
├── rackup
├── restclient
└── shef
ローカルモードの準備
knifeコマンドのデフォルト動作をローカルモードにするためknife.rb
を作ります。この記述はコマンドラインの--local-mode
オプションと同じ働きです。
$ mkdir .chef
$ echo 'local_mode true' > .chef/knife.rb
これでローカルモードで動作するようになります。
Chef-Client/Server環境のコマンド、knife environment list
等を叩いてみましょう。
$ ./bin/knife environment list -V
WARN: No cookbooks directory found at or above current directory. Assuming /Users/sawanoboriyu/Dev/worktmp/my_chefrepo.
INFO: Starting chef-zero on host localhost, port 8889 with repository at repository at /Users/sawanoboriyu/Dev/worktmp/my_chefrepo
One version per cookbook
$ ./bin/knife node list -V
WARN: No cookbooks directory found at or above current directory. Assuming /Users/sawanoboriyu/Dev/worktmp/my_chefrepo.
INFO: Starting chef-zero on host localhost, port 8889 with repository at repository at /Users/sawanoboriyu/Dev/worktmp/my_chefrepo
One version per cookbook
この記述 Starting chef-zero on host localhost, port 8889 with repository at repository at /Users/sawanoboriyu/Dev/worktmp/my_chefrepo
がポイントです。
ローカルのディレクトリをベースにChefZeroが起動して、ChefServerの代わりをしています。
なおWARNが出ていますが、単に./cookbooks
ディレクトリが無いためです。
あとで勝手にできるので、これ以降WARN: No cookbooks directory〜
は省略します。
Environmentをつくる
新しいEnvironment、development
を作ってみましょう。knife environment create development
です。
$ ./bin/knife environment create development
## ---エディタが開く
{
"name": "development",
"description": "",
"cookbook_versions": {
},
"json_class": "Chef::Environment",
"chef_type": "environment",
"default_attributes": {
},
"override_attributes": {
}
}
## --- 保存して終了
Created development
リストに出るようになりました。
$ ./bin/knife environment list
development
ファイルとして保存されています。
$ tree environments/
environments/
└── development.json
knife search
でenvironment
を対象に探せばちゃんと見つかります。
$ ./bin/knife search environment 'name:dev*'
1 items found
chef_type: environment
cookbook_versions:
default_attributes:
description:
json_class: Chef::Environment
name: development
override_attributes:
余談:ChefZeroを単体で上げる
knife serve
knife serve
サブコマンドを使うと、ローカルのディレクトリをChef-Repoに見立てたChefZeroが起動します。
※ 通常のchef-zeroコマンドではすべてオンメモリで、リソース空っぽで起動して終了時に何も保存しません。$ ./bin/knife serve Serving files from: repository at /Users/sawanoboriyu/Dev/worktmp/my_chefrepo One version per cookbook >> Starting Chef Zero (v2.2)... >> WEBrick (v1.3.1) on Rack (v1.5) is listening at http://localhost:8889 >> Press CTRL+C to stop
この状態なら、Chef-Serveに問い合わせる要領でオブジェクトを取得することもできるので、色々動作確認してみたい場合は使える機能です。
$ curl -H 'Accept: application/json' localhost:8889/environments { "development": "http://localhost:8889/environments/development" }
Accept: application/json
ヘッダを忘れずに。$ curl -H 'Accept: application/json' localhost:8889/environments/development { "name": "development", "description": "", "cookbook_versions": { }, "json_class": "Chef::Environment", "chef_type": "environment", "default_attributes": { }, "override_attributes": { } }
ついでに言うと、これらのオブジェクトはファイルベースなので
rm
でもサクッと消せます。
Data Bagをつくる
同様にData Bagを作ってみます。
$ ./bin/knife data bag create samplebag sampleitem
## ---エディタが開くので編集する
{
"id": "sampleitem",
"foo": "bar"
}
## --- 保存して終了
Created data_bag[samplebag]
Created data_bag_item[sampleitem]
リストOK。
$ ./bin/knife data bag list
samplebag
$ ./bin/knife data bag show samplebag sampleitem
foo: bar
id: sampleitem
これもファイルとして保存されています。
$ tree data_bags/
data_bags/
└── samplebag
└── sampleitem.json
1 directory, 1 file
追記:
この段落をサーバ側で実行すれば、単体でChef-Soloを実行するのとだいたいおなじ感覚になります。
適当なNodeを用意する knife-sakura
ではChefの管理対象とするリソースとして、今回はLinuxサーバを用意します。
サーバはSSHが繋がるならば既存のものでも良いですし、aws cliでもterraformでも、ローカルのVagrantでも好きなように調達してください。
さて、今回はせっかくなのでなんかしらクラウドで。
Knifeのプラグインを利用してさくらのクラウドから調達します。みなさんたいていクーポンが遊んでいるでしょう。
- 参考&詳しい使い方は: cl-lab-k/knife-sakura
Vagrant+VirtualBoxでマシンを調達するならば Vagrantでknife-zeroを使うためのベストプラクティス | 割り箸ポテチ も参考になるでしょう。
さくらのクラウド(knife-sakura)セットアップ
.chef/knife.rb
をちょろちょろっと編集して、環境変数をエクスポートしておきます。
local_mode true
## SakuraCloud credentials
knife[:sakuracloud_api_token] = ENV['SAKURACLOUD_API_TOKEN']
knife[:sakuracloud_api_token_secret] = ENV['SAKURACLOUD_API_TOKEN_SECRET']
knife[:sakuracloud_ssh_key] = ENV['SAKURACLOUD_USER_KEY_ID']
さくらのクラウド(knife-sakura)でサーバ調達
サーバを調達するには、knife sakura server create
です。
server1,server2,server3として、3台ほど調達を試みます。
ついでに--no-bootstrap
として、Chef-Server連携用のbootstrapをキャンセルします。 (※ この後のknife-zeroのため)
$ for x in {1..3} ; do echo ./bin/knife sakura server create --server-plan 1001 --disk-plan 4 --source-archive 112500463685 --no-bootstrap -n server${x}; done
Instance ID: 112600642xxx
Server Plan: プラン/1Core-1GB
Public IP Address: 133.242.231.xxx
Instance ID: 112600642xxx
Server Plan: プラン/1Core-1GB
Public IP Address: 133.242.230.xxx
Instance ID: 112600642xxx
Server Plan: プラン/1Core-1GB
Public IP Address: 133.242.237.xxx
新鮮なサーバが3台とれました。
$ ./bin/knife sakura server list
ID Name Status Created at
112600642xxx 1a966089-d6bb-42cb-a7df-08beda84cxxx up 2014-08-25Txx:xx:xx+09:00
112600642xxx aa897042-ecf0-49fd-9eaa-05dea1be3xxx up 2014-08-25Txx:xx:xx+09:00
112600642xxx 9bd5969f-a682-465d-b3c0-6e86148a4xxx up 2014-08-25Txx:xx:xx+09:00
じゃあこれらをChefローカルモードの管理下においていきます。
knife-zeroでnodeを管理下に
knife zero bootstrap
をすることで、前回のようにします。
-E development
をつけて、Environent => development
のノードとして登録しましょう。
## server1をbootstrap
$ ./bin/knife zero bootstrap 133.242.231.xxx -x ubuntu -E development --sudo -N server1
...
133.242.231.xxx Chef Client finished, 0/0 resources updated in 3.692237549 seconds
## server2をbootstrap
$ ./bin/knife zero bootstrap 133.242.230.xxx -x ubuntu -E development --sudo -N server2
...
133.242.230.xxx Chef Client finished, 0/0 resources updated in 3.692237549 seconds
## server3をbootstrap
$ ./bin/knife zero bootstrap 133.242.237.xxx -x ubuntu -E development --sudo -N server3
...
133.242.237.xxx Chef Client finished, 0/0 resources updated in 3.692237549 seconds
無事Zero Bootstrapが終わったので、nodeのリストが取れることを確認しましょう。
$ ./bin/knife node list
server1
server2
server3
もちろんファイルとしてローカルにありつつ。
$ tree nodes/
nodes/
├── server1.json
├── server2.json
└── server3.json
0 directories, 3 files
knife node show
などで情報を表示することができます。
$ ./bin/knife node show server1
Node Name: server1
Environment: development
FQDN: localhost
IP: 133.242.231.xxx
Run List:
Roles:
Recipes:
Platform: ubuntu 12.04
Tags:
Environent => development
なNodeをサーチすれば、それぞれがちゃんと引っかかりますね。
$ ./bin/knife search node 'chef_environment:development'
3 items found
Node Name: server1
Environment: development
FQDN: localhost
IP: 133.242.231.xxx
Run List:
Roles:
Recipes:
Platform: ubuntu 12.04
Tags:
Node Name: server2
Environment: development
FQDN: localhost
IP: 133.242.230.xxx
Run List:
Roles:
Recipes:
Platform: ubuntu 12.04
Tags:
Node Name: server3
Environment: development
FQDN: localhost
IP: 133.242.237.xxx
Run List:
Roles:
Recipes:
Platform: ubuntu 12.04
Tags:
標準のknife ssh
もローカルモードで動作させれば、このとおり。
$ ./bin/knife ssh 'chef_environment:development' -x ubuntu --attribute ipaddress uptime
133.242.231.xxx xx:40:51 up 1:41, 1 user, load average: 0.00, 0.01, 0.05
133.242.230.xxx xx:40:51 up 1:40, 1 user, load average: 0.00, 0.02, 0.05
133.242.237.xxx xx:40:51 up 1:38, 1 user, load average: 0.00, 0.02, 0.05
※ 標準で接続先に使われるFQDNが全部localhost
なので、--attribute ipaddress
を指定してSSHの接続対象をIPにしています。
追記: Knife-Zero 1.8.0で、Bootstrapで指定したIPを
node.knife_zero.host
で保持するようにしました。
IPアドレスを複数持つ一部の環境ではnode.ipaddress
が手元からつながらない場合があるため、Bootstrapでの接続実績を使い回しできるようにする更新です。
そっちを使う場合は、--attribute ipaddress
の代わりに、--attribute knife_zero.host
でどうぞ。
Cookbookを作ってレシピを適用、Data Bag, SearchもOK
knife cookbook create
でCookbookを作りましょう。
$ ./bin/knife cookbook create demobook
** Creating cookbook demobook
** Creating README for cookbook: demobook
** Creating CHANGELOG for cookbook: demobook
** Creating metadata for cookbook: demobook
local_mode
なので./cookbooks/
ディレクトリを自動でつくって、雛形をおいてくれます。
$ tree cookbooks/
cookbooks/
└── demobook
├── CHANGELOG.md
├── README.md
├── attributes
├── definitions
├── files
│ └── default
├── libraries
├── metadata.rb
├── providers
├── recipes
│ └── default.rb
├── resources
└── templates
└── default
11 directories, 4 files
Data Bagを使うレシピ
C/S環境と同様にかつ、ノード側に特にプラグイン無しでData Bagが利用できることを確認するため、次のようなRecipeを作りました。
text = data_bag_item('samplebag', 'sampleitem')
file '/tmp/from_databag.txt' do
content text['foo']
end
Searchを使うレシピ
同様にSearchが利用できることを確認するため、次のようなRecipeを作りました。
nodes = search(:node, "chef_environment:#{node.chef_environment}")
list = nodes.map {|n| n.to_s}
file '/tmp/nodes_from_search.txt' do
content list.join("\n")
end
ランリストをまとめるRoleを作る
Environemntなどと同様に、knife role create
でRoleを作ります。
$ ./bin/knife role create demorole
## ---エディタが開く
{
"name": "demorole",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
},
"chef_type": "role",
"run_list": [
"demobook::data_bag", ## ここを追記
"demobook::search" ## ここを追記
],
"env_run_lists": {
}
}
## --- 保存して終了
Created role[demorole]
role show
で確認したりも可と。
$ ./bin/knife role show demorole
chef_type: role
default_attributes:
description:
env_run_lists:
json_class: Chef::Role
name: demorole
override_attributes:
run_list:
recipe[demobook::data_bag]
recipe[demobook::search]
server1
にrole[demorole]
の役割を与えてみましょう。
knife node run_list add
です。
$ knife node run_list add server1 'role[demorole]'
server1:
run_list: role[demorole]
適用するにはまたKnife-Zeroで作った拡張のknife zero converge
でOKです。
まあポートフォワードを付けてChef-Clientを叩いてくるだけなのですが。
追記:
zero chef_client
はzero converge
に(主に気分で)変えました。zero chef_client
も使えます。
$ ./bin/knife zero converge 'name:server1' -x ubuntu --sudo --attribute ipaddress
133.242.231.xxx Starting Chef Client, version 11.14.6
## RunListからCookbookを取得する
133.242.231.xxx resolving cookbooks for run list: ["demobook::data_bag", "demobook::search"]
133.242.231.xxx Synchronizing Cookbooks:
133.242.231.xxx - demobook
133.242.231.xxx Compiling Cookbooks...
133.242.231.xxx Converging 2 resources
## demobook::data_bagの実行
133.242.231.xxx Recipe: demobook::data_bag
133.242.231.xxx * file[/tmp/from_databag.txt] action create
133.242.231.xxx - create new file /tmp/from_databag.txt
133.242.231.xxx - update content in file /tmp/from_databag.txt from none to fcde2b
133.242.231.xxx --- /tmp/from_databag.txt 2014-08-25 xx:15:49.135991498 +0900
133.242.231.xxx +++ /tmp/.from_databag.txt20140825-3969-1tnpdkw 2014-08-25 xx:15:49.135991498 +0900
133.242.231.xxx @@ -1 +1,2 @@
133.242.231.xxx +bar ## Data Bagの中身をファイルに出力
## demobook::searchの実行
133.242.231.xxx Recipe: demobook::search
133.242.231.xxx * file[/tmp/nodes_from_search.txt] action create
133.242.231.xxx - create new file /tmp/nodes_from_search.txt
133.242.231.xxx - update content in file /tmp/nodes_from_search.txt from none to 37ab54
133.242.231.xxx --- /tmp/nodes_from_search.txt 2014-08-25 xx:15:49.139991498 +0900
133.242.231.xxx +++ /tmp/.nodes_from_search.txt20140825-3969-ln7sth 2014-08-25 xx:15:49.139991498 +0900
133.242.231.xxx @@ -1 +1,4 @@ ## Searchの結果をファイルに出力
133.242.231.xxx +node[server1]
133.242.231.xxx +node[server2]
133.242.231.xxx +node[server3]
133.242.231.xxx
133.242.231.xxx Running handlers:
133.242.231.xxx Running handlers complete
133.242.231.xxx Chef Client finished, 2/2 resources updated in 4.011358121 seconds
Data Bag,Searchの機能がちゃんと使えていることがわかりますね。
ちなみにローカルモードでknife status
も有効です。
最後にknife zero converge
を実行したのが何時なのかわかって助かりますね。
$ ./bin/knife status
47 minutes ago, server2, localhost, 133.242.230.xxx, ubuntu 12.04.
45 minutes ago, server3, localhost, 133.242.237.xxx, ubuntu 12.04.
6 minutes ago, server1, localhost, 133.242.231.xxx, ubuntu 12.04.
最後にserver1
の現状をnode show
で確認してチュートリアルをおわりましょう。
$ ./bin/knife node show server1
Node Name: server1
Environment: development
FQDN: localhost
IP: 133.242.231.xxx
Run List: role[demorole]
Roles: demorole
Recipes: demobook::data_bag, demobook::search
Platform: ubuntu 12.04
Tags:
ワークフローの補足
ここで紹介しているワークフローは先日出版された『Chef活用ガイド』の内容を踏襲しています。
Chef-Solo系では難しかったワークフローだったのですが、ローカルモードを上手く使えばChef-Serverが無くてもむしろ書籍の内容をほぼ100%実践できます。
書中でもChef-Serverについて配布用のハブであり、情報の集約をするとしていますが、ローカルモード+Knife-Zeroがその役割を全部担える以上、Chef-Server本体は特に必要ありませんね。
おわりに
この例ではChefなので、ローカルのディレクトリをChef-Repoとしてだけ扱いました。ローカルディレクトリで完結することにはそれなりに意味があります、他のツールと組み合わせやすいんですよね。
なにかしらCLIでs3のバケットを確保してもよし、route53やdnsimpleのCLIでDNSをいじっても良いし、kumogataでCloudFormationを作ってみたりVagrantやTerraformでDigital Oceanのホストを作ったりherokuにアプリをおいてもOK。
で、Recipeが使いたい、構成情報をとっておきたいといったノードに対してのみChefをつかったり、Chef-MetalやChef-Container(Docker)と合わせるのも良いでしょう。
Test-KitchenやServerspecのテストコードをいれて、テストが通ったらほぼシームレスにNode(Searchで抽出)に適用するようなフローも可能です。
リソースが確保できるか/それがどこにあるか、どのようにリソースを使うか/使わてれいるか、またそれらはクエリ可能か、とこういった概ね現状がわかる情報をふくめたインフラの構成内容をツールで管理しつつGit等で追跡できるようになって、Infrastructure as Codeってやつが捗るんじゃないかと思います。