マルチターゲットエクスポーター パターンの理解と使用

このガイドでは、マルチターゲットエクスポーター パターンについて説明します。これを実現するために、

  • マルチターゲットエクスポーター パターンとその使用理由を説明します。
  • 例として、blackbox エクスポーターを実行します。
  • blackbox エクスポーターのカスタムクエリモジュールを設定します。
  • blackbox エクスポーターに Prometheus の ウェブサイトに対して基本的なメトリッククエリを実行させます。
  • relabeling を使用して、Prometheus がエクスポーターをスクレイピングするように設定する一般的なパターンを調べます。

マルチターゲットエクスポーター パターンとは?

マルチターゲット エクスポーター パターンとは、特定の設計を指します。

  • エクスポーターはネットワーク プロトコル経由でターゲットのメトリックを取得します。
  • エクスポーターは、メトリックが取得されるマシン上で実行される必要はありません。
  • エクスポーターは、Prometheus の GET リクエストのパラメータとしてターゲットとクエリ設定文字列を取得します。
  • エクスポーターは、Prometheus の GET リクエストを受信した後、スクレイピングを終了したらスクレイピングを開始します。
  • エクスポーターは複数のターゲットをクエリできます。

このパターンは、blackboxSNMP exporter などの特定のエクスポーターでのみ使用されます。

その理由は、SNMP を話すネットワーク機器のようにターゲット上でエクスポーターを実行できない場合や、ネットワーク外部の特定のポイントからウェブサイトへの距離(レイテンシや到達可能性)に特に興味がある場合(blackbox エクスポーターの一般的なユースケース)です。

マルチターゲットエクスポーターの実行

マルチターゲットエクスポーターは、環境に対して柔軟であり、多くの方法で実行できます。通常のプログラムとして、コンテナ内、バックグラウンドサービスとして、ベアメタル上で、仮想マシン上で。ネットワーク経由でクエリし、クエリを実行するため、適切なオープンポートが必要です。それ以外は控えめです。

それでは、ご自身で試してみましょう!

ターミナルでこれを実行して、Docker を使用して blackbox エクスポーター コンテナを開始します。システム構成によっては、コマンドの前に sudo を追加する必要がある場合があります。

docker run -p 9115:9115 prom/blackbox-exporter

いくつかのログ行が表示され、すべてがうまくいけば、最後の行は msg="Listening on address" と報告されるはずです。

level=info ts=2018-10-17T15:41:35.4997596Z caller=main.go:324 msg="Listening on address" address=:9115

マルチターゲットエクスポーターの基本的なクエリ

クエリの方法は 2 つあります。

  1. エクスポーター自体にクエリする。エクスポーターには独自のメトリックがあり、通常は /metrics で利用できます。
  2. 他のターゲットをスクレイプするためにエクスポーターにクエリする。通常は「説明的な」エンドポイント、例えば /probe で利用できます。これは、マルチターゲットエクスポーターを使用する場合、おそらくあなたが最も関心のあることです。

別のターミナルで curl を使用して最初のクエリタイプを試すこともできます。または、この リンク を使用してください。

curl 'localhost:9115/metrics'

応答は次のようになります。

# HELP blackbox_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, and goversion from which blackbox_exporter was built.
# TYPE blackbox_exporter_build_info gauge
blackbox_exporter_build_info{branch="HEAD",goversion="go1.10",revision="4a22506cf0cf139d9b2f9cde099f0012d9fcabde",version="0.12.0"} 1
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 9

[…]

# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 0.05
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 1.048576e+06
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 7
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 7.8848e+06
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.54115492874e+09
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 1.5609856e+07

これらは Prometheus フォーマットのメトリックです。エクスポーターの インストルメンテーション から取得され、実行中のエクスポーター自体の状態について教えてくれます。これはホワイトボックスモニタリングと呼ばれ、日常の運用で非常に役立ちます。興味がある場合は、独自のアプリケーションをインストルメントする方法に関するガイドを試してみてください。

2 番目のクエリタイプでは、HTTP GET リクエストのパラメータとしてターゲットとモジュールを指定する必要があります。ターゲットは URI または IP で、モジュールはエクスポーターの設定で定義されている必要があります。blackbox エクスポーター コンテナには、意味のあるデフォルト設定が付属しています。ターゲット prometheus.io と定義済みのモジュール http_2xx を使用します。これは、ブラウザで prometheus.io にアクセスした場合のようにエクスポーターに GET リクエストを実行させ、200 OK レスポンスを期待するように指示します。

