OpenStack MonascaのWebhook統合
2016-03-25
Machine-translated — the English original is authoritative.
グレアムのWebhook簡易歴史 [非技術編]
もちろん、皆さんはWebhookが何かご存知でしょうが、私は先月、別のHelion OpenStack統合の準備をするまでそれを知りませんでした。
私の理解を簡略化すると – Webhookは「プッシュ通知」です。
インターネットの登場により、私たちは非常に迅速に賢くなり、M2M通信のためにこれらの奇妙なUDPやTCPプロトコルを使い始めました。帯域幅は問題にならなかった(冗談です)ため、効率性は最初の要件ではありませんでした。
多くの監視ソリューションはHTTPを最適なプロトコルとして採用し、関心のあるリソースを単純にポーリングして応答を待ちました。このアプローチを使用したい場合は、MonascaがRESTful APIを提供しています。
しかし、クラウドにはスケールの課題が伴います。そして、数秒間で何十万ものサービスをポーリングしようとしている場合、効率性は非常に重要です。そこでWebhookが登場し、事態を救います。
報告するものがなくてもHTTP GETに続いてHTTP POSTを必要とする、‘昔ながら’で非効率なポーリングとは異なり、Webhookは単一のHTTP POSTを必要とし、POSTする価値のあるものがあって初めてトリガーされます!!!
要約すると – 頻繁なHTTP GET/POST versus 稀なHTTP POSTです。GithubがWebhookを導入した際、新しいコード変更を監視するユーザーからのサーバー負荷を66倍削減したという都市伝説がネット上に流れています。[ 私には事実がありません ]
設定方法は?簡単です。特に以前のSMTP統合ブログをお読みであれば。まずはGUIから始めましょう – これはすべてCLIから実行可能ですが、それにはさらに多くの資料を読む必要があります。
注: 運用コンソールのGUIはHelion OpenStackディストリビューション固有のものです。Helionを使用していない場合は、Monasca CLIを使用する必要があります。
HOS MonascaでのWebhook設定
-
クラウド管理者ユーザーとしてHelion Ops Consoleにログインします。

-
画面左上の‘ハンバーガー’メニューから「Notification Methods」オプションを選択します。

-
新しい通知方法を作成し、Webhookを選択して、HTTP POSTで通知を送信したいURLの詳細を入力します。

これでWebhookの設定は完了です。しかし待ってください、「どうやってテストして検証するのか」とお考えでしょう… 続きを読む。
テストアラームの作成
再び‘ハンバーガー’メニューに戻り、今回は「Alarm Creation」を選択して、以下のように新しいアラームを作成します – ここでは誤警報を発生させたいので、メトリックとして cpu.idle を使用し、おかしな値を設定します –

新しいアラーム定義の作成
これはこのアラームが初めて実行されるため、以前の状態を持っていないため、最初は「Unknown(不明)」のアラームが2つ表示される場合があります。しかし、辛抱強く待ってください。数分後には、以下に示すようにダッシュボードが点灯するはずです。

数分待ちます(5分)
これで、詳細を表示するためにアラームを選択できます。

アラームを確認

アラーム詳細の表示
そして当然のことながら、私たちが待望していたもの – Webhookアラート!!!
おっと!Webhookアラートをどうテストするのか…
多くのエンタープライズグレードの監視ソリューションは、今日でもWebhookをサポートしていません – これらの企業はアジャイルを理解できず、なぜ小規模な競合他社に追い越されるのか不思議がっています。
再度言いますが、これから見ることを本番環境で実行することはお勧めしません – これはWebhookをテストおよび検証するためだけのものです。また、HOSコントロールプレーンのファイアウォールでポートを開け、デプロイノードをポート3001で実行されるWebhookサーバーとして使用できるようにしました。[ この手順をラボ内でテストしたい場合は、以前のSMTP投稿を参照してください ]
注: 世界中のコーダーの皆様、私が破っているすべてのルール、悪いコーディングなどについて、今から謝罪します。あなたの公開物のおかげでこれらの例をこじつけたので、優しく見守ってください 🙂
以下に2つの例示スクリプトを提供します。1つはNodeJS用、もう1つはPython用です。Pythonは多くのOpenStackユーザーに馴染みがあるためです。NodeJSは、それを使う良い機会が欲しかったからです – とても良いです!ここではPythonやNodeの環境設定方法についてはカバーしません。これらのトピックに関するブログは山ほどあります。Pythonを使用する場合は、仮想環境(virtualenv)があなたの味方です – それを使用してください。
Pythonの例
以下のPythonスクリプトをコピーしてファイルに保存し、webhook.py という名前を付けてください。このスクリプトはWebhook通知を待ち受け、受信するとログファイルに書き込みます。これはレガシーな監視ソリューションがアラートを解析するために使用できます – エンタープライズグレードではありませんが、例として提示しています。
webhook.py
# Author: Graham Joseph Land
# Blog: allthingscloud.eu
# Twitter: @allthingsclowd
# Email: graham@ the above domain
# Date: 24/03/2016
#
# Name: webhook.py
# Version: 0.1
# Purpose: This script listens for webhook notifications and then writes them to a logfile
#
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import json
import logging
import logging.handlers
# log file for this script
log_file = '/home/stack/monitoring/venv/webhook/webhook.log'
log_max_size = 25165824 # 24 MB
log_level = logging.INFO
#log_level = logging.DEBUG # DEBUG is quite verbose
log = logging.getLogger('log')
log.setLevel(log_level)
log_handler = logging.handlers.RotatingFileHandler(log_file,
maxBytes=log_max_size,
backupCount=4)
f = logging.Formatter("%(asctime)s %(filename)s %(levelname)s %(message)s",
"%B %d %H:%M:%S")
log_handler.setFormatter(f)
log.addHandler(log_handler)
class webhookReceiver(BaseHTTPRequestHandler):
def do_POST(self):
"""
receives post, handles it
"""
log.info('<<<<<<<<< Alert Start >>>>>>>>')
message = 'OK'
self.rfile._sock.settimeout(5)
data_string = self.rfile.read(int(self.headers['Content-Length']))
self.send_response(200)
self.send_header("Content-type", "text")
self.send_header("Content-length", str(len(message)))
self.end_headers()
self.wfile.write(message)
# parse data
text = json.loads(data_string)
text = json.dumps(text, indent=2)
log.info(text)
log.info('<<<<<<<<< Alert End >>>>>>>>')
def log_message(self, formate, *args):
"""
disable printing to stdout/stderr for every post
"""
return
def main():
"""
the main event.
"""
try:
server = HTTPServer(('', 3001), webhookReceiver)
log.info('started web server...')
server.serve_forever()
except KeyboardInterrupt:
log.info('ctrl-c pressed, shutting down.')
server.socket.close()
if __name__ == '__main__':
スクリプトを実行し、ログファイルをtailします – 今、戻ってアラートを再度生成し、何が起こるか確認してください..

