kintoneに乗るっ!

非エンジニアが勉強がてら kintone で遊ぶブログ

Prometheus&Alertmanager&kintoneで監視・エスカレーション体制を実現しよう!

f:id:ibukintone:20210702103142p:plain

最近やや疲れ気味のいぶろぐです。

近年サーバー監視界隈でその名を耳にすることが多くなった「Prometheus」。

Alertmanager」というアラート管理システムと一緒に使うことで、Slackやメールに通知を飛ばすことができます。

kintoneとうまく組み合わせれば、いい感じのエスカレーション体制を作れそう!

やりたいこと

  1. Prometheusでメトリクス収集
  2. 異常発生でアラートが発火、Alertmanagerに通知
  3. AlertmanagerがWebhookを自作ハンドラーに送信
  4. 自作ハンドラーがkintoneにレコードを登録

今回はちょっと技術的な記事になります。需要あんのかね。

kintoneアプリ作成

まずはデータを登録するkintoneアプリを作成します。 f:id:ibukintone:20210701230210p:plain

フィールドとフィールドコードは以下の通り。

フィールド名 フィールド フィールドコード
アラート 文字列1行 alertname
作成日時 文字列1行 starts_at
概要 文字列複数行 summary


フィールド配置後、下記の作業も行って、アプリを保存します。

  • レコード追加権限のあるAPIトークンの発行
  • プロセス管理の有効化

監視システムセットアップ

次は監視システムを構築していきます。事前に次の環境を準備しておいてください。

  • docker
  • docker-compose

各設定ファイルを配置したディレクトリ構造は次のようになります。確認できたら、設定ファイルを記述していきます。

├── alertmanager
│   └── config.yaml
├── docker-compose.yaml
└── prometheus
    ├── alert.rules
    └── prometheus.yaml

docker-compose.yamlの内容はQiitaを参考に。Node-Exporterコンテナはローカルのprocから情報を取りたいので、rootディレクトリを読み込み専用でマウントしています。

version: '3'
services:
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    volumes:
      - ./prometheus:/etc/prometheus
    command: "--config.file=/etc/prometheus/prometheus.yaml"
    ports:
      - 9090:9090
    restart: always
  exporter:
    image: prom/node-exporter
    container_name: node-exporter
    ports:
      - 9100:9100
    command:
      - '--path.rootfs=/host'
    network_mode: host
    pid: host
    volumes:
      - '/:/host:ro,rslave'
    restart: always
  alertmanager:
    image: prom/alertmanager
    container_name: alertmanager
    volumes:
      - ./alertmanager:/etc/alertmanager
    command: "--config.file=/etc/alertmanager/config.yaml"
    ports:
      - 9093:9093
    restart: always

続いてPrometheusの設定ファイルprometheus.yamlを準備。アラート送信先やメトリクスの収集対象を記述します。

global:
  scrape_interval:     15s 
  evaluation_interval: 15s 

rule_files:
  - /etc/prometheus/alert.rules

alerting:
  alertmanagers:
    - scheme: http
      static_configs:
      - targets:
        - alertmanager:9093

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets:
        -  prometheus:9090
        -  ホストのIPアドレス:9100

alert.rulesでPrometheusのアラート発火条件を設定します。今回はサーバーが1分ダウンしたら通知するようにしました。

groups:
- name: example
  rules:
  - alert: instance_down
    expr: up == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "{{ $labels.instance }} がダウンしました..."

Alertmanagerのconfig.yamlの内容。アラートを受信したら自作ハンドラーにWebhookを飛ばします。

route:
  receiver: 'handler'

receivers:
- name: 'handler'
  webhook_configs:
    - url: 'http://handler:9083'
      send_resolved: true

以上で監視システム部分の設定は完了!

自作ハンドラー開発

続いてAlertmanagerから受け取ったWebhookをkintoneに飛ばすハンドラーを開発します。ハンドラーを追加した最終的なディレクトリ構造は以下のようになります。