これで、ターミナルで curl を使用して blackbox エクスポーターに prometheus.io をクエリするように指示できます。

curl 'localhost:9115/probe?target=prometheus.io&module=http_2xx'

これにより、多くのメトリックが返されます。

# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds
# TYPE probe_dns_lookup_time_seconds gauge
probe_dns_lookup_time_seconds 0.061087943
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds 0.065580871
# HELP probe_failed_due_to_regex Indicates if probe failed due to regex
# TYPE probe_failed_due_to_regex gauge
probe_failed_due_to_regex 0
# HELP probe_http_content_length Length of http content response
# TYPE probe_http_content_length gauge
probe_http_content_length 0
# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects
# TYPE probe_http_duration_seconds gauge
probe_http_duration_seconds{phase="connect"} 0
probe_http_duration_seconds{phase="processing"} 0
probe_http_duration_seconds{phase="resolve"} 0.061087943
probe_http_duration_seconds{phase="tls"} 0
probe_http_duration_seconds{phase="transfer"} 0
# HELP probe_http_redirects The number of redirects
# TYPE probe_http_redirects gauge
probe_http_redirects 0
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
probe_http_ssl 0
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
probe_http_status_code 0
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
probe_http_version 0
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
probe_ip_protocol 6
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
probe_success 0

ほとんどのメトリックの値が 0 であることに注意してください。最後の probe_success 0 という値は、プロバーが prometheus.io に正常に到達できなかったことを意味します。その理由は、値が 6probe_ip_protocol メトリックに隠されています。デフォルトでは、プロバーは明示的に指示されない限り IPv6 を使用します。しかし、Docker デーモンは明示的に指示されない限り IPv6 をブロックします。そのため、Docker コンテナで実行されている blackbox エクスポーターは IPv6 で接続できません。

ここで、Docker に IPv6 を許可するように指示するか、blackbox エクスポーターに IPv4 を使用するように指示することができます。実際の状況ではどちらも理にかなっており、多くの場合、「何をすべきか」という質問への答えは「状況によります」となります。これはエクスポーターのガイドなので、エクスポーターを変更し、カスタムモジュールを設定する機会を得ます。

モジュールの設定

モジュールは、docker コンテナ内の config.yml というファイルに事前に定義されています。これは、GitHub リポジトリの blackbox.yml のコピーです。

このファイルをコピーし、ニーズに合わせて適応 させ、エクスポーターにコンテナに含まれる設定ファイルではなく、私たち独自のコンフィグファイルを使用するように指示します。

まず、curl またはブラウザを使用してファイルをダウンロードします。

curl -o blackbox.yml https://raw.githubusercontent.com/prometheus/blackbox_exporter/master/blackbox.yml

エディタで開きます。最初の数行は次のようになります。

modules:
  http_2xx:
    prober: http
  http_post_2xx:
    prober: http
    http:
      method: POST

YAML は階層を表現するために空白のインデントを使用するため、http_2xxhttp_post_2xx という 2 つの modules が定義されており、どちらも http プロバーを持ち、一方ではメソッド値が具体的に POST に設定されていることがわかります。ここで、モジュール http_2xx を、プロバー httppreferred_ip_protocol を明示的に文字列 ip4 に設定することで変更します。

modules:
  http_2xx:
    prober: http
    http:
      preferred_ip_protocol: "ip4"
  http_post_2xx:
    prober: http
    http:
      method: POST

利用可能なプロバーとオプションについて詳しく知りたい場合は、ドキュメント を参照してください。

次に、blackbox エクスポーターに、新しく変更したファイルを使用するように指示する必要があります。これは --config.file="blackbox.yml" フラグで行えます。しかし、Docker を使用しているため、このファイルをコンテナ内で 利用可能 にする必要があり、--mount コマンドを使用します。

macOS を使用している場合は、まず Docker デーモンに blackbox.yml があるディレクトリへのアクセスを許可する必要があります。これは、メニューバーの小さな Docker のクジラをクリックし、次に Preferences -> File Sharing -> + をクリックすることで行えます。その後、Apply & Restart を押します。

