AlertmanagerでSMSとTelegramアラートを設定する方法

Monitoring tutorial - IT technology blog
Monitoring tutorial - IT technology blog

問題の概要

あなたのITシステムは毎日スムーズに稼働しているかもしれませんが、問題が発生したらどうなるでしょうか?サーバーが突然停止したり、重要なサービスでエラーが発生したり、システムリソースが危険なレベルに達したりするかもしれません。信頼できるアラートシステムがなければ、ユーザーが不満を言い始めてから初めて問題に気づくかもしれません。その時までに、結果は非常に深刻になっている可能性があります。

監視(モニタリング)は、安定したシステムを維持するための最初かつ不可欠なステップです。しかし、監視だけでは十分ではありません。いつでもどこでも即座に通知を受け取れる効果的なアラートシステムが必要です。この記事では、PrometheusのコアコンポーネントであるAlertmanagerを設定し、SMSとTelegram経由でアラートを送信する方法を説明します。これらは、管理者にとって非常に適した、迅速で信頼性の高い通知チャネルです。

監視の設定を始めたばかりの頃、私も「アラート疲れ」を経験しました。無数の重要ではないアラートによって圧倒され、本当に深刻な問題をほとんど見逃すところでした。しきい値(threshold)の調整とAlertmanagerの設定に多くの時間を費やしました。目標は、本当に必要な場合にのみ通知する、バランスの取れたアラートシステムを構築することでした。そのため、基本的な設定ガイドに加えて、最初から「アラート疲れ」を避けるのに役立つ経験も共有します。

コアコンセプト

効果的なアラートを設定するには、まずこのプロセスに関わる主要なコンポーネントを理解する必要があります。

Prometheus: 監視システムの心臓

この記事はAlertmanagerに焦点を当てていますが、Prometheusを無視することはできません。これはオープンソースの監視およびアラートシステムであり、設定されたターゲットからメトリクスを収集することに特化しています。メトリクスがしきい値を超えると、Prometheusはアラートを生成します。ただし、直接送信するのではなく、Alertmanagerに転送します。

Alertmanager: アラート処理の頭脳

Alertmanagerは独立したコンポーネントです。Prometheus(または他のソース)からアラートを受け取り、事前に設定されたルールに基づいて処理します。Alertmanagerの主な機能は次のとおりです。

  • グルーピング (Grouping): 複数の類似アラートを単一の通知にまとめます。例えば、10台のサーバーが同時にディスク容量エラーを報告した場合、Alertmanagerは個別の10通のメッセージではなく、1つの共通通知を送信します。
  • 抑制 (Inhibition): プライマリアラートがアクティブになったときに、依存するアラートをブロックします。例えば、メインサーバーが接続喪失を報告した場合、Alertmanagerはそのサーバーで実行されているサービスに関するアラートを自動的に抑制します。
  • サイレンス (Silencing): 特定の期間(例:システムメンテナンス中)アラートを一時的に無効にします。
  • ルーティング (Routing): アラートのラベルに基づいて、さまざまなレシーバー(受信者)にアラートを送信します。レシーバーは、Eメール、Slack、PagerDuty、Webhookなどです。この記事では、TelegramとSMSに焦点を当てます。

なぜSMSとTelegramなのか?

現代のシステム環境において、タイムリーなアラート受信は極めて重要な要素です。

  • Telegram: 人気のあるメッセージングアプリであるTelegramは、柔軟なボットAPIを提供しており、通知の送信との統合が容易です。主な利点:完全に無料で、メールよりも多くの情報を送信でき、ほぼ瞬時に通知されます。これは技術チームにとって非常に便利なツールです。
  • SMS: 「古典的」に見えるかもしれませんが、SMSは依然として非常に信頼性の高い通知チャネルです。特に緊急事態でインターネット接続がない場合やメッセージングアプリが機能しない場合でも、SMSは機能します。すべての携帯電話で利用でき、特別なアプリは必要ありません。SMSは、最も深刻なアラートにとって重要なフォールバックチャネルです。

詳細な実践: Alertmanagerによるアラート設定

開始するにあたり、PrometheusとAlertmanagerが既に稼働していることを前提とします。まだの場合、itfromzero.comのPrometheusとGrafanaのインストールガイドを参照するか、Dockerを使用して迅速にセットアップできます。

1. Telegram通知の設定

Telegramは、その柔軟性と完全無料であることから、人気のあるアラートチャネルです。

ステップ1: Telegram Botを作成し、Bot Tokenを取得する

  1. Telegramアプリを開き、@BotFatherを検索します。
  2. @BotFatherとの会話を開始し、/newbotと入力します。
  3. ガイドに従って、ボットの名前(例:itfromzero_alert_bot)と一意のユーザー名(例:itfromzero_alert_bot)を設定します。
  4. 完了後、@BotFatherからHTTP API Tokenが提供されます。このトークンを慎重に保存してください。例:123456789:ABCDEFGH-IJKLMN_OPQRSTUVXYZ

