Kubernetesパフォーマンス監視:最適化のためのツールとテクニック
有用なメトリクス、Prometheus、Grafana、kubectl、実践的なリソース調整の習慣を使ってKubernetesのパフォーマンスを監視します。
Kubernetesパフォーマンス監視:最適化のためのツールとテクニック
Kubernetesのパフォーマンス監視は、単にCPUチャートを見るだけではありません。クラスターの平均CPU使用率が低くても、ユーザーが遅いリクエストを経験することがあります。Podは一日のほとんどの時間帯で十分なメモリを持っていても、バッチジョブ中に強制終了されることがあります。ノードはディスクプレッシャーがPodの退避を始めるまで健全に見えることがあります。優れた監視は、クラスターのシグナルを人々が実際に気にする体験、つまりサービスが高速で、利用可能で、予測可能かどうかに結びつけます。
最初の間違いは、ツールから始めて質問をしないことです。Prometheus、Grafana、metrics-server、kube-state-metrics、クラウド監視プラットフォームはすべて有用ですが、何が重要かを決めるのはツールではありません。ワークロードを理解することで、あなたがそれを決めます。パブリックAPIはレイテンシとエラーを気にします。キュー・ワーカーはバックログと処理レートを気にします。夜間ジョブは完了時間と失敗したPodを気にします。データベースのようなワークロードはディスクレイテンシとメモリプレッシャーを気にします。
簡単な確認には、kubectl topが依然として便利です:
kubectl top nodes
kubectl top pods -A
kubectl top pod -n production api-7d9c8f7b9d-2x4mq --containers
これらのコマンドはmetrics-serverに依存しています。直近のCPUとメモリ使用量を提供しますが、完全な履歴は提供しません。トリアージ中に使用し、唯一の監視システムとしては使用しないでください。Podが10分前にメモリ不足で再起動した場合、kubectl topはその原因となったスパイクを表示しない可能性があります。
Prometheusは、時系列データをスクレイピングし、Kubernetesのサービスディスカバリとうまく連携するため、Kubernetesメトリクスの共通基盤です。典型的なセットアップでは、メトリクスはいくつかの場所から取得されます。kubeletはコンテナとPodのリソースメトリクスを公開します。kubeletに統合されたcAdvisorは、コンテナのCPU、メモリ、ファイルシステム、ネットワークデータを提供します。node-exporterはホストレベルのメトリクスを報告します。kube-state-metricsはKubernetesオブジェクトの状態をメトリクスに変換します:希望するレプリカ数、利用可能なレプリカ数、Podのフェーズ、ノードの状態など。
Grafanaはそれらのメトリクスをダッシュボードに変換します。優れたダッシュボードはゲージの壁ではありません。特定の質問に迅速に答えるべきです:どのサービスが遅いか、どのPodがスロットリングされているか、どのノードがプレッシャー下にあるか、どのDeploymentのロールアウトが失敗しているか、オートスケーリングが追いついているかどうか。
アプリケーション層から始めてください。ユーザー向けサービスの場合、最も重要なシグナルはリクエストレート、エラーレート、レイテンシです。SLOがある場合は、それらをグラフ化してください。PodのCPUチャートは、チェックアウトが失敗しているかどうかを教えてくれません。アプリケーションメトリクスがそれを教えてくれます。Prometheusクライアントライブラリ、OpenTelemetry、またはプラットフォームがすでに使用している監視システムでサービスを計装してください。Kubernetesメトリクスはサービスが不健全な理由を説明します。アプリケーションメトリクスはそれが不健全であることを教えてくれます。
次に、アプリケーションの症状をPodリソースに結びつけてください。KubernetesではCPU使用率を誤解しやすいです。CPU制限のあるコンテナは、平均CPUが劇的に見えなくてもスロットリングされることがあります。スロットリングは、コンテナがスケジューリング期間内に制限以上のCPU時間を使用しようとしたときに発生します。レイテンシに敏感なアプリケーションでは、これによりランダムに見える遅いリクエストが発生する可能性があります。
スロットリングに便利なPromQLクエリは次のとおりです:
rate(container_cpu_cfs_throttled_periods_total{namespace="production", container!=""}[5m])
値が上昇している場合、コンテナがスロットリングされていることを意味します。CPU使用率とリクエストレイテンシと組み合わせてください。レイテンシのスパイクがスロットリングと一致する場合は、CPU制限の引き上げまたは削除、レプリカ数の増加、またはコードパスの最適化を検討してください。一部のチームは、レイテンシに敏感なサービスのためにCPUリクエストを設定しますが、CPU制限は避け、代わりにリクエスト、オートスケーリング、ノード容量制御に依存します。それは合理的かもしれませんが、ノイズの多いワークロードが他のワークロードを飢えさせないように、クラスターレベルの規律が必要です。
メモリは異なる動作をします。CPUはスロットリングできますが、メモリは同じように遅くすることはできません。コンテナがメモリ制限を超えると、OOMKilledされる可能性があります。再起動の理由を探してください:
kubectl describe pod -n production api-7d9c8f7b9d-2x4mq
kubectl get pod -n production api-7d9c8f7b9d-2x4mq -o jsonpath='{.status.containerStatuses[*].lastState}'
Prometheusでは、ワーキングセットメモリを監視し、制限と比較してください:
container_memory_working_set_bytes{namespace="production", container!=""}
静かな1時間だけからメモリを調整しないでください。ピークトラフィック、バッチウィンドウ、デプロイメント、ガベージコレクションの動作を確認してください。Java、Go、Node.js、Pythonのサービスは異なるメモリプロファイルを持っています。通常のトラフィックでは寛大に見える制限も、起動時、キャッシュウォームアップ時、または大きなリクエスト時には厳しすぎる可能性があります。
リソースリクエストは、スケジューラがPodの配置に使用するため重要です。リクエストが低すぎると、Kubernetesは同じノードに多くのビジーなPodを詰め込みすぎる可能性があります。それらのPodが同時にビジーになるまでは、すべてが効率的に見えます。リクエストが高すぎると、クラスターは容量を浪費し、オートスケーリングが必要以上に早くノードを追加する可能性があります。最適なリクエストは通常、観測された使用量にヘッドルームを加えたものに基づいており、他のサービスからコピーした値ではありません。
Vertical Pod Autoscalerは、履歴使用量からリクエストを推奨することで役立ちます。多くのチームは、最初にVPAを推奨モードで実行します。自動更新は設定とワークロードタイプに応じてPodを再起動する可能性があるためです。推奨事項を入力として扱い、絶対的なルールとして扱わないでください。まれではあるが重要なスパイクがあるサービスは、平均的な履歴が示唆するよりも多くのヘッドルームを必要とする場合があります。
Horizontal Pod Autoscalerは、より多くのレプリカが実際にスループットを向上させる場合に便利です。ステートレスなWebサービスや負荷を共有できるワーカーに適しています。シングルスレッドのボトルネック、データベースロック、またはすでに飽和状態にあるダウンストリーム依存関係を修正するものではありません。
基本的なHPAは次のようになります:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
HPAの動作を監視し、レプリカ数だけでなく確認してください。常にスケールアップとスケールダウンを繰り返している場合は、安定化ウィンドウ、ターゲット、またはメトリクスを調整してください。maxReplicasに達してもレイテンシが悪いままの場合、問題は容量、コード、または依存関係にある可能性があります。Podが明らかに過負荷であるのにスケールしない場合は、メトリクスの可用性とリクエストが設定されているかどうかを確認してください。CPU使用率のターゲットはCPUリクエストに依存します。リクエストがないか非現実的だと、オートスケーリングが誤解を招く可能性があります。
ノードの健全性は次のレイヤーです。1つのノード上の多くのサービスにわたって現れるPodの問題は、通常ノードの問題です。CPU飽和、ロードアベレージ、利用可能なメモリ、ディスクプレッシャー、inode使用量、ファイルシステムレイテンシ、ネットワークエラー、kubeletの健全性を監視してください。MemoryPressure、DiskPressure、PIDPressureなどのノード状態は、ダッシュボードとアラートで表示されるべきです。
ノードが疑わしい場合はkubectl describe nodeを使用してください:
kubectl describe node worker-12
状態、割り当てられたリソース、イベント、ノードにスケジュールされたPodを確認してください。ノードは制限、リクエスト、または実際の使用量によってオーバーコミットされる可能性があります。割り当てられたリソースセクションは、スケジューリングの前提が現実と一致しているかどうかを確認するのに役立ちます。
アプリケーションPodが正常に見えても、コントロールプレーンの監視は重要です。APIサーバーのレイテンシは、デプロイメント、オートスケーリング、コントローラーを遅くする可能性があります。etcdのレイテンシやディスクの問題は、クラスター全体を遅く感じさせる可能性があります。コントローラーマネージャーやスケジューラーの問題は、Podの配置や調整を遅らせる可能性があります。マネージドKubernetesでは、すべてのコントロールプレーンコンポーネントが見えないかもしれませんが、クラウドプロバイダーは通常、いくつかの健全性とAPIサーバーレイテンシのメトリクスを公開しています。
イベントはインシデント中に便利ですが、長期的なメトリクスストアではありません。それでも、何が起こったかを説明することがよくあります:
kubectl get events -A --sort-by=.lastTimestamp
スケジューリングの失敗、イメージプルエラー、プローブの失敗、退避、バックオフメッセージを探してください。イベントはノイズが多い場合があるので、必要に応じて名前空間や関連オブジェクトでフィルタリングしてください。
プローブは注意深く監視する価値があります。攻撃的なLiveness Probeは、遅いが回復中のアプリを再起動させ、インシデントを悪化させる可能性があります。正しく失敗するReadiness Probeは、不良なPodをサービスから削除することでユーザーを保護できます。プローブの失敗を追跡し、CPUスロットリング、GCポーズ、ダウンストリームタイムアウト、デプロイと相関させてください。
ストレージを多用するワークロードの場合、コンテナのCPUとメモリだけでは不十分です。永続ボリュームのレイテンシ、ディスクスループット、キュー深度、ファイルシステムの充満度を監視してください。遅いストレージを待っているPodは、ブロックされているために低いCPUを示す可能性があります。データベースやキューがKubernetes上で実行されている場合、ストレージメトリクスはアプリケーションパフォーマンスの一部であり、インフラストラクチャの些細なことではありません。
実践的なトラブルシューティングのパスは、広く始めて狭めていきます。まず、ユーザー向けの症状を確認します:レイテンシ、エラー、失敗したジョブ、バックログ。次に、範囲を特定します:1つのPod、1つのDeployment、1つのノード、1つの名前空間、またはクラスター全体。第三に、最近の変更を確認します:デプロイメント、設定の更新、オートスケーラーのアクティビティ、ノードのローテーション、トラフィックスパイク。第四に、Podのリソース動作を検査します:CPUスロットリング、メモリプレッシャー、再起動、プローブの失敗。第五に、ノードと依存関係の健全性を検査します。
アラートは、無害なノイズで人を起こさないようにすべきです。まずユーザーへの影響でアラートを出します:高いエラーレート、高いレイテンシ、ジョブの期限超過、キューエイジの増加。次に、強い先行指標でアラートを出します:頻繁なOOMKill、レイテンシに敏感なサービスでの持続的なCPUスロットリング、希望するレプリカ数を下回るPod、ノードプレッシャー、持続的な保留中のPod、サービスメトリクスが悪いのにHPAが最大レプリカでスタックしていること。
目標は完全な使用率ではありません。一日中95%のリソース使用率で動作しているクラスターは、1つのノードが故障してPodを再スケジュールする余地がなくなるまで効率的に見えるかもしれません。ロールアウト、リトライ、トラフィックバースト、障害のために容量を残してください。最適化は、インシデントを小さく保つバッファを削除せずに無駄を減らすべきです。
優れたKubernetesパフォーマンス監視は実用的に感じられます。ダッシュボードを開いて、20のタブを探し回ることなく、サービスの健全性、Podの健全性、ノードの健全性、スケーリング動作を確認できます。スローダウンがコード、リソース制限、ノードプレッシャー、ストレージ、ネットワーク、またはコントロールプレーンのいずれであるかを答えられます。そして、リクエスト、制限、またはオートスケーリングを変更したときに、変更が役立ったかどうかを推測ではなく確認できます。
名前空間レベルのビューは、多くのチームがクラスターを共有する場合に便利です。単一のチームは、自分のDeploymentだけを見ていると、ノードレベルの飽和が来ていることに気づかないかもしれません。プラットフォームチームは、名前空間のCPUとメモリのリクエスト、実際の使用量、Pod数、再起動、スロットリングを示すダッシュボードを公開する必要があります。これにより、容量に関する会話が感情的ではなくなります。チームが「使いすぎ」と言う代わりに、リクエストの傾向、ピーク使用量、無駄を示すことができます。
コスト最適化は、信頼性のシグナルの後に行うべきであり、その前ではありません。サービスが一度もリクエストを調整したことがない場合、簡単な節約が見つかるかもしれません。しかし、リクエストを積極的に削減すると、スケジューリングプレッシャーやノイジーネイバーの問題を引き起こす可能性があります。良いプロセスは、一度に1つのワークロードクラスを変更し、レイテンシと再起動を監視し、ロールバックのメモを残します。リソース調整をプロダクションコードのように扱ってください:小さな変更、測定された結果。
デプロイメント自体がパフォーマンスインシデントを引き起こす可能性があります。一度にあまりにも多くのPodを置き換えるロールアウトは、コールドキャッシュ、コネクションプール、またはダウンストリームサービスを過負荷にする可能性があります。ロールアウトの期間、利用不可のレプリカ数、デプロイ中のアプリケーションレイテンシを監視してください。サービスの起動時の動作に基づいてmaxSurgeとmaxUnavailableを調整してください。ウォームアップが遅いサービスは、定常状態のパフォーマンスが良好でも、保守的なロールアウトが必要な場合があります。
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
その設定は普遍的に最適ではありませんが、トレードオフを示しています:より遅いロールアウト、容量低下に対するより多くの保護。即座に起動するステートレスサービスの場合、より速いロールアウトを選択するかもしれません。キャッシュをウォームアップし、多くのダウンストリーム接続を開くJVMサービスの場合、より遅い方が安全かもしれません。
メトリクスのカーディナリティに注意してください。Kubernetesラベルは魅力的ですが、Pod UID、リクエストID、ユーザーIDなどの高カーディナリティラベルは、Prometheusを高価で遅くする可能性があります。集約に役立つラベルを使用してください:名前空間、ワークロード、Pod、コンテナ、ノード、ステータスコード、ルートパターン。ユーザーやリクエストごとに新しい時系列を作成するラベルは避けてください。監視がクラスターパフォーマンスを損なうものであってはなりません。
ログとトレースが全体像を完成させます。メトリクスはレイテンシが増加したことを教えます。トレースはどのダウンストリーム呼び出しが遅くなったかを示すことができます。ログは正確なエラーやタイムアウトを示すことができます。OpenTelemetryはこれらのシグナルを接続するために一般的に使用されますが、ツールよりも相関関係が重要です。一貫したサービス名、名前空間、バージョン、トレースIDを使用して、アラートから関連するログに推測せずに移動できるようにしてください。
バッチおよびワーカーシステムの場合、PodのCPUだけでなく、バックログエイジを監視してください。キュー・ワーカーは、Podレベルでは健全でも、受信作業が処理能力を超えているために遅れをとることがあります。最も古いメッセージエイジ、1分あたりの完了ジョブ数、リトライ、デッドレター数などのメトリクスは、コンテナ使用率よりも重要であることがよくあります。CPUが間違ったシグナルである場合、HPAはカスタムまたは外部メトリクスからスケールできます。
インシデント後にダッシュボードをレビューしてください。対応者が同じ質問に答えるために5つの手動コマンドを実行しなければならなかった場合、その質問はダッシュボードまたはランブックに属しています。監視は使用を通じて改善されます。目標はすべての障害を予測することではなく、次の調査をより短く、一人の記憶に依存しないものにすることです。