4.4 イベントとアクション

トリガーイベントに対する自動応答と通知システムの詳細設定

概要

**イベント(Events)**は、Zabbixシステム内で発生する重要な出来事を表現するオブジェクトです。**アクション(Actions)**は、特定のイベントが発生した際に自動的に実行される一連の処理を定義します。この組み合わせにより、監視システムの自動化と迅速な問題対応を実現します。

イベント・アクションシステムの構成

要素説明
イベントソースイベント発生元トリガー、ディスカバリ、自動登録
イベントタイプイベントの種類Problem, OK, Unknown
アクション条件実行条件ホストグループ、深刻度、時間帯
アクション操作実行する処理通知送信、リモートコマンド実行

イベントの種類と生成

トリガーイベント

基本的なイベントタイプ

ini
# Problem イベント
Event type: Problem
Trigger state: Problem → OK
Generated when: トリガー条件が満たされた時

# OK イベント  
Event type: OK
Trigger state: OK → Problem
Generated when: トリガー条件が解決された時

# Unknown イベント
Event type: Unknown
Generated when: アイテムがサポートされていない、エージェント未応答

イベント生成の流れ

ディスカバリイベント

ネットワークディスカバリイベント

ini
# デバイス発見
Event: Host discovered
Details: New device found in network range 192.168.1.0/24

# サービス発見
Event: Service discovered  
Details: HTTP service found on host 192.168.1.100:80

# デバイス喪失
Event: Host lost
Details: Device 192.168.1.50 no longer responding

低レベルディスカバリイベント

ini
# ファイルシステム発見
Event: Filesystem discovered
Details: New filesystem /data mounted on server-01

# ネットワークインターフェース発見
Event: Network interface discovered
Details: Interface eth1 discovered on server-01

自動登録イベント

ini
# エージェント自動登録
Event: Agent auto-registration
Details: Agent from 192.168.1.200 requested registration
Hostname: new-server-01
Metadata: Linux,web-server,production

アクション設定の基礎

基本的なアクション設定

アクション作成の流れ

  1. Configuration → Actions
  2. Event source選択(トリガー、ディスカバリ等)
  3. 条件設定
  4. 操作設定
  5. 有効化

アクション条件の設定

基本的な条件例

ini
# ホストグループ条件
Condition: Host group equals "Web servers"
Operator: equals
Value: Web servers

# 深刻度条件
Condition: Trigger severity >= Warning
Operator: >=
Value: Warning

# 時間条件
Condition: Time period in "Business hours"
Operator: in
Value: Business hours (09:00-18:00, Mon-Fri)

# トリガー名条件
Condition: Trigger name like "CPU"
Operator: like
Value: CPU

複雑な条件組み合わせ

ini
# 営業時間内の重要サーバーアラート
Condition A: Host group equals "Critical servers"
Condition B: Trigger severity >= High  
Condition C: Time period in "Business hours"
Condition D: Trigger name not like "Test"

Logic: (A and B and C) and not D

条件タイプの詳細

ホストベース条件

ini
# 特定ホスト
Host name equals "web-server-01"

# ホストメタデータ
Host metadata like "production"

# ホストIPアドレス
Host IP equals "192.168.1.100"

トリガーベース条件

ini
# トリガー名パターン
Trigger name like "CPU|Memory|Disk"

# トリガー深刻度範囲
Trigger severity >= Average
Trigger severity <= High

# トリガー値
Trigger value equals "PROBLEM"

時間ベース条件

ini
# 定義済み時間帯
Time period in "Maintenance window"
Time period not in "Backup time"

# 日時条件
Day of week in "Monday,Tuesday,Wednesday,Thursday,Friday"
Time of day >= "09:00"
Time of day <= "18:00"

通知メディアタイプ

Email通知

基本設定

ini
# SMTP設定
Type: Email
SMTP server: smtp.company.com
SMTP port: 587
SMTP helo: zabbix.company.com
SMTP security: STARTTLS
Username: [email protected]
Password: smtp_password

# 認証設定
Authentication: Username and password

高度なEmail設定

ini
# HTMLメール設定
Message format: HTML
Subject: {ALERT.STATUS}: {ALERT.SUBJECT}

# メールテンプレート
Body: |
<html>
<head><title>Zabbix Alert</title></head>
<body>
<h2 style="color: {ALERT.COLOR}">{ALERT.STATUS}: {ALERT.SUBJECT}</h2>
<table border="1">
<tr><td>Host</td><td>{HOST.NAME}</td></tr>
<tr><td>Trigger</td><td>{TRIGGER.NAME}</td></tr>
<tr><td>Severity</td><td>{TRIGGER.SEVERITY}</td></tr>
<tr><td>Time</td><td>{EVENT.DATE} {EVENT.TIME}</td></tr>
<tr><td>Value</td><td>{ITEM.VALUE1}</td></tr>
</table>
<p>Problem description:<br>{TRIGGER.DESCRIPTION}</p>
</body>
</html>