まず、ターミナルで古いコンテナを停止します(ctrl+c を押します)。blackbox.yml を含むディレクトリにいることを確認してください。次に、このコマンドを実行します。これは長いですが、説明します。

docker \
  run -p 9115:9115 \
  --mount type=bind,source="$(pwd)"/blackbox.yml,target=/blackbox.yml,readonly \
  prom/blackbox-exporter \
  --config.file="/blackbox.yml"

このコマンドで、docker に次のように指示しました。

  1. コンテナを run し、コンテナの外側のポート 9115 をコンテナ内のポート 9115 にマッピングします。
  2. 現在のディレクトリ($(pwd) は作業ディレクトリを表示します)の blackbox.yml ファイルを readonly モードで /blackbox.ymlmount します。
  3. prom/blackbox-exporter イメージを Docker hub から使用します。
  4. --config.file フラグを使用して blackbox-exporter を実行し、/blackbox.yml を設定ファイルとして使用するように指示します。

すべてが正しければ、次のようなものが表示されるはずです。

level=info ts=2018-10-19T12:40:51.650462756Z caller=main.go:213 msg="Starting blackbox_exporter" version="(version=0.12.0, branch=HEAD, revision=4a22506cf0cf139d9b2f9cde099f0012d9fcabde)"
level=info ts=2018-10-19T12:40:51.653357722Z caller=main.go:220 msg="Loaded config file"
level=info ts=2018-10-19T12:40:51.65349635Z caller=main.go:324 msg="Listening on address" address=:9115

これで、ターミナルで新しい IPv4 を使用するモジュール http_2xx を試すことができます。

curl 'localhost:9115/probe?target=prometheus.io&module=http_2xx'

これにより、次のような Prometheus メトリックが返されるはずです。

# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds
# TYPE probe_dns_lookup_time_seconds gauge
probe_dns_lookup_time_seconds 0.02679421
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds 0.461619124
# HELP probe_failed_due_to_regex Indicates if probe failed due to regex
# TYPE probe_failed_due_to_regex gauge
probe_failed_due_to_regex 0
# HELP probe_http_content_length Length of http content response
# TYPE probe_http_content_length gauge
probe_http_content_length -1
# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects
# TYPE probe_http_duration_seconds gauge
probe_http_duration_seconds{phase="connect"} 0.062076202999999996
probe_http_duration_seconds{phase="processing"} 0.23481845699999998
probe_http_duration_seconds{phase="resolve"} 0.029594103
probe_http_duration_seconds{phase="tls"} 0.163420078
probe_http_duration_seconds{phase="transfer"} 0.002243199
# HELP probe_http_redirects The number of redirects
# TYPE probe_http_redirects gauge
probe_http_redirects 1
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
probe_http_ssl 1
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
probe_http_status_code 200
# HELP probe_http_uncompressed_body_length Length of uncompressed response body
# TYPE probe_http_uncompressed_body_length gauge
probe_http_uncompressed_body_length 14516
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
probe_http_version 1.1
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
probe_ip_protocol 4
# HELP probe_ssl_earliest_cert_expiry Returns earliest SSL cert expiry in unixtime
# TYPE probe_ssl_earliest_cert_expiry gauge
probe_ssl_earliest_cert_expiry 1.581897599e+09
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
probe_success 1
# HELP probe_tls_version_info Contains the TLS version used
# TYPE probe_tls_version_info gauge
probe_tls_version_info{version="TLS 1.3"} 1

プローブが成功し、フェーズごとのレイテンシ、ステータスコード、SSL ステータス、証明書の有効期限など、多くの有用なメトリックが得られることがわかります。これらは Unix 時間 で表示されます。blackbox エクスポーターは、localhost:9115 で、最後の数回のプローブ、ロードされた設定、デバッグ情報などを確認できる小さな Web インターフェイスも提供しています。prometheus.io をプローブするための直接リンクさえ提供しています。何かが機能しない理由を疑問に思っている場合に便利です。

Prometheus によるマルチターゲットエクスポーターのクエリ

ここまでは順調です。自分自身を祝福してください。blackbox エクスポーターは機能し、リモートターゲットをクエリするように手動で指示できます。あと一歩です。次に、Prometheus にクエリを実行させるように指示する必要があります。

以下に最小限の Prometheus 設定を示します。これは、以前curl 'localhost:9115/metrics' で行ったように、エクスポーター自体をスクレイプするように Prometheus に指示しています。

