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

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

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

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

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

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

このパターンは、blackboxおよびSNMPエクスポーターなどの特定のエクスポーターにのみ使用されます。

その理由は、ターゲット上でエクスポーターを実行できない場合(例: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応答を期待するように指示されます。

これで、blackboxエクスポーターにターミナルで`curl`を使って`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`に正常に到達できなかったことを意味します。その理由は、値`6`のメトリクス`probe_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_2xx`と`http_post_2xx`という2つの`modules`が定義されており、どちらも`http`というプローバーを持ち、一方はメソッド値が明示的に`POST`に設定されていることがわかります。ここで、`http_2xx`モジュールを変更し、プローバー`http`の`preferred_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. コンテナの外部ポート`9115`をコンテナ内部のポート`9115`にマッピングしてコンテナを`run`します。
  2. 現在のディレクトリ(`$(pwd)`は作業ディレクトリを表示する)から`blackbox.yml`ファイルをコンテナ内の`/blackbox.yml`に`readonly`モードで`mount`します。
  3. Docker hubからイメージ`prom/blackbox-exporter`を使用します。
  4. `--config.file`フラグを使ってblackbox-exporterを実行し、`/blackbox.yml`をconfigファイルとして使用するように指示します。

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

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で小さなウェブインターフェースも提供しており、最後の数回のプローブ、ロードされた設定、デバッグ情報を確認できます。`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"`をクエリさせるには、Prometheus設定ファイル`prometheus.yml`に`metrics_path`を`/probe`に、パラメータを`params:`の下に設定した別のスクレイプジョブ`blackbox-http`を追加します。

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. 実際のターゲットがパラメータ設定に含まれており、非常に珍しく、後で理解するのが難しい。
  2. `instance`ラベルの値がblackboxエクスポーターのアドレスになっているが、これは技術的には正しいが、私たちが関心のあることではない。
  3. プローブしたURLを確認できない。これは非実用的であり、複数のURLをプローブすると異なるメトリクスが混同される。

これを解決するには、リラベルを使用します。リラベルは、Prometheusの多くのことが内部ラベルで設定されているため、ここで役立ちます。詳細は複雑で、このガイドの範囲外です。したがって、必要なものに限定します。しかし、もっと知りたい場合は、この講演をチェックしてください。今のところは、これを理解していれば十分です。

  • `__`で始まるすべてのラベルはスクレイプ後に削除されます。ほとんどの内部ラベルは`__`で始まります。
  • `__param_`という内部ラベルを設定できます。これらはスクレイプ要求のURLパラメータにキー``を設定します。
  • `__address__`という内部ラベルがあり、これは`static_configs`の`targets`によって設定され、その値はスクレイプ要求のホスト名です。デフォルトでは、後で各メトリクスにアタッチされ、メトリクスがどこから来たかを示す`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には新しいリラベルルールが含まれています。

  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

リラベルルールを適用する前、Prometheusが作成するリクエストのURIは"https://prometheus.dokyumento.jp/probe?module=http_2xx"のようになります。リラベル後は"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にはターゲットパラメータが追加されます: "https://prometheus.dokyumento.jp/probe?target=https://prometheus.dokyumento.jp&module=http_2xx"

次に、__param_targetラベルから値を取得し、その値でインスタンスラベルを作成します。

  relabel_configs:
    - source_labels: [__param_target]
      target_label: instance

リクエスト自体は変更されませんが、リクエストから返されるメトリクスにはinstance="https://prometheus.dokyumento.jp"というラベルが付与されます。

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

  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にブラックボックスエクスポーターに対するリクエストを行わせることができます。

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

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

サマリー

このガイドでは、マルチターゲットエクスポーターパターンがどのように機能するか、カスタマイズされたモジュールでブラックボックスエクスポーターを実行する方法、およびリラベルを使用してプロバーラベル付きのメトリクスをスクレイプするようにPrometheusを設定する方法を学びました。

このページの内容