Kubernetesクラスターのパフォーマンス最適化のベストプラクティス
適切なリソースサイジング、オートスケーリング、効率的なネットワーキング、ストレージの選択、安定した可観測性でKubernetesのパフォーマンスを最適化します。
Kubernetesクラスターのパフォーマンス最適化のベストプラクティス
Kubernetesクラスターのパフォーマンス問題は、通常、ロールアウトの遅延、保留中のPod、ノイジーネイバー、または予想外のクラウド請求として現れます。修正は単一の魔法のような設定ではなく、正確なリソースサイジング、需要に合ったスケーリングルール、そして圧力がどこから始まるかを確認できる十分な可観測性が必要です。
このチェックリストを使用して、推測ではなくクラスターを調整してください。
リクエストと制限から始める
スケジューラーはCPUとメモリのrequestsを使用して、Podがどこに収まるかを決定します。リクエストが低すぎると、ノードは実際よりも空に見え、ワークロードがリソースを奪い合います。リクエストが高すぎると、スケジューラーは容量を無駄にし、Podが保留状態になる可能性があります。
実際の使用データからリクエストを設定します。例えば、APIコンテナが通常のトラフィック時に約300ミリコアで推移し、デプロイのウォームアップ時に700ミリコア近くにピークを迎える場合、次のように開始できます:
resources:
requests:
cpu: "300m"
memory: "512Mi"
limits:
memory: "1Gi"
CPU制限には注意してください。厳格なCPU制限は、ノードに余裕がある場合でも、レイテンシーに敏感なサービスをスロットリングする可能性があります。メモリ制限は依然として有用です。メモリ制限を超えたコンテナは、ノード全体をメモリプレッシャーに追い込む前に強制終了される可能性があるからです。
明確なシグナルでオートスケーリングを使用する
Horizontal Pod Autoscalerは、メトリクスがユーザーの需要を追跡している場合にうまく機能します。CPUは単純なステートレスサービスには十分ですが、キュー深度、リクエストレート、またはカスタムアプリケーションメトリクスが、より良いスケーリングシグナルとなることがよくあります。
kubectl autoscale deployment api \
--cpu-percent=70 \
--min=3 \
--max=20
Cluster Autoscaler、Karpenter、またはクラウドプロバイダーのノードオートスケーリングレイヤーは、Podが長期間保留状態になる前にノードを追加する余地を持つ必要があります。ノードグループが、ワークロードに必要なインスタンスサイズ、ゾーン、GPU要件、またはテイントをカバーしているか確認してください。
スケジューリングを予測可能に保つ
重要なPodが過負荷または不適切なノードに配置されると、パフォーマンスが低下します。高トラフィックサービスにはトポロジースプレッド制約、ハードウェア固有のワークロードにはノードアフィニティ、そして狭いクラスのPodのみを実行すべきノードにはテイントを使用します。
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: api
これにより、クラスターにより良い配置オプションがある場合に、レプリカが1つのノードに集中するのを防ぎます。
実際に問題がある箇所のネットワーキングを調整する
ほとんどのクラスターは、エキゾチックなネットワーク調整を必要としません。まず、遅いパスを見つけることから始めます:DNSルックアップ時間、サービスメッシュのオーバーヘッド、クロスゾーントラフィック、過負荷のイングレス、またはPodからデータベースへのレイテンシー。
有用なチェックには以下が含まれます:
kubectl top pods -A
kubectl get endpointslices -A
kubectl describe ingress <name>
kubectl logs -n kube-system -l k8s-app=kube-dns
チャットなサービスの場合、Podとその主要な依存関係を同じリージョンに、可能であれば同じゾーンに維持します。サービスメッシュを使用する場合は、メッシュの変更を広く展開する前に、1つのワークロードでサイドカーインジェクションありとなしのp95およびp99レイテンシーを測定します。
ストレージをワークロードに合わせる
ストレージの選択は、データベース、キュー、CIワークロードのパフォーマンスを支配する可能性があります。容量だけでなく、レイテンシー、IOPS、スループット、および障害動作に基づいてボリュームを選択します。
例えば、PostgreSQL Podには、予測可能なレイテンシーと明確なバックアップ動作を持つ永続ボリュームクラスが必要です。ビルドキャッシュはスループットをより重視し、再構築を許容する場合があります。ステートレスなWebサービスは、本当の理由がない限り、永続ボリュームを完全に避けるべきです。
これらの症状に注意してください:
- ボリュームのアタッチが遅いため、Podが
ContainerCreatingでスタックする。 - CPUが正常なのにアプリケーションのレイテンシーが上昇する。
- ノードのディスクプレッシャーがPodを退避させる。
- ボリュームが1つのゾーンに固定されているため、StatefulSetがブロックされる。
変更する前にクラスターを観察する
ベースラインメトリクスなしの最適化は、単なる無駄な作業です。最低限、CPU、メモリ、再起動、保留中のPod、ノードのプレッシャー状態、APIサーバーのレイテンシー、およびワークロードのp95レイテンシーを追跡します。
kubectl get nodes
kubectl describe node <node-name>
kubectl get pods -A --field-selector=status.phase=Pending
kubectl top nodes
Prometheusを実行している場合は、持続的なノードプレッシャー、高い再起動率、最大レプリカのHPA、および重要なDeploymentの利用不可レプリカに対するアラートを追加します。
まとめ
ワークロードから外側に向かってKubernetesを最適化します。リクエストを適切にサイジングし、不要なCPUスロットリングを回避し、需要シグナルからスケーリングし、レプリカを分散させ、ワークロードに合ったストレージを選択します。その後、各変更後に測定して、クラスターが高速化、低コスト化、または単に異なるものになったかを確認します。