前回の続き。
デプロイのエラー処理(検知)について
任意のコマンドが実行出来そうだ
stretcher にはデプロイプロセスが成功した際、失敗した際に任意のコマンドを実行することが出来るようだ。
以下は README からの抜粋。
commands: pre: - echo 'staring deploy' post: - echo 'deploy done' success: - echo 'deploy success' failure: - echo 'deploy failed!!' - cat >> /path/to/failure.log
任意のコマンドを実行出来るということは、上記の例のようにファイルへのログの出力や Slack 等への通知や fluentd へ JSON メッセージを転送したりすることも出来そうであるが、対象の台数が多くなると Slack 等の通知が半端ない数になってしまうなどの課題が無いわけでもない。
成功 or 失敗
成功と失敗はどのように判定されているのかはソースコードを見れば...と思ったが、残念ながらソースコードを見る能力が無いので実際に試してみる。
以下のように post
で実行するコマンドを exit 1
だけにしたマニフェストを書いてデプロイを実行してみる。
src: http://consul_deploy:8000/app.tar.gz checksum: 4b4fedd8ef18df2b42134fa81bbc75bc dest: /tmp/service commands: pre: - echo 'staring deploy' >> /tmp/stretcher.log post: - exit 1 success: - echo 'deploy success' >> /tmp/stretcher.log failure: - echo 'deploy failed!!' >> /tmp/stretcher.log
引き続き、post
で実行するコマンドを 0
に変えてデプロイを実行してみる。
src: http://consul_deploy:8000/app.tar.gz checksum: 4b4fedd8ef18df2b42134fa81bbc75bc dest: /tmp/service commands: pre: - echo 'staring deploy' >> /tmp/stretcher.log post: - exit 0 success: - echo 'deploy success' >> /tmp/stretcher.log failure: - echo 'deploy failed!!' >> /tmp/stretcher.log
デプロイ先では以下のようなログが記録された。
$ cat /tmp/stretcher.log staring deploy deploy failed!! staring deploy deploy success
どうやら post
で定義されているコマンドの終了コードが 0
以外の場合には failure
にて定義されているコマンドが実行されるようだ。(※ pre
でコマンドが定義されている場合にも同じようだ。)
Consul を使ったエラー処理実装案
ということで、Consul を利用したエラーの判定について判った(つもり)ところで、デプロイ時のエラー処理について考えてみる。尚、エラー処理というと範囲が広いので今回はエラー検知方法を試してみる。
案(1)KVS + consul-kv-dashboard を利用する
イメージ
試す
consul-kv-dashboard については以下の記事にて。
consul-kv-dashboard を利用して KVS の情報を取得する場合には登録するキーは以下のように定義する必要があるが...
/v1/kv/{namespace}/{category}/{node}(/{key})?flags={flags}
逆を言うと、上記のキーに従えば簡単に consul-kv-dashboard を利用することが出来るので、以下のようなシェルスクリプトを用意して...
#!/bin/sh datetime=`date +%s` result_str=$1 result_code=$2 datetime_code=`expr ${datetime} \* 1000 + ${result_code}` node_name=`curl -s localhost:8500/v1/agent/self | python -c "exec(\"import json,sys\\nj=json.load(sys.stdin)\\nprint j['Member']['Name']\")"` curl -X PUT -d "{\"result\": \"${result_str}\", \"timestamp\": \"${datetime}\"}" "localhost:8500/v1/kv/dashboard/deploy/${node_name}/result?flags=${datetime_code}"
result.sh というファイル名で保存して実行権限を付与してデプロイパッケージに含めておく。
更にマニフェストの command
の success
と failure
を以下のように設定する。
src: http://consul_deploy:8000/app.tar.gz checksum: 4b4fedd8ef18df2b42134fa81bbc75bc dest: /tmp/service commands: pre: - echo 'staring deploy' >> /tmp/stretcher.log post: - sed -i "s/$/`hostname -s`/g" /tmp/service/app/html/index.html - pkill python; pushd /tmp/service/app/html; /tmp/service/app/start.sh > /dev/null 2>&1 success: - echo 'deploy success' >> /tmp/stretcher.log - /tmp/service/app/result.sh success 0 failure: - echo 'deploy failed!!' >> /tmp/stretcher.log - /tmp/service/app/result.sh failure 2
実際にデプロイしてみる。
/usr/local/bin/consul event -node="consul_0" -name deploy_demo http://consul_deploy:8000/deploy.yml
以下のように結果が反映されている。
意図的に失敗させてみる(exit 1
してみる)。
素晴らしひ。
メリデメ
- 複数のノードの結果を一つの画面でリアルタイムに確認することが出来る(メリ)
- 複雑な開発等が不要でマニフェストを修正するだけで導入することが出来る(メリ)
- Consul クラスタ内のノードの何れかにインストールしておくだけで良い(メリ)
- 特にデメリットは感じない(強いていえば consul-kv-dashboard のプロセス管理が必要にある)(デメ)
案(2)KVS + Consul watch + スクリプトを利用する
イメージ
試す
こちらのようなスクリプトをハンドラとして consul watch
を任意のノード(デプロイイベントを送るノード又は専用のノード)にて起動する。尚、consul watch
の type
は keyprefix
を指定することで、deploy/
キーを含む全てのキーの変化を検知してハンドラを起動することが出来る。
consul watch -type keyprefix -prefix deploy/ /path/to/result_hook.py &
また、result.sh を以下のように修正する。
#!/bin/sh datetime=`date +%s` result_str=$1 datetime_code=`expr ${datetime} \* 1000 + ${result_code}` node_name=`curl -s localhost:8500/v1/agent/self | python -c "exec(\"import json,sys\\nj=json.load(sys.stdin)\\nprint j['Member']['Name']\")"` curl -X PUT -d "{\"result\": \"${result_str}\", \"timestamp\": \"${datetime}\"}" "localhost:8500/v1/kv/deploy/${node_name}/result?flags=${datetime}"
更にマニフェストも以下のように少し修正。
src: http://consul_deploy:8000/app.tar.gz checksum: 4b4fedd8ef18df2b42134fa81bbc75bc dest: /tmp/service commands: pre: - echo 'staring deploy' >> /tmp/stretcher.log post: - sed -i "s/$/`hostname -s`/g" /tmp/service/app/html/index.html - pkill python; pushd /tmp/service/app/html; /tmp/service/app/start.sh > /dev/null 2>&1 success: - echo 'deploy success' >> /tmp/stretcher.log - /tmp/service/app/result.sh success failure: - echo 'deploy failed!!' >> /tmp/stretcher.log - /tmp/service/app/result.sh failure
実際にデプロイしてみる。
# デプロイイベント発行 $ /usr/local/bin/consul event -node="consul_0" -name deploy_demo http://consul_deploy:8000/deploy.yml Event ID: 6d29dafa-763a-8f80-3436-80239b5d5e20 # 以下のように結果が出力される 2015-07-08 08:21:56 4991 consul_01 {"result": "failure", "timestamp": "1436343716"} 2015-07-08 08:21:56 4989 consul_02 {"result": "failure", "timestamp": "1436343716"} 2015-07-08 08:21:56 4990 consul_03 {"result": "failure", "timestamp": "1436343716"}
デプロイ成功の場合でも...
# デプロイイベント発行 $ /usr/local/bin/consul event -node="consul_0" -name deploy_demo http://consul_deploy:8000/deploy.yml Event ID: 2f62c232-ebdf-feec-6562-8875011da110 # 以下のように結果が出力される 2015-07-08 08:24:08 4996 consul_01 {"result": "success", "timestamp": "1436343848"} 2015-07-08 08:24:08 4995 consul_02 {"result": "success", "timestamp": "1436343848"} 2015-07-08 08:24:08 4994 consul_03 {"result": "success", "timestamp": "1436343848"}
一応、ログっぽいものが表示される。もちろん、ログ出力以外に通知等もハンドラスクリプトに手を加えることで対応することが出来る。
メリデメ
- Consul の機能 + ハンドラスクリプトだけで完結出来る(メリ)
- ハンドラスクリプトの出来次第(ちゃんと作り込めればそれなりに...)(メリ)
consul watch
の挙動をちゃんと把握していないとツライ(デメ)- 画面での確認が出来ない(デメ)
ということで...
stretcher でデプロイを行った際のエラー処理(エラー検知)については consul-kv-dashboard を利用すると良いと思われる。