どうも炎の料理人三ツ星シェルの かっぱこと 川原 洋平(@inokara)です。
はじめに
前回の test-kitchen 記事を書いててテストが終わったら通知が欲しいよなあと思ったので Chef-handler の Report 及び Exception ハンドラを利用すれば出来そうな気がしたので試してみた。
Chef-handler について
以下のスライドや記事が纏まっていて良い。
上記の記事を参考にさせて頂いて、Chef-handler はざっくりと以下のようなもの。
種類
以下の三種類。
- Start は chef-client が実行される前に実行される
- Report は chef-client が正常に終了した際に実行される
- Exception は chef-client が異常終了した際に実行される
利用方法
- solo.rb や client.rb に設定しておく
- Cookbook** 内から LWRP の chef_handler リソースを呼び出す
何が出来る?
- 各種レポート(適用したノードのダンプ、経過時間、収束が発生したリソースのリスト、例外が発生したクラス、スタックトレース)
- JSON ファイル、その他色々…(ここ参照)なところにレポートを出力
流れと cookbook
ひと通りウンチクを書いたので実際にやってみたい。
流れ
今回は通知に関しては AWS のメール送信サービスである SNS を、レポートの可視化については InfluxDB に放り込んで Grafana で見るというような流れを作りたい。以下のようなイメージ。
また、今回は test-kitchen での cookbook 単体のテストを対象としたいので cookbook 内にハンドラ用のレシピを一つ追加する感じやってみる。
cookbook
前回に続いて以下の cookbook で試す。
中途半端な cookbook ですんません。
各種設定(1)
chef-handler-sns
chef-handler-sns はその名の通り Amazon SNS を利用して通知を行う。IAM にも対応しているらしい。
こちら を参考にして以下のようなレシピを追加する。
# argument_array = [ :access_key => "AKxxxxxxxxxxxxxxxxxx”, :secret_key => “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”, :topic_arn => "arn:aws:sns:us-east-1:1234567890:chef-test", ] # include_recipe "xml::ruby" # chef_gem "chef-handler-sns" # chef_handler "Chef::Handler::Sns" do source "#{Gem::Specification.find_by_name("chef-handler-sns").lib_dirs_glob}/chef/handler/sns" arguments argument_array # Exception のイベントのみを送信したい場合には true #supports :exception => true action :enable end
適当なファイル名(reporting.rb とか)で recipe/ 以下に放り込んでおく。尚、AWS のアクセスキーやシークレットアクセスキー、SNS の Topic ARN を事前に用意しておく必要がある。
Berkshelf のお出まし
レシピを見ると include_recipe をしている関係で複数の cookbook を利用することになるので Berkshelf を使うことになるので、以下のように依存する cookbook を Berksfile に記述する。
cd ${chef-repo}/site-cookbooks/influxdb-chef vim Berksfile
依存する cookbook は xml と chef_handler になるので以下のように記述する。また、それらを利用することになる自身の cookbook も記載する。
source "https://api.berkshelf.com" cookbook "xml" cookbook "chef_handler" cookbook "influxdb-chef”, path: "."
一旦、試す
ここまでで test-kitchen を実行すると漏れ無く SNS 経由でメール通知が届くことになる。
kitchen converge
を実行すると…以下のように test-kitchen が終了する。
また間を置かずに SNS サブスクリプションのエンドポイントに指定しているメールアドレス宛てにも以下のようにメールが届く。
おお、便利かも。イタズラして Exception させてみたいので以下のようにレシピを修正して kitchen converge する。
diff --git a/recipes/default.rb b/recipes/default.rb index b34c6ab..09eeb1b 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -9,7 +9,6 @@ end execute "install_influxdb" do command "rpm -Uvh /tmp/#{REMOTE_FILE}" - not_if { ::File.exists?("/usr/bin/influxdb") } end %w(httpd vim redhat-lsb-core).each do |sv|
以下のように収束に失敗する。すると以下のようにハンドラも実行される。
そして SNS 経由で以下のようなメールも届く。
おお。
これで test-kitchen 実行した後画面に張りつかなくても別の事が出来たりして捗るかもしれない。
各種設定(2)
chef-handler-influxdb
次にやりたいのが test-kitchen の結果をメトリクスとして保存して可視化したい…という今流行りの発想。メトリクスの保存先としては InfluxDB を利用する。InfluxDB についてはこちらあたりを見て頂くと雰囲気は掴めるかも。
尚、 InfluxDB のインストールについては割愛。既にセットアップ済みの環境を利用するが事前にデータベースは作っておきたいの以下のようにして InfluxDB の HTTP API を利用してデータベースを作っておく。
curl -X POST 'http://${influxdb_host}:8086/db?u=${user}&p=${pass}' -d '{"name": “chef”}’
レスポンスボディが表示されないので、ちゃんと出来たかが解らないので以下のように確認する。
curl 'http://${influxdb_host}:8086/db?u=${user}&p=${pass}'
以下のように出力されればおけけ。
[{“name”:”chef”}]%
次に先ほど chef-handler-sns の設定をしたレシピに以下を追加する。
handler_gem=['influxdb', 'chef-handler-influxdb'] handler_gem.each do |g| chef_gem g do action :install end end chef_handler 'ChefInfluxDB' do source ::File.join(Gem::Specification.find_by_name('chef-handler-influxdb').lib_dirs_glob, 'chef-handler-influxdb.rb') arguments [ :host => ‘xxx.xxx.xxx.xxx’, :port => ‘8086’, :user => ‘user’, :pass => ‘pass’, :database => 'chef', :series => 'report', ] action :enable end
kitchen converge を実行すると…以下のように出力される。
さらに InfluxDB を Web コンソール(http://${influxdb_host}:8083/)からアクセスして…
Databases から chef の Explore Data » を選択して…
Read Points で select * from report を実行した結果が以下の通り。
おお、elapsed_time が INFO: Chef Run complete in 3.656150432 seconds の部分だったり、アップデートがかかったリソースは 1 つだったりが時系列で確認が出来るのはいいねえ。
まあ、せっかくなので
Grafana でも見てみましょう。
適当にリソースを更新したりしながら kitchen converge を繰り返したのが上の図。
項目についてちょっとうんちく。
- elapsed_time は chef-client が実行開始( start_time )してから終了するまで(end_time)までの差分
- resources_updated は chef-client が更新したリソースの数
詳細についてはこちら。
最終的には…
以下のようなレポート用のレシピが出来た。
# for handler handler_gem=['influxdb', 'chef-handler-sns', 'chef-handler-influxdb'] handler_gem.each do |g| chef_gem g do action :install end end # for SNS argument_array = [ :access_key => “xxxxxxxxxxxxxxxxxxxxxxxxxx”, :secret_key => “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”, :topic_arn => "arn:aws:sns:us-east-1:1234567890:chef-test", ] # for SNS include_recipe "xml::ruby" # for SNS chef_handler "Chef::Handler::Sns" do source "#{Gem::Specification.find_by_name("chef-handler-sns").lib_dirs_glob}/chef/handler/sns" arguments argument_array #supports :exception => true action :enable end # for influxdb chef_handler 'ChefInfluxDB' do source ::File.join(Gem::Specification.find_by_name('chef-handler-influxdb').lib_dirs_glob, 'chef-handler-influxdb.rb') arguments [ :host => ‘xxx.xxx.xxx.xxx’, :port => '8086', :user => ‘user’, :pass => ‘pass’, :database => 'chef', :series => 'report', #:data => node[:cookbook][:attribute].to_hash, ] action :enable end
お疲れ様でしたー。
まとめ
やったこと
- Chef のイベントハンドラ 2 種類を試した
- 通知は chef-handler-sns レポートは chef-handler-influxdb を利用した
これで…
test-kitchen による cookbook のテストもちょっと楽しくなるかもしれないなー
元記事は、こちら