Dev Study
AWSサービスの内部原理 コース

125. デプロイとは『宣言・差分・段階的切り替え』である — 1つの変更がリリースされるまでの地図

1行のコード変更が、コミットからユーザーに届くまでにどんな部品を通り抜けるのか——この編で見てきた全部品を1枚の地図に並べ、上から下へ追っていきます。VPC編の総括が「1つのリクエストがどこを通るか」という空間の地図だったのに対し、こちらは「1つの変更がどう届くか」という時間の地図です。

① 上流:コミットがパイプラインを起動する

git pushソース変更で新バージョン誕生
実行が下流ステージへ
SourceステージCodePipeline
1回の実行=1つの変更の集合。実行ごとに一意のID
成果物(artifact)を出力
BuildステージCodeBuild
buildspecの4フェーズ: install→pre_build→build→post_build
アーティファクトストアS3
次のステージが同じ場所から拾う
  • 「実行」の定義は "a set of changes released by a pipeline. Each pipeline execution is unique and has its own ID"——マージされたコミットなど「変更の集合」に対応する(公式表現)
  • ソースがGitHub/CodeCommitなら「変更のバージョン」=コミット(source revision)。S3ソースならオブジェクトのバージョン
  • 1つのステージは同時に1つの実行しか処理しない。"a pipeline stage processes only one execution at a time"——処理中のステージはロックされる
  • アクション同士の受け渡しは「パイプラインのアーティファクトバケット」経由。"CodePipeline copies artifacts to the artifact store, where the action picks them up"
  • buildspecで使えるビルドフェーズは install / pre_build / build / post_build の4つ。各フェーズのcommandsは「1つずつ、書かれた順に」実行される

コミットは「変更の集合に一意のIDを付けた実行」となってパイプラインを流れ、各ステージはS3のアーティファクトストアを介して成果物をバケツリレーする。ここまでは箱から箱へモノが流れるだけの世界。

② 宣言の層:テンプレートと現実の差分を計算する

DeployステージCloudFormation / SAM
依存グラフの順に適用
変更セット新テンプレ vs 現スタック
「何が変わるか」の要約。変更したリソースだけを更新
置換が必要な変更なら
リソースA
依存が無ければ並列
リソースB
リソースC
失敗したら
置換新リソースを作ってから旧リソースを消す
ロールバック最後の正常状態へ巻き戻る
  • 「宣言」の意味: CloudFormationが呼ぶAPIは「すべてテンプレートによって宣言されている」("The calls that CloudFormation makes are all declared by your template")。人間はあるべき状態を書き、エンジンが現実を合わせる
  • 変更セット: "CloudFormation compares the modified template with the original template and generates a change set"。更新時は "updating only the resources that you modified"
  • 並列と依存順: "CloudFormation creates, updates, and deletes resources in parallel to the extent possible"。!Ref/!GetAttなどの参照は暗黙の依存になり、参照される側が先に作られる(削除は逆順)
  • 置換の例: RDSデータベースの名前を変えると新DBを作って旧DBを削除——旧DBのデータは(バックアップがない限り)失われる。変更セットを生成すれば「この変更は置換になる」と実行前に分かるので、データが消える前に計画できる
  • 失敗時: "rolls back changes to restore the stack to the last known working state"(トランザクションのロールバックと同じ)
  • SAMの短縮記法: AutoPublishAliasは新コードの検知・新バージョンの発行・エイリアスの作成/更新を自動化。さらにDeploymentPreferenceで段階的デプロイを有効にすると「CodeDeployリソースが自動で作られる」——短い宣言が展開されて実体の束になる

ここが宣言の層。gitや仮想DOMと同じく「比較して最小の変更だけを適用する」。適用は依存グラフの順(依存が無ければ並列)、置換は「新を作ってから旧を消す」、失敗すれば直前の正常状態へ巻き戻る——差分とトランザクションの世界。

③ 切り替えの層:同じ振り付けを3つの舞台で踊る

新旧を同時に生かす実体を2世代並走
参照を段階的に動かす確率と観測で少しずつ
異常なら参照を戻すアラーム/検証が合図
どの舞台でも
Lambda/SAM重み付きエイリアス+CodeDeploy(Canary/Linear)
ECSBlue/Green+Lambdaフック
EC2/BeanstalkRolling/Immutable/Traffic splitting
実体は不変・参照だけ動くエイリアス・リスナ・LBターゲット
  • Lambda/SAM: 参照=エイリアス。Canaryは2段階(例 Canary10Percent10Minutes=まず10%を即時シフト、10分後に残り全部)、Linearは等間隔で均等増、AllAtOnceは一気に。pre/postトラフィックテストが失敗するかCloudWatchアラームが発火すると、CodeDeployがデプロイをロールバック
  • ECS(CodeDeploy Blue/Green): 参照=ロードバランサのリスナと2つのターゲットグループ。置換タスクセット(green)を作り、まずテストリスナで検証トラフィックを流し、BeforeInstall/AfterAllowTestTraffic/BeforeAllowTraffic/AfterAllowTraffic等のフック(Lambda関数)で検証。ロールバックは「トラフィックを置換タスクセットから元のタスクセットへ戻す」だけ
  • EC2/Beanstalk: Immutableは新インスタンス群を「別のAuto Scalingグループ」("separate Auto Scaling group")に立ててから入れ替え、新インスタンスがヘルスチェックに通らなければ新を終了して旧を無傷のまま残す
  • Traffic splittingは新群に "a specified percentage of incoming client traffic" を一定の評価時間だけ流してカナリア観測。健全なら全トラフィックを新へ移して旧を終了、ダメならトラフィックを旧へ戻して新を終了——"There's never any service interruption"