Docker for Mac または Docker for Windows を使用している場合、最後の行で localhost:9115 を使用することはできませんが、host.docker.internal:9115 を使用する必要があります。これは、これらのオペレーティングシステムで Docker を実装するために使用される仮想マシンに関連しています。本番環境ではこれを使用しないでください。

Linux 用 prometheus.yml

global:
  scrape_interval: 5s

scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
  metrics_path: /metrics
  static_configs:
    - targets:
      - localhost:9115

macOS および Windows 用 prometheus.yml

global:
  scrape_interval: 5s

scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
  metrics_path: /metrics
  static_configs:
    - targets:
      - host.docker.internal:9115

これで Prometheus コンテナを実行し、上記のコンフィグファイルをマウントするように指示します。コンテナからホストのネットワークにアクセスする方法のため、Linux では MacOS および Windows とは少し異なるコマンドが必要です。

Linux で Prometheus を実行する(本番環境では --network="host" を使用しないでください)

docker \
  run --network="host"\
  --mount type=bind,source="$(pwd)"/prometheus.yml,target=/prometheus.yml,readonly \
  prom/prometheus \
  --config.file="/prometheus.yml"

macOS および Windows で Prometheus を実行する

docker \
  run -p 9090:9090 \
  --mount type=bind,source="$(pwd)"/prometheus.yml,target=/prometheus.yml,readonly \
  prom/prometheus \
  --config.file="/prometheus.yml"

このコマンドは、設定ファイルを使用した blackbox エクスポーターの実行と同様に機能します。

すべてがうまくいった場合、localhost:9090/targets にアクセスし、blackbox の下で状態が緑色の UP になっているエンドポイントを確認できるはずです。赤色の DOWN が表示される場合は、上記で開始した blackbox エクスポーターがまだ実行中であることを確認してください。何も表示されないか、黄色い UNKNOWN が表示される場合は、非常に速すぎます。ブラウザのタブをリロードするまで数秒待つ必要があります。

Prometheus に "localhost:9115/probe?target=prometheus.io&module=http_2xx" をクエリするように指示するには、blackbox-http という別のスクレイプジョブを追加し、Prometheus 設定ファイル prometheus.ymlmetrics_path/probe に設定し、params: の下でパラメータを指定します。

global:
  scrape_interval: 5s

scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
  metrics_path: /metrics
  static_configs:
    - targets:
      - localhost:9115   # For Windows and macOS replace with - host.docker.internal:9115

- job_name: blackbox-http # To get metrics about the exporter’s targets
  metrics_path: /probe
  params:
    module: [http_2xx]
    target: [prometheus.io]
  static_configs:
    - targets:
      - localhost:9115   # For Windows and macOS replace with - host.docker.internal:9115

設定ファイルを保存した後、Prometheus Docker コンテナがあるターミナルに切り替えて、ctrl+C を押して停止し、設定をリロードするために既存のコマンドを使用して再度開始します。

ターミナルには "Server is ready to receive web requests." というメッセージが表示され、数秒後には Prometheus でカラフルなグラフが表示され始めるはずです。

これは機能しますが、いくつかの欠点があります。

  1. 実際のターゲットは param 設定にあり、これは非常に珍しく、後から理解するのが困難です。
  2. instance ラベルの値は blackbox エクスポーターのアドレスであり、技術的には正しいですが、私たちが関心のあるものではありません。
  3. どの URL をプローブしたかを確認できません。これは実用的ではなく、複数の URL をプローブした場合、異なるメトリックが 1 つに混同されます。

これを修正するために、relabeling を使用します。relabeling は、Prometheus の多くのものが内部ラベルで設定されているため、ここで役立ちます。詳細は本ガイドの範囲外です。したがって、必要なものに限定します。さらに詳しく知りたい場合は、この トーク を参照してください。今のところ、これを理解しておけば十分です。

  • __ で始まるすべてのラベルは、スクレイプ後にドロップされます。ほとんどの内部ラベルは __ で始まります。
  • __param_<name> と呼ばれる内部ラベルを設定できます。これらは、スクレイプ要求のキー <name> を持つ URL パラメータを設定します。
  • __address__ という内部ラベルがあり、これは static_configstargets によって設定され、その値はスクレイプ要求のホスト名になります。デフォルトでは、これは後で各メトリックに添付され、メトリックの発生元を示す instance ラベルの値に設定されます。

