Carpe Diem

備忘録

Prometheus の監視対象を ServiceDiscovery で動的に設定する

概要

PrometheusはPull型の監視ツールであるため、監視対象がどれかを教えてあげなければいけません。
これまでの記事は全てstatic_configsを用いた静的な値で、スケールした時やサービスが増減した時に柔軟性がありません。

PrometheusはServiceDiscoveryを指定することで動的にターゲットを検知できるのでそれを用います。

環境

利用できるService Discoveryは?

Configuration | Prometheus に対応しているSD一覧があります。
主に使いそうなのは以下でしょうか。

Kubernetesの例

今回はKubernetesを用いた方法を説明します。

ロール(ServiceDiscoveryの種類)

PrometheusはKubernetesAPIを用いてターゲットを探します。
Prometheusで使えるKubernetesのSDは以下の5種類があります。

ロール 何ができるか
node クラスタを構成するノードを検出
kubeletをスクレイプする
endpoints Serviceにぶら下がったPodを検出
service Serviceに見えるがロードバランシングされるのでPod検出には向かない
サービスが応答するかのブラックボックスモニタリングに向く
pod Serviceに繋がっていないPodも含め全てのPodを検出
ingress ingressクラスタ外にKubernetes Serviceを公開するのでserviceロールと同じように使う

よく使うであろうロールは

  • node
  • endpoints or pod

です。後者はメトリクス取得したい全てのPodはServiceに紐付けるというインフラ上のローカルルールがあればendpointsを使用しますし、そうでなければpodを使用することになります。

nodeロール

nodeロールを用いてクラスタのノードを検出してみます。
kubletをスクレイプするのでHTTPSである必要があり、TLSなどの設定も必要です。
ただ現在のDocker for Mac Kubernetesの場合TLS周りが上手く行かないのでinsecure_skip_verify: trueが必要です。

scrape_configs:
  - job_name: 'kubernetes-nodes'
    kubernetes_sd_configs:
    - role: node
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      insecure_skip_verify: true
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token

ServiceDiscovery結果

ちゃんと監視対象として認識されてTarget Labelが登録されてます。

f:id:quoll00:20190723200750p:plain

Targets結果

/metricsからメトリクスを取得できていることが分かります。

f:id:quoll00:20190723200838p:plain

cAdvisor

kubeletは/metrics/cadvisorにて各Podのコンテナ用メトリクスを公開しています。
なのでmetrics_path: /metrics/cadvisorを設定することでcAdvisorのメトリクスを取得できるようになります。

- job_name: 'cadvisor'
    kubernetes_sd_configs:
    - role: node
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      insecure_skip_verify: true
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    metrics_path: /metrics/cadvisor

Targets結果

/metrics/cadvisorからメトリクスを取得できていることが分かります。

f:id:quoll00:20190723201258p:plain

Grafanaで見てみる

各PodのCPU使用率が出てますね。

f:id:quoll00:20190723201658p:plain

endpointsロール

kube-apiserverのServiceを除く全てのServiceを対象にします。

scrape_configs:
  - job_name: 'kubernetes-service-endpoints'
    kubernetes_sd_configs:
    - role: endpoints
    relabel_configs:
    - source_labels:
      - __meta_kubernetes_namespace
      - __meta_kubernetes_service_name
      regex: default;kubernetes
      action: drop
    - source_labels:
      - __meta_kubernetes_namespace
      - __meta_kubernetes_pod_container_port_number
      regex: default;9100
      action: keep
    - source_labels:
      - __meta_kubernetes_service_name
      target_label: job
    - source_labels:
      - __meta_kubernetes_pod_name
      target_label: pod

数行毎に説明していきます。

kube-apiserverのServiceを取り除く

    - source_labels:
      - __meta_kubernetes_namespace
      - __meta_kubernetes_service_name
      regex: default;kubernetes
      action: drop

ここではkube-apiserverのServiceを取り除くため、
__meta_kubernetes_namespacedefault
かつ
__meta_kubernetes_service_namekubernetes
のものをaction: dropしています。

特定のnamespace, portのものを残す

今回各サーバは9100に/metricsをexposeしているので、そのサーバのみ監視対象にします。

    - source_labels:
      - __meta_kubernetes_namespace
      - __meta_kubernetes_pod_container_port_number
      regex: default;9100
      action: keep

jobラベルを書き換える

jobラベルをService名に書き換えています。

    - source_labels:
      - __meta_kubernetes_service_name
      target_label: job

podラベルを追加する

podラベルを追加し、pod名をセットしています。

    - source_labels:
      - __meta_kubernetes_pod_name
      target_label: pod

ServiceDiscovery結果

ちゃんと監視対象として認識されてTarget Labelが登録されてます。

f:id:quoll00:20190723213305p:plain

action: dropにしたものはフィルタされてます。

f:id:quoll00:20190723212030p:plain

Targets結果

各Podが認識されてます。

f:id:quoll00:20190723213745p:plain

動作検証

Podの数を変えて動的にTargetsが変化するか見てみます。

スケールアウトさせてみる

replicas: 1->replicas: 3にしてみます。

f:id:quoll00:20190723214129p:plain

増えました。

スケールインさせてみる

replicas: 3->replicas: 1に戻します。

f:id:quoll00:20190723214246p:plain

減りました。

まとめ

Prometheusの監視対象をServiceDiscoveryにすることで動的に監視対象を検知することができました。

サンプルコード

今回のサンプルコードはこちらです。

github.com

参考