Kubernetes 1.28: SIG-Scheduling の変更内容

Kubernetes 1.28 の [CHANGELOG](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.28.md) から、SIG-Scheduling に関するところを抜粋して紹介します。
:pencil: は筆者によるコメントです。

過去 3 リリースの変更内容：

- [Kubernetes 1.27: SIG-Scheduling の変更内容](https://qiita.com/ordovicia/items/6046be0f50f999cdb063)
- [Kubernetes 1.26: SIG-Scheduling の変更内容](https://qiita.com/everpeace/items/8ffce0195f7d8371c54f)
- [Kubernetes 1.25: SIG-Scheduling の変更内容](https://qiita.com/everpeace/items/b2bb8a0b02a8b30c9299)

## :pencil: 所感

今回のリリースは、Kubernetes スケジューラの内部に関する変更の割合が多くなっています。

スケジューリングキューへの pod の追加をより賢くおこなうための queueing hint 機能の開発が進んでいます。
Kubernetes 1.26 で導入された [Pod Scheduling Readiness 機能](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-scheduling-readiness/) では、pod がゲートされている間、その pod のスケジューリングをおこなわないようにできます。
同じ考えで、pod のスケジューリングが（例えばクラスタ上の空きリソースの不足によって）失敗した場合、その理由が解決される（例えばノードの追加によって）まで、その pod の再スケジューリング（キューへの追加）をおこなわないという最適化が、queueing hint 機能です。
より詳しい説明が [Urgent Upgrade Notes](#urgent-upgrade-notes必ず一読してからアップグレードしなければならない事項) にあります。
[@sanposhiho](https://github.com/sanposhiho) さんが開発をリードしており、トラッキングイシューは [introduce QueueingHint for wise-enqueueing · Issue #114297 · kubernetes/kubernetes](https://github.com/kubernetes/kubernetes/issues/114297) のようです。

また、スケジューラプラグインの呼び出しの最適化（`PreScore`/`PreFilter` 拡張点が `Skip` ステータスを返した場合、同じプラグインの `Score`/`Filter` 拡張点をスキップする）が着々と進んでいます。

## Urgent Upgrade Notes（必ず一読してからアップグレードしなければならない事項）

カスタムのスケジューラプラグインの開発者は、`EnqueueExtension` インターフェイスに破壊的変更が入ったことに対応する必要があります。
`EventsToRegister` メソッドが、`ClusterEvent` ではなく `ClusterEventWithHint` を返すようになりました。

`ClusterEventWithHint` 構造体は `QueueingHintFn` コールバック関数をフィールドにもっており、これは不要なイベントを無視することで pod の無用な再スケジューリングを抑制することができます。
スケジューラは、クラスタのイベント（ノードの追加など）が起こった際、前回のスケジューリングサイクルでその pod を拒否したプラグインの `QueueingHintFn` 関数を呼びます。
その結果によって、pod を unschedulable pool から backoff queue / active queue に移すかどうかを決定します。

- 一つ以上の `QueueingHintFn` が `QueueImmediately` を返した場合、その pod はすぐ active queue に移されます。
- すべての `QueueingHintFn` が `QueueImmediately` を返さず、一つ以上が `QueueAfterBackoff` を返した場合、その pod は backoff queue に移されます（すでにバックオフを過ぎていたら active queue）。
- すべての `QueueingHintFn` が `QueueSkip` を返した場合、その pod は unschedulable pool に残ります。

適切な `QueueingHintFn` を定義することで、無用な再スケジューリングを抑制し、スケジューラの性能向上に役立ちます。

**移行方法**

後方互換性のため、`QueueingHintFn` フィールドが `nil` の場合は、`QueueAfterBackoff` を常に返すものとして扱われます。
そのため、現在の挙動を保ちたい場合は、`QueueingHintFn` をもたない `ClusterEventWithHint` を登録すればよいです。
しかし、適切な `QueueingHintFn` を登録することが、当然ながらスケジューリングの性能にとってよりよいです。

([#118551](https://github.com/kubernetes/kubernetes/pull/118551), [@sanposhiho](https://github.com/sanposhiho))

## Changes by Kind（種類別の変更）

### Deprecation（非推奨）

- kube-scheduler の非推奨のフラグ `--lock-object-namespace` および `--lock-object-name` が削除されました。これらのパラメータを設定するには、`--leader-elect-resource-namespace` および `--leader-elect-resource-name` または `ComponentConfig` を使用してください。([#119130](https://github.com/kubernetes/kubernetes/pull/119130), [@SataQiu](https://github.com/SataQiu))

### API Change（API 変更）

- kube-scheduler のリーダーが更新されたときのメモリ効率とスケジューリング速度のトレードオフを選択できる新しい設定オプション `delayCacheUntilActive` が `KubeSchedulerConfiguration` に追加されました。([#115754](https://github.com/kubernetes/kubernetes/pull/115754), [@linxiulei](https://github.com/linxiulei))
  - :pencil: `true` にすると、リーダー選出が有効の場合、kube-scheduler プロセスがリーダーに選ばれるまで informer のキャッシュを暖気しなくなります。すると、メモリ使用量は減りますが、新しいリーダーが立ち上がるまで時間がかかることになります。
- `NodeVolumeLimits` プラグインは、Pod が制限を持つボリュームを使用しない場合に Filter フェイズをスキップするために `PreFilter` 拡張点を実装するようになりました。([#115398](https://github.com/kubernetes/kubernetes/pull/115398), [@tangwz](https://github.com/tangwz))
  - :pencil: `PreFilter` 拡張点で `Skip` ステータスを返すことで、同じプラグインの `Filter` 拡張点をスキップします。
- ResourceClaimTemplate から生成される ResourceClaim の名前が自動生成されるようになりました。基本的な名前はこれまで同様 `<pod>-<claim name>` ですが、ランダムな接尾辞が付くことで名前の衝突を回避します。([#117351](https://github.com/kubernetes/kubernetes/pull/117351), [@pohly](https://github.com/pohly))
- `component-base/logs` は、同じ構成を複数回適用しようとしたときにエラーを返すようになりました。これが必要なバイナリはオーバーライドできます。([#117108](https://github.com/kubernetes/kubernetes/pull/117108), [@pohly](https://github.com/pohly))
- ` kube-scheduler` の設定 (`KubeSchedulerConfiguration`) について、 `kubescheduler.config.k8s.io/v1beta2` は v1.28 で削除されました。`kubescheduler.config.k8s.io/v1` に移行してください。([#117649](https://github.com/kubernetes/kubernetes/pull/117649), [@SataQiu](https://github.com/SataQiu))
  - :pencil: v1beta3 も Kubernetes 1.29 で削除されます。移行方法は [このドキュメント](https://kubernetes.io/docs/reference/scheduling/config/#scheduler-configuration-migrations) が参考になります。

### Feature（機能追加）

- 新しいフィーチャゲート `SchedulerQueueingHints` を追加しました（デフォルトで有効）。この新しいフィーチャゲートは、スケジューラプラグインに関連するイベントの詳細なフィルタリングのためのフレームワークを有効にします。このリリースでは、デフォルトのスケジューリングプラグインはヒントフレームワークを使用しないため、挙動の変更は期待できません。([#119328](https://github.com/kubernetes/kubernetes/pull/119328), [@sanposhiho](https://github.com/sanposhiho))
  - :pencil: 前述の queueing hint 機能を有効にするフィーチャゲートです。
- ResourceClaims が関与する場合のスケジューリングが速くなりました。([#119078](https://github.com/kubernetes/kubernetes/pull/119078), [@pohly](https://github.com/pohly))
  - :pencil: スケジューラプラグインで `PreEnqueue` 拡張点を実装し、ResourceClaim がまだ存在しない pod のスケジューリングをおこなわないようにしています。また、前述の queueing hint 機能を使い、pod の再スケジューリングをおこなう契機を、ResourceClaim に関するイベントなどに絞っています。
- `scheduler_scheduler_goroutines` メトリックは削除されました。代わりに `scheduler_goroutines` を使用してください。([#117727](https://github.com/kubernetes/kubernetes/pull/117727), [@kerthcet](https://github.com/kerthcet))
- `pkg/scheduler/framework/preemption` が [contextual logging](https://k8s.io/docs/concepts/cluster-administration/system-logs/#contextual-logging) を使うよう移行しました。([#116835](https://github.com/kubernetes/kubernetes/pull/116835), [@mengjiao-liu](https://github.com/mengjiao-liu))
- `noderesources` スケジューラプラグイン が [contextual logging](https://k8s.io/docs/concepts/cluster-administration/system-logs/#contextual-logging) を使うよう移行しました。([#116748](https://github.com/kubernetes/kubernetes/pull/116748), [@mengjiao-liu](https://github.com/mengjiao-liu))
- `podtopologyspread` スケジューラプラグインが [contextual logging](https://k8s.io/docs/concepts/cluster-administration/system-logs/#contextual-logging) を使うよう移行しました。([#116797](https://github.com/kubernetes/kubernetes/pull/116797), [@mengjiao-liu](https://github.com/mengjiao-liu))
- スケジューラは、スケジュールサイクルが開始する前にハンドラが同期を完了するのを待つようになりました。([#116729](https://github.com/kubernetes/kubernetes/pull/116729), [@AxeZhan](https://github.com/AxeZhan))
- Kubernetes apiserver は、`podAffinity` または `topologySpreadConstraints` の中で `null` のラベルセレクタを持つ Pod に対して警告メッセージを発行するようになりました。`null` のラベルセレクタは「どの pod ともマッチさせない」を意味します。これを `podAffinity` または `topologySpreadConstraint` で使用すると、意図しない動作が発生する可能性があります。([#117025](https://github.com/kubernetes/kubernetes/pull/117025), [@sanposhiho](https://github.com/sanposhiho))
- スケジューラは、Pod に対してすることがないときに、`InterPodAffinity` プラグインの `Score` 拡張点をスキップします。これは `InterPodAffinity` プラグインの `Score` 拡張点に関するメトリクスの値に影響します。([#117794](https://github.com/kubernetes/kubernetes/pull/117794), [@utam0k](https://github.com/utam0k))
  - :pencil: `PreScore` 拡張点で `Skip` ステータスを返すことで、同じプラグインの `Score` 拡張点をスキップします。
- スケジューラは、spread constraint が存在しない場合に `PodTopologySpread` プラグインの `Filter` 拡張点をスキップします。これは、`PodTopologySpread` プラグインの `Filter` プラグインに関するメトリクスの値に影響します。([#117683](https://github.com/kubernetes/kubernetes/pull/117683), [@utam0k](https://github.com/utam0k))
- スケジューラは、Pod に対してすることがないときに、`PodTopologySpread` プラグインの `Score` 拡張点をスキップします。これは `PodTopologySpread` プラグインの `Score` 拡張点に関するメトリクスの値に影響します。([#118608](https://github.com/kubernetes/kubernetes/pull/118608), [@utam0k](https://github.com/utam0k))
- スケジューラのインターフェースとキャッシュに関するメソッドを contextual logging [contextual logging](https://k8s.io/docs/concepts/cluster-administration/system-logs/#contextual-logging) を使うよう移行しました。([#116849](https://github.com/kubernetes/kubernetes/pull/116849), [@mengjiao-liu](https://github.com/mengjiao-liu))
- `plugin_evaluation_total` メトリックは、`PreScore`/`Score` 拡張点をサポートするようになりました。このメトリックは、`PreScore`/`Score` プラグインがスケジューリング中の pod に対してすることがない場合は増加しません。([#118025](https://github.com/kubernetes/kubernetes/pull/118025), [@AxeZhan](https://github.com/AxeZhan))

### Documentation（ドキュメント改善）

SIG-Scheduling に関するものはありません。

### Failing Test（失敗しているテスト）

SIG-Scheduling に関するものはありません。

### Bug or Regression（バグ修正）

- クリティカルなコードパスで頻繁にメトリックをルックアップすることによるスケジューラの性能低下が修正されました。([#117594](https://github.com/kubernetes/kubernetes/pull/117594), [@tosi3k](https://github.com/tosi3k))
- `PreEnqueue` 拡張点を実装する プラグインが `backoffQ` を介して `activeQ` に移動される Pod に対して実行されない既知の問題を修正しました。([#117194](https://github.com/kubernetes/kubernetes/pull/117194), [@sanposhiho](https://github.com/sanposhiho))
  - :pencil: 1.27 にあったバグです。カスタムした `PreEnqueue` プラグインでは、backoff queue にある（つまり、いちどゲートを通った） pod がゲートされた状態に戻されることがありえますが、このケースを想定していませんでした。
- リソース要求量がゼロの場合、kube-scheduler は pod のリソース要求量のチェックをスキップするようになりました。([#116408](https://github.com/kubernetes/kubernetes/pull/116408), [@ChenLingPeng](https://github.com/ChenLingPeng))
  - :pencil: 具体的には `NodeResourceFit` プラグインです。
- `pod_scheduling_duration_seconds` メトリックは、pod が `PreEnqueue` に失敗した場合（ゲートされた場合など）の時間を考慮しないようになりました。([#118049](https://github.com/kubernetes/kubernetes/pull/118049), [@helayoty](https://github.com/helayoty))
  - :pencil: Pod がゲートされていたあいだの時間は含まれずに、active queue に追加された時点からの時間が計算されることになります。

### Other (Cleanup or Flake)（その他）

- プリエンプションされた pod の詳細（プリエンプションされた pod とした pod を含む）を出力する、v2 レベルの info ログが追加されました。([#117214](https://github.com/kubernetes/kubernetes/pull/117214), [@HirazawaUi](https://github.com/HirazawaUi))
- `pkg/scheduler/framework/runtime` が [contextual logging](https://k8s.io/docs/concepts/cluster-administration/system-logs/#contextual-logging) を使うよう移行しました。([#116842](https://github.com/kubernetes/kubernetes/pull/116842), [@mengjiao-liu](https://github.com/mengjiao-liu))
- `interpodaffinity` プラグインが [contextual logging](https://k8s.io/docs/concepts/cluster-administration/system-logs/#contextual-logging) を使うよう移行しました。([#116635](https://github.com/kubernetes/kubernetes/pull/116635), [@mengjiao-liu](https://github.com/mengjiao-liu))
- `volumezone` プラグインが [contextual logging](https://k8s.io/docs/concepts/cluster-administration/system-logs/#contextual-logging) を使うよう移行しました。([#116829](https://github.com/kubernetes/kubernetes/pull/116829), [@mengjiao-liu](https://github.com/mengjiao-liu))
- フィーチャゲート `CSIMigrationGCE` は GA に昇格し、v1.25 で無条件に有効化していた部分が削除されました。`gcepd` パッケージもすべて削除されました。([#117055](https://github.com/kubernetes/kubernetes/pull/117055), [@cyclinder](https://github.com/cyclinder))
- フィーチャーゲート `DisableAcceleratorUsageMetrics` および `PodSecurity` は GA に昇格し、v1.28 で無条件に有効化されていた部分が削除されました。([#114068](https://github.com/kubernetes/kubernetes/pull/114068), [@cyclinder](https://github.com/cyclinder))
- `TestPerPodSchedulingMetrics` に対してテーブルドリブンテストを使用するようになりました。([#118842](https://github.com/kubernetes/kubernetes/pull/118842), [@helayoty](https://github.com/helayoty))