7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-12-21

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

ここでは、Kubernetes 1.20 の CHANGELOG から Metrics の変更と SIG Instrumentation の取り組みについてまとめています。

Kubernetes v1.20 で SIG Instrumentation が扱うテーマは 2 つあります。では順番に確認していきます。

Runtime log sanitation

ログは機密データの漏洩を防ぐため、ランタイムの保護機能を設定できるようになりました。 この実験的な機能の詳細はドキュメントに記載されています。

簡単にこの機能を説明すると、Kubernetes component から出力されるログにパスワードやトークンなどが含まれていた場合、ログの出力を抑制し機密データの漏洩を防ぐ機能となります。この機能は次の KEP で検討されています。

この KEP のノンゴールにも記載されている通り、「Kubernetes システムコンポーネントログを介し、セキュリティ上の機密データを公開するリスクを完全に排除する」ことは困難ですので、あくまで保険的な機構となります。

こちらの機能は --experimental-logging-sanitization フラグを使って有効にします。
ドキュメントを確認してみると「ログのサニタイズにはかなりの計算オーバーヘッドが発生する可能性があるため、本番環境では有効にしないでください」とあります。

KEP ではその他に補完的な解決方法として静的コード分析も検討されています。

Pod resource metrics

オンデマンドのメトリクスが /metrics/resources から利用できるようになりました。この機能を有効にすると実行中の Pod のリソースリクエストが取得できます。

公式リリースの内容を補足すると、kube-scheduler のエンドポイントに /metrics/resource が追加され、そこから Pod のリソースリクエストのメトリクスが取得できる機能になります。このメトリクスでキャパシティプランニングを実行し、ダッシュボードなどからリソース不足のためにスケジュールできないワークロードをすばやく特定できます。

すでに kube-state-metrics で実現できていますが、後ほど背景や違いについて確認していきます。
こちらは実際にどのようなメトリクスが取得できるか確認した方が理解しやすいのでクラスタを作成して、メトリクスを取得してみます。

# Kubernetes クラスタの作成
# メトリクスを簡単に確認するため bind-address、port も設定し起動する
 ❯❯ minikube version
minikube version: v1.16.0
commit: 9f1e482427589ff8451c4723b6ba53bb9742fbb1

 ❯❯ minikube start \
  --kubernetes-version 1.20.0 \
  --vm-driver hyperkit \
  --extra-config 'scheduler.v=6' \
  --extra-config 'scheduler.show-hidden-metrics-for-version=1.20' \ # v1.20 では指定なしでも取得可
  --extra-config 'scheduler.bind-address=0.0.0.0' \
  --extra-config 'scheduler.port=10251'

😄  minikube v1.16.0 on Darwin 10.15.7
✨  Using the hyperkit driver based on existing profile
👍  Starting control plane node minikube in cluster minikube
🔥  Creating hyperkit VM (CPUs=2, Memory=4000MB, Disk=20000MB) ...
🐳  Preparing Kubernetes v1.20.0 on Docker 20.10.0 ...
    ▪ scheduler.v=6
    ▪ scheduler.show-hidden-metrics-for-version=1.20
🔎  Verifying Kubernetes components...
🌟  Enabled addons: storage-provisioner, default-storageclass

❗  /Users/wmatsui/.local/bin/kubectl is version 1.18.5, which may have incompatibilites with Kubernetes 1.20.0.
    ▪ Want kubectl v1.20.0? Try 'minikube kubectl -- get pods -A'
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

proxy 経由で /metrics/resources エンドポイントにアクセスすると、kube_pod_resource_requestkube_pod_resource_limit のメトリクスが取得できます。

# proxy 経由でアクセスするためバックグラウンドで実行
 ❯❯ kubectl proxy --port 8080 &

# proxy 経由で `/metrics/resources` エンドポイントにアクセス
 ❯❯ curl -sLf http://localhost:8080/api/v1/namespaces/kube-system/pods/kube-scheduler-minikube:10251/proxy/metrics/resources