ステップ2: グループまたはユーザーのChat IDを取得する

Alertmanagerは、メッセージをどこに送信するかを知る必要があります。これは個人またはグループにすることができます。

  1. Telegramでボットを検索して会話を開始するか、アラートを受け取りたいグループチャットにボットを追加します。
  2. ボットまたはボットがいるグループチャットに任意のメッセージを送信します。
  3. ブラウザを開き、次のURLにアクセスします(<BOT_TOKEN>をあなたのトークンに置き換えてください):
    https://api.telegram.org/bot<BOT_TOKEN>/getUpdates
  4. JSON応答を受け取ります。chatフィールドとidフィールドを探してください。これがあなたが必要とするchat_idです。グループの場合、IDは負の数値になります(例:-123456789)。

ステップ3: Alertmanagerの設定 (alertmanager.yaml) を編集する

alertmanager.yamlファイルにreceiversroutesのセクションを追加または編集します。

# alertmanager.yaml
route:
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 1h
  receiver: 'default-receiver' # デフォルトのレシーバー設定

  routes:
  - match:
      severity: 'critical' # 'critical'の重大度を持つアラート
    receiver: 'telegram-critical'
  - match:
      severity: 'warning' # 'warning'の重大度を持つアラート
    receiver: 'telegram-warning'
  # ここに他のルールを追加できます

receivers:
  - name: 'default-receiver'
    # デフォルトのアラートを望まない場合は、何らかのデフォルトレシーバーを設定するか、空にすることができます。
    # telegram_configs:
    #   - chat_id: '<CHAT_ID_DEFAULT>'
    #     parse_mode: 'HTML'

  - name: 'telegram-critical'
    telegram_configs:
      - bot_token: '<YOUR_BOT_TOKEN>'
        chat_id: '<CRITICAL_GROUP_CHAT_ID>' # Criticalアラートを受け取るグループ/ユーザーのChat ID
        parse_mode: 'HTML'
        send_resolved: true # アラートが解決されたときに通知を送信する

  - name: 'telegram-warning'
    telegram_configs:
      - bot_token: '<YOUR_BOT_TOKEN>'
        chat_id: '<WARNING_GROUP_CHAT_ID>' # Warningアラートを受け取るグループ/ユーザーのChat ID
        parse_mode: 'HTML'
        send_resolved: true

:ルーティング機能を示すために、criticalwarningに異なるchat_idを使用しています。必要であれば、すべてのアラートに同じchat_idを使用することも可能です。<BOT_TOKEN_CUA_BAN><CHAT_ID_NHOM_CRITICAL><CHAT_ID_NHOM_WARNING>を実際の情報に置き換えてください。

ステップ4: Alertmanagerの設定をリロードする

alertmanager.yamlファイルを変更した後、Alertmanagerが変更を適用するために設定をリロードする必要があります。

# Alertmanagerをサービスとして実行している場合
sudo systemctl reload alertmanager

# または、有効にしている場合はAPI経由で(推奨)
curl -XPOST http://localhost:9093/-/reload

ステップ5: Telegramアラートをテストする

テストするには、Prometheusでダミーアラートを作成するか、実際のアラート状況をトリガーする必要があります。

Prometheusでのテストアラート設定例:

prometheus.ymlファイル(またはあなたのルールファイル)に追加します:

# prometheus.yml
# ...
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093'] # あなたのAlertmanagerアドレス

rule_files:
  - "alert_rules.yml" # このファイルがPrometheusによって読み込まれることを確認してください
# ...

alert_rules.ymlファイル:

# alert_rules.yml
groups:
- name: general.rules
  rules:
  - alert: HighLoadTest
    expr: node_load1 > 0.01 # トリガーしやすくするためにこのしきい値を変更してください
    for: 1s
    labels:
      severity: 'critical' # telegram-criticalルートに合わせるため
    annotations:
      summary: "Server {{ $labels.instance }} の負荷が高い (テスト)"
      description: "{{ $labels.instance }} の1分間の平均負荷は {{ $value }} です。"
  - alert: LowDiskSpaceTest
    expr: node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100 < 90 # 空き容量が90%未満
    for: 1s
    labels:
      severity: 'warning' # telegram-warningルートに合わせるため
    annotations:
      summary: "{{ $labels.instance }} 上の {{ $labels.mountpoint }} ディスクが満杯になりそう (テスト)"
      description: "{{ $labels.instance }} の空き容量は残り {{ $value | humanizePercentage }} です。"

Prometheusの設定をリロードする:


curl -XPOST http://localhost:9090/-/reload