├── alertmanager
│   └── config.yaml
├── docker-compose.yaml
├── handler
│   ├── account.yaml
│   ├── Dockerfile
│   └── handler.py
└── prometheus
    ├── alert.rules
    └── prometheus.yaml

ちょうどQiitaに参考になりそうな記事がありました。 qiita.com

上の記事を参考にしてコードを書き書き。レコード登録にはpykintoneを使っています。

import json
import logging
from http.server import BaseHTTPRequestHandler
from http.server import HTTPServer
import pykintone
from pykintone import model

# ログ関連設定
logging.basicConfig(level=logging.DEBUG, format="%(asctime)-15s %(message)s")
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

class TroubleHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        self.send_response(200)
        self.end_headers()
        data = json.loads(self.rfile.read(int(self.headers['Content-Length'])))

        alert_data = self.build_alert_data(data)
        logging.info("recieved data:%s" % alert_data)
        self.create_alert_kintone_record(alert_data, data["status"])

    # Webhookのデータからアラートデータを作成
    def build_alert_data(self, data):
        alert_data = {
            "status": data["status"],
            "alertname": data["alerts"][0]["labels"]["alertname"],
            "starts_at": data["alerts"][0]["startsAt"],
            "summary": data["alerts"][0]["annotations"]["summary"]
        }
        return alert_data
    
   # kintoneにレコード登録
    def create_alert_kintone_record(self, alert_data, alert_status):
        k = KintonePoster()
        k.create_alert_kintone(alert_data)

# kintoneアプリのフィールドに合わせてpykintoneのModelを定義
class KintoneModel(model.kintoneModel):
    def __init__(self):
        super(KintoneModel, self).__init__()
        self.alertname = ""
        self.starts_at = ""
        self.summary = ""
# pykintoneを使ってkintoneにレコード登録
class KintonePoster(KintoneModel):
    def create_alert_kintone(self, data):
        if data["status"] == "firing":
            account = pykintone.load("account.yaml")
            app = account.app()

            record = KintoneModel()
            record.alertname = data["alertname"]
            record.starts_at = data["starts_at"]
            record.summary = data["summary"]

            app.create(record)

if __name__ == "__main__":
    httpd = HTTPServer(('', 9083), TroubleHandler)
    httpd.serve_forever()

pykintoneに読み込ませる認証情報をaccount.yamlに記述します。

domain: サブドメイン
apps:
  test:
    id: アプリID
    token: APIトークン

最後に、先ほど書いたPythonを実行するコンテナの元となるDockerfileを記述。pykintoneをpipでインストールしておきます。

FROM python:3
USER root

RUN mkdir -p /root/src
COPY handler.py /root/src
COPY account.yaml /root/src
WORKDIR /root/src

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install pykintone

ENTRYPOINT ["python"]
CMD ["handler.py"]

動作確認

docker-compose.yamlが配置されたディレクトリ内で、次のコマンドを実行。コンテナ群を起動しましょう。

docker-compose up -d

ブラウザでhttp://サーバーのIPアドレス:9090にアクセスすると、Prometheusが表示されるはず。 f:id:ibukintone:20210628222845p:plain

通知動作の確認をしたいので、擬似的にサーバーダウンした状態を作ります。Node-Exporterコンテナを停止してみましょう。

docker stop node-exporter

1分後待って、ブラウザでhttp://サーバーのIPアドレス:9093にアクセスしてAlertmanagerを確認しましょう。ちゃんとアラートが飛んでいるはずです。 f:id:ibukintone:20210701235059p:plain

kintoneのアプリも確認。レコードが登録されていますね! f:id:ibukintone:20210702101446p:plain

登録されたレコード上でプロセス管理を使えば、いい感じに担当者割り当てやエスカレーションを実現できます! f:id:ibukintone:20210701235547p:plain

Prometheus&Alertmanager&kintoneでいい感じに監視・エスカレーションシステムを実現してみました。

PrometheusとAlertmanagerの設定はガバガバなので、もっと丁寧にできると思います。

ではでは〜。