# 添付ファイル
Include event details: Yes
Include trigger description: Yes

SMS通知

基本SMS設定

ini
# SMS Gateway設定
Type: SMS
GSM modem: /dev/ttyUSB0
Baudrate: 115200

# または HTTP Gateway
Type: Webhook
URL: https://api.sms-gateway.com/send

SMS用スクリプト

bash
#!/bin/bash
# /usr/lib/zabbix/alertscripts/send_sms.sh

TO=$1
SUBJECT=$2
MESSAGE=$3

# SMS API経由での送信
curl -X POST "https://api.sms-service.com/send" \
     -H "Authorization: Bearer API_TOKEN" \
     -H "Content-Type: application/json" \
     -d "{
       \"to\": \"$TO\",
       \"message\": \"$SUBJECT: $MESSAGE\"
     }"

Webhook通知

Slack通知設定

json
{
  "channel": "#{ALERT.CHANNEL}",
  "username": "Zabbix",
  "icon_emoji": ":warning:",
  "attachments": [
    {
      "color": "{ALERT.COLOR}",
      "title": "{ALERT.STATUS}: {ALERT.SUBJECT}",
      "fields": [
        {
          "title": "Host",
          "value": "{HOST.NAME}",
          "short": true
        },
        {
          "title": "Trigger",
          "value": "{TRIGGER.NAME}",
          "short": true
        },
        {
          "title": "Severity",
          "value": "{TRIGGER.SEVERITY}",
          "short": true
        },
        {
          "title": "Time",
          "value": "{EVENT.DATE} {EVENT.TIME}",
          "short": true
        },
        {
          "title": "Current Value",
          "value": "{ITEM.VALUE1}",
          "short": false
        }
      ],
      "footer": "Zabbix Monitoring",
      "ts": "{EVENT.TIMESTAMP}"
    }
  ]
}

Microsoft Teams通知

json
{
  "@type": "MessageCard",
  "@context": "http://schema.org/extensions",
  "summary": "{ALERT.STATUS}: {ALERT.SUBJECT}",
  "themeColor": "{ALERT.COLOR}",
  "sections": [
    {
      "activityTitle": "{ALERT.STATUS}: {ALERT.SUBJECT}",
      "activitySubtitle": "Host: {HOST.NAME}",
      "facts": [
        {
          "name": "Trigger:",
          "value": "{TRIGGER.NAME}"
        },
        {
          "name": "Severity:",
          "value": "{TRIGGER.SEVERITY}"
        },
        {
          "name": "Current Value:",
          "value": "{ITEM.VALUE1}"
        },
        {
          "name": "Time:",
          "value": "{EVENT.DATE} {EVENT.TIME}"
        }
      ]
    }
  ],
  "potentialAction": [
    {
      "@type": "OpenUri",
      "name": "View in Zabbix",
      "targets": [
        {
          "os": "default",
          "uri": "{TRIGGER.URL}"
        }
      ]
    }
  ]
}

カスタム通知スクリプト

LINE通知スクリプト

python
#!/usr/bin/env python3
# /usr/lib/zabbix/alertscripts/line_notify.py

import requests
import sys

def send_line_notify(token, message):
    """LINE Notifyを使用して通知を送信"""
    url = "https://notify-api.line.me/api/notify"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/x-www-form-urlencoded"
    }
    data = {"message": message}
    
    response = requests.post(url, headers=headers, data=data)
    return response.status_code == 200

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: line_notify.py <token> <subject> <message>")
        sys.exit(1)
    
    token = sys.argv[1]
    subject = sys.argv[2]
    message = sys.argv[3]
    
    full_message = f"{subject}\n{message}"
    
    if send_line_notify(token, full_message):
        print("Notification sent successfully")
        sys.exit(0)
    else:
        print("Failed to send notification")
        sys.exit(1)

エスカレーション設定

基本的なエスカレーション

段階的エスカレーション設定

ini
# Step 1: 初期通知(0-30分)
Step duration: 30m
Send to: オンコール担当者
Condition: Default

# Step 2: 上司への通知(30-60分)
Step duration: 30m  
Send to: チームリーダー + オンコール担当者
Condition: Problem not resolved

# Step 3: 管理者への通知(60分以降)
Step duration: 0 (継続)
Send to: システム管理者 + チームリーダー + オンコール担当者
Condition: Problem not resolved

条件付きエスカレーション

