ChefのReport, Exeptionハンドラを使う

  • 16
    Like
  • 0
    Comment
More than 1 year has passed since last update.

この記事は最終更新から1年以上経過しています。 気をつけてね。

Chefのクライアント(ChefSolo/ChefClient)を実行して、締めの処理をなにかしら行いたい。

詳細はこちら。 Chef Docs: About Exception and Report Handlers

2つのハンドラ

  • exception handler: 例外発生がトリガ
  • report handler: 正常終了がトリガ

Chef_runの実行結果によって、このどちらか一方のみトリガされます。
同じ物を指定するのも構いません。

ハンドラ仕様

ハンドラについてはこんな感じです。

  • Chef::Handlerを継承したクラス
  • reportメソッドを持つ
  • run_statusを持っているので中身を適当に処理

トリガ原因がexceptionでもreportでも、reportメソッドが実行されます。

サンプルハンドラ

ではシンプルなchef-handler-updated-resourcesというのを使ってみます。

クライアント実行後に、今回更新されたリソース一覧をINFOレベルでログに出力します。

updated_resources.rb
#
# Copyright:: 2011, Joshua Timberman <chefcode@housepub.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");

require 'chef/handler'

module SimpleReport
  class UpdatedResources < Chef::Handler

    def report
      Chef::Log.info "Resources updated this run:"
      run_status.updated_resources.each {|r| Chef::Log.info " #{r.to_s}"}
    end
  end
end

def reportありますね。

gem & Chefのコンフィグに書く

さきほどのchef-handler-updated-resourcesはGemなのでRubyGemsから導入します。

gem install chef-handler-updated-resources --no-ri --no-rdoc

このハンドラを使うためにはsolo.rb/client.rbで指定すればOKです。

solo.rb/client.rb
require 'chef/handler/updated_resources'

report_handlers << SimpleReport::UpdatedResources.new
exception_handlers << SimpleReport::UpdatedResources.new

実行サンプル: report

ファイルを置く、nginxをenableにするレシピを書きました。

hand/recipes/default.rb
file '/tmp/hogehoge' do
  content Time.now.to_s
end                                                                                                                                   

file '/tmp/mogemoge' do
  content Time.now.to_s
end

service 'nginx' do
  action :enable
end

nginxが止まっている時

Shell_Out
$ chef-solo -c solo.rb -o 'hand' -l info
Starting Chef Client, version 11.4.4
[2013-07-23T06:33:40+00:00] INFO: *** Chef 11.4.4 ***
-- snip --
[2013-07-23T06:33:43+00:00] INFO: Chef Run complete in 0.491601172 seconds
[2013-07-23T06:33:43+00:00] INFO: Running report handlers
[2013-07-23T06:33:43+00:00] INFO: Resources updated this run:
[2013-07-23T06:33:43+00:00] INFO:   file[/tmp/hogehoge]
[2013-07-23T06:33:43+00:00] INFO:   file[/tmp/mogemoge]
[2013-07-23T06:33:43+00:00] INFO:   service[nginx]
[2013-07-23T06:33:43+00:00] INFO: Report handlers complete
Chef Client finished, 3 resources updated

Running report handlersから数行、レポートが出力されています。
最近は標準のログもわかりやすくなりましたね。

nginxが動いている時

Shell_Out
$ chef-solo -c solo.rb -o 'hand' -l info
Starting Chef Client, version 11.4.4
[2013-07-23T06:33:40+00:00] INFO: *** Chef 11.4.4 ***
-- snip --
[2013-07-23T06:38:16+00:00] INFO: Chef Run complete in 0.391962671 seconds
[2013-07-23T06:38:16+00:00] INFO: Running report handlers
[2013-07-23T06:38:16+00:00] INFO: Resources updated this run:
[2013-07-23T06:38:16+00:00] INFO:   file[/tmp/hogehoge]
[2013-07-23T06:38:16+00:00] INFO:   file[/tmp/mogemoge]
[2013-07-23T06:38:16+00:00] INFO: Report handlers complete
Chef Client finished, 2 resources updated

ファイルたちは中身がTime.nowなので更新されていますが、nginxについてはノータッチだった事がわかりますね。

実行サンプル: exception

例外を起こすために、レシピをちょっといじりました。

