プロンプトと対象範囲
外部スケジューリングコンポーネントが、プリエンプション後の反復フィルタリングを削減するためにPending状態のPodに対してノードを推奨します。KubernetesのnominatedNodeNameに基づいて連携プロトコルを設計し、それがnodeNameを代替できない理由、スケジューラによる上書きやリソース変更の処理方法、およびロールバック方法を説明してください。
Kubernetes v1.35ではnominatedNodeNameがベータ版となっています。これは、外部コンポーネントが保留中のPodに対してノードを推薦(ノミネート)するために使用できるstatusフィールドです。この推薦はベストエフォートであり、スケジューラによって上書きされる可能性があり、推薦されたノードがスケジューリングチェックで不合格になることもあります。この面接では、意図を示すヒントと最終的なバインディングを明確に区別できているかが試されます。
面接官が見ているポイント
status書き込み権限とオーナーシップ、推薦とフィルタリングのタイミング、プリエンプション対象(victim)のグレースフル終了、nodeNameとnominatedNodeNameのセマンティクス上の違い、冪等で有効期限付きの外部決定、メトリクス、そしてfeature-gateのロールアウトとロールバックを網羅してください。
30秒での回答
「私はnominatedNodeNameを約束ではなく、取り消し可能なヒントとして扱います。外部コンポーネントは明示的な許可がある場合にのみstatusを更新し、バージョンと理由を記録します。スケジューラは毎サイクルで推薦されたノードを検証し、失敗した場合はすべての候補ノードにフォールバックします。優先度の高いPodがそのノードを取得する可能性があり、スケジューラがフィールドを書き換えたりクリアしたりすることもあります。私は最終的なnodeNameとバインディングイベントを結果として扱い、ヒット率、フォールバック率、スケジューリングレイテンシ、対象の終了時間を測定し、それらのシグナルが悪化した場合はfeature-gateまたは外部ライターを無効化します。」
ステップ別の解決策
ステップ 1: フィールドのセマンティクスを分離する
nodeNameはPod specにおけるハードな割り当てです。スケジューラをバイパスするため、ノードが存在しない場合やリソース不足の場合、Podは直接失敗する可能性があります。nominatedNodeNameはstatusに存在し、保留中のPodに対する候補を表します。外部の推薦者とスケジューラのプリエンプションの両方が書き込む可能性があるため、これはソフトステート(soft state)です。
ステップ 2: 外部権限を定義する
外部コンポーネントには対象Podのstatusのみを更新できる最小限のRBACを付与し、推薦理由、アルゴリズムバージョン、タイムスタンプをアノテーションまたはイベントに記録します。spec.nodeNameへの書き込みや、statusの更新によってkubeletが即座にPodをバインドすると仮定してはなりません。
apiVersion: v1
kind: Pod
metadata:
name: batch-worker
status:
nominatedNodeName: worker-07ステップ 3: スケジューラのオーナーシップを尊重する
スケジューラは、プリエンプション後、またはWaitOnPermitやPreBindに入る際にこのフィールドを書き込む場合があります。外部コンポーネントは上書きを受け入れ、書き込み競合(write war)を回避しなければなりません。更新前には毎回resourceVersionを比較し、競合が発生した場合は再読み込みして再計算します。
ステップ 4: フィルタリングとフォールバックを設計する
スケジューラはまず、推薦されたノードがリソース、アフィニティ、taint、トポロジのフィルタを依然として通過するかどうかを確認します。通過しない場合は、通常の候補ノード評価フローが継続されます。外部コンポーネントは推薦前に高速な事前チェックを行うべきですが、その結果がスケジューラの最終決定になることは決してありません。
ステップ 5: プリエンプションウィンドウを処理する
プリエンプションは対象となるPodにグレースフル終了期間を与えるため、それらが終了するまでの間、推薦されたノードは実行不可能な状態のままになることがあります。スケジューラはフィールドをクリアするか、より優先度の高いPodにノードを譲る場合があります。ビジネストラフィックは、推薦statusを使用可能状態として扱うのではなく、バインディングイベントを待つ必要があります。
ステップ 6: 決定を冪等かつ有効期限付きにする
各推薦に追跡可能な決定IDと短いTTLを付加します。ノードリソースの変更、Pod specの更新、優先度の変更、またはキューの順序変更によって、古い推薦は陳腐化します。反復的な調整(reconciliation)では、決定がまだ有効である場合にのみ同じ値を書き込む必要があります。
ステップ 7: オブザーバビリティを定義する
推薦書き込みの成功、statusの競合、推薦ノードでのフィルタ失敗、フォールバックスケジューリングレイテンシ、Pendingからバインディングまでの時間、対象の終了時間、およびフィールドクリア数を測定します。これらをクラスタ、優先度、スケジューラ、外部アルゴリズムバージョンごとにドリルダウンし、パフォーマンスの低下箇所を特定します。
ステップ 8: ロールアウトとロールバック
まずは少数のネームスペースと低リスクのPriorityClassでこのパスを有効にし、スケジューリングレイテンシとプリエンプションの結果を比較します。フィルタリング時間、誤ったバインディング、またはstatusの頻繁な書き換え(churn)が増加した場合は、外部statusの書き込みを停止し、スケジューラのfeature-gateを無効化します。通常のスケジューリングは利用可能な状態を維持し、nodeNameを書き込むことで強制的にフォールバックさせないようにします。
トレードオフと境界
nominatedNodeNameかnodeNameか
nominatedNodeNameはフィルタリング、プリエンプション、バインディングをスケジューラの制御下に維持するため、外部からの推奨に適しています。nodeNameはスケジューラをバイパスし、呼び出し元がリソースと障害の責任を負う高度なユースケースのために予約されています。これは一般的な高速化メカニズムではありません。
ヒント優先か全ノードスキャンか
最初にヒントを試すことで、プリエンプション後の大規模クラスタにおける反復フィルタリングを削減できますが、ノードの状態が変化している可能性があります。完全なフォールバックスキャンは正当性の基準であり、パフォーマンス最適化のために省略することはできません。
可視化か制御か
Statusは最終的な制御権を与えることなくスケジューリングの意図を可視化します。アラート、コントローラ、およびビジネス自動化は、nominatedNodeName単体ではなく、バインディング、FailedScheduling、およびイベントを監視する必要があります。
障害訓練と発展
推薦されたノードのキャパシティが失われた場合
推薦後に優先度の高いPodを起動し、スケジューラがフィールドを上書きまたはクリアし、元のPodが永久にPendingのままにならずにフォールバックすることを確認します。
status更新の競合が発生した場合
同じPodのstatusを同時に更新し、外部コンポーネントが古いオブジェクトでスケジューラを上書きするのではなく、resourceVersionの競合後に再読み込みすることを確認します。
被プリエンプションPodの終了が遅い場合
プリエンプション対象に長いtermination grace periodを設定します。推薦されたノードが早期に使用可能として報告されないことを確認し、Pendingからバインディングまでのレイテンシのテールを監視します。
よくあるミスとフォローアップ
ミス 1: nominatedNodeNameをバインディング結果として扱う
フォローアップ:フィールドが存在すれば、Podがそこで実行されることは保証されますか?いいえ。スケジューラが再度フィルタリングを行うため、最終的なnodeNameとバインディングイベントがその結果となります。
ミス 2: 推薦をnodeNameで置き換える
フォローアップ:直接nodeNameを書き込まないのはなぜですか?リソース、taint、アフィニティ、およびプリエンプションの安全保護をバイパスしてしまい、不適切なノードで失敗する可能性があるためです。
ミス 3: statusを繰り返し上書きする
フォローアップ:スケジューラがフィールドを変更した場合はどうしますか?オーナーシップの競合を受け入れ、スケジューラと競合するのではなく、resourceVersion、決定TTL、および冪等な調整を使用します。
より深いフォローアップと模範解答
なぜ推薦されたノードが最終決定にならない場合があるのか?
対象Podの終了中に別のノードでキャパシティが解放されたり、優先度の高いPodが推薦ノードを取得したりする可能性があるためです。スケジューラは試行を継続し、推薦をクリアまたは上書きすることがあります。
最適化が機能していることをどのように証明するか?
ロールアウトの前後で、フィルタリング時間、Pendingからバインディングまでのレイテンシ、推薦ヒット率、フォールバック率、および対象の終了時間を比較します。書き込み回数だけでは、スケジューリングが高速化されたことの証明にはなりません。
外部コンポーネントの最小安全境界は何か?
認可されたPodのstatusのみを更新し、nodeNameや優先度およびリソースのspecは決して書き込まず、バインディングイベントを通じて結果を確認することです。すべての決定には有効期限があり、監査可能で、ロールバック可能である必要があります。