Kubernetes 1.21: Metrics Changes と SIG Instrumentation の変更内容

- [Kubernetes 1.19 SIG Instrumentation の変更内容](https://qiita.com/watawuwu/items/8be903465f92e44f4286)
- [Kubernetes 1.20 SIG Instrumentation の変更内容](https://qiita.com/watawuwu/items/ab5a0f11210d15cc6a86)

## はじめに(What’s New の内容含む)

ここでは、Kubernetes 1.21 の [CHANGELOG](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.21.md) から Metrics の変更と SIG Instrumentation の取り組みについてまとめています。

- [v1.21 Release Notes | Kubernetes Blog](https://kubernetes.io/docs/setup/release/notes/#v1-21-0)
- [Kubernetes 1.21: Power to the Community | Kubernetes Blog](https://kubernetes.io/blog/2021/04/08/kubernetes-1-21-release-announcement/)

今回 Kubernetes v1.21 で SIG Instrumentation が扱う主要なテーマは 1 つとなります。では確認していきます。

### Structured Logging in Kubelet

原文の What's New では次のように紹介されています。

<!-- Kubelet has adopted structured logging, thanks to community effort in accomplishing this within the release timeline. Structured logging in the project remains an ongoing effort -- for folks interested in participating, [keep an eye / chime in to the mailing list discussion](https://groups.google.com/g/kubernetes-dev/c/y4WIw-ntUR8). -->
> Kubernetes v1.19 から始まった構造化ロギングの取り組みが、コミュニティの努力により kubelet で採用されました。引き続き構造化ロギングの導入に取り組んでいます。この取り組みに関心のある人は、[メーリングリスト](https://groups.google.com/g/kubernetes-dev/c/y4WIw-ntUR8)のディスカッションを参照してください。

構造化ロギングの取り組みに関しては Kubernetes v1.19 の記事で簡単な内容ですが紹介しています。興味がある方はそちらも参照してください。

- [1602-structured-logging kubernetes/enhancements](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/1602-structured-logging) 
- [Kubernetes 1.19 SIG Instrumentation の変更内容](https://qiita.com/watawuwu/items/8be903465f92e44f4286#%E3%81%AF%E3%81%98%E3%82%81%E3%81%ABwhats-new-%E3%81%AE%E5%86%85%E5%AE%B9%E5%90%AB%E3%82%80)

[こちらの移行計画をもとに](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md)、ログ出力の割合が多い重要なログに焦点を絞りメソッドの置き換えが進められています。Tracking Issue は[こちら](https://github.com/kubernetes/enhancements/issues/1602)です。v1.21 で対応された issue はこの [Github Project](https://github.com/orgs/kubernetes/projects/53?card_filter_query=milestone%3Av1.21) から確認できます。この移行だけでも 52 個もの PR がマージされています。主な変更点は Severity に合わせて klog.InfoS と klog.ErrorS に置き換えることですが [Change log functions to structured equivalent](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#change-log-functions-to-structured-equivalent) に合わせ、Warning を klog.InfoS に置き換える Severity やフォーマットなどの調整も合わせて実施されています。

### Dynamic Cardinality Enforcement

その他にも今回のリリースに関連の深い 次の KEP があります。

- [Dynamic Cardinality Enforcement](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/2305-metrics-cardinality-enforcement)

この KEP では Kubernetes コンポーネントの実行時にメトリクスのラベル値を制限できる仕組みが提案されています。過去に何度も引き起こされた、メトリクスの増大によりメモリリークが発生した件に対応するためです。

私達も以前 `reflector_xxx` メトリクスのラベルが動的に生成されメモリが増大する問題に直面しました。その時の対応は価値の低いメトリクスだったことから[メトリクスが削除され](https://github.com/kubernetes/kubernetes/pull/74636)、対応したバイナリがリリースされました。
この時の対応もそうですが、メトリクスが引き起こすメモリリークの問題はメトリクスの削減、または削除の対応後にバイナリのリリースが必要となります。バイナリのリリースには時間が掛かるため、この KEP では実行時に問題を回避する方法を提案しています。

今回のリリースでは component-base に `--allow-metric-labels` フラグが含まれています。これを利用することでメトリクスのラベル値を制限できます。ただし今回のリリースでこのフラグが取り込まれているコンポーネントは `kube-scheduler` `kube-controller-manager` `kube-apiserver` となります。残念ながら v1.21.0 の段階では `kube-proxy`、`kubelet` にこのフラグは含まれません。

使用方法は以下のようになります。

```
spec) --allow-label-value <metric_name>,<label_name>='<allow_value1>, <allow_value2>...', <metric_name2>,<label_name>='<allow_value1>, <allow_value2>...', ...

ex) --allow-metric-labels=metric1,label1='v1,v2,v3',metric1,label2='v1,v2,v3'metric2,label1='v1,v2,v3'
```

またこの KEP とは直接関係ないようですが、メトリクス自体を一次的に無効化するフラグも component-base に取り込まれました。
こちらも v1.21.0 の段階で使用できるコンポーネントは `kube-scheduler` `kube-controller-manager` `kube-apiserver` になります。

使用方法は以下のようになり、複数メトリクスを指定する場合は区切り文字にカンマが利用できます。

```
--disabled-metrics=bad_metric1,bad_metric2
```

これらの機能で Kubernetes v1.21 以降ではメトリクスによるメモリリークが発生してしまっても比較的簡単に回避できそうです。
ただ `--allow-label-value` と `--disabled-metrics` オプションの挙動を確認したところ、意図した挙動ではなかったため引き続き検証予定です。検証が終わり次第記事を更新します。


### その他

他にも SIG-Instrumentation と関連がある次の KEP がありますが別の SIG のため今回は省略します。

- [Kubelet endpoint for pod resource assignment](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2043-pod-resource-concrete-assigments)


それでは恒例の `Metrics Changes` について説明していきます。
ChangeLog から `Metrics Changes` の項目は削除されているため、私の方で全ての変更点からメトリクスの変更に関連するものを抜粋した内容を `Metrics Changes` としてまとめました。

## メトリクスの変更（Metrics Changes）

### 追加

#### kube-apiserver
<!-- - Add metric etcd_lease_object_counts for kube-apiserver to observe max objects attached to a single etcd lease. ([#97480](https://github.com/kubernetes/kubernetes/pull/97480), [@lingsamuel](https://github.com/lingsamuel)) [SIG API Machinery, Instrumentation and Scalability] -->
- 1 つの etcd Lease に接続されているオブジェクト数を記録します([#97480](https://github.com/kubernetes/kubernetes/pull/97480), [@&#xFFF0;lingsamuel](https://github.com/lingsamuel))
  - Histogram: `etcd_lease_object_counts`

<!-- - Rename metrics `etcd_object_counts` to `apiserver_storage_object_counts` and mark it as stable. The original `etcd_object_counts` metrics name is marked as "Deprecated" and will be removed in the future. ([#99785](https://github.com/kubernetes/kubernetes/pull/99785), [@&#xFFF0;erain](https://github.com/erain)) [SIG API Machinery, Instrumentation and Testing] -->
<!-- - `apiserver_storage_objects` (a newer version of `etcd_object_counts`) is promoted and marked as stable. ([#100082](https://github.com/kubernetes/kubernetes/pull/100082), [@logicalhan](https://github.com/logicalhan)) -->
- ストレージに保存されているオブジェクト数を記録します([#99785](https://github.com/kubernetes/kubernetes/pull/99785), [@&#xFFF0;erain](https://github.com/erain))
  - Gauge: `apiserver_storage_objects`
    - Labels: {"resource"}
    - `etcd_object_counts` メトリクスは非推奨となりました。代わりに `apiserver_storage_objects` メトリクスを利用するように変更してください。
  - :memo: メトリクス名のリネームという扱いのため、初めてのリリースですが StabilityLevel は Stable となっています([#100082](https://github.com/kubernetes/kubernetes/pull/100082), [@&#xFFF0;logicalhan](https://github.com/logicalhan))

#### kubelet

<!-- 時間があれば
- The BoundServiceAccountTokenVolume feature has been promoted to beta, and enabled by default.
  - This changes the tokens provided to containers at `/var/run/secrets/kubernetes.io/serviceaccount/token` to be time-limited, auto-refreshed, and invalidated when the containing pod is deleted.
  - Clients should reload the token from disk periodically (once per minute is recommended) to ensure they continue to use a valid token. `k8s.io/client-go` version v11.0.0+ and v0.15.0+ reload tokens automatically.
  - By default, injected tokens are given an extended lifetime so they remain valid even after a new refreshed token is provided. The metric `serviceaccount_stale_tokens_total` can be used to monitor for workloads that are depending on the extended lifetime and are continuing to use tokens even after a refreshed token is provided to the container. If that metric indicates no existing workloads are depending on extended lifetimes, injected token lifetime can be shortened to 1 hour by starting `kube-apiserver` with `--service-account-extend-token-expiration=false`. ([#95667](https://github.com/kubernetes/kubernetes/pull/95667), [@&#xFFF0;zshihang](https://github.com/zshihang)) [SIG API Machinery, Auth, Cluster Lifecycle and Testing]
-->

<!-- 時間があれば
- Enables Kubelet to check volume condition and log events to corresponding pods. ([#99284](https://github.com/kubernetes/kubernetes/pull/99284), [@&#xFFF0;fengzixu](https://github.com/fengzixu)) [SIG Apps, Instrumentation, Node and Storage] -->

<!-- - Add `csi_operations_seconds` metric on kubelet that exposes CSI operations duration and status for node CSI operations. ([#98979](https://github.com/kubernetes/kubernetes/pull/98979), [@&#xFFF0;Jiawei0227](https://github.com/Jiawei0227)) [SIG Instrumentation and Storage] -->
- CSI 操作の Duration と Status を記録します([#98979](https://github.com/kubernetes/kubernetes/pull/98979), [@&#xFFF0;Jiawei0227](https://github.com/Jiawei0227))
  - Histogram: `csi_operations_seconds`
    - Labels: {"driver_name", "method_name", "grpc_status_code", "migrated"}

#### kube-controller-manager

<!-- - A new histogram metric to track the time it took to delete a job by the `TTLAfterFinished` controller ([#98676](https://github.com/kubernetes/kubernetes/pull/98676), [@&#xFFF0;ahg-g](https://github.com/ahg-g)) -->
- `TTLAfterfined` controller でジョブを削除するのにかかる時間を記録します([#98676](https://github.com/kubernetes/kubernetes/pull/98676), [@&#xFFF0;ahg-g](https://github.com/ahg-g))
  - Histogram: `ttl_after_finished_controller_job_deletion_duration_seconds`

<!-- - Added `ephemeral_volume_controller_create[_failures]_total` counters to kube-controller-manager metrics ([#99115](https://github.com/kubernetes/kubernetes/pull/99115), [@&#xFFF0;pohly](https://github.com/pohly)) [SIG API Machinery, Apps, Cluster Lifecycle, Instrumentation and Storage] -->
- Generic ephemeral volumes の作成操作を記録します([#99115](https://github.com/kubernetes/kubernetes/pull/99115), [@&#xFFF0;pohly](https://github.com/pohly))
  - Counter: `ephemeral_volume_controller_create_total`
  - Counter: `ephemeral_volume_controller_create_failures_total`

<!-- - Adds two new metrics to cronjobs, a histogram to track the time difference when a job is created and the expected time when it should be created, as well as a gauge for the missed schedules of a cronjob ([#99341](https://github.com/kubernetes/kubernetes/pull/99341), [@&#xFFF0;alaypatel07](https://github.com/alaypatel07)) -->
- CronJob が実行されスケジュールされてから対応するジョブが作成されるまでの時間を記録します([#99341](https://github.com/kubernetes/kubernetes/pull/99341), [@&#xFFF0;alaypatel07](https://github.com/alaypatel07))
  - Histogram: `cronjob_controller_cronjob_job_creation_skew_duration_seconds`

#### kube-proxy
<!-- - Kube-proxy iptables: new metric sync_proxy_rules_iptables_total that exposes the number of rules programmed per table in each iteration ([#99653](https://github.com/kubernetes/kubernetes/pull/99653), [@&#xFFF0;aojea](https://github.com/aojea)) [SIG Instrumentation and Network] -->
- iptables のテーブルごと（filter、nat、mangle）に登録されたルール数を記録します([#99653](https://github.com/kubernetes/kubernetes/pull/99653), [@&#xFFF0;aojea](https://github.com/aojea))
  - Gauge: `kubeproxy_sync_proxy_rules_iptables_total`
    - Labels: {"table"}

#### component-base

<!-- - A client-go metric, rest_client_exec_plugin_call_total, has been added to track total calls to client-go credential plugins. ([#98892](https://github.com/kubernetes/kubernetes/pull/98892), [@&#xFFF0;ankeesler](https://github.com/ankeesler)) [SIG API Machinery, Auth, Cluster Lifecycle and Instrumentation] -->
- client-go の credential plugins へのコール数を記録します。これは終了コードと発生したイベントのタイプ（no_error、plugin_execution_error、plugin_not_found_error、client_internal_error）をラベルに持ちます。呼び出しが成功した場合にのみ、終了コードは 0 が設定されます。([#98892](https://github.com/kubernetes/kubernetes/pull/98892), [@&#xFFF0;ankeesler](https://github.com/ankeesler))
  - `rest_client_exec_plugin_call_total`
    - Labels: {"code", "call_status"}

### 変更

#### kube-apiserver
<!-- - apiserver_request_duration_seconds is promoted to stable status. ([#99925](https://github.com/kubernetes/kubernetes/pull/99925), [@&#xFFF0;logicalhan](https://github.com/logicalhan)) [SIG API Machinery, Instrumentation and Testing] -->
- 次のメトリクスの StabilityLevel が Stable になりました([#99925](https://github.com/kubernetes/kubernetes/pull/99925), [@&#xFFF0;logicalhan](https://github.com/logicalhan))
  - Histogram: `apiserver_request_duration_seconds`

<!-- - The `apiserver_request_total` metric is promoted to stable status and no longer has a content-type dimensions, so any alerts/charts which presume the existence of this will fail. This is however, unlikely to be the case since it was effectively an unbounded dimension in the first place. ([#99788](https://github.com/kubernetes/kubernetes/pull/99788), [@&#xFFF0;logicalhan](https://github.com/logicalhan)) -->
- 次のメトリクスの StabilityLevel が Stable になりました。またその際にあまり使われない `content-type` ラベルが削除されました([#99788](https://github.com/kubernetes/kubernetes/pull/99788), [@&#xFFF0;logicalhan](https://github.com/logicalhan))。
  - Counter: `apiserver_request_total`
    - Lables: {"verb", "dry_run", "group", "version", "resource", "subresource", "scope", "component", ~~"content-type",~~ "code"}

#### kube-controller-manager
<!-- - Add `migrated` field into `storage_operation_duration_seconds` metric ([#99050](https://github.com/kubernetes/kubernetes/pull/99050), [@&#xFFF0;Jiawei0227](https://github.com/Jiawei0227)) [SIG Apps, Instrumentation and Storage] -->
- 次のメトリクスに `migrated` ラベルが追加されました。CSI Migration 機能によって移行済みかどうかをモニタリングできます([#99050](https://github.com/kubernetes/kubernetes/pull/99050), [@&#xFFF0;Jiawei0227](https://github.com/Jiawei0227))
  - Histogram: `storage_operation_duration_seconds`
    - Lables: {"volume_plugin", "operation_name", "status", "migrated"}

#### component-base
<!-- - Process start time on Windows now uses current process information ([#97491](https://github.com/kubernetes/kubernetes/pull/97491), [@&#xFFF0;jsturtevant](https://github.com/jsturtevant)) [SIG API Machinery, CLI, Cloud Provider, Cluster Lifecycle, Instrumentation and Windows] -->
- Windows でのプロセス開始時刻の[取得方法](https://pkg.go.dev/golang.org/x/sys/windows#CurrentProcess)を修正しました([#97491](https://github.com/kubernetes/kubernetes/pull/97491), [@&#xFFF0;jsturtevant](https://github.com/jsturtevant))
  - Gauge: `process_start_time_seconds`

### 非推奨

#### kube-apiserver
<!-- - Rename metrics `etcd_object_counts` to `apiserver_storage_object_counts` and mark it as stable. The original `etcd_object_counts` metrics name is marked as "Deprecated" and will be removed in the future. ([#99785](https://github.com/kubernetes/kubernetes/pull/99785), [@&#xFFF0;erain](https://github.com/erain)) [SIG API Machinery, Instrumentation and Testing] -->
- ストレージに保存されているオブジェクト数を記録する次のメトリクスは非推奨となりました([#99785](https://github.com/kubernetes/kubernetes/pull/99785), [@&#xFFF0;erain](https://github.com/erain))
  - Gauge: `etcd_object_counts`
  - 代わりに Gauge: `apiserver_storage_objects` を利用してください

#### kubelet
<!-- - The metric `storage_operation_errors_total` is not removed, but is marked deprecated, and the metric `storage_operation_status_count` is marked deprecated. In both cases the `storage_operation_duration_seconds` metric can be used to recover equivalent counts (using `status=fail-unknown` in the case of `storage_operations_errors_total`). ([#99045](https://github.com/kubernetes/kubernetes/pull/99045), [@&#xFFF0;mattcary](https://github.com/mattcary)) -->
- 次のメトリクスが非推奨となりました。([#99045](https://github.com/kubernetes/kubernetes/pull/99045), [@&#xFFF0;mattcary](https://github.com/mattcary))。
  - Counter: `storage_operation_errors_total`
  - Counter: `storage_operation_status_count`
  - 代わりに `storage_operation_duration_seconds` メトリクスを利用してください。`storage_operation_errors_total` の変わりは `status` のラベル値 `fail-unknown` が利用できます

### 削除
#### kube-scheduler
<!-- - Remove the deprecated metrics "scheduling_algorithm_preemption_evaluation_seconds" and "binding_duration_seconds", suggest to use "scheduler_framework_extension_point_duration_seconds" instead. ([#96447](https://github.com/kubernetes/kubernetes/pull/96447), [@&#xFFF0;chendave](https://github.com/chendave)) [SIG Cluster Lifecycle, Instrumentation, Scheduling and Testing] -->
- 非推奨だった次のメトリクスが削されました。([#96447](https://github.com/kubernetes/kubernetes/pull/96447), [@&#xFFF0;chendave](https://github.com/chendave))
  - Histogram: `scheduling_algorithm_preemption_evaluation_seconds`
  - Histogram: `binding_duration_seconds`
  - 代わりに `scheduler_framework_extension_point_duration_seconds` メトリクスを利用してください

### 修正
#### component-base
<!-- - Fixed authentication_duration_seconds metric scope. Previously, it included whole apiserver request duration which yields inaccurate results. ([#99944](https://github.com/kubernetes/kubernetes/pull/99944), [@&#xFFF0;marseel](https://github.com/marseel)) -->
- 認証時間を記録するメトリクスに、apiserver へのリクエスト処理の全ての時間が記録されていたため修正しました([#99944](https://github.com/kubernetes/kubernetes/pull/99944), [@&#xFFF0;marseel](https://github.com/marseel))
  - Histogram: `authentication_duration_seconds`

#### kubelet
<!-- - Fix missing cadvisor machine metrics. ([#97006](https://github.com/kubernetes/kubernetes/pull/97006), [@&#xFFF0;lingsamuel](https://github.com/lingsamuel)) [SIG Node] -->
- 削除されてしまった プレフィックス `machine_` のメトリクスを元に戻しました([#97006](https://github.com/kubernetes/kubernetes/pull/97006), [@&#xFFF0;lingsamuel](https://github.com/lingsamuel))
  - ex) `machine_cpu_cores`
  - ex) `machine_memory_bytes`
  - :memo: この修正は v1.19.7/v1.20.2 にも cherry-pick されています

<!-- - Readjust `kubelet_containers_per_pod_count` buckets to only show metrics greater than 1. ([#98169](https://github.com/kubernetes/kubernetes/pull/98169), [@&#xFFF0;wawa0210](https://github.com/wawa0210)) -->
- Backet を調整し、1 を超えるメトリクスだけを表示するように修正しました([#98169](https://github.com/kubernetes/kubernetes/pull/98169), [@&#xFFF0;wawa0210](https://github.com/wawa0210))
  - Histogram: `kubelet_containers_per_pod_count`

## メトリクス以外の変更

### 機能追加(Feature)

<!-- - Removes cAdvisor JSON metrics (/stats/container, /stats/<podname>/<containername>, /stats/<namespace>/<podname>/<poduid>/<containername>) from the kubelet. ([#99236](https://github.com/kubernetes/kubernetes/pull/99236), [@&#xFFF0;pacoxu](https://github.com/pacoxu)) -->
- kubelet から cAdvisor JSON metrics (/stats/container, /stats/\<podname\>/\<containername\>, /stats/\<namespace\>/\<podname\>/\<poduid\>/\<containername\>) が削除されました([#99236](https://github.com/kubernetes/kubernetes/pull/99236), [@&#xFFF0;pacoxu](https://github.com/pacoxu))

<!-- - Component owner can configure the allowlist of metric label with flag '--allow-metric-labels'. ([#99385](https://github.com/kubernetes/kubernetes/pull/99385), [@&#xFFF0;YoyinZyc](https://github.com/YoyinZyc)) [SIG API Machinery, CLI, Cloud Provider, Cluster Lifecycle, Instrumentation and Release] -->
<!-- - Component owner can configure the allowlist of metric label with flag '--allow-metric-labels'. ([#99738](https://github.com/kubernetes/kubernetes/pull/99738), [@&#xFFF0;YoyinZyc](https://github.com/YoyinZyc)) [SIG API Machinery, Cluster Lifecycle and Instrumentation] -->
- component-base にメトリクスのラベル値の許可リストを指定できる `--allow-metric-labels` フラグが追加されました([#99385](https://github.com/kubernetes/kubernetes/pull/99385), [@&#xFFF0;YoyinZyc](https://github.com/YoyinZyc)) ([#99738](https://github.com/kubernetes/kubernetes/pull/99738), [@&#xFFF0;YoyinZyc](https://github.com/YoyinZyc))
  - [Dynamic Cardinality Enforcement](#dynamic-cardinality-enforcement-3)

<!-- - Metrics can now be disabled explicitly via a command line flag (i.e. '--disabled-metrics=metric1,metric2') ([#99217](https://github.com/kubernetes/kubernetes/pull/99217), [@&#xFFF0;logicalhan](https://github.com/logicalhan)) -->
- コマンドラインのフラグを使って、明示的にメトリクスを無効化できるようになりました([#99217](https://github.com/kubernetes/kubernetes/pull/99217), [@&#xFFF0;logicalhan](https://github.com/logicalhan))
  - ex) --disabled-metrics=metric1,metric2

### 不具合の修正(Bug or Regression)

<!-- - Updated k8s.gcr.io/ingress-gce-404-server-with-metrics-amd64 to a version that serves /metrics endpoint on a non-default port. ([#97621](https://github.com/kubernetes/kubernetes/pull/97621), [@&#xFFF0;vbannai](https://github.com/vbannai)) [SIG Cloud Provider] -->
- [GCE Load-Balancer Controller Addon] `k8s.gcr.io/ingress-gce-404-server-with-metrics-amd64` を、デフォルト以外のポートで /metrics エンドポイントにサービスを提供するバージョンに更新しました([#97621](https://github.com/kubernetes/kubernetes/pull/97621), [@&#xFFF0;vbannai](https://github.com/vbannai))

<!-- - Pod Log stats for windows now reports metrics ([#99221](https://github.com/kubernetes/kubernetes/pull/99221), [@&#xFFF0;jsturtevant](https://github.com/jsturtevant)) [SIG Node, Storage, Testing and Windows] -->
- Windows の Pod のログ統計(`/stats/summary `) が記録されるようになりました ([#99221](https://github.com/kubernetes/kubernetes/pull/99221), [@&#xFFF0;jsturtevant](https://github.com/jsturtevant))