代表的な面接トピック

システムデザイン面接:プログレッシブデリバリーコントローラーをどのように設計するか?

システム設計難しい
Offer.cc 編集チーム公開日 更新日

質問

ある企業では1日に数百回のデプロイが行われています。新しいバージョンはまず1%のトラフィックを受け取り、その後5%、25%、50%、100%へと段階的に進める必要があります。コントローラーは、エラー、テールレイテンシ、または重要なビジネスメトリクスが悪化した際に、自動的に一時停止またはロールバックしなければなりません。また、手動承認、進行中のリリースを上書きする新しいリリース、リージョン間の差異、および監査可能性をサポートする必要があります。システムを設計し、整合性、メトリクスウィンドウ、ロールバック境界、および障害について説明してください。

プロンプトと適用範囲

これは単にDeploymentのレプリカ数を複数回変更する問題ではなく、リリースコントロールプレーンの問題です。コントローラーは、望ましいバージョン、現在のステップ、トラフィックウェイト、分析結果、および人間の判断を記録し、そのアクションをデータプレーンに確実に反映します。Google SREでは、カナリアを部分型かつ期間限定のデプロイおよび評価と定義しています。KubernetesのRollingUpdateは基本的な可用性を提供しますが、プログレッシブデリバリーはトラフィックベースの分析、一時停止、承認、および自動ロールバックを追加します。

面接官がテストしているポイント

  • コントロールプレーン、ワークロード、ルーティング、およびメトリクス分析の状態を分離すること。
  • プロモーションを復旧不可能なスクリプトではなく、耐久性のある冪等なステートマシンとしてモデル化すること。
  • 比較可能なカナリア/コントロールのウィンドウ、サンプルサイズ、ガードレール、およびメトリクスの遅延を定義すること。
  • 古いリリースを上書きする新しいリリース、コントローラーの再起動、利用不可なメトリクス、および部分的なリージョン成功を処理すること。
  • 誰が承認したか、なぜロールアウトが一時停止または中止されたか、どのバージョンが安定版になったかを保持すること。

最初に明確にすべき質問

  • トラフィックはリクエスト、ユーザー、リージョン、レプリカのどれで分割されますか?安定したバケッティング(割り振りの固定)は必要ですか?
  • どのメトリクスがハードゲートで、どれが観察用ですか?エラーバジェットと最小サンプルサイズはどのように定義されますか?
  • ロールバックはトラフィックを切り替えるだけですか、それともカナリアを停止してスケールダウンしますか?データベースとメッセージのフォーマットはどのように互換性を保ちますか?
  • ステップは自動ですか、それとも手動で承認されますか?承認はどのように認可されますか?
  • 各リージョンは一斉に進みますか、個別に進みますか、それとも1つのリージョンの障害でグローバルロールアウト全体を停止しますか?

30秒での回答

「私はリリースを、ステップ、目標ウェイト、一時停止ポリシー、分析テンプレート、タイムアウト、およびロールバックバージョンを持つ耐久性のあるステートマシンとしてモデル化します。冪等なリコンサイルループが、望ましい状態をワークロードとルーティングに適用し、実際の状態とバージョン範囲のメトリクスを読み取ります。プロモーションには十分なサンプル、完全なウィンドウ、エラー・テールレイテンシ・ビジネスガードレールの合格が必要であり、メトリクスソースが見つからない場合はデフォルトで一時停止します。すべてのアクションにリリースおよびステップのバージョンが含まれるため、再起動しても安全に収束します。承認、一時停止、ロールバック、およびルーティングの変更はすべて監査証跡になります。」

詳細解説

ステップ1:リソースと状態を定義する

リリースリソースには、release_id、候補バージョンと安定バージョン、ステップ、現在のステップ、目標ウェイト、分析テンプレート、一時停止理由、タイムアウト、およびロールバックポリシーが含まれます。状態には、PENDINGRUNNINGPAUSEDPROMOTINGABORTINGSUCCEEDED、およびFAILEDがあります。各遷移には明示的な前提条件と冪等な作用が必要です。

ステップ2:コントロールプレーンとデータプレーンを分離する

コントロールプレーンは望ましい状態と分析結果を保存し、データプレーンはPod、Service、Ingress、またはサービスメッシュを実行します。APIの書き込みが成功したことと、ロールアウトの成功は同義ではありません。利用可能なレプリカ数、実際のウェイト、Readiness、およびバージョンラベルを監視します。KubernetesのmaxUnavailablemaxSurgeは、リクエストレベルのカナリアトラフィックではなく、レプリカの置き換えを制約するものです。

ステップ3:安定したトラフィック割り当てを設計する

単一のユーザーがカナリアとコントロールの間を行き来しないよう、一貫したリクエストまたはユーザーキーを使用します。ルーティングレイヤーは実際のウェイトとバージョンごとのヒット数を報告します。マルチリージョンの場合はリージョンごとに目標ウェイトと実ウェイトを保存し、グローバル平均によって1つのリージョンの100%障害が隠蔽されないようにします。

ステップ4:分析ウィンドウとガードレールを定義する

分析テンプレートでは、クエリ、サンプリング期間、最小サンプル、許容度、連続失敗数、および最大待機時間を宣言します。メトリクスは可用性、テールレイテンシ、リソース飽和度、および重要なビジネス成果をカバーし、それぞれバージョン、リージョン、トラフィック分母でタグ付けされます。不完全なウィンドウやデータの欠落は一時停止を引き起こします。データ欠落は成功を意味しません。

