インプレースPodリサイズが抱えていた「Deferred」問題
Kubernetesでは、PodのCPUやメモリをデプロイ後に動的に変更できる「インプレースPodリサイズ」機能がv1.35でGA(General Availability)となりました。これにより、アプリケーションの再起動なしにリソースを調整できるようになり、運用性が大きく向上しました。(出典)
しかし、この機能には課題がありました。ノードのリソースが不足している状態でPodのリソース増強が要求されると、Kubeletはその要求を「Deferred」状態として扱っていました。
「Deferred」は、リクエスト自体は有効だが、ノードに空きリソースがないため一時的に実行できない状態を指します。この状態のPodは、リソースが自然に解放されるのを待ち続けるしかなく、場合によっては無期限にブロックされる可能性がありました。
「Deferred」状態のリサイズ要求は、ノードのリソース不足によって高優先度アプリケーションの安定稼働を妨げるリスクがありました。
これまでの運用では、このような状況に直面した場合、クラスター管理者は手動で低優先度Podを退避させたり、クラスターオートスケーラーによるノード追加を待ったりする必要がありました。しかし、これらの対応は手動作業の負担や、Podの再スケジューリングによるダウンタイム発生など、インプレースリサイズの「再起動なし」というメリットを損なうものでした。
v1.37で導入された「Scheduler Preemption for In-Place Pod Resize」の仕組み
Kubernetes v1.37では、この「Deferred」問題を解決するために、「Scheduler Preemption for In-Place Pod Resize」がアルファ版機能として導入されました。この機能はInPlacePodVerticalScalingSchedulerPreemptionというFeature Gateの背後で提供されます。(出典)
この新しいメカニズムにより、Kubernetesスケジューラーは、リソースが逼迫したノード上で、高優先度アプリケーションの「Deferred」状態にあるリサイズ要求を成功させるために、低優先度のワークロードを積極的に強制終了(プリエンプション)できるようになります。これにより、必要なリソースが確保され、重要なPodのリソース増強が自動的に行われるようになります。
これはかなり衝撃的なニュースです。これまで手動でノードを調整していた経験があるエンジニアの方々にとっては、待ち望んでいた機能ではないでしょうか。
既存のPodプリエンプション機能は、主に新規Podのスケジューリング時に利用されていましたが、今回の機能は「実行中のPodのリソース増強」という文脈でプリエンプションが導入された点が重要です。
| 機能 | 対象 | 動作 |
|---|---|---|
| 既存のPodプリエンプション | 新規Podのスケジューリング | 低優先度Podを強制終了し、高優先度Podのためのスペースを確保 |
| v1.37の新機能 | 実行中のPodのインプレースリサイズ | 低優先度Podを強制終了し、高優先度Podのリソース増強のためのスペースを確保 |
ノードライフサイクル条件との関連性
今回の機能は、Kubernetes v1.37で同時に導入された「Node Lifecycle Conditions」と関連付けて考えることもできると感じます。Node Lifecycle Conditionsは、ノードの状態をより詳細に表現するための新しい条件(DrainInProgress、MaintenancePlannedなど)を提供します。(出典)
両者は直接的には異なる機能ですが、どちらも「ノードの状態」に基づいたKubernetesの運用自動化を進めるものと捉えられます。例えば、特定のノードがメンテナンス状態に入ることが事前に分かっていれば、今回のプリエンプション機能と組み合わせて、メンテナンス前に高優先度Podのリソースを別のノードへ振り分けるなどの高度なスケジューリング戦略が考えられるかもしれません。この辺りは今後の進化に注目したい点です。
今回のプリエンプション機能は、特にVPA(Vertical Pod Autoscaler)を使用している環境でその真価を発揮するでしょう。VPAが自動的にリソース要求を調整した際、ノードのリソースが不足しても、高優先度設定されたPodであれば、自動的にリソースを確保できるようになるため、運用の手間が大幅に削減されるはずです。自分のプロダクトでもVPAの導入を検討しているので、この機能はぜひ活用したいです。