はじめに
こんにちは!
前回はZabbix設定編①ということで、Zabbix Proxy経由でCisco DevNet SandboxのNW機器を監視してインターフェースDownを検知するところまでやりました!
前回の記事はこちら↓
【Zabbix設定編①】Zabbix × ServiceNow × AWX × Bedrockで障害初動対応を自動化してみた
今回はその続きとして、Lambda作成編を書いていきます。
次回のZabbix設定編②でZabbixのメディアタイプを設定してWebhookをLambdaに投げるんですが、その前に受け取り側であるLambdaを先に作っておかないといけません。
ただ、いきなりServiceNow / AWX / Bedrock全部の連携を書いても動作確認がややこしくなるので、今回はZabbixからのWebhookを受け取って内容をログに出すだけのシンプルな構成から始めます。
連携部分のコードは後続の記事で足していく形にします!
今回のゴール
ZabbixからのWebhookを受け取って、障害/復旧の内容をログに出力するLambda関数を作成することをゴールとします。
今回の流れ
| # | 内容 |
|---|---|
| 1 | Lambdaの役割を整理する |
| 2 | IAMロールの作成 |
| 3 | Lambda関数の作成 |
| 4 | 関数コードの実装 |
| 5 | タイムアウト・メモリの設定 |
| 6 | 関数URLの有効化 |
| 7 | テスト |
Lambdaの役割を整理する
今回の構成でLambdaがどんな役割を担うか整理しておきます。
ZabbixがアラートをWebhookで外部に通知したとき、その受け口になるのがLambdaです。
最終的にはServiceNow起票・AWXジョブ実行・Bedrock解析まで全部Lambdaが仕切る予定です。
今回作るLambdaの処理フロー
[Zabbix] Webhook (障害/復旧)
↓ HTTPS POST
[Lambda 関数URL]
↓
bodyをパースしてevent_typeを確認
↓
CloudWatch Logsにログ出力
↓
200 OKを返す
IAMロールの作成
それではやっていきましょう!
LambdaにはまずIAMロールが必要です。
今の段階ではLambdaはCloudWatch Logsにログを書くだけなので、必要な権限も最小限で済みます。
後続で連携が増えたらポリシーを追加していけばOKです。
IAMコンソール → ロール → ロールを作成
ステップ1: 信頼されたエンティティを選択
| 項目 | 設定値 |
|---|---|
| 信頼されたエンティティタイプ | AWSのサービス |
| ユースケース | Lambda |
ステップ2: 許可ポリシーを追加
| ポリシー名 | 用途 |
|---|---|
| AWSLambdaBasicExecutionRole | CloudWatch Logsへのログ出力 |
ステップ3: ロールの詳細
| 項目 | 設定値 |
|---|---|
| ロール名 | zabbix-lambda-role |
今回追加するポリシーはAWSLambdaBasicExecutionRoleだけです。
BedrockやS3のポリシーは、後続の連携を追加するタイミングで足していきます。
ロールを作成をクリックして完了です!
Lambda関数の作成
続いてLambda関数を作成していこうと思います。
一から作成 を選択して以下の設定で作成します。
| 項目 | 設定値 |
|---|---|
| 関数名 | verification-lambda |
| ランタイム | Python 3.11 |
| アーキテクチャ | x86_64 |
| 実行ロール | zabbix-lambda-role |
設定できたら関数を作成をクリックします。
関数コードの実装
関数が作成できたら、実際にコードを書いていきます。
今回のコードはシンプルです。
Webhookで送られてきたbodyをパースして、event_typeとホスト名・トリガー名をログに出すだけです。
import json
def lambda_handler(event, context):
print("Received event:", json.dumps(event))
# bodyをパース
try:
body = json.loads(event.get('body', '{}'))
except Exception as e:
print("Failed to parse body:", e)
return {'statusCode': 400, 'body': 'Bad Request'}
event_type = body.get('event_type', '')
host = body.get('host', '')
trigger_name = body.get('trigger_name', '')
print(f"event_type : {event_type}")
print(f"host : {host}")
print(f"trigger_name: {trigger_name}")
if event_type == 'PROBLEM':
print("[PROBLEM] 障害を受信しました")
elif event_type == 'RECOVERY':
print("[RECOVERY] 復旧を受信しました")
else:
print(f"[UNKNOWN] 未知のevent_type: {event_type}")
return {
'statusCode': 200,
'body': json.dumps('OK')
}
最後に Deploy ボタンを押して保存します!
コードのポイント
json.loads(event['body']) している理由
関数URL経由のリクエストはbodyが文字列で届くため、Pythonの辞書型に変換してから中身を取り出しています。
200 OKを必ず返す理由
Zabbixはレスポンスを確認していて、200以外が返るとWebhook送信失敗と判断します。
タイムアウト・メモリの設定
続いてタイムアウト値を変更しておきます。
今回はWebhookを受け取ってログを出すだけなのでデフォルトのままでも問題ないですが、
連携が増えたときのことを考えて今のうちに変えておきましょう。
設定タブ→一般設定→編集
| 項目 | 設定値 | 理由 |
|---|---|---|
| タイムアウト | 5分0秒 | 後続連携でAWXジョブの完了待ちが入るためバッファを確保 |
| メモリ | 256MB | 念のため |
ちなみにタイムアウトのデフォルト値は3秒です。
関数URLの有効化
続いてZabbixがWebhookを投げる先のエンドポイントを作ります。
LambdaにはHTTPSで直接呼び出せる 関数URL という機能があるので今回はそれを使います。
設定タブ → 関数URL → 関数URLを作成
| 項目 | 設定値 |
|---|---|
| 認証タイプ | NONE |
認証タイプNONEにすると誰でもこのURLにリクエストを投げられます。
今回は検証環境なのでNONEにしていますが、本番環境ではAWS_IAM認証を検討してください。
作成すると以下のような形式のURLが発行されます。
https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/
このURLを次回のZabbixメディアタイプ設定で使うのでメモしておきましょう!

