TT Lab
はじめる
学ぶ 学習パス コース

CNPA — クラウドネイティブプラットフォームエンジニアリングアソシエイト

復旧は次のPodが起動しても維持されなければならない

TT Labで続きを見る

一言でいうと

安全な復旧は、正常な応答を1回得ただけでは証明されません。現在の宣言を観測したコントローラーの状態、その宣言から生まれたPod、実際の応答、そして代替Podの設定が、そろって一致する必要があります。

なぜ必要なのか

新しいPodがreadinessチェックに失敗しても、サービスは正常なことがあります。以前のPodが引き続きリクエストを処理しているからです。これは必ずしも異常な状態ではなく、悪いデプロイが既存の容量を一度に奪わないように設計した結果かもしれません。

問題は、正常なHTTP応答を見て、新しいバージョンまで成功したと判断するときです。既存のPodが応答したのであれば、それは新しいバージョンの成功の証拠ではありません。逆に、新しいPodが1つ準備できていないからといって、すべてのユーザーが障害を経験していると断定してもいけません。デプロイの進行とユーザーへの影響は関連していますが、同じ値ではありません。

実際の調査では、既存の正常なPod 2つと、準備できていない新しいPod 1つが共存していました。サービスは、既存のPodで正常に応答しました。最初のロールバックは完了しましたが、既存のPodを入れ替えたあと、一部の容量が再び準備できませんでした。復旧の定義にPodの入れ替えを含めるべきだという根拠は、ここから出てきました。

どう動くのか

宣言が読み取られたかを最初に確認する

変更を保存したAPIの応答は、コントローラーがすでに処理したという意味ではありません。Deploymentのmetadata.generationとstatus.observedGenerationを一緒に読んで、現在の宣言が観測されたかを確認します。続いて、新しいテンプレートのレプリカ数、Readyの数、利用可能な数を区別します。以前の状態のAvailable条件だけが残っていることもあります。

今回の例では、レプリカ2つ、maxSurge: 1、maxUnavailable: 0を使います。新しいPodがReadyにならなければ、既存の正常な容量を先に減らさないようにする設定です。終了処理中のPodが一時的に追加で見えることがあるため、単純な一覧の長さと、デプロイの容量計算を混同しないでください。

観測コマンドが所定の時間内に終わらなかったという事実も、正確に表現する必要があります。それは、その観測ウィンドウでは完了を確認できなかったという意味です。デプロイコントローラーが報告する進行期限超過や、実際のアプリのreadiness失敗とは、別の証拠です。タイムアウトだけを見て同じインストールを再開すると、原因を消してしまったり、実行が重なったりすることがあります。

応答したPodが誰かを結び付ける

例のアプリは、応答にPod名、読み込んだ設定バージョン、正常かどうかを含めます。この値だけを信じるのでは不十分です。取得したPodが該当のReplicaSetに属し、そのReplicaSetが今回のDeploymentに属するかも、UIDで照合します。名前は再利用されることがあるからです。

個々のPodの/readyzの応答と、KubernetesのReady条件を一緒に見ます。プロセスが生きているというlivenessと、トラフィックを受けてよいというreadinessは、違います。例では、誤った設定でもプロセスは生きていますが、readinessの応答は503です。サービスの成功応答が、どの正常なPodから来たのかも結び付けます。

実務のアプリが、こうした情報を外部のユーザーに常に公開すべきだという意味ではありません。この小さな教育用の応答は、観測対象の関係を見せるための仕掛けです。本番環境では、内部の診断経路、ログ、デプロイのメタデータなど、アクセスを制御した観測手段を選びます。

次のPodで復旧を試す

以前のバージョンに戻ったあと、正常なPodを1つ入れ替えます。既存のUIDが消え、新しいUIDができたことを確認したうえで、その新しいPodが以前の設定を実際に読み込んでReadyになったかを見ます。以前の正常なPodの応答を、新しいPodの成功として再利用しません。

この入れ替えは、自分の個人VMの中の、指定されたワークロードでのみ行います。実際の本番環境で、復旧を確認するためだと言って、任意のPodを削除する手順ではありません。本番環境では、容量、中断バジェット、トラフィック、承認されたテスト範囲を、まず考慮する必要があります。調査時の削除リクエストにも、UIDとresourceVersionの条件を付け、別のオブジェクトや同時変更を無視しないようにしました。

現場での姿

プラットフォームチームは、デプロイツールを提供すると同時に、失敗を理解できる手がかりを提供する必要があります。「デプロイ失敗」の1行よりも、「現在、新しいレプリカ1つが設定v2で実行されていますが、readinessの応答は503で、既存のv1の2つがサービス中です」という説明のほうが、開発者が次の行動を決めるうえではるかに役立ちます。

復旧の記録には、何を変えたかだけでなく、何を保存したかも残します。この実験では、ほかのチームのDeployment UIDと正常な応答を、最後にもう一度確認しました。これがすべてのテナントの分離を証明するわけではありませんが、自分のアプリを生かすためにほかのアプリを消すという、誤った成功は排除できます。

記録を保存するときは、現在の実行と対象のUIDを結び付け、以降のステップが過去の観測を上書きしないようにします。取得の失敗を、空のリストや正常な状態として記録しません。最後まで終えたあとで同じステップをもう一度採点しても、以前の証拠の意味が維持されてこそ、学習者が何を学んだのかを振り返れます。

次のラボですること

変更可能な設定でデプロイとロールバックを行い、Podの入れ替え後に再発することを観測します。続いて、バージョンごとの不変設定の参照で復旧し、代替のPodまで正常になった結果を比較します。コマンドの終了コード、コントローラーの状態、実際の応答、設定のソースを、それぞれ別の証拠として読むことが目標です。

公式ドキュメント