CNPA — クラウドネイティブプラットフォームエンジニアリングアソシエイト
ロールバックしたのに、次のPodはなぜまた故障するのか
目標
同じイメージの実際のアプリで、設定変更・ロールアウト・ロールバック・Podの入れ替えを比較します。変更可能な設定を参照したロールバックで問題が再発することを観測し、 バージョンごとの不変設定を参照する復旧が、新しいPodでも維持されるかを確認します。
なぜ重要なのか
成功したrollbackコマンドと正常なサービス応答だけでは、外部設定まで復元されたと判断できません。 以前のPodが正常に応答している間に、新しいPodは誤った設定を受け取ることがあります。実際のk3s・kubelet・コンテナを使う個人VMであり、 KWOKや偽のReady状態ではありません。インストールに数分かかることがあります。55分のラボで、さらに必要なら期限が切れる前に時間を延長してください。 VMとファイルは、セッション終了時に回収されます。必要な記録は先にダウンロードしてください。本番クラスターのPodを入れ替える手順ではありません。
用意されている環境とツール
- 自分のアプリ: cnpa-rollback/checkout、最初のPod 2つと、変更可能なConfigMap settings。初期値は、CONFIG_REVISION=v1、HEALTHY=trueです。
- 保存の対象: cnpa-rollback-other/sentinel。ほかのチームのUIDと実際のHTTPを、最後まで維持します。
- アプリは、固定されたイメージダイジェスト、非root、capabilityの削除、サービスアカウントトークンの自動マウントのオフ、読み取り専用のルートファイルシステムを使用します。
- readiness /readyzは、エラー設定では503で、liveness /livezは正常です。エラー設定を、プロセスの停止と混同しません。
- ステートレスで短いGETアプリのSIGTERM終了猶予は、5秒です。データベースや長いリクエストに、この値を一般化しないでください。
- ヘルパー: python3 /opt/fixtures/cnpa_config_lab.pyのあとに、act・capture・observe・gradeとステップ番号を付けます。
actは、明示した変更だけを行います。captureは、最大75秒観測してからJSONを保存し、observeは1回だけ取得します。 gradeは、学習者のファイルやリソースを変更しません。完了した過去の観測は、後のステップの現在の状態で上書きしません。 record JSONは、自分で整えて作る答えではなく、観測に成功したあとで保存される資料です。入力のJSONだけを、指定された値で作成してください。 ステップ3・6・7のrelease JSONは、Deployment全体ではなくstrategic merge patchであり、name=appコンテナの残りのセキュリティ設定を維持します。
ステップ
- capture 1で/root/cnpa-release/baseline.jsonを保存してください。cnpa-rollback/checkout Deploymentの実際のPod 2つが設定v1を読み込んでReadyになっているか、サービスの応答を返したPodがそのDeploymentの所有かを確認します。
- /root/cnpa-release/mutable-config.jsonに、v1のConfigMap settings(ネームスペースcnpa-rollback)を作成してください。dataはCONFIG_REVISION="v2"、HEALTHY="false"、immutable=falseです。act 2で適用し、capture 2でenv-unchanged.jsonを保存します。設定は変わりましたが、最初のPod 2つのUIDと、実際のv1の環境変数は維持されている必要があります。
- /root/cnpa-release/mutable-release.jsonに、spec.template.metadata.annotationsのlabhub.io/releaseだけをmutable-v2に設定するJSONパッチを作成してください。act 3とcapture 3でrollout-incomplete.jsonを保存します。新しいPod 1つはv2・readiness 503、既存の2つはv1・正常である必要があり、サービスは既存のPodで応答します。
- act 4で、インストール時に観測した以前のリビジョンにrollbackし、capture 4でapparent-rollback.jsonを保存してください。rollout statusが成功し、最初のPod 2つが再び正常になっていることと、settingsの内容が依然としてエラー値であることを、合わせて確認します。
- act 5で、自分のラボの正常なPodを1つ入れ替え、capture 5でreplacement-failed.jsonを保存してください。削除したUIDは消え、新しいUIDのPodがエラーのv2設定を受け取ることを確認します。既存のPod 1つは、依然として正常に応答する必要があります。
- /root/cnpa-release/versioned-configs.jsonに、v1のListとしてConfigMap 2つを作成してください。cnpa-rollbackネームスペースのsettings-v1はCONFIG_REVISION="v1"、HEALTHY="true"、settings-v2はCONFIG_REVISION="v2"、HEALTHY="false"で、両方ともimmutable=trueです。versioned-release.jsonには、テンプレートannotationのlabhub.io/release=versioned-v1と、name=appコンテナのenvFrom.configMapRef.name=settings-v1を指定するパッチを作成してください。act 6で適用と不変の変更の拒否を試し、capture 6でversioned-ready.jsonを保存します。
- /root/cnpa-release/bad-release.jsonに、テンプレートannotationのlabhub.io/release=versioned-v2と、name=appコンテナのenvFrom.configMapRef.name=settings-v2を指定するパッチを作成してください。act 7とcapture 7でversioned-incomplete.jsonを保存します。既存の不変v1の2つのPodは正常、新しいv2のPod 1つはreadinessが失敗している必要があります。
- act 8で、ステップ6の実際のリビジョンに復旧したあと、正常なPodを1つ入れ替えてください。capture 8でreplacement-ready.jsonを保存します。入れ替えられた新しいUIDも、不変v1設定で正常であり、settings-v1のUIDと、ほかのチームのcnpa-rollback-other/sentinelのUID・HTTPが維持されているかを確認します。
参考
Deploymentのリビジョンは、Podテンプレートの履歴であって、外部設定の内容のコピーではありません。番号を推測せず、観測したリビジョンを使います。 サービスの応答と個々のPodの応答、現在の観測世代、Pod→ReplicaSet→DeploymentのUIDを結び付けます。終了処理中のPodが、一時的に追加で見えることがあります。 観測の制限時間に達したら、同じ実行の条件とログを調べてください。タイムアウトだけで失敗と断定したり、インストールをやり直したりしないでください。 不変のConfigMapも削除・再作成ができるため、以前のUIDと内容が保存されているかを確認します。ConfigMapに機密値を入れません。 観測の記録は学習の証拠であって、root権限のユーザーを止めるリモートアテステーションや、不正行為の防止装置ではありません。 前のステップの準備は、存在しない以前の入力・観測だけを補い、現在の答えは作りません。すでに進めたステップや、学習者の未完成のファイルを上書きしません。 現在のステップの採点は、実際の状態も見ますが、先へ進んだ過去のステップは、保存された記録を見ます。最終ステップのあとも、復旧状態とほかのチームの正常さを引き続き確認します。 学習者のファイルを失った場合は、消えた過去の状態を成功の記録として作り直さないでください。該当の実行の過去の証拠がないことを、残す必要があります。 公式ドキュメント: ConfigMap・ Deploymentのロールバック。
ベースラインの宣言と応答を結び付ける
capture 1で/root/cnpa-release/baseline.jsonを保存してください。cnpa-rollback/checkout Deploymentの実際のPod 2つが設定v1を読み込んでReadyになっているか、サービスの応答を返したPodがそのDeploymentの所有かを確認します。
サービスの応答1つで終わらせず、Pod→ReplicaSet→Deploymentの所有関係と、個々のreadiness応答を結び付けてください。
設定変更と既存の環境変数を区別する
/root/cnpa-release/mutable-config.jsonに、v1のConfigMap settings(ネームスペースcnpa-rollback)を作成してください。dataはCONFIG_REVISION="v2"、HEALTHY="false"、immutable=falseです。act 2で適用し、capture 2でenv-unchanged.jsonを保存します。設定は変わりましたが、最初のPod 2つのUIDと、実際のv1の環境変数は維持されている必要があります。
環境変数は、コンテナが起動するときに受け取ります。設定オブジェクトの現在の内容と、既存のプロセスが読み込んだ値を、別々に見てください。
サービスが正常であることと、新しいロールアウトの失敗を区別する
/root/cnpa-release/mutable-release.jsonに、spec.template.metadata.annotationsのlabhub.io/releaseだけをmutable-v2に設定するJSONパッチを作成してください。act 3とcapture 3でrollout-incomplete.jsonを保存します。新しいPod 1つはv2・readiness 503、既存の2つはv1・正常である必要があり、サービスは既存のPodで応答します。
テンプレートのannotationの変更は、新しいロールアウトを作ります。maxUnavailable=0なら、Readyにならない新しいPodのせいで、既存の正常な容量が先に減ることはありません。
成功したように見える最初のロールバック
act 4で、インストール時に観測した以前のリビジョンにrollbackし、capture 4でapparent-rollback.jsonを保存してください。rollout statusが成功し、最初のPod 2つが再び正常になっていることと、settingsの内容が依然としてエラー値であることを、合わせて確認します。
戻すのはPodテンプレートです。リビジョン番号は固定せず、最初に観測した値を使います。
代替のPodで再発を確認する
act 5で、自分のラボの正常なPodを1つ入れ替え、capture 5でreplacement-failed.jsonを保存してください。削除したUIDは消え、新しいUIDのPodがエラーのv2設定を受け取ることを確認します。既存のPod 1つは、依然として正常に応答する必要があります。
最初のPodのUIDと、新しく生まれたPodのUIDを照合してください。正常なPodが1つ残っているからといって、全体の復旧が維持されているわけではありません。
不変設定をデプロイ単位にまとめる
/root/cnpa-release/versioned-configs.jsonに、v1のListとしてConfigMap 2つを作成してください。cnpa-rollbackネームスペースのsettings-v1はCONFIG_REVISION="v1"、HEALTHY="true"、settings-v2はCONFIG_REVISION="v2"、HEALTHY="false"で、両方ともimmutable=trueです。versioned-release.jsonには、テンプレートannotationのlabhub.io/release=versioned-v1と、name=appコンテナのenvFrom.configMapRef.name=settings-v1を指定するパッチを作成してください。act 6で適用と不変の変更の拒否を試し、capture 6でversioned-ready.jsonを保存します。
ConfigMapには、apiVersion・kind・metadata・data・immutableが必要です。デプロイ用のパッチは、Deployment全体のドキュメントではなく、strategic merge patchです。
誤ったバージョンの参照をデプロイする
/root/cnpa-release/bad-release.jsonに、テンプレートannotationのlabhub.io/release=versioned-v2と、name=appコンテナのenvFrom.configMapRef.name=settings-v2を指定するパッチを作成してください。act 7とcapture 7でversioned-incomplete.jsonを保存します。既存の不変v1の2つのPodは正常、新しいv2のPod 1つはreadinessが失敗している必要があります。
不変設定は、内容を直さずに、新しい名前を参照します。このステップは、誤ったバージョンをあえて選ぶ実験です。
次のPodまで維持される復旧
act 8で、ステップ6の実際のリビジョンに復旧したあと、正常なPodを1つ入れ替えてください。capture 8でreplacement-ready.jsonを保存します。入れ替えられた新しいUIDも、不変v1設定で正常であり、settings-v1のUIDと、ほかのチームのcnpa-rollback-other/sentinelのUID・HTTPが維持されているかを確認します。
復旧のあとも、同じ名前の新しい設定オブジェクトに差し替えないでください。保存したUIDと、代替Podの実際の応答を、一緒に見ます。