hand/recipes/default.rb
file '/tmpo/hogehoge' do   # 親ディレクトリが存在しない
  content Time.now.to_s
end                                                                                                                                   

file '/tmp/mogemoge' do
  content Time.now.to_s
end
Shell_Out
$ chef-solo -c solo.rb -o 'hand' -l info
Starting Chef Client, version 11.4.4
[2013-07-23T06:33:40+00:00] INFO: *** Chef 11.4.4 ***
-- snip --
[2013-07-23T06:46:32+00:00] ERROR: Running exception handlers
[2013-07-23T06:46:32+00:00] INFO: Resources updated this run:
[2013-07-23T06:46:32+00:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated
[2013-07-23T06:46:32+00:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
[2013-07-23T06:46:32+00:00] FATAL: Chef::Exceptions::EnclosingDirectoryDoesNotExist: file[/tmpo/hogehoge] (han::default line 10) had an error: Chef::Exceptions::EnclosingDirectoryDoesNotExist: Parent directory /tmpo does not exist.

少々見づらいですが Running exception handlers からException handlers completeまでが例外ハンドラのお勤めです。
一つ目でコケたため、残りのリソースに手を出していないことがわかります、途中の場合はそれまでに更新があったリソースが列挙されました。

では一つ目の例外を無視するようレシピを変更します。ignore_failureは共通オプションなので、どのリソースタイプでも有効です。

hand/recipes/default.rb
file '/tmpo/hogehoge' do   # 親ディレクトリが存在しない
  content Time.now.to_s
  ignore_failure true      # 共通オプションの ignore_failure でエラーを無視してみる
end                                                                                                                                   

file '/tmp/mogemoge' do
  content Time.now.to_s
end

この場合failしたリソースは無視され、次以降のリソースは更新されます。

Shell_Out
$ chef-solo -c solo.rb -o 'hand' -l info
Starting Chef Client, version 11.4.4
[2013-07-23T06:33:40+00:00] INFO: *** Chef 11.4.4 ***
-- snip --
[2013-07-23T06:48:48+00:00] INFO: Chef Run complete in 0.222575733 seconds
[2013-07-23T06:48:48+00:00] INFO: Running report handlers
[2013-07-23T06:48:48+00:00] INFO: Resources updated this run:
[2013-07-23T06:48:48+00:00] INFO:   file[/tmp/mogemoge]
[2013-07-23T06:48:48+00:00] INFO: Report handlers complete
Chef Client finished, 1 resources updated

file[/tmp/mogemoge]のみ更新されたようですね、ハンドラもreportの方が使われています。
この場合途中で例外があっても最終的なrun_statusのexcptionはnull になります、使い所の見極めが重要ですね。

一応ignore_failureとしている場合も標準出力のログにはレベル=ERRORで出てきます。

STDOUT(LEVEL=>ERROR)
-- snip --
  * file[/tmpo/hogehoge] action create[2013-07-23T06:51:04+00:00] INFO: Processing file[/tmpo/hogehoge] action create (hand::default li
ne 10)

    * Parent directory /tmpo does not exist.[2013-07-23T06:51:04+00:00] ERROR: file[/tmpo/hogehoge] (hand::default line 10) had an erro
r: Parent directory /tmpo does not exist.; ignore_failure is set, continuing
-- snip --

ignoreしているのでそもそもではありますが、レベル=ERRORのログを見ておけば一応捕捉はできまるようです。

LWRP

ハンドラ自体がLWRPになっているCookbookをChefRepoに追加するタイプです。
レシピにハンドラを記述できます。

詳しくはこちら。https://github.com/opscode-cookbooks/chef_handler

compile phaseにはなにもしないけどchef_run時にのみ実行するという怪しげなやり方も案内されています。

用途

report handlerは日常的にログをためておきたい時に、mongodbやfluentdに投げたり、メトリクスとして実行時間の推移を集計するような使い方ですね。
標準添付のjson_fileもノード状態、リソース状態をまるごと書きだしてくれるのでじっくりデバッグしたいときなどによさそうです(json_fileのレポートは1回分で60kを超えるほどの量があるので放置に注意。)。

exception handlerは公式のサンプルとプラグインにあるように例外をemailやIRCでお知らせしたり、自力で復旧を試みさせたりインスタンスに切腹させるなど考えられますね。