すべてが正しく設定されていれば、これらのアラート条件がトリガーされたときにすぐにTelegramメッセージを受け取ることができます。

2. SMS通知の設定 (Webhookとカスタムスクリプト経由)

Alertmanagerには直接的なSMS統合がありません。そのため、Webhookとカスタムスクリプトを組み合わせてSMS Gatewayサービスを呼び出します。この方法は、高い柔軟性とカスタマイズ性を提供します。

ステップ1: WebhookとSMS Gatewayのメカニズムを理解する

  1. Webhook: Alertmanagerは、アラートが発生したときに、指定したURLにHTTP POSTリクエストを送信します。このリクエストには、JSON形式のアラートの詳細情報が含まれます。
  2. Custom Script/Service: 小さなアプリケーション(例:FlaskでPythonで記述)を実行します。このアプリケーションはAlertmanagerからのPOSTリクエストをリッスンします。リクエストを受信すると、スクリプトはJSONを解析し、必要な情報を取得して、SMSプロバイダー(Twilio、Nexmo、または国内SMSサービスなど)のAPIを呼び出します。

ステップ2: SMS Gatewayサービス(概念)を準備する

簡単にするために、基本的なPythonスクリプトを示します。実際には、SMSプロバイダーのAPIと統合する必要があります。このスクリプトは、Webhookを受信して情報を処理する方法を示すだけです。

sms_gateway.pyファイルが次のようにあると仮定します:

# sms_gateway.py (これはデモンストレーションスクリプトです。SMSプロバイダーに合わせて自分で開発する必要があります)
from flask import Flask, request, jsonify
import os

app = Flask(__name__)

# 実際のSMS受信電話番号に置き換えてください
TARGET_PHONE_NUMBER = os.environ.get("TARGET_PHONE_NUMBER", "+849xxxxxxxx") 

@app.route('/sms-alert', methods=['POST'])
def send_sms_alert():
    try:
        alert_data = request.get_json()
        
        # Alertmanagerからのアラート情報を処理する
        # SMSの内容をどのように表示するかをカスタマイズする必要があります
        for alert in alert_data.get('alerts', []):
            alertname = alert['labels'].get('alertname', 'Unknown Alert')
            severity = alert['labels'].get('severity', 'info')
            instance = alert['labels'].get('instance', 'Unknown Instance')
            summary = alert['annotations'].get('summary'!, 'No Summary')
            
            # SMSメッセージの内容を作成する
            sms_message = f"[ITFZS] {severity.upper()} - {alertname} on {instance}: {summary}"
            
            print(f"SMSを{TARGET_PHONE_NUMBER}に送信中: {sms_message}")
            
            # --- ここで、SMSプロバイダーのAPIを呼び出します ---
            # 仮のAPIの例:
            # import requests
            # sms_api_url = "https://api.sms_provider.com/send"
            # payload = {
            #     "to": TARGET_PHONE_NUMBER,
            #     "message": sms_message,
            #     "api_key": os.environ.get("SMS_API_KEY")
            # }
            # response = requests.post(sms_api_url, json=payload)
            # if response.status_code == 200:
            #     print("SMSが正常に送信されました!")
            # else:
            #     print(f"SMSの送信に失敗しました: {response.status_code} - {response.text}")
            # ---
            
            # この例では、コンソールに出力するだけです
            print("SMSアラートが(概念的に)処理されました。")

        return jsonify({"status": "success", "message": "SMSアラートが概念的に処理されました。"}), 200
    except Exception as e:
        print(f"SMSアラートの処理中にエラーが発生しました: {e}")
        return jsonify({"status": "error", "message": str(e)}), 500

if __name__ == '__main__':
    # このスクリプトをポート(例:9099)で実行します
    # Alertmanagerからアクセスできることを確認してください
    print("ポート9099でSMS Gatewayモックアップを開始します...")
    app.run(host='0.0.0.0', port=9099)

このスクリプトを実行するには、Flaskをインストールし(pip install Flask)、実行する必要があります:


export TARGET_PHONE_NUMBER="+849xxxxxxxx" # 実際の電話番号に置き換えてください
<a href="https://itfromzero.com/ja/python-vi-ja/venv-%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89-%e3%81%99%e3%81%b9%e3%81%a6%e3%81%ae%e3%83%97%e3%83%ad%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%81%a7-python-%e4%bb%ae%e6%83%b3%e7%92%b0%e5%a2%83.html">python</a> sms_gateway.py

このスクリプトが継続的に実行され、Alertmanagerからアクセスできることを確認してください(同じサーバー上、または別のサーバーに配置されている場合はネットワーク経由)。

ステップ3: SMS用のAlertmanager設定 (alertmanager.yaml) を編集する

webhook_configsを使用して、SMS Gatewayスクリプトを指す新しいreceiverを追加します。

