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

このガイドでは、マルチターゲットエクスポーターパターンを紹介します。そのためには、

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

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

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

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

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

その理由は、SNMPを話すネットワーク機器など、ターゲット上でエクスポーターを実行できないか、ネットワーク外の特定のポイントからのWebサイトのレイテンシや到達可能性など、距離に明示的に関心があるためです。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`に正常に到達できなかったことを意味します。理由は、値が`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`の`preferred_ip_protocol`を明示的に文字列`ip4`に設定することにより、モジュール`http_2xx`を変更します。

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クジラをクリックし、次に`設定` - >`ファイル共有` - >`+`をクリックすることで、これを行うことができます。その後、`適用して再起動`を押します。

最初に、古いコンテナの端末に移動して`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` を `readonly`(読み取り専用)モードでコンテナ内の `/blackbox.yml` に `mount`(マウント)します。
  3. Docker Hub から `prom/blackbox-exporter` イメージを使用します。
  4. blackbox-exporter を `--config.file` フラグを付けて実行し、`/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` をクエリするように指示するには、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. 実際のターゲットはパラメータ設定にあり、これは非常に ungewöhnlich で後で理解するのが困難です。
  2. `instance` ラベルの値は、blackbox エクスポーターのアドレスですが、技術的には正しいものの、私たちが関心のあるものではありません。
  3. どの URL をプローブしたかを確認できません。これは実用的ではなく、複数の URL をプローブすると異なるメトリクスが 1 つに混在します。

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

  • `__` で始まるすべてのラベルは、スクレイプ後に削除されます。ほとんどの内部ラベルは `__` で始まります。
  • `__param_` という内部ラベルを設定できます。これらは、スクレイプリクエストのキー `` を使用して URL パラメーターを設定します。
  • `static_configs` の下の `targets` によって設定され、その値がスクレイプリクエストのホスト名である内部ラベル `__address__` があります。デフォルトでは、後でラベル `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`。再ラベル付け後、次のようになります。`http://localhost: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` から値を取得し、その値を使用してラベルインスタンスを作成します。

  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 に blackbox エクスポーターに対してリクエストを作成させることができます。

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

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

まとめ

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

このドキュメントはオープンソースです。問題の報告またはプルリクエストを送信して、改善にご協力ください。