質問とシナリオ
共有Kubernetes Gatewayを設計してください。プラットフォームチームがGatewayとロードバランシングインフラストラクチャを所有し、アプリケーションチームが各名前空間でホスト名、ポート、HTTPRoute、証明書を所有します。20チームがそれぞれ50リスナー(合計約1,000ドメイン)を持ち、単一Gatewayのベースラインリスナー上限が64であると想定します。
1つの巨大なGatewayからリスナーをListenerSetへと分割し、名前空間を跨ぐアタッチを認可し、競合時にもトラフィックの安定性を保ち、チームがAccepted、Programmed、Conflictedの設定状態を識別できるようにステータスを公開する方法を説明してください。
面接官がテストしているポイント
リソース境界と委任
優れた回答では、共有インフラストラクチャ、テナント設定、ルートのアタッチを明確に分離し、アプリケーションチームがプラットフォームのGatewayを直接編集すべきではない理由を説明します。
競合とセキュアなデフォルト設定
ListenerSetのデフォルト拒否、許可された名前空間ソース、決定論的なホスト名の優先順位、証明書参照の境界を明記します。
コントローラーの一貫性
Watch、マージ、バリデーション、ステータス条件(Conditions)、リトライについて網羅します。YAMLオブジェクトが存在するだけでは、データプレーンへのプログラミングが完了したことにはなりません。
スケールと移行
単一Gateway、テナントごとの個別Gateway、Ingressアノテーションを比較します。委任と相互運用性のためにListenerSetの複雑さを導入する価値があるケースを説明します。
回答前の明確化のための質問
- 1,000ドメインすべてが1つのロードバランサーアドレスを共有しますか、それともチームごとに独立したエントリポイントが必要ですか?
- アプリケーションチームが各自のTLS Secretを管理できますか、それともプラットフォームが証明書を承認しますか?
- 名前空間を跨ぐアタッチは、すべての名前空間、ラベルセレクター、それとも同一名前空間のみに限定して許可すべきですか?
- 競合が発生した場合、古い設定でトラフィックの配信を継続すべきですか、それとも新しい設定で上書きしてもよいですか?
- コントローラーはどの程度の速度で変更を反映する必要がありますか?また、クラスタ間レプリケーションは必要ですか?
- HTTPRoute、TLSRoute、その他のルート種別は同じ認可境界を共有しますか?
30秒回答フレームワーク
「プラットフォームチームがGatewayを作成してListenerSetをデフォルト拒否とし、allowedListenersを使用して許可された名前空間を選択するようにします。各アプリケーションチームは自身の名前空間でListenerSetとルートを提出します。コントローラーはParentRef、ホスト名、ポート、プロトコル、証明書参照、AllowedRoutesを検証し、親Gateway、最も古い作成時刻、名前空間/名前の辞書順の優先度でリスナーをマージします。競合が発生した場合はAccepted=FalseおよびConflicted=Trueとマークされ、アクティブなリスナーを置き換えることはできません。データプレーンは検証済みのアグリゲートからのみプログラムされ、ステータス条件とメトリクスによって拒否、競合、未プログラム、プログラム済みの状態を区別します。」
ステップごとの詳細な回答
ステップ1:規模の見積もりとリソースの選定
20チーム × 50リスナーで約1,000のエントリポイントとなります。1つのGatewayに1,000件すべての宣言を記述すると、単一オブジェクトへの書き込み競合、権限の肥大化、コントローラーによる頻繁な再計算が発生します。ListenerSetを使用することで、チーム所有の設定を独立したリソースに分割し、Gatewayにはプラットフォームのアドレス、クラス、アタッチポリシーのみを保持させます。
ステップ2:認可ハンドシェイクの確立
allowedListenersがセキュリティゲートとして機能します。NoneはデフォルトでListenerSetを受け入れません。プラットフォームはSame、ラベルSelector、またはAllを選択できます。ListenerSetはparentRefを使用してGatewayを指定します。コントローラーは、双方が関係を認可し、参照が有効で、名前空間の選択が許可されている場合にのみこれを含めます。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: shared-gateway
spec:
allowedListeners:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: shared
---
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: team-a-listeners
namespace: team-a
spec:
parentRef:
name: shared-gateway
namespace: platform
listeners:
- name: app-a
hostname: app-a.example.com
protocol: HTTPS
port: 443ステップ3:マージおよび競合ルールの定義
Gatewayのリスナーと認可されたListenerSetのリスナーを結合し、ポート、プロトコル、該当するホスト名からアイデンティティを決定します。競合は決定論的に解決します。親Gatewayが優先され、次に作成日時が古いListenerSetが優先され、それでも同等の場合は名前空間/名前の順序を使用します。アクティブなトラフィックを通知なく置き換えるのではなく、競合に敗れたリソースにConflictedのマークを付けます。
ステップ4:ルートと証明書の分離
ListenerSetのallowedRoutesにより、ルートのバインドを許可する名前空間を制限します。ルートはparentRefsを使用してListenerSetのセクションをターゲットにします。プラットフォームのポリシーでTLS Secretの参照を制限し、証明書の承認とアプリケーションのリリース権限を分離します。チームは自身のListenerSetとSecretを編集できますが、ParentRefを使用して他テナントのリソースを読み取ることはできません。
ステップ5:コントローラーの収束性の確保
Gateway、ListenerSet、Route、名前空間ラベル、Secretを監視(Watch)し、Gatewayごとにグループ化された望ましい状態(desired model)を構築します。イベントを重複排除およびデバウンスし、アグリゲートを検証した上でロードバランサーをプログラムします。Accepted、Programmed、ResolvedRefs、Conflictedの各条件を返します。リトライは冪等であり、新しい設定が正常にプログラムされるまでは最後の望ましい状態が維持されます。
ステップ6:代替案と障害経路の比較
テナントごとに1つのGatewayを割り当てると権限境界は単純化されますが、アドレス、ロードバランサー、証明書のコストが増加します。アノテーション付きの単一Gatewayは低コストですが、共通スキーマ、競合セマンティクス、実装間の相互運用性に欠けます。ListenerSetのコントロールプレーンが利用できなくなった場合は、最後にProgrammedされたスナップショットを維持し、未知の新しいリスナーを拒否します。親Gatewayが消失したりParentRefが無効になった場合は、子リソースを未承認としてマークし、復旧後に調整(Reconcile)します。
高品質な回答例
「私はGatewayをプラットフォームが所有する共有境界として扱い、ListenerSetをテナントが所有する宣言として扱います。プラットフォームはGatewayClass、アドレス、allowedListenersを設定し、デフォルトを拒否とします。gateway-access=sharedというラベルが付いた名前空間のみがアタッチ可能です。各チームは自身のListenerSet、HTTPRoute、証明書参照を提出します。
各イベントにおいて、コントローラーはマージ前にParentRef、名前空間の認可、ポート/プロトコル/ホスト名、AllowedRoutes、Secret参照を検証します。競合時は親Gatewayが最優先され、続いてListenerSetの作成時刻、名前空間/名前順の優先度となります。敗者側にはAccepted=FalseおよびConflicted=Trueが付与され、稼働中のトラフィックを奪うことはできません。検証済みのアグリゲートのみがロードバランサーをプログラムし、Programmedはデータプレーンへの適用が完了したことを示します。
20チーム × 50リスナー(約1,000エントリ)の場合、リソースを分割することで単一オブジェクトへの書き込み競合や権限の集中を回避できます。コントローラーのダウンタイム中も、データプレーンは最後の安定したスナップショットで稼働し続け、競合する追加を拒否します。テナントが分離されたアドレス、コンプライアンス境界、障害ドメインを必要とする場合は、インフラコストを許容した上で個別のGatewayを採用します。」
よくある間違い
- 全チームにGatewayの編集を許可する → 設定が上書きし合い、権限が過大になる → プラットフォームがGatewayを所有し、テナントがListenerSetを所有する形にする。
- デフォルトですべての名前空間を許可する → どのテナントでも共有Ingressを要求できてしまう → デフォルトをNoneにし、SameまたはSelectorで絞り込む。
- ラストライターウィン(後勝ち)にする → 新しいリスナーがホスト名を乗っ取るリスクがある → 決定論的な優先順位を使用し、敗者に競合マークを付ける。
- ホスト名のみを比較する → プロトコルが異なる場合でも衝突する可能性がある → ポート、プロトコル、該当ホスト名を組み合わせて比較する。
- Secret名をデータプレーンに直接渡す → 名前空間を跨いだ権限昇格や証明書の漏洩につながる → 参照と認可を事前に検証する。
- すべてのイベントに対して即座に再プログラムを実行する → 一時的な無効状態でチャーン(不要な再処理)が発生する → デバウンスを行い、冪等にマージし、成功後に切り替え、スナップショットを保持する。
- ステータスにReadyのみを公開する → テナントが拒否、競合、プログラミング遅延の区別がつかない → Accepted、Programmed、ResolvedRefs、Conflicted条件を使用する。
- ListenerSetを無制限にスケールするものとして扱う → コントローラーやロードバランサーには依然として制限がある → Gatewayごとにシャーディングし、テナントクォータを設定し、収束性を監視する。
フォローアップの質問と回答
フォローアップ1:2つのチームが同じホスト名とポートを提出した場合、どちらが優先されますか?
親Gatewayが優先されます。ListenerSet間では作成日時が古い方が優先され、同等の場合は名前空間/名前の順序で決定されます。敗者側はConflicted状態で可視化され続け、リトライのタイミングによって結果が変わることはありません。
フォローアップ2:プラットフォームが特定のテナントを一時的に凍結するにはどうすればよいですか?
該当テナントの名前空間ラベルを削除するか、allowedListenersのセレクターを絞り込みます。コントローラーは最新のスナップショットを保持したまま、ListenerSetを未承認としてマークします。監査のために凍結を記録し、古いオブジェクトを盲目的に信用せず、復旧時に再検証を行います。
フォローアップ3:ListenerSetに64個のリスナーがあります。さらに拡張できますか?
実装ごとの制限は依然として適用され、総容量は無限ではありません。クォータを用いてテナントを複数のListenerSetやGatewayに分割してください。共有よりもアドレスや証明書の分離が重要である場合は、複数のGatewayを使用します。
フォローアップ4:サービス停止を発生させずにTLS Secretをローテーションするにはどうすればよいですか?
Secretのバージョンを監視し、そのチェーン、ホスト名、有効期限を検証し、データプレーンが新しい証明書を確認した後にのみProgrammedを更新します。猶予期間中は古い証明書を保持し、失敗した場合は最後に確認された正常なバージョンでの配信を継続してアラートを発報します。
フォローアップ5:コントローラーの再起動中に、新しいRouteが稼働中のトラフィックを置き換えることはありますか?
いいえ。データプレーンが最後に成功したスナップショットでトラフィックを処理している間に、望ましい状態を永続化または再構築します。再起動後、参照と競合を再計算した上で、観測可能な設定バージョンへと一度に切り替えます。
出典 1: Gateway API ListenerSet ユーザーガイド
このガイドでは、ListenerSetの委任されたマルチテナント利用、64リスナー制限、allowedListeners、parentRef、競合の優先順位が定義されています。これらの事実はリソースモデル、認可ハンドシェイク、競合処理、ステータス設計の根拠となります。
出典 2: GEP-1713
GEP-1713は、リソース競合、名前空間を跨ぐ管理、大規模ドメインのユースケースについて説明し、親Gateway、作成日時、辞書順のマージルールを規定しています。キャパシティの見積もりと代替案はこの制約に基づいています。
出典 3: Kubernetes Gateway API v1.5 リリースノート
リリースノートには、ListenerSetのStandardへの移行と、マルチテナンシー、委任リスナー、64リスナー以上のサポートへの注力が記載されています。この回答は、その公開された変更を移行およびガバナンスの意思決定へと落とし込んでいます。
出典 4: 一般的なシステムデザイン面接ガイド
この公開ガイドでは、要件の明確化、スケールと障害の議論、トレードオフの説明の重要性が強調されています。明確化の質問、見積もり、競合に関するフォローアップ、代替案は、これらの面接評価シグナルに対応しています。