テスト
では実際にテストしてみましょう。
Lambdaコンソールの テスト タブから動作確認します。
Zabbixから実際にWebhookが来たときと同じ形式のJSONをテストイベントとして用意します。
テストイベントの設定
| 項目 | 設定値 |
|---|---|
| テストイベント名 | zabbix-problem-test |
実際にZabbixから送られてくるWebhookのbodyの中身はこちらです。
{
"event_type": "PROBLEM",
"trigger_name": "Cisco Interface Down検知",
"host": "devnetsandboxiosxec9k.cisco.com",
"event_id": "12345"
}
HTTPのbodyはネットワーク上をテキスト(文字列)として流れます。
そのためLambdaが受け取ると、上のJSONオブジェクトは event['body'] に文字列としてそのまま入ってきます。
テストイベントではその状態を再現する必要があるため、bodyの値をJSON文字列(\" でエスケープされた形)で渡します。
{
"body": "{\"event_type\": \"PROBLEM\", \"trigger_name\": \"Cisco Interface Down検知\", \"host\": \"devnetsandboxiosxec9k.cisco.com\", \"event_id\": \"12345\"}"
}
保存出来たらテストボタンをクリックして実行します。
以下のようにログが出力されていれば成功です!
Received event: {"body": "{...}"}
event_type : PROBLEM
host : devnetsandboxiosxec9k.cisco.com
trigger_name: Cisco Interface Down検知
[PROBLEM] 障害を受信しました
まとめ
今回は、ZabbixからのWebhookを受け取ってログに出力するだけのシンプルなLambda関数を作成しました!
今はまだ連携が何もない状態ですが、Webhookの受信・bodyのパース・event_typeによる振り分けという形は作ることできました。
後続の記事でServiceNow / AWX / Bedrockの連携をひとつずつ足していく形にしていきます。
今回やったことをまとめると以下です。
| # | やったこと |
|---|---|
| 1 | IAMロールの作成(AWSLambdaBasicExecutionRoleのみ) |
| 2 | Lambda関数の作成(Python 3.11 / zabbix-lambda-role) |
| 3 | Webhook受信・ログ出力のコード実装 |
| 4 | タイムアウト・メモリの設定 |
| 5 | 関数URLの有効化 |
| 6 | テストイベントによる受信確認 |
次回はZabbix設定編②として、ZabbixのメディアタイプとActionを設定して
実際にZabbixからこのLambdaにWebhookを投げるところまでやっていきます!