深刻度別エスカレーション

ini
# Warning レベル
Step 1: オンコール担当者(即座)
Step 2: チームリーダー(1時間後)

# High レベル  
Step 1: オンコール担当者 + チームリーダー(即座)
Step 2: システム管理者(30分後)

# Disaster レベル
Step 1: 全関係者(即座)
Step 2: 役員レベル(15分後)

時間帯別エスカレーション

ini
# 営業時間内
Condition: Time period in "Business hours"
Step 1: 担当者(5分後)
Step 2: チームリーダー(15分後)

# 営業時間外
Condition: Time period not in "Business hours"  
Step 1: オンコール担当者(即座)
Step 2: オンコール責任者(30分後)

復旧通知の設定

ini
# 問題解決通知
Recovery operations: Enabled
Notify all involved: Yes
Custom recovery message: |
RESOLVED: {TRIGGER.NAME}
Host: {HOST.NAME}
Resolution time: {EVENT.RECOVERY.DATE} {EVENT.RECOVERY.TIME}
Duration: {EVENT.DURATION}

リモートコマンド実行

SSH経由のリモートコマンド

基本設定

ini
# SSH設定
Type: SSH
Username: zabbix
Port: 22
Private key file: /home/zabbix/.ssh/id_rsa

自動復旧コマンド例

bash
# Webサーバー再起動
#!/bin/bash
echo "Restarting web server due to Zabbix alert"
sudo systemctl restart httpd
sleep 5
sudo systemctl status httpd

# ディスク容量クリーンアップ
#!/bin/bash
echo "Cleaning up disk space"
sudo find /tmp -type f -mtime +7 -delete
sudo find /var/log -name "*.log" -mtime +30 -delete
sudo docker system prune -f

# プロセス再起動
#!/bin/bash
SERVICE_NAME=$1
echo "Restarting service: $SERVICE_NAME"
sudo systemctl restart $SERVICE_NAME
sudo systemctl status $SERVICE_NAME

IPMI経由のハードウェア制御

bash
# サーバー再起動
#!/bin/bash
IPMI_HOST=$1
IPMI_USER="admin"
IPMI_PASS="password"

echo "Performing IPMI power cycle on $IPMI_HOST"
ipmitool -I lan -H $IPMI_HOST -U $IPMI_USER -P $IPMI_PASS power cycle

# ハードウェア情報収集
#!/bin/bash
IPMI_HOST=$1
echo "Collecting hardware status from $IPMI_HOST"
ipmitool -I lan -H $IPMI_HOST -U $IPMI_USER -P $IPMI_PASS sensor list
ipmitool -I lan -H $IPMI_HOST -U $IPMI_USER -P $IPMI_PASS sel list last 10

カスタムスクリプト実行

アプリケーション固有の復旧

python
#!/usr/bin/env python3
# /usr/lib/zabbix/externalscripts/auto_recovery.py

import subprocess
import sys
import logging
import json

def restart_application(app_name, host):
    """アプリケーション再起動"""
    try:
        # Docker コンテナの場合
        if app_name.startswith('docker_'):
            container_name = app_name.replace('docker_', '')
            cmd = f"ssh {host} 'docker restart {container_name}'"
        
        # Systemd サービスの場合
        else:
            cmd = f"ssh {host} 'sudo systemctl restart {app_name}'"
        
        result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
        return result.returncode == 0, result.stdout, result.stderr
        
    except Exception as e:
        return False, "", str(e)

def clear_application_cache(app_name, host):
    """アプリケーションキャッシュクリア"""
    cache_commands = {
        'redis': "ssh {host} 'redis-cli FLUSHALL'",
        'memcached': "ssh {host} 'echo flush_all | nc localhost 11211'",
        'nginx': "ssh {host} 'sudo nginx -s reload'"
    }
    
    if app_name in cache_commands:
        cmd = cache_commands[app_name].format(host=host)
        result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
        return result.returncode == 0

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: auto_recovery.py <action> <app_name> <host>")
        sys.exit(1)
    
    action = sys.argv[1]
    app_name = sys.argv[2]  
    host = sys.argv[3]
    
    if action == "restart":
        success, stdout, stderr = restart_application(app_name, host)
        if success:
            print(f"Successfully restarted {app_name} on {host}")
            sys.exit(0)
        else:
            print(f"Failed to restart {app_name}: {stderr}")
            sys.exit(1)
    
    elif action == "clear_cache":
        if clear_application_cache(app_name, host):
            print(f"Successfully cleared cache for {app_name}")
            sys.exit(0)
        else:
            print(f"Failed to clear cache for {app_name}")
            sys.exit(1)

高度なアクション設定

マクロを活用した動的アクション

