システムコンポーネントのメトリクスを利用すると、コンポーネント内部の動作をより詳しく把握できます。 メトリクスは、ダッシュボードやアラートの構築に特に役立ちます。
KubernetesコンポーネントはPrometheus形式でメトリクスを出力します。 この形式は構造化されたプレーンテキストで、人間にも機械にも読み取れるように設計されています。
ほとんどの場合、メトリクスはHTTPサーバーの/metricsエンドポイントで利用できます。
デフォルトでエンドポイントを公開していないコンポーネントについては、--bind-addressフラグを使用して有効にできます。
そのようなコンポーネントの例を以下に示します:
本番環境では、Prometheus Serverやその他のメトリクススクレイパーを設定して、これらのメトリクスを定期的に収集し、何らかの時系列データベースで利用できるようにすることが推奨されます。
kubeletは/metrics/cadvisor、/metrics/resource、/metrics/probesエンドポイントでもメトリクスを公開していることに注意してください。
これらのメトリクスのライフサイクルは同一ではありません。
クラスターでRBACを使用している場合、メトリクスの読み取りには/metricsへのアクセスを許可するClusterRoleを持つユーザー、グループ、またはServiceAccountによる認可が必要です。
以下はその例です:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- nonResourceURLs:
- "/metrics"
verbs:
- get
Alphaメトリクス → Betaメトリクス → Stableメトリクス → 非推奨メトリクス → 非表示メトリクス → 削除済みメトリクス
Alphaメトリクスには安定性の保証がありません。 これらのメトリクスはいつでも変更または削除される可能性があります。
Betaメトリクスは、Stableメトリクスよりも緩いAPIの契約に従います。 Betaメトリクスでは、ライフタイム中にラベルが削除されることはありませんが、Betaステージ中にラベルが追加される可能性はあります。
Stableメトリクスは変更されないことが保証されています。 具体的には以下を意味します:
非推奨メトリクスは削除が予定されていますが、引き続き利用可能です。 これらのメトリクスには、非推奨になったバージョンに関するアノテーションが含まれます。
以下はその例です:
非推奨化の前
# HELP some_counter this counts things
# TYPE some_counter counter
some_counter 0
非推奨化の後
# HELP some_counter (Deprecated since 1.15.0) this counts things
# TYPE some_counter counter
some_counter 0
非表示メトリクスはスクレイピング用に公開されなくなりますが、引き続き利用可能です。 非推奨メトリクスは、その安定性レベルに基づく一定期間の後、非表示メトリクスになります:
非表示メトリクスを使用するには、有効化する必要があります。 詳細については、非表示メトリクスの表示セクションを参照してください。
削除済みメトリクスは公開されなくなり、使用できません。
上記のとおり、管理者はコマンドラインフラグを使用して、特定のバイナリで非表示メトリクスを有効にできます。 これは、前のリリースで非推奨化されたメトリクスの移行を見逃した場合の管理者向けのエスケープハッチとして提供されています。
show-hidden-metrics-for-versionフラグは、そのリリースで非推奨化されたメトリクスを表示するためのバージョンを受け取ります。
バージョンはx.yの形式で表現され、xはメジャーバージョン、yはマイナーバージョンです。
メトリクスがパッチリリースで非推奨化される可能性があっても、パッチバージョンは不要です。
これは、メトリクスの非推奨ポリシーがマイナーリリースに対して適用されるためです。
このフラグは、前のマイナーバージョンのみを値として受け取ることができます。
前のリリースで非表示になったすべてのメトリクスを表示したい場合は、show-hidden-metrics-for-versionフラグに前のバージョンを設定できます。
古すぎるバージョンの使用は、メトリクスの非推奨ポリシーに違反するため許可されていません。
例えば、メトリクスAが1.29で非推奨化されたとします。
メトリクスAが非表示になるバージョンは、その安定性レベルによって異なります:
AがALPHAの場合、1.29で非表示になる可能性があります。AがBETAの場合、最も早くて1.30で非表示になります。
1.30にアップグレードする際にAがまだ必要な場合は、コマンドラインフラグ--show-hidden-metrics-for-version=1.29を使用する必要があります。AがSTABLEの場合、最も早くて1.32で非表示になります。
1.32にアップグレードする際にAがまだ必要な場合は、コマンドラインフラグ--show-hidden-metrics-for-version=1.31を使用する必要があります。controller managerのメトリクスは、controller managerのパフォーマンスと健全性に関する重要な情報を提供します。 これらのメトリクスには、go_routineの数などの一般的なGo言語ランタイムメトリクスや、etcdリクエストのレイテンシーやクラウドプロバイダー(AWS、GCE、OpenStack)のAPIレイテンシーなど、コントローラー固有のメトリクスが含まれており、クラスターの健全性を測定するために利用できます。
Kubernetes 1.7以降、GCE、AWS、Vsphere、OpenStackのストレージ操作に関する詳細なクラウドプロバイダーメトリクスが利用可能です。 これらのメトリクスは、永続ボリューム操作の健全性を監視するために使用できます。
例えば、GCEの場合、これらのメトリクスは以下のように呼ばれます:
cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}
Kubernetes v1.21 [beta]
スケジューラーは、すべての実行中のPodの要求されたリソースと希望する制限を報告するオプションのメトリクスを公開します。 これらのメトリクスは、キャパシティプランニングダッシュボードの構築、現在または過去のスケジューリング制限の評価、リソース不足によりスケジュールできないワークロードの迅速な特定、実際の使用量とPodのリクエストの比較に使用できます。
kube-schedulerは、各Podに設定されたリソースの要求と制限を識別します。 要求または制限のいずれかがゼロでない場合、kube-schedulerはメトリクスの時系列を報告します。 この時系列には以下のラベルが付与されます:
cpu)cores)Podが完了状態に達すると(restartPolicyがNeverまたはOnFailureで、SucceededまたはFailedのPodフェーズにある場合、もしくは削除されてすべてのコンテナが終了状態になった場合)、スケジューラーは他のPodを実行するようスケジュールできるようになるため、この時系列は報告されなくなります。
2つのメトリクスはkube_pod_resource_requestとkube_pod_resource_limitと呼ばれます。
メトリクスはHTTPエンドポイント/metrics/resourcesで公開されます。
これらのメトリクスには/metrics/resourcesエンドポイントの認可が必要であり、通常は/metrics/resources非リソースURLに対するget動詞を持つClusterRoleによって付与されます。
Kubernetes 1.21では、これらのAlphaメトリクスを公開するには--show-hidden-metrics-for-version=1.20フラグを使用する必要があります。
Kubernetes v1.36 [stable](デフォルトで有効)カーネルでPSIが有効になっている場合(バージョン4.20以降)、kubeletはCPU、メモリ、I/Oの使用に関するPressure Stall Information(PSI)を収集します。 この情報は、ノード、Pod、コンテナレベルで収集されます。
Prometheusメトリクス: /metrics/cadvisorエンドポイントで、合計ストール時間を秒単位で表す累積カウンター(合計値)として公開されます。
メトリクスはこのエンドポイントで以下の名前で公開されます:
container_pressure_cpu_stalled_seconds_total
container_pressure_cpu_waiting_seconds_total
container_pressure_memory_stalled_seconds_total
container_pressure_memory_waiting_seconds_total
container_pressure_io_stalled_seconds_total
container_pressure_io_waiting_seconds_total
Summary API: /stats/summaryエンドポイントで公開され、累積のtotalsと移動平均(avg10、avg60、avg300)の両方をJSON形式で提供します。
これらの平均は、それぞれ10秒、60秒、5分の間隔において、タスクがリソース上でストールしていた時間の割合を表します。
これらのメトリクスは、ノードの/proc/pressure/内の対応するファイル(cpu、memory、io)を通じて、以下の形式でネイティブにエクスポートもされます:
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0
これらのメトリクスをどのように組み合わせて解釈すればよいでしょうか?
例として、Summary APIに対する以下のクエリを考えます:
kubectl get --raw "/api/v1/nodes/$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')/proxy/stats/summary" | jq '.pods[].containers[] | select(.name=="<CONTAINER_NAME>") | {name, cpu: .cpu.psi, memory: .memory.psi, io: .io.psi}'。
これにより、以下のようなJSON形式で情報が返されます。
{
"name": "<CONTAINER_NAME>",
"cpu": {
"full": {
"total": 0,
"avg10": 0,
"avg60": 0,
"avg300": 0
},
"some": {
"total": 35232438,
"avg10": 0.74,
"avg60": 0.52,
"avg300": 0.21,
},
},
"memory": {
"full": {
"total": 539105,
"avg10": 0,
"avg60": 0,
"avg300": 0
},
"some": {
"total": 658164,
"avg10": 0.01,
"avg60": 0.01,
"avg300": 0.00,
},
}
},
"io": {
"full": {
"total": 33190987,
"avg10": 0.31,
"avg60": 0.22,
"avg300": 0.05,
},
"some": {
"total": 40809937,
"avg10": 0.52,
"avg60": 0.45,
"avg300": 0.12,
}
}
}
以下は単純なスパイクのシナリオです。
cpu.someのavg10値0.74は、直近10秒間に、このコンテナ内の少なくとも1つのタスクがCPU上で時間の0.74%(0.0074秒、つまり74ミリ秒)の間ストールしていたことを示します。
同じリソースにおいてavg10(0.74)がavg300(0.21)よりも著しく高いため、これは持続的な長期のボトルネックではなく、最近のリソース競合の急増を示唆しています。
継続的に監視してavg300メトリクスも増加する場合は、より深刻で持続的な問題であると診断できます!
さらに、この例ではcpu.someが圧迫を示している一方で、cpu.fullは0.00のままであることに注目してください。
これは、一部のプロセスはCPU時間を待って遅延していたものの、コンテナ全体としては依然として処理が進んでいたことを示しています。
fullの値がゼロでない場合は、アイドル状態でないすべてのタスクが同時にストールしていたことを示し、これははるかに大きな問題です。
人間にとって読みやすくはありませんが、total値の35232438は累積ストール時間をマイクロ秒単位で表しており、平均では現れないようなレイテンシーのスパイクを検出できます。
また、Prometheusのような監視システムが、特定の時間枠における正確な増加率を計算するのにも役立ちます。
最後に、高いI/O圧迫が低いメモリ圧迫とともに観測される場合、これはアプリケーションが利用可能なRAMの不足によって失敗しているのではなく、ディスクのスループットを待っていることを示している可能性があります。
ノードはメモリをオーバーコミットしておらず、ディスク消費に関する別の診断を調査できます。
PSIメトリクスは、すべてのcgroupについてあらゆるレベルでリアルタイムのリソース競合を監視する、より堅牢な方法を実現し、システム全体のワークロードを動的に扱う機会を開きます。 PSIメトリクスの詳細については、PSIメトリクスの理解を参照してください。
Pressure Stall Informationには以下が必要です:
コマンドラインフラグ--disabled-metricsを使用して、メトリクスを明示的に無効にできます。
例えば、メトリクスがパフォーマンスの問題を引き起こしている場合に使用できます。
入力は無効にするメトリクスのリストです(例: --disabled-metrics=metric1,metric2)。
無制限のディメンションを持つメトリクスは、計測対象のコンポーネントでメモリの問題を引き起こす可能性があります。
リソースの使用を制限するために、--allow-metric-labelsコマンドラインオプションを使用して、メトリクスのラベル値の許可リストを動的に設定できます。
Alphaステージでは、このフラグはメトリクスラベル許可リストのマッピングの系列のみを受け取ることができます。
各マッピングは<metric_name>,<label_name>=<allowed_labels>の形式で、<allowed_labels>は許可されるラベル名のカンマ区切りリストです。
全体のフォーマットは以下のとおりです:
--allow-metric-labels <metric_name>,<label_name>='<allow_value1>, <allow_value2>...', <metric_name2>,<label_name>='<allow_value1>, <allow_value2>...', ...
以下はその例です:
--allow-metric-labels number_count_metric,odd_number='1,3,5', number_count_metric,even_number='2,4,6', date_gauge_metric,weekend='Saturday,Sunday'
CLIからの指定に加えて、設定ファイル内でも行うことができます。
コンポーネントへの--allow-metric-labels-manifestコマンドライン引数を使用して、その設定ファイルへのパスを指定できます。
以下はその設定ファイルの内容の例です:
"metric1,label2": "v1,v2,v3"
"metric2,label1": "v1,v2,v3"
さらに、cardinality_enforcement_unexpected_categorizations_totalメタメトリクスは、カーディナリティ制限中の予期しないカテゴリ分けの数を記録します。
これは、許可リストの制約に対して許可されていないラベル値が検出された場合に発生します。