「初老丸の独り Advent calendar 2015」の十九日目の記事です。
tl;dr
Chef 等の構成管理ツールの使い方をすっかり忘れていることに気付いたので手を動かして再入門してみることにした。
ちなみに、自分の Chef 知識は 2013 年位で止まっているので、階級的には Hello World 準一級(そこそこ初心者)であるので記事内の用語などについては誤りなどがあるかもしれないので注意。
参考
- https://github.com/higanworks/knife-zero/
- http://www.creationline.com/lab/9853
- http://knowledge.sakura.ad.jp/tech/2708/
今回の目標
- Chef-Client のローカルモードを体感する
- knife zero を利用してリモートホストにレシピを適用する
今回の環境
- Workstation
$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=14.04 DISTRIB_CODENAME=trusty DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS" $ chef-client --version Chef: 12.5.1
$ knife ssh 'name:ip-xx-x-x-xx.ap-northeast-1.compute.internal' --attribute knife_zero.host -x ubuntu 'cat /etc/lsb-release' xx.xxx.xx.xx DISTRIB_ID=Ubuntu xx.xxx.xx.xx DISTRIB_RELEASE=14.04 xx.xxx.xx.xx DISTRIB_CODENAME=trusty xx.xxx.xx.xx DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS" $ knife ssh 'name:ip-xx-x-x-xx.ap-northeast-1.compute.internal' --attribute knife_zero.host -x ubuntu 'chef-client --version' xx.xxx.xx.xx Chef: 12.5.1
今回の教材
EC2 を構築するための terraform テンプレートのみ。
早速、t2.nano を使った。
Chef-Client のローカルモードを体感する
ChefDk のインストール
Chef をサクッと始めたい場合には Chef 社が配布する ChefDk(Chef Development Kit)を利用するのが手っ取り早いようだ。
上記から環境に合わせたセットアップファイルをダウンロードしておく。
$ wget https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/12.04/x86_64/chefdk_0.10.0-1_amd64.deb
$ sudo dpkg -i chefdk_0.10.0-1_amd64.deb
インストールが完了したら chef-client のバージョンを確認する。
$ chef-client --version
Chef: 12.5.1
はじめての Chef リポジトリ
ChefDk のインストールが終了したら Chef の Cookbook を管理する Chef リポジトリを作成する。Chef リポジトリの作成には chef generate
コマンドを利用するとよさそう。
$ chef generate repo chef-repo
カレントディレクトリに chef-repo
というリポジトリが作成されたのでディレクトリ構造を見てみる。
$ tree --charset=x chef-repo chef-repo |-- chefignore |-- cookbooks | |-- example | | |-- attributes | | | `-- default.rb | | |-- metadata.rb | | |-- README.md | | `-- recipes | | `-- default.rb | `-- README.md |-- data_bags | |-- example | | `-- example_item.json | `-- README.md |-- environments | |-- example.json | `-- README.md |-- LICENSE |-- README.md `-- roles |-- example.json
既に example という Cookbook が作成されている。
初めての Chef-Client ローカルモード
作成した Chef-repo に移動して以下のように Chef-Client をローカルモードで実行してみる。
$ chef-client -z -o example
以下のように出力される。
Starting Chef Client, version 12.5.1 [2015-12-19T19:36:26+09:00] WARN: Run List override has been provided. [2015-12-19T19:36:26+09:00] WARN: Original Run List: [] [2015-12-19T19:36:26+09:00] WARN: Overridden Run List: [recipe[example]] resolving cookbooks for run list: ["example"] Synchronizing Cookbooks: - example (1.0.0) Compiling Cookbooks... Converging 1 resources Recipe: example::default * log[Welcome to Chef, Sam Doe!] action write [2015-12-19T19:36:26+09:00] WARN: Skipping final node save because override_runlist was given Running handlers: Running handlers complete Chef Client finished, 1/1 resources updated in 01 seconds
ローカルホストに対して log リソースを使ったレシピが適用された。おお、簡単。
ちなみに、前後するが -z
と -o
オプションについて確認する。
$ chef-client --help 2>&1 | egrep '\-o|\-z' (snip) -z, --local-mode Point chef-client at local repository (snip) -o RunlistItem,RunlistItem..., Replace current run list with specified items for a single run --override-runlist
-z
オプションがローカルモード、-o
で適用するレシピや role を直接指定している。
以下のように knife コマンドについてもローカルモードで動作するとのことなので、node のリストについても取得することが出来る。
$ knife node list
vagrant-ubuntu-trusty-64
おお。確認してみるとレシピを適用した段階で自動的に chef-repo/nodes/
以下にローカルホストの情報を登録してくれていた。
$ tree --charset=x chef-repo chef-repo |-- chefignore |-- cookbooks | |-- example | | |-- attributes | | | `-- default.rb | | |-- metadata.rb | | |-- README.md | | `-- recipes | | `-- default.rb | `-- README.md |-- data_bags | |-- example | | `-- example_item.json | `-- README.md |-- environments | |-- example.json | `-- README.md |-- LICENSE |-- nodes | `-- vagrant-ubuntu-trusty-64.json |-- README.md `-- roles |-- example.json `-- README.md 9 directories, 15 files
尚、Chef-Client のローカルモードについては以下の記事を参考にさせて頂いた。
knife zero を利用してリモートホストにレシピを適用する
knife zero に関する情報
knife zero に関する情報は検索すると多くの情報を目にすることが出来たが、まずは以下の公式ドキュメントと記事を読むと良いと思った。
レシピをリモートホストに適用するまで(ざっくり)
で、Chef-Client を体感したところでリモートホストに knife zero を使ってレシピを適用するまでの流れを整理してみる。
- Workstation で Chef を使えるようにする(ChefDk をインストールする)→済んでる
knife zero
をインストールするknife zero bootstrap
でリモートホストに Chef-Client をインストールする- 対象ノードに適用する cookbook を追加する
knife zero converge --why-run
で確認knife zero converge
でリモートホストに適用する- 余裕があれば Cookbook を追加してみる
ということで、上記の流れに沿ってやってみる。
knife zero のインストールと knife の設定
以下のように knife zero をインストールする。
$ chef gem install knife-zero
合わせて knife.rb に以下を設定する。
$ cd chef-repo $ cat knife.rb current_dir = File.absolute_path( File.dirname(__FILE__) ) cookbook_path ["#{current_dir}/cookbooks"] node_path "#{current_dir}/nodes" role_path "#{current_dir}/roles" ssl_verify_mode :verify_peer local_mode true knife[:use_sudo] = true knife[:identity_file] = "~/.ssh/key.pem"
key.pem
は対象のリモートホストに合わせたキーのファイル名を指定すること。
リモートホストの構築
リモートホストの構築には terraform を利用する。以下のように EC2 を terraform で作成しておく。(教材を利用する前提)
$ make tf-apply
以下のようにインスタンスのグローバル IP とインスタンス ID が出力されるので控えておく。
Outputs: EC2 IP address = xxx.xxx.xxx.xxx EC2 Instance ID = i-xxxxxxxx
リモートホストに Chef-Client をインストールする
インスタンスの構築が完了したら Chef-Client をインストールする。インストールは knife zero bootstrap
を利用する。
$ knife zero bootstrap xxx.xxx.xxx.xxx -i ~/.ssh/key.pem -x ubuntu --sudo
以下のように chef-repo/nodes 以下にノード情報が作成されている。
$ cd chef-repo $ ls -l nodes/ip-xx-x-x-xx.ap-northeast-1.compute.internal.json
以下のように JSON ファイルになっている。
$ cat nodes/ip-xx-x-x-xx.ap-northeast-1.compute.internal.json { "name": "ip-xx-x-x-xx.ap-northeast-1.compute.internal", "normal": { "knife_zero": { "host": "xx.xxx.xx.xx" }, "tags": [ ] }, (snip)
リモートホストに適用したいレシピを登録する
インスタンスに Chef-Client のインストールが完了したら、適用したいレシピを登録する。登録には knife node run_list add
を利用する。
$ knife node run_list add -z ip-xx-x-x-xx.ap-northeast-1.compute.internal recipe[example]
以下のように出力される。
ip-xx-x-x-xx.ap-northeast-1.compute.internal: run_list: recipe[example]
そして、以下のようにノード情報の JSON ファイルに run_list
が追加されている。
$ cd chef-repo $ cat nodes/ip-xx-x-x-xx.ap-northeast-1.compute.internal.json (snip) }, "run_list": [ "recipe[example]" ] }
knife zero converge --why-run で適用されるレシピを確認する
まずはレシピがちゃんと適用されるかを確認してみる。
$ knife zero converge 'name:ip-xx-x-x-xx.ap-northeast-1.compute.internal' --attribute knife_zero.host -x ubuntu--why-run
以下のように出力される。
xx.xxx.xx.xx Starting Chef Client, version 12.5.1 xx.xxx.xx.xx resolving cookbooks for run list: ["example"] xx.xxx.xx.xx Synchronizing Cookbooks: xx.xxx.xx.xx - example (1.0.0) xx.xxx.xx.xx Compiling Cookbooks... xx.xxx.xx.xx Converging 1 resources xx.xxx.xx.xx Recipe: example::default xx.xxx.xx.xx * log[Welcome to Chef, Sam Doe!] action write xx.xxx.xx.xx xx.xxx.xx.xx [2015-12-19T11:10:04+00:00] WARN: In whyrun mode, so NOT performing node save. xx.xxx.xx.xx xx.xxx.xx.xx Running handlers: xx.xxx.xx.xx Running handlers complete xx.xxx.xx.xx Chef Client finished, 1/1 resources would have been updated
よしよし、うまくいくようだ。
knife zero converge でリモートホストに適用する
本番。以下のように実行する。
knife zero converge 'name:ip-xx-x-x-xx.ap-northeast-1.compute.internal' --attribute knife_zero.host -x ubuntu -i ~/.ssh/key.pem --sudo
以下のように出力される。
xx.xxx.xx.xx Starting Chef Client, version 12.5.1 xx.xxx.xx.xx resolving cookbooks for run list: ["example"] xx.xxx.xx.xx Synchronizing Cookbooks: xx.xxx.xx.xx - example (1.0.0) xx.xxx.xx.xx Compiling Cookbooks... xx.xxx.xx.xx Converging 1 resources xx.xxx.xx.xx Recipe: example::default xx.xxx.xx.xx * log[Welcome to Chef, Sam Doe!] action write xx.xxx.xx.xx xx.xxx.xx.xx xx.xxx.xx.xx Running handlers: xx.xxx.xx.xx Running handlers complete xx.xxx.xx.xx Chef Client finished, 1/1 resources updated in 01 seconds
おけ、おけ。
調子に乗って Cookbook を追加して別のレシピを適用してみる
まずは以下のように新しい Cookbook をこさえる。
$ cd chef-repo $ knife cookbook create helloworld -o ./cookbooks/
以下のように出力される。
** Creating cookbook helloworld in /home/vagrant/git/oreno-chef-2015/chef-repo/cookbooks ** Creating README for cookbook: helloworld ** Creating CHANGELOG for cookbook: helloworld ** Creating metadata for cookbook: helloworld
レシピ(chef-repo/cookbooks/helloworld/recipes/default.rb)は以下のように記載。
log "Welcome to Chef, #{node["example"]["name"]}!" do level :info end
レシピから呼び出されるアトリビュート(chef-repo/cookbooks/helloworld/attributes/default.rb)は以下のように記載。
default["example"]["name"] = "Komanechi!!!!"
先ほどと同様に knife node run_list add
を利用して対象のノードの run_list
にレシピを追加する。
$ knife node run_list add -z ip-xx-x-x-xx.ap-northeast-1.compute.internal recipe[helloworld]
以下のように出力される。
ip-xx-x-x-xx.ap-northeast-1.compute.internal: run_list: recipe[example] recipe[helloworld]
そして...why-run
からの適用。(ここからはダイジェストで)
# # why-run # $ knife zero converge 'name:ip-xx-x-x-xx.ap-northeast-1.compute.internal' --attribute knife_zero.host -x ubuntu --why-run xx.xxx.xx.xx Starting Chef Client, version 12.5.1 xx.xxx.xx.xx resolving cookbooks for run list: ["example", "helloworld"] xx.xxx.xx.xx Synchronizing Cookbooks: xx.xxx.xx.xx - helloworld (0.1.0) xx.xxx.xx.xx - example (1.0.0) xx.xxx.xx.xx Compiling Cookbooks... xx.xxx.xx.xx Converging 2 resources xx.xxx.xx.xx Recipe: example::default xx.xxx.xx.xx * log[Welcome to Chef, Komanechi!!!!!] action write xx.xxx.xx.xx xx.xxx.xx.xx Recipe: helloworld::default xx.xxx.xx.xx * log[Welcome to Chef, Komanechi!!!!!] action write xx.xxx.xx.xx xx.xxx.xx.xx [2015-12-19T11:22:21+00:00] WARN: In whyrun mode, so NOT performing node save. xx.xxx.xx.xx xx.xxx.xx.xx Running handlers: xx.xxx.xx.xx Running handlers complete xx.xxx.xx.xx Chef Client finished, 2/2 resources would have been updated # # 適用 # $ knife zero converge 'name:ip-xx-x-x-xx.ap-northeast-1.compute.internal' --attribute knife_zero.host -x ubuntu xx.xxx.xx.xx Starting Chef Client, version 12.5.1 xx.xxx.xx.xx resolving cookbooks for run list: ["example", "helloworld"] xx.xxx.xx.xx Synchronizing Cookbooks: xx.xxx.xx.xx - example (1.0.0) xx.xxx.xx.xx - helloworld (0.1.0) xx.xxx.xx.xx Compiling Cookbooks... xx.xxx.xx.xx Converging 2 resources xx.xxx.xx.xx Recipe: example::default xx.xxx.xx.xx * log[Welcome to Chef, Komanechi!!!!!] action write xx.xxx.xx.xx xx.xxx.xx.xx Recipe: helloworld::default xx.xxx.xx.xx * log[Welcome to Chef, Komanechi!!!!!] action write xx.xxx.xx.xx xx.xxx.xx.xx xx.xxx.xx.xx Running handlers: xx.xxx.xx.xx Running handlers complete xx.xxx.xx.xx Chef Client finished, 2/2 resources updated in 01 seconds
helloworld が適用されている。(example と同じアトリビュートを見ているので出力は同じ)
その他
knife search の Attribute 指定
name
$ knife search node 'name:*' --attribute name 2 items found ip-xx-x-x-xx.ap-northeast-1.compute.internal: name: ip-xx-x-x-x.ap-northeast-1.compute.internal vagrant-ubuntu-trusty-64: name: vagrant-ubuntu-trusty-64
knife_zero.host
$ knife search node 'name:*' --attribute knife_zero.host 2 items found ip-xx-x-x-xx.ap-northeast-1.compute.internal: knife_zero.host: xx.xxx.xx.xx vagrant-ubuntu-trusty-64: knife_zero.host:
ipaddress
$ knife search node 'name:*' --attribute ipaddress 2 items found ip-xx-x-x-xx.ap-northeast-1.compute.internal: ipaddress: xx.x.x.xx vagrant-ubuntu-trusty-64: ipaddress:
ひとまず
今回の目的は達成したものの、SuperMarket にアップロードされている Cookbook を利用する方法などについては引き続き手を動かしていきたい。
以上。