PrometheusとBlackbox Exporterでサーバ死活監視

Prometheusとはオープンソースの監視ツールです。このツールの主な特徴は以下の通りです。

  1. メトリクスの収集をHTTPを通じたPull型で行います。
  2. 柔軟性に富んだクエリで集計した後にグラフとして表示することができます。このクエリのことを公式的に「PromQL」と称しています。
  3. 複数のコンポーネントから構成されています。Prometheus自体は監視サーバであり、GUI部分はGrafana、アラート部分はAlertManagert等のコンポーネントが担っています。

上記の特徴が全て私のニーズにマッチしており、非常にお気に入りのツールになっています。

さて、この記事で取り扱うのはBlackbox Exporterというコンポーネントです。このコンポーネントは各種通信プロトコルを通じて対象サーバの死活状態に関するメトリクスを生成します。Prometheusを運用する上で是非とも押さえておきたいコンポーネントなのですが、このコンポーネントに関する日本語の記事が見受けられません。そこで、備忘録を兼ねて構築から運用までの方法を以下に記します。

構築方法

手軽に監視環境を構築するならDockerを利用することをお勧めします。Dockerイメージは公式のものを利用します。Docker Composeファイルは以下の通りです。

./docker-compose.yml

version: '2'
services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - 9090:9090
    volumes:
      - data-prometheus:/prometheus
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    command: -config.file=/etc/prometheus/prometheus.yml -storage.local.path=/prometheus -web.console.libraries=/usr/share/prometheus/console_libraries -web.console.templates=/usr/share/prometheus/consoles

  blackbox_exporter:
    image: prom/blackbox-exporter:latest
    volumes:
      - ./blackbox_exporter/config.yml:/etc/blackbox_exporter/config.yml

volumes:
  data-prometheus:
    driver: local

Blackbox Exporterの設定

Blackbox Exporterの設定ファイルはGitHubレポジトリのものを流用します。独自でリクエストやレスポンス等の細かい調整ができますので、興味がある方はConfigurationもしくはExampleをご参照ください。

./blackbox_exporter/config.yml

modules:
  http_2xx:
    prober: http
    http:
  http_post_2xx:
    prober: http
    http:
      method: POST
  tcp_connect:
    prober: tcp
  pop3s_banner:
    prober: tcp
    tcp:
      query_response:
      - expect: "^+OK"
      tls: true
      tls_config:
        insecure_skip_verify: false
  ssh_banner:
    prober: tcp
    tcp:
      query_response:
      - expect: "^SSH-2.0-"
  irc_banner:
    prober: tcp
    tcp:
      query_response:
      - send: "NICK prober"
      - send: "USER prober prober prober :prober"
      - expect: "PING :([^ ]+)"
        send: "PONG ${1}"
      - expect: "^:[^ ]+ 001"
  icmp:
    prober: icmp

Prometheusの設定

scrape_configsにて利用したいモジュールを設定します。以下主なプロトコルにおける設定方法を記載します。

HTTPを利用する場合

モジュールとしてhttp_2xxを設定してください。targetsではURLを設定します。再ラベルの設定についてはPrometheus Configurationを流用します。replacementではBlackbox ExporterコンポーネントIPアドレスもしくはホスト名とポート番号(9115)を設定します。

./prometheus/prometheus.yml

scrape_configs:
  - job_name: 'blackbox_http'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
        - http://example.com:8080
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox_exporter:9115

ICMPを利用する場合

モジュールとしてicmpを設定してください。targetsではIPアドレスもしくはホスト名を設定します。

./prometheus/prometheus.yml

scrape_configs:
  - job_name: 'blackbox_icmp'
    metrics_path: /probe
    params:
      module: [icmp]
    static_configs:
      - targets:
        - example.com
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox_exporter:9115

ポート指定のTCPを利用する場合

モジュールとしてtcp_connectを設定してください。targetsではIPアドレスもしくはホスト名とポート番号を設定します。

./prometheus/prometheus.yml

scrape_configs:
  - job_name: 'blackbox'
    metrics_path: /probe
    params:
      module: [tcp_connect]
    static_configs:
      - targets:
        - example.com:1666
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox_exporter:9115

運用方法

対象サーバの死活状態についてはprobe_successメトリクスを確認します。1であれば稼働、0であれば停止を意味します。

f:id:mmorita44:20170823172251p:plain

Prometheusのアラートルールに以下の記述を追加すれば、2分間以上停止したインスタンスが存在した場合にアラートが作動します。実際のアラート通知に関してはAlertManagerコンポーネントが受け持ちます。このコンポーネントについては対象範囲外のため説明は割愛します。

ALERT probe_down
  IF probe_success == 0
  FOR 2m
  LABELS { severity = "critical" }
  ANNOTATIONS {
    summary = "Instance {{ $labels.instance }} down",
    description = "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 2 minutes.",
  }

最後に

快適なPrometheus生活をお過ごしください。