舞台装置は違っても振り付けは1つ——新旧を同時に生かし、参照を確率と観測で少しずつ動かし、異常なら参照を戻す。Canaryは「一部にだけ流して様子を見る確率実験」そのもの。

④ 本編の3原則で締める

宣言あるべき状態をファイルに書く
テンプレート/appspec/buildspec
差分比較して最小の変更だけ適用
変更セット=git=仮想DOM
段階的切り替え不変の実体+可変の参照
確率と観測で参照を動かす
デプロイ1つの変更を事故らせずユーザーへ運ぶ骨格
  • 宣言: CloudFormationは「テンプレートが宣言したAPI呼び出し」だけを行う。テンプレート外での手変更で生まれる「実際の構成と期待される構成のずれ」はドリフト検出が見つける("detect whether a stack's actual configuration differs, or has drifted, from its expected configuration")
  • スタックポリシーは「スタック更新中に重要リソースが意図せず更新・削除されるのを防ぐJSON文書」——ただしスタック更新時だけに効くフェイルセーフで、IAMのようなアクセス制御ではない
  • 差分: 変更セットは「新旧テンプレートを比較して生成」される。gitのdiff、Reactの仮想DOM差分と同型
  • 段階的切り替え: BeanstalkのImmutableは「新群を別ASGに立ててから」、SAMのCanaryは「重みを段階的に」——どれも実体は作り直し、参照だけを動かす

宣言・差分・段階的切り替え。この3つが1つのコード変更を、事故らずにユーザーへ運ぶ最小の骨格。

⑤ 種明かし:マネージドサービスの中身は全部CS基礎だった

マネージドサービス群デプロイを支える部品たち
既習の主役たちが1つの物語に合流
トポロジカルソート依存グラフの適用順(DAG)
diff変更セット/git/仮想DOM
トランザクション失敗時の巻き戻し
ポインタ付け替えエイリアス重み/LBターゲット
確率実験Canary(一部にだけ流す)
Step Functions編宣言と実体の分離
キャッシュ/コンテナ/Lambda編イミュータブル+参照の付け替え
可観測性編アラームによる観測フィードバック
  • 対応表(1/3): CloudFormation依存グラフの適用順(暗黙依存+DependsOn)=DAGのトポロジカルソート(依存が無ければ並列)/変更セット・git・仮想DOM=diff(比較して最小変更)/失敗時ロールバック=トランザクションの巻き戻し/ドリフト検出・スタックポリシー=宣言と現実の差分監視・更新時のフェイルセーフ
  • 対応表(2/3): Lambdaエイリアスの重み=ポインタ/参照の付け替え/SAM Canary10Percent10Minutes=確率実験(2段階カナリア)/SAM Linear=等間隔の均等シフト/CodeDeploy PreTraffic・PostTrafficフック(Lambda)=デプロイ前後の検証ゲート/CodeDeploy(ECS)本番・テストリスナ+2ターゲットグループ=ポインタの付け替え(参照=リスナ)
  • 対応表(3/3): CloudWatchアラーム→自動ロールバック=観測フィードバックによる中断/Beanstalk Immutable(別ASGに新群)=イミュータブルな実体生成/Beanstalk TrafficSplitting=LBターゲットでのカナリア/CodePipeline実行ID・アーティファクトストア(S3)=一意な実行単位・成果物の受け渡し/CodeBuild buildspec(install/pre_build/build/post_build)=宣言されたビルド手順の逐次実行
  • Canary10Percent10MinutesはSAMドキュメントの例に登場する実在の値。BeanstalkのDeploymentPolicy設定値はAllAtOnce/Rolling/RollingWithAdditionalBatch/Immutable/TrafficSplitting(公式記載)
  • DVAドメイン3(デプロイ)の総復習——「どのサービスのどの設定名が、どの原理の実装か」を1枚で引ける対応表がこの編の到達点

デプロイのマネージドサービスは魔法ではない。DAG・diff・トランザクション・ポインタ・確率実験——コンピュータの基礎で組み上がっていた。空間の地図(VPC編)と時間の地図(この編)が揃い、コース横断テーマの「デプロイ版の最終回答」がここに出そろう。

公式ドキュメントで詳しく ↗