はじめに
PrometheusとAlertmanagerを使った監視環境では、アラートの通知先としてWebhookを利用することがあります.
この記事では,AlertmanagerのWebhook通知を受け取るWebhookサーバーをFlaskで構築する方法を説明していきます.
実装手順
1. 事前準備・環境構成
この記事は以下の環境で検証を行いました.
- Python:3.12.3
- Flask:3.1.1
- OS:Ubuntu 24.04.2
2. 仮想環境の作成とFlaskのインストール
まずは仮想環境を作成し、Flaskのインストールをします。
qiita@test:~$ python3 -m venv venv
qiita@test:~$
qiita@test:~$ source venv/bin/activate
(venv) qiita@test:~$
仮想環境が有効になると,プロンプトが(venv)と表示されます。
(venv) qiita@test:~$ pip install flask
Collecting flask
Using cached flask-3.1.1-py3-none-any.whl.metadata (3.0 kB)
Collecting blinker>=1.9.0 (from flask)
Using cached blinker-1.9.0-py3-none-any.whl.metadata (1.6 kB)
Collecting click>=8.1.3 (from flask)
Using cached click-8.2.1-py3-none-any.whl.metadata (2.5 kB)
Collecting itsdangerous>=2.2.0 (from flask)
Using cached itsdangerous-2.2.0-py3-none-any.whl.metadata (1.9 kB)
Collecting jinja2>=3.1.2 (from flask)
Using cached jinja2-3.1.6-py3-none-any.whl.metadata (2.9 kB)
Collecting markupsafe>=2.1.1 (from flask)
Using cached MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)
Collecting werkzeug>=3.1.0 (from flask)
Using cached werkzeug-3.1.3-py3-none-any.whl.metadata (3.7 kB)
Using cached flask-3.1.1-py3-none-any.whl (103 kB)
Using cached blinker-1.9.0-py3-none-any.whl (8.5 kB)
Using cached click-8.2.1-py3-none-any.whl (102 kB)
Using cached itsdangerous-2.2.0-py3-none-any.whl (16 kB)
Using cached jinja2-3.1.6-py3-none-any.whl (134 kB)
Using cached MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (23 kB)
Using cached werkzeug-3.1.3-py3-none-any.whl (224 kB)
Installing collected packages: markupsafe, itsdangerous, click, blinker, werkzeug, jinja2, flask
Successfully installed blinker-1.9.0 click-8.2.1 flask-3.1.1 itsdangerous-2.2.0 jinja2-3.1.6 markupsafe-3.0.2 werkzeug-3.1.3
(venv) qiita@test:~$
インストール後は以下のようにバージョンを確認できます.
(venv) qiita@test:~$ python -m flask --version
Python 3.12.3
Flask 3.1.1
Werkzeug 3.1.3
(venv) qiita@test:~$
3. アラートを受け取るサーバーの実装
Flaskの準備の次は、実際にWebhookのPOSTリクエストを受け取るサーバーを実装します。
app.pyという名前でファイルを作成し、以下のコードを記述します。
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
print(data)
return "OK", 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
このコードでは、/webhookというエンドポイントでPOSTリクエストを受け取ります。
request.get_json()でJSONデータを取得しています。
4. サーバーの起動
Flaskアプリを起動するために以下を実行します。
(venv) qiita@test:~$ python app.py
* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://192.168.100.98:5000
Press CTRL+C to quit
この状態で、ローカルマシンはポート5000番でリクエストを受け付けています。
5. Webhookの受信テスト(curl)
今回は,以下のアラートが通知された場合を想定したリクエストを送信してサーバーが正しく受信できているかを確認します.
以下のcurlコマンドを実行して、Webhookの受信動作をテストします。
qiita@test:~$ curl -X POST http://localhost:5000/webhook \
-H "Content-Type: application/json" \
-d '{
"receiver": "redmine",
"status": "firing",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "Internal Monitoring Cluster Pod oom check",
"id": "/",
"instance": "redmine-test-master:32700",
"job": "test-cAdvisor",
"severity": "critical"
},
"annotations": {
"alert_title": "Monitoring Cluster Pod oom-kill: /-",
"description": "Pod oom-kill: /-",
"runbook_url": "https://runbooks.prometheus-operator.dev/runbooks/alertmanager/alertmanagerfailedreload",
"summary": "container oom-kill"
},
"startsAt": "2025-07-09T08:49:11.747Z",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "http://prometheus-d7dfd6b8d-j6w79:9090/graph?g0.expr=increase%28container_oom_events_total%5B1m%5D%29+%3D%3D+0&g0.tab=1",
"fingerprint": "5c344b24b3fc7467"
}
],
"version": "4",
}'"groupKey": "12345"
OKqiita@test:~$
Flaskサーバーのターミナルには以下のようなログが表示されます。
(venv) qiita@test:~$ python app.py
* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://192.168.100.98:5000
Press CTRL+C to quit
{'receiver': 'redmine', 'status': 'firing', 'alerts': [{'status': 'firing', 'labels': {'alertname': 'Internal Monitoring Cluster Pod oom check', 'id': '/', 'instance': 'redmine-test-master:32700', 'job': 'test-cAdvisor', 'severity': 'critical'}, 'annotations': {'alert_title': 'Monitoring Cluster Pod oom-kill: /-', 'description': 'Pod oom-kill: /-', 'runbook_url': 'https://runbooks.prometheus-operator.dev/runbooks/alertmanager/alertmanagerfailedreload', 'summary': 'container oom-kill'}, 'startsAt': '2025-07-09T08:49:11.747Z', 'endsAt': '0001-01-01T00:00:00Z', 'generatorURL': 'http://prometheus-d7dfd6b8d-j6w79:9090/graph?g0.expr=increase%28container_oom_events_total%5B1m%5D%29+%3D%3D+0&g0.tab=1', 'fingerprint': '5c344b24b3fc7467'}], 'version': '4', 'groupKey': '12345'}
127.0.0.1 - - [13/Jul/2025 12:53:30] "POST /webhook HTTP/1.1" 200 -
^C(venv) qiita@test:~$
このように,Alertmanagerから通知されるアラートをJSON形式で正しく受け取れていることが確認できます.
注意点
今回の実装方法では,一番最新のアラートの1件をcurlで受け取ることになるので,複数のアラートが通知された場合は最新のアラートの1件に上書きされてしまうので注意してください.
おわりに
今回は,Alertmanagerから送信されるWebhookを受け取るサーバーをFlaskを使って実装する方法について説明しました.
今後は,受け取ったアラートに応じたログの出力や通知など機能を拡張をしていくことができます.