このページでは、動的リソース割り当て(DRA)を利用するKubernetesクラスターを設定する際のグッドプラクティスについて説明します。 これらの手順は、クラスター管理者向けです。
DRAは、複数の異なるAPIを通じてオーケストレーションされます。 RBACや他のソリューションなどの認可ツールを使用して、ユーザーのペルソナに応じて適切なAPIへのアクセスを制御してください。
一般的に、DeviceClassとResourceSliceは管理者とDRAドライバーに制限する必要があります。 クレームを持つPodをデプロイするクラスターオペレーターは、ResourceClaimとResourceClaimTemplate APIへのアクセスが必要です。 これらのAPIはどちらもNamespaceスコープです。
DRAドライバーは、クラスターの各ノードで実行されるサードパーティアプリケーションで、そのノードのハードウェアとKubernetesのネイティブDRAコンポーネントとのインターフェースを提供します。 インストール手順は選択したドライバーによって異なりますが、クラスター内のすべてのノードまたは一部のノード(ノードセレクターや類似のメカニズムを使用)にDaemonSetとしてデプロイされる可能性が高いです。
DRAドライバーは、kubeletpluginパッケージインターフェースを実装します。
ドライバーは、このインターフェースのプロパティを実装することで シームレスアップグレード をサポートする場合があります。
これにより、同じDRAドライバーの2つのバージョンが短時間共存できます。
これはkubeletバージョン1.33以降でのみ利用可能で、古いバージョンのKubernetesを実行しているノードが接続された異種クラスターでは、ドライバーがサポートしていない可能性があります。
必ずドライバーのドキュメントを確認してください。
シームレスアップグレードが利用可能な環境の場合は、ドライバーの更新時のスケジューリング遅延を最小限に抑えるために使用を検討してください。
シームレスアップグレードを使用できない場合、アップグレードのためのドライバーのダウンタイム中に次のことが発生する可能性があります。
DRAドライバーは、DRAドライバーのグッドプラクティスの一部として、ヘルスチェック用のgRPCソケットを実装している可能性が高いです。 このgRPCソケットを利用する最も簡単な方法は、DRAドライバーをデプロイするDaemonSetのLiveness Probeとして設定することです。 ドライバーのドキュメントまたはデプロイツールにはすでにこれが含まれている可能性がありますが、設定を個別に構築している場合や、DRAドライバーをKubernetes Podとして実行していない場合は、オーケストレーションツールがこのgRPCソケットへのヘルスチェックの失敗時にDRAドライバーを再起動するようにしてください。 これにより、DRAドライバーの偶発的なダウンタイムを最小限に抑え、自己修復の機会を増やし、スケジューリングの遅延やトラブルシューティングの時間を削減できます。
DRAドライバーは、Podに割り当てられたデバイスの準備解除を担当します。 クレームを持つPodが削除される前にDRAドライバーがドレインされると、クリーンアップを完了できません。 ノードのカスタムドレインロジックを実装する場合は、DRAドライバー自体を終了する前に、割り当て/予約されたResourceClaimまたはResourceClaimTemplateがないことを確認することを検討してください。
コントロールプレーンコンポーネントkube-schedulerと、kube-controller-managerコンポーネントによってオーケストレーションされる内部ResourceClaimコントローラーは、DRA APIに格納されたメタデータに基づいてクレームを持つPodのスケジューリング中に重い処理を行います。 DRA以外のスケジュールされたPodと比較して、DRAクレームを使用するPodに必要なAPIサーバー呼び出しの数、メモリ、CPU使用率がこれらのコンポーネントで増加します。 さらに、DRAドライバーやkubeletなどのノードローカルコンポーネントは、Pod sandboxの作成時にハードウェアリクエストを割り当てるためにDRA APIを利用します。 特に、多数のノードを持つクラスターや、DRAで定義されたリソースクレームを大量に利用するワークロードをデプロイする大規模環境では、クラスター管理者は増加した負荷を予測するように関連コンポーネントを設定する必要があります。
調整が不適切なコンポーネントは、直接的または雪だるま式に影響を及ぼし、Podのライフサイクル中にさまざまな症状を引き起こすことがあります。
kube-schedulerコンポーネントのQPSとバースト設定が低すぎる場合、スケジューラーはPodに適したノードを迅速に識別できますが、Podをそのノードにバインドするのに時間がかかる場合があります。
DRAでは、Podのスケジューリング中に、kube-controller-manager内のclient-go設定のQPSとBurstパラメーターが重要です。
クラスターを調整するための具体的な値は、ノード/Podの数、Podの作成頻度、入れ替わり(churn)の度合いなど、DRA以外の環境でもさまざまな要因に依存します。
詳細については、SIG ScalabilityのKubernetesスケーラビリティしきい値に関するREADMEを参照してください。
100ノードのDRA対応クラスターに対して、720個の長期稼働Pod(飽和度90%)、80個の入れ替わり用Pod(10%の入れ替えを10回)、ジョブ作成QPSが10の場合でスケールテストを実施しました。
その結果、kube-controller-managerのQPSを75、Burstを150という低い値に設定しても、DRA以外のデプロイメントと同等のメトリクス目標を達成できました。
この下限値では、クライアント側のレートリミッターが発動したことで、APIサーバーを急激なバーストから保護できていた一方で、この値はPodの起動SLOに影響しないほど十分に高かったことが観測されました。
これは良い出発点ですが、次のメトリクスを監視することで、デプロイメントのDRAパフォーマンスに最も大きな影響を与えるさまざまなコンポーネントを調整する方法について、より良いアイデアを得ることができます。
Kubernetesのすべての安定版メトリクスの詳細については、Kubernetesメトリクスリファレンスを参照してください。
kube-controller-managerメトリクス次のメトリクスは、kube-controller-managerコンポーネントによって管理される内部ResourceClaimコントローラーを詳しく調べるためのものです。
sum(rate(workqueue_adds_total{name="resource_claim"}[5m]))を監視して、ResourceClaimコントローラーにアイテムが追加される速度を測定します。sum(workqueue_depth{endpoint="kube-controller-manager", name="resource_claim"})を追跡して、ResourceClaimコントローラーのバックログを特定します。histogram_quantile(0.99, sum(rate(workqueue_work_duration_seconds_bucket{name="resource_claim"}[5m])) by (le))を観測して、ResourceClaimコントローラーが作業を処理する速度を把握します。Workqueue Add Rateが低い、Workqueue Depthが高い、Workqueue Work Durationが高い、のいずれか1つでも当てはまる場合、コントローラーが最適に動作していないことを示唆しています。 QPS、バースト、CPU/メモリ設定などのパラメーターの調整を検討してください。
Workqueue Add RateとWorkqueue Depthが高く、Workqueue Work Durationが妥当な場合、コントローラーは作業を処理していますが、並行性が不十分である可能性があることを示しています。 並行性はコントローラー内でハードコードされているため、クラスター管理者としては、Pod作成QPSを下げることで調整でき、リソースクレームのワークキューへの追加速度がより管理しやすくなります。
kube-schedulerメトリクス次のスケジューラーのメトリクスは、DRAを使用するPodだけでなく、スケジュールされたすべてのPodのパフォーマンスを集約する高レベルのメトリクスです。
エンドツーエンドのメトリクスは、ResourceClaimTemplateを多用するデプロイメントにおいて、ResourceClaimTemplateからResourceClaimを作成するkube-controller-managerのパフォーマンスに最終的に影響を受けることに注意してください。
histogram_quantile(0.99, sum(increase(scheduler_pod_scheduling_sli_duration_seconds_bucket[5m])) by (le))を監視します。histogram_quantile(0.99, sum(increase(scheduler_scheduling_algorithm_duration_seconds_bucket[5m])) by (le))を追跡します。kubeletメトリクスノードにバインドされたPodのResourceClaimを満たす必要がある場合、kubeletはDRAドライバーのNodePrepareResourcesおよびNodeUnprepareResourcesメソッドを呼び出します。
この動作は、kubeletの視点から次のメトリクスで観測できます。
histogram_quantile(0.99, sum(rate(dra_operations_duration_seconds_bucket{operation_name="PrepareResources"}[5m])) by (le))を監視します。histogram_quantile(0.99, sum(rate(dra_operations_duration_seconds_bucket{operation_name="UnprepareResources"}[5m])) by (le))を追跡します。DRAドライバーは、kubeletpluginパッケージインターフェースを実装します。
これは、基盤となるgRPCオペレーションのNodePrepareResourcesおよびNodeUnprepareResourcesについて、独自のメトリクスを公開します。
この動作は、内部kubeletpluginの視点から次のメトリクスで観測できます。
histogram_quantile(0.99, sum(rate(dra_grpc_operations_duration_seconds_bucket{method_name=~".*NodePrepareResources"}[5m])) by (le))を観測します。histogram_quantile(0.99, sum(rate(dra_grpc_operations_duration_seconds_bucket{method_name=~".*NodeUnprepareResources"}[5m])) by (le))を観測します。