# alertmanager.yaml (上記Alertmanager設定ファイルに追加)
# ...
route:
  # ... (既存のルートセクション)
  routes:
  - match:
      severity: 'critical'
    receiver: 'sms-critical' # CriticalアラートをSMSにルーティングする
  - match:
      severity: 'emergency' # 例えば、極めて緊急の重大度を追加
    receiver: 'sms-critical' # 緊急アラートもSMS経由で送信される
  # ... (その他のルート)

receivers:
  # ... (既存のTelegramレシーバー)
  - name: 'sms-critical'
    webhook_configs:
      - url: 'http://localhost:9099/sms-alert' # カスタムSMS GatewayスクリプトのURL
        send_resolved: true
        # スクリプトが認証を必要とする場合は、http_configを設定できます
        # http_config:
        #   basic_auth:
        #     username: 'smsuser'
        #     password: 'smspassword'

http://localhost:9099/sms-alertを、sms_gateway.pyスクリプトが実行されている実際のIPアドレスまたはドメインに置き換えてください。

ステップ4: Alertmanagerの設定をリロードしてテストする

Telegramの場合と同様にAlertmanagerの設定をリロードします。


curl -XPOST http://localhost:9093/-/reload

Prometheusのalert_rules.ymlを更新できます。severity: 'critical'(またはemergency)のアラートを作成してテストしてください。sms_gateway.pyスクリプトがWebhookを受信し、メッセージを出力するかどうかを確認します。sms_gateway.pyのコンソールにSending SMS to ...という行が表示された場合、AlertmanagerはWebhookを正常に送信しています。次のステップは、このスクリプトを実際のSMSプロバイダーのAPIと統合することです。

3. アラートの最適化と「アラート疲れ」の回避

共有したように、「アラート疲れ」は大きな問題です。Alertmanagerはアラートフローを管理するための多くの便利な機能を提供します。

  • グルーピング (Grouping):
    routegroup_bygroup_waitgroup_intervalrepeat_intervalを使用します。これにより、多くの類似アラートが同時に発生したときに「スパム」状態になるのを防ぐことができます。

    route:
      group_by: ['alertname', 'instance', 'severity'] # アラート名、インスタンス、および重大度でグループ化する
      group_wait: 30s # 送信する前に30秒待って追加のアラートを収集する
      group_interval: 5m # グループ内に新しいアラートがある場合、再送信する前にさらに5分待つ
      repeat_interval: 4h # 解決されていない場合、4時間ごとにアラートを繰り返す
      receiver: 'default-receiver'
    

    この設定により、Alertmanagerは同じインスタンス上の同じ問題に関連するアラートをグループ化します。その結果、受け取る通知の数が大幅に減少します。

  • 抑制 (Inhibition):
    プライマリアラートがアクティブになったときに、「セカンダリ」アラートをブロックします。例えば、サーバー全体がダウンした場合、そのサーバーに関する通知のみを受け取りたいはずです。そのサーバーで実行されているサービスに関する数十のアラートを受け取りたくはないでしょう。

    # alertmanager.yaml
    inhibit_rules:
    - source_match:
        severity: 'critical' # サーバーダウンに関するアラートの重大度は 'critical'
      target_match:
        severity: 'warning' # サービスに関するアラートの重大度は 'warning'
      equal: ['instance'] # 同じインスタンス上で発生した場合に適用する
    # このルールは次のように述べています:特定の 'instance' で 'critical' アラートが発生した場合、
    # その同じ 'instance' 上の他のすべての 'warning' アラートを抑制します。
    
  • サイレンス (Silences):
    メンテナンスイベントや一時的な問題が事前に分かっている場合は、Alertmanagerのウェブインターフェース(通常はhttp://localhost:9093)からsilenceを作成してください。この機能は、特定期間アラートを一時的に停止するのに役立ち、問題に積極的に対処しているときやシステムをアップグレードしているときに非常に便利です。

これらの機能を賢く利用することで、効果的なアラートシステムを構築できます。このシステムはコア情報のみに焦点を当て、アラート疲れを避け、あらゆる問題に迅速に対応できるよう支援します。

結論

効果的な監視およびアラートシステムのセットアップは、安定したITシステムにとって不可欠な要素です。この記事では、Alertmanagerを設定してTelegramとSMSにアラートを送信する方法を学びました。これらは強力で信頼性の高い2つの通知チャネルです。

Telegramを統合することで、チームは無料で迅速かつ充実した情報のアラートを受け取ることができます。一方、SMSは最後の警報レイヤーとして機能します。これにより、最も過酷な状況下でも、問題に関する情報を把握できます。

今日から設定を開始して、システムの対応能力を向上させ、安定性を維持してください。適切に設定されたアラートシステムは、安心感を与えるだけでなく、プロフェッショナルで信頼性の高いITインフラストラクチャの証となります。

Share: