kashionki38 blog

something like tech blog

【暫定版】 Kubernetesの性能監視で必要なメトリクス一覧とPrometheusでのHowTo

GitHubKubernetesの性能監視で必要なメトリクス一覧をまとめた。
また、それに伴って必要なPrometheusのExporter、それらのmetrics endpointに対するScrapeの方針とyamlのサンプル、GrafanaのダッシュボードJsonもまとめた。
改善余地はまだまだあると思うのでPRやコメント等大歓迎です。

監視すべき項目

監視すべき項目はUSE×REDだと認識している。
それを各コンポーネントの粒度でまとめている。
Cluster, Node, Pod/Container, MW(Java, Go, Nodejs, etc), Kubernetesコンポーネント自体

サービス監視(RED)

  • Rate : =Throughput, 秒間リクエスト数, 秒間 PV 数
  • Error Rate : エラー率, 5xx とか
  • Duration : =ResponseTime, %ile 評価が一般的

リソース監視(USE)http://www.brendangregg.com/usemethod.html

  • Utilization : 使用率 E.g. CPU 使用率
  • Saturation : 飽和度, どれくらいキューに詰まっているか
    E.g. ロードアベレージ
  • Errors : エラーイベントの数

前提条件

以下のバージョンを前提に設定のサンプルは用意している。

  • Kubernetes : v1.16.11-gke.5
  • Istio : 1.4.10-gke.4
  • Prometheus : prom/prometheus:v2.18.0
  • Grafana : grafana/grafana:7.0.1
  • NodeExporter : prom/node-exporter:v1.0.0

メトリクス一覧

以下のGitHubにも同様のReadme.mdをおいてます。 github.com

サービス監視(RED)

Jmeter

Grafana Dashboard

性能試験時のクライアント
Jmeter のメトリクスを収集
BackendListner->InfluxDB->Grafana

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/jmeter-metrics-dashboard.json

メトリクス USE x RED
Throughput R
ResponseTime D
Error% E

システムサイド  Istio Telemet

Istio のテレメトリ機能で各 service のメトリクスを収集

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/Istio-Mesh-Dashboard.json
https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/Istio-Workload-Dashboard.json
https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/Istio-Service-dashboard.json

メトリクス USE x RED Prometheus
Throughput R o
ResponseTime D o
Error% E o

システムサイド  Prometheus クライアントライブラリを利用

• 各言語のクライアントライブラリ使って Prometheus にメトリクスとして送る(request_duration_seconds をヒストグラム集計) https://github.com/devopsdemoapps/sockshop/search?q=request_duration_seconds&unscoped_q=request_duration_seconds

Grafana Dashboard

TBD

メトリクス USE x RED Prometheus Grafana Dashboard Prometheus metrics
Throughput request_duration_seconds をヒストグラム集計 R o TBD
ResponseTime D o
Error% E o

OS リソース監視(USE)

クラスタ全体

NodeExporter と cAdvisor にて収集

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/kubernetes-cluster-dashboard.json

メトリクス USE x RED Prometheus
Node Availability ノード全体の稼働率
各ノードの Ready 時間合計/(集計期間 × ノード数)
Availability
Node 数 Availability o
unschedulable Node 数 Availability o
Node の詳細
kubernetes.node.name,各リソース量
Conf o
Pods Availability Available Pods Availability o
Pods status
Running / Pending / Failed / Unknown
Availability o
Container Availability Containers status
Ready / Terminated / Waiting / Running
Availability o
Deployment Count Deployment Count Availability o
StatefulSet Count StatefulSet Count Availability o
DaemonSet Count DaemonSet Count Availability o
Job Count Job Count Availability o
Failed Job Count Availability o

Node

Node Exporter で収集

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/node-exporter-dashboard.json

メトリクス USE x RED Prometheus
Node Availability ノード全体の稼働率
各ノードの Ready 時間合計/(集計期間 × ノード数)
Availability o
Node 数 Availability o
unschedulable Node 数 Availability o
Node の詳細
kubernetes.node.name,各リソース量
Conf o
pods Pods Allocatable Conf o
Pods Capacity Conf o
Pods Allocation o
CPU CPU 使用率 U o
CPU 使用率コアごと U o
ロードアベレージ S o
CPU Core Capacity Conf o
CPU Core Limits Conf o
CPU Core Requests Conf o
CPU Core Allocatable Conf o
メモリ メモリ使用量 U o
スワップイン量 S o
スワップアウト量 S o
スワップ使用率 S o
スワップサイズ S o
Memory Capacity Conf o
Memory Limits Conf o
Memory Requests Conf o
Memory Allocatable Conf o
ディスク ディスクビジー U o
ディスク I/O 待ち数 S o
ディスク I/O 待ち時間 S o
ディスク読込み量 U o
ディスク書込み量 U o
ディスク読込み回数 U o
ディスク書込み回数 U o
パーティション使用率 U o
パーティションサイズ U o
inode 総数/使用率 U o
ネットワーク 送信トラフィック U o
受信トラフィック U o
ポート/Socket U
Drops E o
Errs E o
ping Availability
ファイルディスクリプタ U o
プロセス プロセス数 U
プロセス数(ゾンビ) U
占有プロセス状況(プロセスキューサイズ) U

Pod/Container

cAdvisor にて収集 (Kubelet バイナリに統合されているので scrape の設定のみで OK)

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/pod_detail-dashboard.json

メトリクス USE x RED Prometheus
Pods Availability Available Pods Availability o
Pods Restarts Availability o
Pods status
Running / Pending / Failed / Unknown
Availability o
Container Availability Restarts Availability o
Errors
Terminated Reason
Waiting Reason
Restart Reason
E o
Containers status
Ready / Terminated / Waiting / Running
Availability o
CPU CPU 使用率 U o
ロードアベレージ S o
Throttle S o
CPU Core Limits Conf o
CPU Core Requests Conf o
メモリ メモリ使用量 U o
スワップイン量 S x
スワップアウト量 S x
スワップ使用量 S o
スワップサイズ S x
Memory Limits Conf o
Memory Requests Conf o
ディスク ディスクビジー U o
ディスク I/O 待ち数 S o
ディスク I/O 待ち時間 S o
ディスク読込み量 U o
ディスク書込み量 U o
ディスク読込み回数 U o
ディスク書込み回数 U o
パーティション使用率 U o
パーティションサイズ U
inode 総数/使用率 U o
ネットワーク 送信トラフィック U o
受信トラフィック U o
ポート/Socket U
Drops E o
Errs E o
ping Availability
ファイルディスクリプタ U

Persistent Volume

kubelet の metics エンドポイントから収集

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/pv-dashboard.json

メトリクス USE x RED Prometheus
ファイルシステム ディスク領域使用量 U o
inode 総数/使用率 U o

MW リソース監視

Nginx

Grafana Dashboard

TBD

メトリクス USE x RED Prometheus
コネクション数 Active / Dropped S
スループット request per sec R
HTTP レスポンスコード E
レイテンシ Response Time D
Network bytes

Java (Jetty on SpringBoot)

SpringBoot2 系以降から実装の、Micrometer Actuator を使用
(pom.xml 変更のみで良いはず)

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/jmx-exporter-dashboard.json

メトリクス USE x RED Prometheus
ヒープメモリ 全体ヒープメモリ使用量 U o
Young U o
Old U o
Metaspace U o
Code Cache U o
GC 頻度(Full/Young) S o
時間(Full/Young) S o
レスポンスタイム レスポンスタイム D ?
レスポンスコード レスポンスコード E ?
スレッド数 スレッド数 S o
空きスレッド数 空きスレッド数 Conf ?
スレッドプール使用率 スレッドプール使用率 S ?
コネクションプール使用数 コネクションプール使用数 S ?

Go

golang クライアントライブラリの promhttp を使用
https://github.com/prometheus/client_golang/tree/master/prometheus/promhttp

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/go-process-dashboard.json

メトリクス USE x RED Prometheus
Process Memory U o
Memory Stats U o
Goroutines S o
GC duration S o | ##### Grafana Dashboard

Nodejs

nodejs クライアントライブラリの prom-client を使用
https://github.com/siimon/prom-client

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/nodejs-dashboard.json

メトリクス USE x RED Prometheus
Process Memory U o
Active Handlers S o

MySQL

Grafana Dashboard

mongodb

Grafana Dashboard

Redis

Grafana Dashboard

Kubernetes コンポーネント

kube-api-server

kube-api-server の metrics エンドポイントから収集

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/kube-apiserver-dashboard.json

メトリクス USE x RED Prometheus
API コール REST リクエスト数 R o
API リクエストレイテンシ D o
API リクエストエラー E o
Controller Manager から ワークキューの追加率 o
ワークキューの待ち時間 o
ワークキューの深さ o
etcd から etcd キャッシュエントリ x
etcd キャッシュのヒット/ミス率 x
etcd キャッシュ期間 x
リソース メモリ使用量 o
CPU 使用量 o
Go routine o

kube-controller-manager

Controller manager の metrics エンドポイントから収集
デフォルトでエンドポイントを公開しないコンポーネントの場合、--bind-address フラグを使用して有効にする

Grafana Dashboard

TBD

メトリクス USE x RED Prometheus
インスタンス kube-controller-manager インスタンスの数
ワークキュー情報 ワークキューのレイテンシー
ワークキューレート
ワークキューの深さ
kube-api kube-api リクエストレート
kube-api リクエストレイテンシ
リソース メモリ使用量
CPU 使用量
Go routine

etcd

kube-scheduler の metrics エンドポイントから収集
デフォルトでエンドポイントを公開しないコンポーネントの場合、--bind-address フラグを使用して有効にする

Grafana Dashboard

TBD

メトリクス USE x RED Prometheus
Leader Leader 変更回数
Database 系 DB サイズ
Disk 同期レイテンシ
Disk 操作 (fsync, commit)
Network Client Trafic
Peer Trafic
Raft Proposal
Proposal Committed
Proposal Pending
grpc
snapshot snapshot レイテンシ

Grafana Dashboard

kube-scheduler

Grafana Dashboard

TBD

メトリクス USE x RED Prometheus
Scheduling Scheduling レート
Scheduling レイテンシ
kube-api kube-api リクエストレート
kube-api リクエストレイテンシ
リソース メモリ使用量
CPU 使用量
Go routine
Leader Leader 変更回数

kube-proxy

kube-proxy の metrics エンドポイントから収集
デフォルトでエンドポイントを公開しないコンポーネントの場合、--bind-address フラグを使用して有効にする

Grafana Dashboard

TBD

メトリクス USE x RED Prometheus
Proxy ルール Sync Proxy ルール Sync レート R
Proxy ルール Sync レイテンシ D
Network Programming Network Programming レート R
Network Programming レイテンシ D
kube-api kube-api リクエストレート
kube-api リクエストレイテンシ
リソース メモリ使用量
CPU 使用量
Go routine

kubelet

各ノードの 10255 ポート

Grafana Dashboard

https://github.com/kashinoki38/prometheus-sample-yaml/blob/master/grafana/kubelet-dashboard.json

メトリクス USE x RED Prometheus
インスタンス kubelet インスタンスの数 Availability o
ボリュームの数 Availability o
error error E o
オペレーション 各タイプのランタイムオペレーションの総数 U o
オペレーションのエラーの数
※コンテナランタイムの問題など、ノード内の低レベルの問題を示す良い指標
E o
オペレーションの間隔時間 S o
Pod の管理 ポッドのスタートレートと間隔時間
コンテナのランタイムまたはイメージへのアクセスの問題を示している可能性がある
S o
ポッドスタートオペレーションの数 U o
ストレージ ストレージオペレーション数 U o
ストレージオペレーションエラー E o
ストレージオペレーション時間 S o
Cgroup マネージャ Cgroup マネージャのオペレーション数 U o
Cgroup マネージャのオペレーション時間 S o
ポッドライフサイクルイベントジェネレータ ポッドライフサイクルイベントジェネレーター(PLEG):
relist レート、relist インターバル、relist 間隔時間。これらの値のエラーまたは過度の遅延は、ポッドの Kubernetes ステータスに問題を引き起こす可能性があ
U o

Prometheus

Grafana Dashboard

以下のGitHubにも同様のReadme.mdをおいてます。 github.com

必要な Exporter

Exporter Link
Node Exporter NodeExporter
https://github.com/kashinoki38/microservices-demo/blob/master/deploy/kubernetes/manifests-monitoring/node-exporter-ds.yml
kube-state-metrics kube-state-metrics
https://github.com/kubernetes/kube-state-metrics/tree/master/docs

各 Exporter に対する Scrape 方針

Exporter Scrape Target Endpoint Scrape Config Sample の job name
cadvisor apiserver の以下 metrics パス
https://kubernetes.default.svc:443/api/v1/nodes/gke-cn-horiuchiysh-s-cn-horiuchiysh-s-2b141725-5coq/proxy/metrics/cadvisor
kubernetes-cadvisor
NodeExporter 各 pod のコンテナポートの/metrics へ投げる
nodexporter/metrics
kubernetes-pods
go 各 pod のコンテナポートの/metrics へ投げる
go/metrics
kubernetes-service-endpoints
nodejs 各 pod のコンテナポートの/metrics へ投げる
nodejs/metrics
kubernetes-service-endpoints
mongodb 各 pod のコンテナポートの/metrics へ投げる
mongodb/metrics
kubernetes-pods
Istio Mesh istio-telemetry サービスの endpoint port name が prometheus
http://10.48.2.14:42422/metrics
istio-mesh
kubelet 各ノードの 10255 ポート
http://10.30.3.20:10255/metrics10255
kubernetes-nodes
kube-apiserver default namespace に api server 向けの svc と endpoint がある
https://104.198.95.200:443/metrics
kubernetes-service-endpoints
kube-state-metrics 各サービスの/metrics へ投げる
http://kube-state-metrics:8080/metrics
kubernetes-service-endpoints
prove /api/v1/nodes/gke-cn-horiuchiysh-s-cn-horiuchiysh-s-2b141725-5coq/proxy/metrics/probes
ベット job が必要
kube-controll-manager デフォルトでエンドポイントを公開しないコンポーネントの場合、--bind-address フラグを使用して有効にする
/metrics
kube-proxy デフォルトでエンドポイントを公開しないコンポーネントの場合、--bind-address フラグを使用して有効にする
/metrics
kube-scheduler デフォルトでエンドポイントを公開しないコンポーネントの場合、--bind-address フラグを使用して有効にする
/metrics

Scrape Config Sample

kubernetes-pods

- job_name: kubernetes-pods
  honor_timestamps: true
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  kubernetes_sd_configs:
  - role: pod
  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
    separator: ;
    regex: ""true""
    replacement: $1
    action: keep
  - source_labels: [__meta_kubernetes_pod_node_name]
    separator: ;
    regex: (.*)
    target_label: node
    replacement: $1
    action: replace
  - source_labels: [__meta_kubernetes_namespace]
    separator: ;
    regex: (.*)
    target_label: namespace
    replacement: $1
    action: replace
  - source_labels: [__meta_kubernetes_pod_name]
    separator: ;
    regex: (.*)
    target_label: pod_name
    replacement: $1
    action: replace

kubernetes-nodes

各ノードの 10255 ポート

- job_name: kubernetes-nodes
  honor_timestamps: true
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  kubernetes_sd_configs:
    - role: node
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  tls_config:
    insecure_skip_verify: true
  relabel_configs:
    - separator: ;
      regex: (.*)
      target_label: __scheme__
      replacement: https
      action: replace
    - source_labels: [__meta_kubernetes_node_label_kubernetes_io_hostname]
      separator: ;
      regex: (.*)
      target_label: instance
      replacement: $1
      action: replace
    - source_labels: [__address__]
      separator: ;
      regex: ^(.+?)(?::\d+)?$
      target_label: __address__
      replacement: $1:10255
      action: replace

kubernetes-cadvisor

apiserver の以下 metrics パス
/api/v1/nodes/gke-cn-horiuchiysh-s-cn-horiuchiysh-s-2b141725-5coq/proxy/metrics/cadvisor

- job_name: kubernetes-cadvisor
  honor_timestamps: true
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: https
  kubernetes_sd_configs:
    - role: node
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    insecure_skip_verify: false
  relabel_configs:
    - separator: ;
      regex: __meta_kubernetes_node_label_(.+)
      replacement: $1
      action: labelmap
    - separator: ;
      regex: (.*)
      target_label: __address__
      replacement: kubernetes.default.svc:443
      action: replace
    - source_labels: [__meta_kubernetes_node_name]
      separator: ;
      regex: (.+)
      target_label: __metrics_path__
      replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
      action: replace

istio-mesh

istio-telemetry サービスの endpoint port name が prometheus の port