ステップ5:復旧可能なリコンサイルを実装する

コントローラーはリリース、ワークロード、ルート、および分析結果を定期的に読み取り、次の1つのアクションを計算します。外部への書き込みにはrelease_idとステップバージョンが含まれるため、再試行によってルールや承認が重複することはありません。再起動後は、永続化された状態と観測された状態から収束します。実際のウェイトが乖離している場合は、プロモーションの前に一時停止して修復します。

ステップ6:一時停止、承認、タイムアウトを処理する

ステップは、自動的、一定期間、または承認のために無期限に一時停止することができます。承認にはID、スコープ、および現在のステップバージョンが含まれ、古い承認で新しいリリースをプロモートすることはできません。タイムアウト時は、トラフィックを拡大するのではなく、ポリシーに従って一時停止または中止します。強制プロモート(Force-promote)には認可と理由が必要です。

ステップ7:ロールバックと互換性の境界を設計する

ロールバックは通常、まずトラフィックを安定バージョンに戻し、その後にカナリアを停止するかスケールダウンするかを決定します。データベースのマイグレーション、イベントスキーマ、キャッシュフォーマットには両バージョンが共存できるオーバーラップウィンドウが必要です。バイナリをロールバックしても、不可逆的な書き込みを元に戻すことはできません。ロールバック自体も冪等かつ観測可能であり、以前の安定バージョンを保持する必要があります。

ステップ8:検証、監査、リハーサル

プロモーション、ルーティングウェイト、メトリクスグループ化、一時停止、コントローラー再起動、メトリクス停止、リージョン停止、重複Webhook、および進行中のリリースを上書きする新しいリリースをテストします。望ましい状態と実際の状態、実行者、時刻、理由、およびメトリクスのスナップショットを監査します。この演習では、APIが200を返したことだけでなく、異常なシグナルによって拡大が確実に停止することを証明しなければなりません。

トレードオフと境界

ネイティブのRollingUpdate対プログレッシブコントローラー

RollingUpdateは、段階的なレプリカの置き換えとReadinessチェックが必要なサービスに適しています。トラフィック、ビジネスメトリクス、承認、および自動ロールバックには、追加のコントローラーまたはプラットフォーム機能が必要です。レプリカの割合はリクエストの割合ではありません。

自動ロールバック対人間の判断

ハードゲートは、信頼性が高く迅速に検出できる障害に適しています。遅延を伴う、または曖昧なビジネスメトリクスの場合、自動化によって一時停止し、オーナーに通知する必要があります。ポリシーには最終的な停止権限者を明記しなければなりません。

グローバル対リージョンの進行

グローバルな進行はシンプルですが、リージョンのリスクを増幅させます。独立した進行はより安全ですが、より多くの状態とキャパシティを必要とします。トラフィックの分離、データレジデンシー、および障害ドメインの境界に基づいて選択します。

障害訓練と進化

障害:カナリアレプリカの比率をトラフィック比率として扱う

レプリカ数はリクエスト数ではありません。コネクションの再利用やリージョントラフィックによって実際のウェイトが偏る可能性があります。ルーティングレイヤーで割り当てを行い、ヒット数を記録してください。

障害:メトリクスが欠落しているときにプロモートする

クエリの遅延、ラベルエラー、またはサンプル不足により、空の結果が返されることがあります。データが欠落している場合は一時停止し、復旧後に完全なウィンドウを再構築してください。

障害:アプリケーションイメージのみをロールバックする

スキーマ、イベント、またはキャッシュへの不可逆な書き込みにより、古いバージョンが読み取り不能になる可能性があります。ロールアウト前に互換性ゲートを追加し、データ修復の前にトラフィックを切り替えてください。

よくある間違いとフォローアップ

間違い:ステートマシンをコントローラーのメモリ内のみで保持する

再起動するとステップ、承認、ロールバックバージョンが失われます。リリースリソースと監査イベントを永続化してください。メモリは単なるキャッシュです。

フォローアップ:古いコントローラーが新しいリリースを上書きするのを防ぐには?

リソースバージョンとステップバージョンを条件付き更新(Conditional Update)で使用します。書き込み前に再読み込みを行い、バージョンが変更されている場合は古いアクションを中止します。

フォローアップ:同時に2つのリリースが発生した場合はどう処理するか?

ServiceまたはRouteのミューテックスを使用するか、候補バージョン間でトラフィックバジェットを明示的に配分します。2つのコントローラーが同一のウェイトを個別に変更してはなりません。

フォローアップ:平均レイテンシが正常なのにp99が悪化するのはなぜか?

平均値は、ごく少数の深刻に遅延したリクエストを隠蔽します。同じバージョン、リージョン、分母でテールレイテンシとエラーを比較してください。

フォローアップ:メトリクスシステムがダウンしている場合はどうするか?

一時停止してANALYSIS_UNAVAILABLEとマークし、現在のウェイトを維持します。復旧後にウィンドウを再実行します。データの欠落は成功ではありません。

フォローアップ:コントローラー自体をどのように測定するか?

ステップの滞留時間、目標ウェイトと実ウェイトの誤差、誤ロールバック率、検出遅延、復旧時間、監査の完全性、および手動オーバーライドを追跡します。

公開情報ソース

関連する質問

関連面接ツール

システム設計の回答には「回答する」を使用

まず要件を明確にし、スケール、アーキテクチャ、コンポーネント選定、トレードオフの順に進めます。

ツールを見る