これで完了です – Webhook – 「簡単!」
Monascaの問題を除外するために、以下のようにcurlコマンドを使用してこのスクリプトをテストすることもできます。
curl -H "Content-Type: application/json" -X POST -d '{"alarm_id": "1234","alarm_definition_id": "freddef","alarm_name": "fire alarm","alarm_description": "alarmDescription","alarm_timestamp": "timestamp","state": "Critical","old_state": "oldState","message": "this is the message","tenant_id": "tenant1234","metrics": "1234"}' --trace-ascii debugdump.txt http://172.16.60.9:3000/openstack/alerts
NodeJSの例
Pythonの例で使用したものとは異なるWebhookエンドポイントを使用していることに注意してください。

NodeJSの例示アプリケーションには、やや複雑なファイル構造が必要です。
メインの app server.js を使用し、そこから受信時にWebhookを処理する‘route’アプリ webhook.js を呼び出します。
(venv)stack@helion-cp1-c0-m1-mgmt:~/monitoring/nodejs$ tree -I node_modules
.
|-- routers
| `-- webhook.js
`-- server.js
以下の2つのアプリを、上記に示すディレクトリ構造と同じ名前のファイルにコピーします。
server.js
var bodyParser = require( 'body-parser' ),
express = require( 'express' ),
app = express();
var webhook = require( './routers/webhook' );
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded({
extended: true
}) );
app.get( '/', function ( req, res, next ) {
res.send( 'Hooks listener running' );
});
app.use( '/openstack/alerts', webhook );
app.listen( 3001 );
そしてroutersサブディレクトリ内には
webhook.js
var express = require( 'express' ),
bodyParser = require('body-parser'),
router = express.Router();
router.use(bodyParser.json());
router.post( '/', function ( req, res, next ) {
console.log(req.body);
res.status(200).json({message: 'Monasca Hook received!'})
});
module.exports = router;
アプリを起動し、まずcurlでテストします –
stack@helion-cp1-c0-m1-mgmt:~$ curl -H "Content-Type: application/json" -X POST -d '{"alarm_id": "1234","alarm_definition_id": "freddef","alarm_name": "fire alarm","alarm_description": "alarmDescription","alarm_timestamp": "timestamp","state": "Critical","old_state": "oldState","message": "this is the message","tenant_id": "tenant1234","metrics": "1234"}' --trace-ascii debugdump.txt http://172.16.60.9:3001/openstack/alerts
{"message":"Monasca Hook received!"}stack@helion-cp1-c0-m1-mgmt:~$
結果は以下のようになります
(venv)stack@helion-cp1-c0-m1-mgmt:~/monitoring/nodejs$ nodejs server.js
{ alarm_id: '1234',
alarm_definition_id: 'freddef',
alarm_name: 'fire alarm',
alarm_description: 'alarmDescription',
alarm_timestamp: 'timestamp',
state: 'Critical',
old_state: 'oldState',
message: 'this is the message',
tenant_id: 'tenant1234',
metrics: '1234' }
最後に、前述の手順に従ってMonascaからアラートを送信し、Webhook通知が届いてアプリによって処理されるのを見ます。

[注: 通知配信のトラブルシューティング]
- まだトラフィックが表示されない場合、かつ
/var/log/monasca/notification/notification.logファイルが空の場合は、monascaを再設定してみてください。
cd ~/scratch/ansible/next/hos/ansible
ansible-playbook -i hosts/verb_hosts monasca-reconfigure.yml
-
既存のアラーム定義を再設定する際は、通知チェックボックスと必要な個別の通知方法の両方を選択してください。

-
TCPDUMPを使用して、Webhookトラフィックが3つのコントローラーノードのいずれかのインターフェースから送信されているか確認します [Webhookポート番号で検索]。
Originally published on allthingscloud.eu (2016-03-25).