動的通知内容

ini
# ホスト情報を含む通知
Subject: {ALERT.STATUS}: {TRIGGER.NAME} on {HOST.NAME}

Message: |
Alert Details:
- Host: {HOST.NAME} ({HOST.IP})
- Trigger: {TRIGGER.NAME}
- Severity: {TRIGGER.SEVERITY}
- Current Value: {ITEM.VALUE1}
- Time: {EVENT.DATE} {EVENT.TIME}
- Problem ID: {EVENT.ID}

Host Information:
- Location: {HOST.LOCATION}
- Groups: {HOST.GROUPS}
- Templates: {HOST.TEMPLATES}

Action Required:
{TRIGGER.DESCRIPTION}

Zabbix URL: {TRIGGER.URL}

条件付きマクロ使用

ini
# 深刻度別の色分け
Color macro: {ALERT.COLOR}
Values:
  Information: #36A2EB
  Warning: #FFCE56  
  Average: #FF6384
  High: #FF9F40
  Disaster: #FF6384

# 時間帯別の通知先
{ALERT.SENDTO}
Conditions:
  Business hours: [email protected]
  After hours: [email protected]
  Weekends: [email protected]

イベント相関とグループ化

関連イベントのグループ化

ini
# Problem correlation
Event correlation rules:
1. Close old events: If new event matches pattern
2. Suppress similar events: Same host, similar trigger
3. Group related events: Same service group

# Example rule
Name: Group CPU alerts
Event tag: Service = Web
If event tag value: CPU matches "cpu|CPU"
Operations: 
  - Close old events
  - Create correlated event

自動インシデント作成

json
{
  "incident_creation": {
    "trigger_severity": "High",
    "auto_create": true,
    "incident_fields": {
      "title": "{TRIGGER.NAME} on {HOST.NAME}",
      "description": "{TRIGGER.DESCRIPTION}",
      "priority": "{TRIGGER.SEVERITY}",
      "assigned_team": "{HOST.GROUPS}",
      "tags": ["{HOST.NAME}", "{TRIGGER.SEVERITY}"]
    }
  }
}

トラブルシューティング

一般的な問題と解決策

通知が送信されない

ini
# チェック項目
1. アクション条件の確認
   - ホストグループは正しいか
   - 深刻度フィルターは適切か
   - 時間条件は合っているか

2. メディアタイプ設定の確認
   - SMTP設定は正しいか
   - 認証情報は有効か
   - ポート・プロトコルは正しいか

3. ユーザー設定の確認
   - メディア設定は有効か
   - 深刻度フィルターは適切か
   - 期間設定は正しいか

重複通知の問題

ini
# 重複通知の対策
1. エスカレーション設定の見直し
2. 回復通知の設定
3. イベント相関ルールの活用
4. 通知間隔の調整

# 設定例
Recovery message: Enabled
Default operation step duration: 60s
Pause operations for suppressed problems: Yes

リモートコマンドが実行されない

bash
# デバッグ手順
1. SSH接続テスト
ssh -i /home/zabbix/.ssh/id_rsa user@target_host echo "test"

2. 権限確認
sudo -l -U zabbix

3. ログ確認
tail -f /var/log/zabbix/zabbix_server.log | grep -i "remote command"

4. 手動実行テスト
/usr/lib/zabbix/externalscripts/test_script.sh

監査とログ記録

アクション実行ログ

ini
# ログ設定
Log level: Debug
Log file: /var/log/zabbix/zabbix_server.log

# 監査項目
- アクション実行時刻
- 実行対象ホスト
- 実行コマンド
- 実行結果
- エラーメッセージ

通知履歴の追跡

sql
-- 通知履歴の確認
SELECT 
  a.clock as notification_time,
  h.host as hostname,
  mt.name as media_type,
  a.sendto as recipient,
  a.subject,
  a.status
FROM alerts a
JOIN hosts h ON a.eventid = h.hostid  
JOIN media_type mt ON a.mediatypeid = mt.mediatypeid
WHERE a.clock > UNIX_TIMESTAMP(NOW() - INTERVAL 24 HOUR)
ORDER BY a.clock DESC;

まとめ

Zabbixのイベント・アクションシステムは、監視データに基づく自動化された問題対応を実現する強力な機能です。適切な条件設定、効果的な通知設定、段階的なエスカレーション、自動復旧機能により、迅速で確実な問題解決を支援します。継続的な設定の見直しと最適化により、組織の運用要件に最適化された監視システムを構築できます。

これで第4部「コア監視機能」の全セクションが完了しました。次の第5部では、より高度な設定と管理機能について学習します。


参考リンク

← 前へ: 4.3 トリガーシステム | 目次に戻る