これを実現するために使用する設定を以下に示します。一度に少し多すぎるように感じても心配しないでください。ステップバイステップで説明します。

global:
  scrape_interval: 5s

scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
  metrics_path: /metrics
  static_configs:
    - targets:
      - localhost:9115   # For Windows and macOS replace with - host.docker.internal:9115

- job_name: blackbox-http # To get metrics about the exporter’s targets
  metrics_path: /probe
  params:
    module: [http_2xx]
  static_configs:
    - targets:
      - https://prometheus.dokyumento.jp    # Target to probe with http
      - https://prometheus.dokyumento.jp   # Target to probe with https
      - http://example.com:8080 # Target to probe with http on port 8080
  relabel_configs:
    - source_labels: [__address__]
      target_label: __param_target
    - source_labels: [__param_target]
      target_label: instance
    - target_label: __address__
      replacement: localhost:9115  # The blackbox exporter’s real hostname:port. For Windows and macOS replace with - host.docker.internal:9115

では、最後の設定と比較して何が新しいですか?

params には target が含まれなくなりました。代わりに、static configs: targets の下に実際のターゲットを追加しました。また、可能なので複数使用します。

  params:
    module: [http_2xx]
  static_configs:
    - targets:
      - https://prometheus.dokyumento.jp    # Target to probe with http
      - https://prometheus.dokyumento.jp   # Target to probe with https
      - http://example.com:8080 # Target to probe with http on port 8080

relabel_configs には新しい relabeling ルールが含まれています。

  relabel_configs:
    - source_labels: [__address__]
      target_label: __param_target
    - source_labels: [__param_target]
      target_label: instance
    - target_label: __address__
      replacement: localhost:9115  # The blackbox exporter’s real hostname:port. For Windows and macOS replace with - host.docker.internal:9115

relabeling ルールを適用する前に、Prometheus が行う要求の URI は次のようになります:"https://prometheus.dokyumento.jp/probe?module=http_2xx"。relabeling 後は次のようになります:"https://:9115/probe?target=https://prometheus.dokyumento.jp&module=http_2xx"

では、各ルールがどのように機能するかを見てみましょう。

まず、ラベル __address__targets の値を含む)の値を取得し、新しいラベル __param_target に書き込みます。これにより、Prometheus スクリプト要求に target パラメータが追加されます。

  relabel_configs:
    - source_labels: [__address__]
      target_label: __param_target

これにより、想像上の Prometheus 要求 URI には target パラメータが追加されます:"https://prometheus.dokyumento.jp/probe?target=https://prometheus.dokyumento.jp&module=http_2xx"

次に、ラベル __param_target の値を取得し、その値を持つラベル instance を作成します。

  relabel_configs:
    - source_labels: [__param_target]
      target_label: instance

要求は変更されませんが、要求から返されるメトリックには instance="https://prometheus.dokyumento.jp" というラベルが付与されるようになります。

その後、値 localhost:9115(エクスポーターの URI)をラベル __address__ に書き込みます。これは、ターゲット URI に直接クエリするのではなく、エクスポーターをクエリするように、Prometheus スクリプト要求のホスト名とポートとして使用されます。

  relabel_configs:
    - target_label: __address__
      replacement: localhost:9115  # The blackbox exporter’s real hostname:port. For Windows and macOS replace with - host.docker.internal:9115

要求は現在 "localhost:9115/probe?target=https://prometheus.dokyumento.jp&module=http_2xx" となっています。このようにして、実際のターゲットをそこに配置し、instance ラベルの値として取得しながら、Prometheus が blackbox エクスポーターに対して要求を実行するようにできます。

多くの場合、これらは特定のサービス検出と組み合わせて使用されます。詳細については、設定ドキュメントを参照してください。これらは static_configs で定義された targets と同様に __address__ ラベルに書き込むため、使用しても問題ありません。

これで完了です。Prometheus Dockerコンテナを再起動し、メトリクスを確認してください。メトリクスが実際に収集された期間を選択していることに注意してください。

サマリー

このガイドでは、マルチターゲットエクスポーターパターンの仕組み、カスタマイズされたモジュールでblackboxエクスポーターを実行する方法、そしてrelabelingを使用してPrometheusを構成し、proberラベルでメトリクスをスクレイピングする方法を学びました。

このページの内容