プロンプトとコンテキスト
対象のクラスタで Kubernetes Node Declared Features を導入します。kubelet は管理対象のノード機能を Node status にレポートし、スケジューラはそれに応じて Pod をフィルタリングし、アドミッションコントローラは Pod の更新を検証します。バージョン混在クラスタにおけるロールアウト、オブザーバビリティ、障害処理、ロールバックを設計してください。管理されたノード機能のみが使用され、アプリケーションチームが任意の機能名を書き込むことはできないものとします。
面接官が評価するポイント
- 機能宣言がユーザー制御のラベルではなく、ノード状態のファクトとして扱われているか。
- kubelet、kube-apiserver、kube-scheduler、アドミッション制御の間の依存関係の順序が明確になっているか。
- 旧ノード、古い(stale)ステータス、Pod の更新、feature-gate のロールバックが網羅されているか。
- 単なるプロセスの起動だけでなく、宣言の完全性とスケジューリングの拒否によって安全性が実証されているか。
明確化のための質問
- どの kubelet バージョンがその機能を生成し、古いノードは通常の Pod の処理を継続できますか?
- 目的は初期配置の保護のみですか、それとも Pod がバインドされた後の更新も保護対象ですか?
- カスタムスケジューラ、複数の API サーバ、またはマルチリージョンのコントロールプレーンは存在しますか?
- 誤ったレポートが発生した場合、既存の Pod の実行を継続しつつ、新しい Pod を停止すべきですか?
30秒の回答要約
これをコンポーネント間のファクトチェーンとして扱います。kubelet が status.declaredFeatures を公開し、スケジューラプラグインが PreFilter で Pod の要件を推論してノードをフィルタリングし、アドミッション検証がその後の更新を保護します。まずはロールバック可能なノードプールと少量のワークロードスライスで有効化し、API サーバ、スケジューラ、kubelet 間で feature-gate 設定の一致を確認した後に拡大します。レポートの完全性、スケジューリング拒否の理由、更新の拒否、バージョンの差異を監視します。不整合が発生した場合は、新機能を必要とするワークロードを停止し、他の Pod 向けの通常のスケジューリングパスは維持します。
ステップごとの解決策
- 信頼できる情報源(Source of Truth)の定義。 起動時に kubelet は管理対象機能を検出し、それらを
Node.status.declaredFeaturesに書き込みます。アプリケーションラベルはこれと同等ではありません。機能名は、管理された feature-gate または明示的なコンポーネント規約に由来する必要があります。 - 依存関係の明確化。 Kubernetes では、kube-apiserver、kube-scheduler、kubelet で NodeDeclaredFeatures ゲートが必要です。kubelet をアップグレードする前に、コントロールプレーンのバージョンと設定を確認してください。片側のみを有効化すると、誰も消費しないフィールドが作成されるか、ノードが生成できないレポートをスケジューラが期待することになります。
- スケジューリングパスの設計。 スケジューラプラグインは、PreFilter で PodSpec から必要な機能を推論し、Filter でノードの宣言と比較します。必要な宣言を持たないノードは、その Pod に対してスケジュール不可となります。このフィールドを使用するカスタムスケジューラは、同じデフォルトセマンティクスと障害セマンティクスを維持する必要があります。
- 更新パスの保護。
NodeDeclaredFeatureValidatorアドミッションコントローラは、バインドされたノードに対して Pod の更新をチェックし、後からの更新によって機能制約がバイパスされるのを防ぎます。サイレントに劣化させるのではなく、明確な拒否を返します。 - バージョン差異の処理。 古い kubelet はフィールドを省略するか、新しい機能を認識しない場合があります。宣言されていない機能は「未サポート」として扱い、依存する Pod を Pending 状態のままにし、通常の Pod は互換性のあるノードを使用するようにします。バージョンの差異を回避するために Node status を手作業で編集してはいけません。
- 段階的なロールアウト。 ロールバック可能なノードプールでゲートを有効化し、その機能を必要とするプローブワークロードを配置して、徐々に拡大します。レポート欠落率、スケジューリング拒否、Pod 更新拒否、またはスケジューラのレイテンシがベースラインを超えた場合は停止します。
- オブザーバビリティと監査。 ノード宣言のバージョン、機能セットのダイジェスト、スケジューラのフィルタ理由、アドミッション拒否の理由、ゲート設定のフィンガープリントを、プールおよび Kubernetes バージョンごとにスライスして収集します。高カーディナリティのログに完全な Node オブジェクトを書き込むことは避けてください。
- 計画的なロールバック。 その機能に依存する Pod の作成を停止し、通常のスケジューリングを復元し、保留中の依存作業が処理された後にコンポーネント順でゲートを閉じます。ビジネスがすでにその機能に依存している場合は、宣言を消去する前にワークロードを移行するか互換性のあるノードを保持してください。
模範回答
まず、信頼できる情報源と保護境界を特定します。kubelet は管理された status.declaredFeatures を公開し、スケジューラの NodeDeclaredFeatures プラグインが配置をフィルタリングし、NodeDeclaredFeatureValidator がバインド後の更新を保護します。Kubernetes では kube-apiserver、スケジューラ、kubelet でゲートが必要となるため、1つのロールバック可能なプールで有効化する前にバージョンと設定を整合させます。プローブ Pod で機能のレポートと配置を検証し、レポート欠落率、フィルタ拒否、更新拒否、スケジューリングレイテンシを拡大可否のゲートとします。機能を宣言していない古いノードは未サポートとなり、通常の Pod は以前のパスを維持します。ロールバックの際は、新しい依存ワークロードを停止し、既存のワークロードを移行し、ゲートを閉じて、Pending 数と通常のスケジューリングが回復することを確認します。
よくある間違い
declaredFeaturesを通常のラベルとして扱う → ユーザーが機能を偽造してスケジューリングの安全性を破る可能性がある → kubelet が管理するセットのみを受け入れる。- スケジューラでのみゲートを有効化する → ノードがフィールドを公開しない → API サーバ、スケジューラ、kubelet の設定を併せて確認する。
- 「未宣言」をサポート対象として扱う → バージョン混在ノードが互換性のない Pod を受け取る可能性がある → 未宣言は未サポートを意味する。
- 初期配置のみをテストする → Pod の更新によって制約がバイパスされる可能性がある → アドミッション検証も有効化して監視する。
- クラスタ全体で一括有効化する → 障害の原因をプール、バージョン、ワークロードに特定できなくなる → プローブ、段階的展開、停止条件を使用する。
- ゲートを即座に無効化する → 依存する Pod が回復不能になる可能性がある → まず作成を停止し、依存するワークロードを移行する。
フォローアップ質問と回答
ノードが機能をレポートしたものの、ステータスが古い(stale)状態です。スケジューラはどうすべきですか?
レポートの経過時間を運用シグナルとします。その機能を必要とする Pod は、古い宣言に依存するのではなく、待機するか最新のノードに移動する必要があります。鮮度の制限時間を過ぎた場合は、プールを隔離し、オペレータの確認を要求します。
公式プラグインを無視するカスタムスケジューラでは何が問題になり得ますか?
デフォルトのスケジューラが拒否する Pod を許可してしまう可能性があります。カスタムパスは同等の PreFilter、Filter、デフォルト値、バージョンセマンティクスを実装する必要があります。ワークロードがそれを選択できるようにする前に適合性テストを実行してください。
3つのコンポーネントがゲートを変更する際の設定の不整合ウィンドウをどのように回避しますか?
ロールアウトチェックに設定のフィンガープリントを組み込み、通常のワークロードの提供を維持しながら、コントロールプレーン、スケジューラ、ノードプールの順に制御された順序でロールアウトします。不一致があれば拡張を停止します。プロセスの起動だけでは成功とは見なしません。
ビジネスがその機能に依存しているものの、ロールバック時に古いノードがそれをサポートしていないことが判明しました。どう対応しますか?
その機能を宣言するノードのプールを維持し、依存ワークロードを移行または縮小した後にのみゲートを閉じます。移行が不可能な場合は、スケジューリング制約を突然削除するのではなく、ロールバックを一時停止して互換性のあるキャパシティを追加します。