# HELP kube_pod_resource_limit [ALPHA] Resources limit for workloads on the cluster, broken down by pod. This shows the resource usage the scheduler and kubelet expect per pod for resources along with the unit for the resource if any.
# TYPE kube_pod_resource_limit gauge
kube_pod_resource_limit{namespace="kube-system",node="minikube",pod="coredns-74ff55c5b-sxp44",priority="2000000000",resource="memory",scheduler="default-scheduler",unit="bytes"} 1.7825792e+08
# HELP kube_pod_resource_request [ALPHA] Resources requested by workloads on the cluster, broken down by pod. This shows the resource usage the scheduler and kubelet expect per pod for resources along with the unit for the resource if any.
# TYPE kube_pod_resource_request gauge
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="coredns-74ff55c5b-sxp44",priority="2000000000",resource="cpu",scheduler="default-scheduler",unit="cores"} 0.1
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="coredns-74ff55c5b-sxp44",priority="2000000000",resource="memory",scheduler="default-scheduler",unit="bytes"} 7.340032e+07
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="etcd-minikube",priority="2000001000",resource="cpu",scheduler="default-scheduler",unit="cores"} 0.1
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="etcd-minikube",priority="2000001000",resource="ephemeral-storage",scheduler="default-scheduler",unit="bytes"} 1.048576e+08
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="etcd-minikube",priority="2000001000",resource="memory",scheduler="default-scheduler",unit="bytes"} 1.048576e+08
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="kube-apiserver-minikube",priority="2000001000",resource="cpu",scheduler="default-scheduler",unit="cores"} 0.25
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="kube-controller-manager-minikube",priority="2000001000",resource="cpu",scheduler="default-scheduler",unit="cores"} 0.2
kube_pod_resource_request{namespace="kube-system",node="minikube",pod="kube-scheduler-minikube",priority="2000001000",resource="cpu",scheduler="default-scheduler",unit="cores"} 0.1

# バックグラウンドの job を終了(ctrl + c)
 ❯❯ fg
^C

メトリクスを見やすくするために YAML フォーマットにして、値を value ラベルで表示した CoreDNS のメトリクスを見てましょう。

kube_pod_resource_limit:
  namespace: kube-system
  node: minikube
  pod: coredns-74ff55c5b-sxp44
  priority: 2000000000
  resource: memory
  scheduler: default-scheduler
  unit: bytes
  value: 1.7825792e+08

kube_pod_resource_request:
  namespace: kube-system
  node: minikube
  pod: coredns-74ff55c5b-sxp44
  priority: 2000000000
  resource: cpu
  scheduler: default-scheduler
  unit: cores
  value: 0.1

kube_pod_resource_request:
  namespace: kube-system
  node: minikube
  pod: coredns-74ff55c5b-sxp44
  priority: 2000000000
  resource: memory
  scheduler: default-scheduler
  unit: bytes
  value: 7.340032e+07

実際の CoreDNS Pod の Spec は次のとおりです。

 ❯❯ kubectl -n kube-system get pod coredns-74ff55c5b-sxp44 -ojson | jq '.spec.containers[].resources'
{
  "limits": {
    "memory": "170Mi"
  },
  "requests": {
    "cpu": "100m",
    "memory": "70Mi"
  }
}

pod.spec.resrouces の値がメトリクスとして kube-scheduler から取得できました。ただ多くの kubernetes 利用者は既に kube-state-metrics のメトリクスである kube_pod_container_resource_requestskube_pod_container_resource_limits を利用しているはずです。このメトリクスが kube-scheduler に実装された背景はこちらの KEP に記載されています。

こちらの KEP から背景や概要を簡単に説明します。
現在の kube-state-metrics から取得できるメトリクスから、実際に要求されたクラスタの全リソースリクエストを確認することは困難です。
例えば次のようなマニフェストがあるとします。この Pod の配置に必要な CPU のリソースリクエストは、単純に全てのコンテナの resources.request.cpu を合算した値である 150m ではなく 300m です。これは initContainers 単独で実行出来るリソースリクエストを確保をする必要があるためです。

metadata:
  name: nginx
spec:
  initContainers:
  - name: copy-files
    ...
    resources:
      limits:
        cpu: 100m
  - name: generate-config
    ...
    resources:
      requests:
        cpu: 300m
  containers:
  - name: proxy
    ...
    resources:
      requests:
        cpu: 50m
  - name: sidecar-logging
    ...
    resources:
      requests:
        cpu: 100m

またクラスタの全リソースリクエストを確認するには Spec だけではなく Pod の Status も考慮する必要があります。例えば Job などを実行し Pod が Completed になっているとその Pod の情報は除外する必要があります。私の場合は kube_pod_container_resource_requestskube_pod_status_phase{phase="Running"} のメトリクスを結合しリソースリクエストを確認しています。