- job_name: istio-mesh
  honor_timestamps: true
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  kubernetes_sd_configs:
    - role: endpoints
      namespaces:
        names:
          - istio-system
  relabel_configs:
    - source_labels:
        [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
      separator: ;
      regex: istio-telemetry;prometheus
      replacement: $1
      action: keep

kubernetes-service-endpoints

- job_name: kubernetes-service-endpoints
  honor_timestamps: true
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  kubernetes_sd_configs:
    - role: endpoints
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    insecure_skip_verify: false
  relabel_configs:
    - source_labels: [__meta_kubernetes_service_label_component]
      separator: ;
      regex: apiserver
      target_label: __scheme__
      replacement: https
      action: replace
    - source_labels:
        [__meta_kubernetes_service_label_kubernetes_io_cluster_service]
      separator: ;
      regex: "true"
      replacement: $1
      action: drop
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
      separator: ;
      regex: "false"
      replacement: $1
      action: drop
    - source_labels: [__meta_kubernetes_pod_container_port_name]
      separator: ;
      regex: .*-noscrape
      replacement: $1
      action: drop
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
      separator: ;
      regex: ^(https?)$
      target_label: __scheme__
      replacement: $1
      action: replace
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
      separator: ;
      regex: ^(.+)$
      target_label: __metrics_path__
      replacement: $1
      action: replace
    - source_labels:
        [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
      separator: ;
      regex: ^(.+)(?::\d+);(\d+)$
      target_label: __address__
      replacement: $1:$2
      action: replace
    - separator: ;
      regex: ^__meta_kubernetes_service_label_(.+)$
      replacement: $1
      action: labelmap
    - source_labels: [__meta_kubernetes_namespace]
      separator: ;
      regex: (.*)
      target_label: namespace
      replacement: $1
      action: replace
    - source_labels: [__meta_kubernetes_pod_name]
      separator: ;
      regex: (.*)
      target_label: pod_name
      replacement: $1
      action: replace

prometheus.yaml の relabel_config

  • https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
  • relabel_configs で取得すべき項目のラベルを作っている

    • source_labels:元ネタ
    • regex正規表現抽出した項目について replace、keep、drop、labelmap、labeldrop,labelkeep でアクションする
    • replace:regex 連結され source_labels たと照合します。次に、設定 target_label に replacement 一致グループの参照(と、${1}、${2}、...)で replacement、その値によって置換されました。regex 一致しない場合、置換は行われません。
      → 一致した部分を target_label に挿入
    • keep:regex 連結に一致しないターゲットをドロップします source_labels。
    • dropregex 連結に一致するターゲットを削除し source_labels ます。
    • hashmod:連結されたハッシュのに設定さ target_label れ modulus ます source_labels。
    • labelmap:regex すべてのラベル名と照合します。その後で与えられたラベル名に一致するラベルの値をコピー replacement 一致グループの参照を(${1}、${2}中、...)replacement その値によって置換されています。
    • labeldrop:regex すべてのラベル名と照合します。一致するラベルは、ラベルのセットから削除されます。
    • labelkeep:regex すべてのラベル名と照合します。一致しないラベルは、ラベルのセットから削除されます。
  • 元ネタには以下のような meta タグを使用する

__meta_kubernetes_namespace: The namespace of the service object.
__meta_kubernetes_service_annotation_<annotationname>: Each annotation from the service object.
__meta_kubernetes_service_annotationpresent_<annotationname>: "true" for each annotation of the service object.
__meta_kubernetes_service_cluster_ip: The cluster IP address of the service. (Does not apply to services of type ExternalName)
__meta_kubernetes_service_external_name: The DNS name of the service. (Applies to services of type ExternalName)
__meta_kubernetes_service_label_<labelname>: Each label from the service object.
__meta_kubernetes_service_labelpresent_<labelname>: true for each label of the service object.
__meta_kubernetes_service_name: The name of the service object.
__meta_kubernetes_service_port_name: Name of the service port for the target.
__meta_kubernetes_service_port_protocol: Protocol of the service port for the target.
__meta_kubernetes_service_type: The type of the service.

検討必要事項

  • メモリを食うので VictoriaMetrics とかで工夫するかメトリクスを減らす必要がある
  • バージョンによって設定項目が変わってしまうので、設定を Code として git 上に残していくことが重要

Jmeter との連携

https://github.com/kubernauts/jmeter-operator