kube-state-metrics のメトリクスにラベルを追加し、initConntainer や Status を考慮できる PromQL を実行するのも一つの解決方法です。ですが、それはカーディナリティが増加し不要なメトリクスで Disk サイズを圧迫する問題を生じさせます。kube-state-metrics のメトリクスにある個々のコンテナ情報からリソースリクエストを計算するのは大変であり、これらは正確なキャパシティプランニングを阻害するものです。

実際に Pod をスケジュールするのは kube-scheduler であり、上記のような考慮も kube-scheduler には実装されているわけです。そこで KEP により kube-scheduler がリソースメトリクスを持つ提案がされ、今回 Alpha feature state として実装されました。

この実装が進めば将来的に、属性を主眼に置いたメトリクスを生成する kube-state-metrics からリソースメトリクスが削除される可能性があります。

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

メトリクスの変更(Metrics Changes)

追加

kube-apiserver

  • リクエストフィルターのレイテンシーを計測するため、次のメトリクスが追加されました(#95207, @￰tkashem)
    • Histogram: apiserver_request_filter_duration_seconds
      • lables: {"filter"}
  • 自身へのリクエストを記録する、次のメトリクスが追加されました(#94288, @￰LogicalShark)
    • Counter: apiserver_selfrequest_total
      • lables: {"verb", "resource", "subresource"}
  • 中断したリクエストを記録する、次のメトリクスが追加されました(#95002, @￰p0lyn0mial)
    • Counter: apiserver_request_aborts_total
      • labels: {"verb", "group", "version", "resource", "subresource", "scope"}
  • Node Authorizer への負荷を見積もるために使用する次のメトリクスが追加されました(#92466, @￰mborsz)
    • Histogram: node_authorizer_graph_actions_duration_seconds
      • lables: {"operation"}

kubelet

  • 新しい vSphere のメトリクスが追加されました。これは関連するサーバーバージョンと vCenter ホスト名を記録します(#94526, @￰Danil-Grigorev)
    • Gauge: cloudprovider_vsphere_vcenter_versions
      • labels: {"hostname", "version", "build"}
  • /metrics/resource エンドポイントに、次の CPU とメモリのメトリクスが追加されました(#95839, @￰egernst)
    • Gauge: pod_cpu_usage_seconds_total
      • labels: {"pod", "namespace"}
    • Gauge: pod_memory_working_set_bytes
      • labels: {"pod", "namespace"}
    • :pencil: kube-scheduler の Pod Resoruce Metrics と同じく、こちらも既存の container_memory_working_set_bytescontainer_cpu_usage_seconds_total メトリクスと異なり、Pod 単位のメトリクスになっています。
  • Pod Resources API のリクエストの総数を記録する、次のメトリクスが追加されました(#92165, @￰RenaudWasTaken)
    • Counter: kubelet_pod_resources_endpoint_requests_total
      • labeles: {"server_api_version"}
  • Network Plugin の操作を記録する、次のメトリクスが追加されました(#93066, @￰AnishShah)
    • Counter: kubelet_network_plugin_operations_total
      • labels: {"operation_type"}
    • Counter: kubelet_network_plugin_operations_errors_total
      • labels: {"operation_type"}

kube-controller-manager

  • Plugin 名と Volume Mode をラベルに持ち、PV の総数をカウントする次のメトリクスが追加されました(#95719, @￰tsmetana)
    • Counter: pv_collector_total_pv_count
      • labels: {"plugin_name", "volume_mode"}

その他

  • [Cloud Provider] Azure サービスの操作(Route/Loadbalancer)を記録する、次のメトリクスが追加されました(#94124, @￰nilo19)
    • services_ensure_loadbalancer
      • Histogram: cloudprovider_azure_op_duration_seconds
        • labels: {"request", "resource_group", "subscription_id", "source"}
      • Counter: cloudprovider_azure_op_failure_count
        • labels: {"request", "resource_group", "subscription_id", "source"}

変更

kube-apiserver

  • API Priority and Fairness で記録されているメトリクスのラベル名を snake_case に変更しました(#96236, @￰adtac)
    • 変更したラベル
      • flowSchema => flow_schema
      • priorityLevel => priority_level
    • 利用しているメトリクス
      • apiserver_flowcontrol_rejected_requests_total
      • apiserver_flowcontrol_dispatched_requests_total
      • apiserver_flowcontrol_current_inqueue_requests
      • apiserver_flowcontrol_request_queue_length_after_enqueue
      • apiserver_flowcontrol_request_concurrency_limit
      • apiserver_flowcontrol_ecuting_requests
      • apiserver_flowcontrol_request_wait_duration_seconds
      • apiserver_flowcontrol_request_execution_seconds

kubelet

  • 再帰的なアクセス許可の変更を処理する時間を、次のメトリクスの operation_name ラベルに volume_fsgroup_recursive_apply という値で計測するようになりました(#95866, @￰JornShen)
    • Histogram: storage_operation_duration_seconds
    • Histogram: storage_operation_status_count
    • Histogram: storage_operation_errors_total
  • 次のメトリクスのバケットが変更されました(#96054, @￰alvaroaleman)
    • kubelet_runtime_operations_duration_seconds
      • buckets: [0.005 0.0125 0.03125 0.078125 0.1953125 0.48828125 1.220703125 3.0517578125 7.62939453125 19.073486328125 47.6837158203125 119.20928955078125 298.0232238769531 745.0580596923828]
      • impliment: prometheus.ExponentialBuckets(.005, 2.5, 14)

非推奨

kube-scheduler

  • Stability Level が Alpha だった、次のメトリクスが非推奨となりました。これらのメトリクスは scheduler_framework_extension_point_duration_seconds を利用し、前者は PostFilter として、後者は Bind プラグインとしてカバーされています。1.21 で削除される予定です(#95001, @￰arghya88)。
    • scheduler_binding_duration_seconds
    • scheduler_scheduling_algorithm_preemption_evaluation_seconds

削除

kube-scheduler

  • 次の非推奨なメトリクスが削除されました(#94884, @￰arghya88)
    • scheduler_scheduling_duration_seconds
    • scheduler_scheduling_algorithm_predicate_evaluation_seconds
    • scheduler_scheduling_algorithm_priority_evaluation_seconds

修正

kube-apiserver

  • 次のメトリクスは、リクエストフィルターで処理する時間が考慮されるようになりました(#94903, @￰tkashem)
    • apiserver_request_duration_seconds
  • CRD オブジェクトのメトリクスについて誤って記録されていた verbs ラベルの内容を修正しました(#93523, @￰wojtek-t)
  • GET の代わりに LIST が記録されたメトリクスを修正し、verbs と scope のラベルが正しく記録されるようになりました(#95562, @￰wojtek-t)

kube-proxy

  • Endpoints/EndpointSlice が削除され、正しいタイムスタンプが持たない場合のメトリクスを修正しました(#95363, @￰wojtek-t)
    • kubeproxy_network_programming_duration_seconds

その他

  • 修正前は呼び出しの大部分が Inf バケットに分類されていたため、バケットを修正しレイテンシが正しく記憶できるようにしました(#94873, @￰marwanad)
    • cloudprovider_azure_api_request_duration_seconds
  • 削除された apiservices に対してメトリクスが記録されるバグを修正しました(#96421, @￰dgrisonnet)
    • aggregator_unavailable_apiservice

種類別の変更点(Changes by Kind)

API の変更(API changes)

  • kubelet により提供される GPU メトリクスは、デフォルトで無効となりました(#95184, @￰RenaudWasTaken)

非推奨(Deprecation)

  • kubelet の非推奨エンドポイント metrics/resource/v1alpha1 は削除されました。metrics/resource エンドポイントを利用してください(#94272, @￰RainbowMango)
    • :pencil: 取得できるメトリクスは同じです。

機能追加(Feature)

component-base

  • --experimental-logging-sanitization フラグが追加されました。ログからの機密データ漏洩を低減します(#96370, @￰serathius)。

kube-scheduler

  • kube-scheduler の /metrics/resources エンドポイントからメトリクスが取得できるようなりました。このメトリクスを利用することで、管理者は Resource の状態(Pod 上のすべての Resource Requests と Resource Limits)を簡単に確認し、実際に Pod が利用している Resource 使用量、または Node Capacity と比較できます(#94866, @￰smarterclayton)。

終わりに

KEP-1748: Expose Pod Resource Request Metrics で 、Ephemeral Storage の対応が書かれていないので、kube-state-metrics からの移行には課題がありそうです。

他には、現在作業が進められている KEP: Dynamic Cardinality Enforcement があります。これは私自身何度も苦しめられたことがある、メトリクスによる Memory Leak について検討している KEP です。Allow List を定義する方法は骨が折れる作業ですが、どのような結果になるか楽しみです。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?