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

121. Lambdaのカナリアは重み付きエイリアスでできている — 確率でトラフィックを割り、アラームで引き返す

Lambda編で「バージョン=イミュータブルなスナップショット、エイリアス=可変なポインタ」と学びました。この回はその答え合わせ——1つのポインタの重みだけを動かして新旧を同時に生かす「カナリア」の仕組みを、下から上への確率の流れとして図で追っていきます。

① 1つのエイリアスは最大2バージョンを「重み」で指す

エイリアス live可変なポインタ(1つ)
Version 1旧・公開済 90%
residual weight(自動で残りを受け取る)
Version 2新・公開済 10%
こちらだけ重みを指定
  • 公式: 「You can point an alias to a maximum of two Lambda function versions.」——1エイリアス=最大2バージョン。
  • 片方に10%を指定すれば、もう片方は自動で90%(residual weight)。手で両方を足す必要はない。
  • CLIでは --routing-config AdditionalVersionWeights={"2"=0.03} のように追加バージョン側の重みだけを0〜1の小数で書く(この例はVersion 2に3%、残り97%がVersion 1)。

カナリアの本体は、新旧2つの「実体」を同時に生かしたまま、それを指す1つの「ポインタ」に重みという属性を足しただけ。Lambda編のバージョン(イミュータブルなスナップショット)とエイリアス(可変なポインタ)という分離が、そのまま段階的デプロイの土台になっている——コードは1バイトも動いていない。

② 重みを付けられるバージョンには公式の「3つの資格」がある

重み付きエイリアス作れるか?
1つでも欠ければ
同じ実行ロール両バージョンで一致
同じDLQ設定または両方なし
両方とも公開済み$LATESTは不可
重みを持てないエイリアスに重みを設定できない
  • 公式: 「Both versions must have the same execution role.」
  • 公式: 「Both versions must have the same dead-letter queue configuration, or no dead-letter queue configuration.」
  • 公式: 「Both versions must be published. The alias cannot point to $LATEST.」

なぜ「$LATESTは指せない」のか——$LATESTは書き換え可能な作業領域で、実体が固定されていない。動く標的にトラフィックを何%と割り当てても意味がない。カナリアが成立するのは、両側が「発行済み=もう変わらない」スナップショットだからこそ。試験ではこの3条件(同じ実行ロール・同じDLQ・両方公開済み)が急所。

③ 振り分けは「単純な確率モデル」——だから低トラフィックではブレる

呼び出しが1回到着
呼び出し回数が少ないと
当たり → V210%
はずれ → V190%
実測比率がブレる設定値(10%)と大きくズレうる
大数の法則が効かない
  • 公式: 「Lambda uses a simple probabilistic model to distribute the traffic between the two function versions.」——単純な確率モデル。
  • 公式: 「At low traffic levels, you might see a high variance between the configured and actual percentage of traffic on each version.」——低トラフィックでは設定値と実測に大きなばらつき。

これはDynamoDB編で見たハッシュ——キーを乱数的に均等分散させる設計——と同族の「乱数で公平を作る」仕組み。ハッシュもカナリアも、回数が十分あって初めて設計どおりの比率に収束する(大数の法則)。逆に呼び出しが少ないうちは、10%指定でも実測は大きく振れうる、と公式が明言している。

④ 「どっちが動いたか」を答え合わせする窓——公式の2つの方法+1つのディメンション

エイリアス経由で実行確率でどちらかの版が動いた
STARTログ行CloudWatch Logsに Version: 2
1回ごとに記録(公式の方法1)
応答ヘッダーx-amz-executed-version
同期呼び出しのみ(公式の方法2)
ExecutedVersionCloudWatchメトリクスのディメンション
集計を版ごとに割るフィルタ
  • START行の公式例: START RequestId: 1dh194d3759ed-4v8b-a7b4-1e541f60235f Version: 2 ——「Lambda automatically emits a START log entry that contains the invoked version ID for every function invocation.」
  • ヘッダー: 「Responses to synchronous function invocations include an x-amz-executed-version header to indicate which function version has been invoked.」(=同期呼び出しのみ)
  • 公式が「two ways」として挙げるのはログとヘッダーの2つ。ExecutedVersionは同じ節に「For alias invocations, Lambda uses the ExecutedVersion dimension to filter the metric data by the invoked version.」として登場するフィルタ用ディメンション。

確率で振り分けた以上、「今この1回はどっちだったか」を後から特定できなければ検証もロールバック判断もできない。ログ(1回単位)・レスポンスヘッダー(同期時)、そして集計をバージョン別に割るメトリクスのディメンション——粒度の違う窓が用意されている。可観測性がなければ安全な自動化はない、というこの後のセクションの伏線でもある。

⑤ SAM + CodeDeploy が「重みを動かす手作業」を自動運転にする

AutoPublishAliasテンプレートに live と書く
② エイリアス live を新版へ付け替え
新版を自動発行publish
3方式から選択
動かし方を選ぶDeploymentPreference.Type
Canary2段階(例: 10%→残90%)
Linear等間隔で等量(例: 毎2分10%)
AllAtOnce一括
  • AutoPublishAlias は「Detects when new code is being deployed, based on changes to the Lambda function's Amazon S3 URI / Creates and publishes an updated version / Creates an alias ... and points to the updated version」を自動でやる——①②で見た手作業の自動化。
  • Canary: 「Traffic is shifted in two increments.」例 Canary10Percent10Minutes=まず10%、10分後に残り90%(公式:「10 percent of your customer traffic is immediately shifted ... After 10 minutes, all traffic is shifted」)。
  • Linear: 「Traffic is shifted in equal increments with an equal number of minutes between each increment.」例 Linear10PercentEvery2Minutes=2分ごとに10%ずつ。
  • AllAtOnce: 「All traffic is shifted from the original Lambda function to the updated Lambda function version at once.」——一括。

①〜④で手動でやっていた「発行→エイリアス付け替え→重みを少しずつ動かす」を、テンプレート数行に畳んだのがこれ。人間が update-alias を叩き続ける代わりに、CodeDeployが時間を追って重みを機械的に上げていく。

⑥ 設定名は「そのまま仕様」——読み方を覚えれば暗記はいらない

設定名の構造CodeDeployDefault.Lambda[方式][%][間隔]
Every の有無が方式の見分け
Lambdaプラットフォーム
Canary / Linear方式
10Percent割合
5Minutes など間隔
Percent+MinutesCanary=先に10%・N分後に残り
PercentEveryLinear=N分ごとに10%ずつ全量まで
  • Canary系4本: LambdaCanary10Percent5Minutes / 10Minutes / 15Minutes / 30Minutes=最初に10%、残り90%をN分後。
  • Linear系4本: LambdaLinear10PercentEvery1Minute / 2Minutes / 3Minutes / 10Minutes=毎N分ごとに10%ずつ(1Minuteのみ単数形 Minute)。
  • LambdaAllAtOnce: 全トラフィックを一括で切替。
  • Linear は公式:「until all traffic is shifted」——全量に達するまで増やし続ける。

DVA最頻出級。名前がそのまま仕様なので、Canary は2段階・Linear は等間隔等量・Every があれば線形、という読み方さえ持てば、9つの設定名を丸暗記する必要はない。

⑦ 安全装置は2層——アラーム(自動で引き返す)とフック(前後で検証)

デプロイ開始
成功なら
PreTrafficフック検証LambdaがCodeDeployに成否をコールバック
失敗ならデプロイ中止・ロールバック
シフト完了「後」
段階シフト実行その間ずっと Alarms が監視
指定CWアラームが発火したら自動ロールバック
PostTrafficフック検証Lambdaで統合テストなど後段検証
  • Alarms: 「These are CloudWatch alarms that are triggered by any errors raised by the deployment. When encountered, they automatically roll back your deployment.」
  • PreTraffic: 「Before traffic shifting starts, CodeDeploy invokes the pre-traffic hook Lambda function. This Lambda function must call back to CodeDeploy and indicate success or failure.」失敗なら中止(公式:「If the function fails, it aborts and reports a failure back to CloudFormation.」)。
  • PostTraffic: 「After traffic shifting completes, CodeDeploy invokes the post-traffic hook Lambda function.」公式:「Use post-traffic hooks to run integration tests or other validation actions.」
  • どちらのフックも「must call back to CodeDeploy to report a success or failure」——検証Lambdaが自分でCodeDeployに成否を通知する契約。

これは可観測性編で見たアラームのFSM(閾値超過→ALARM状態)が、デプロイのフィードバックループに組み込まれた姿。アラームは「進行中に壊れたら引き返す」自律ブレーキ、フックは「開始前・完了後に人為的なチェックを差し込む」関所。観測(メトリクスとアラーム)が先にあって初めて、この自動ロールバックが成り立つ——編をまたぐ合流点。

⑧ 初回だけは「2段構え」——移行元がなければ段階シフトできない

初回デプロイ前まだ1つもバージョンがない
これで「移行元」ができた
Step 1AutoPublishAlias だけでデプロイ
DeploymentPreference は付けない
Step 2DeploymentPreference を足して段階デプロイ
2回目以降は段階シフトが使える
  • 公式: 「When deploying a Lambda function gradually, CodeDeploy requires a previously deployed function version to shift traffic from.」——段階シフトには移行元が必須。
  • 公式: 「your first deployment should be accomplished in two steps」——Step 1: AutoPublishAlias でデプロイ / Step 2: DeploymentPreference で段階デプロイ。

カナリアは「旧→新」へ重みを動かす操作なので、そもそも「旧」がなければ動かしようがない。初回は普通に1本出して移行元を作り、2回目以降に段階シフトを有効化する——この2段構えが公式の指示。締めに戻ると、カナリアとは新旧2つの実体を同時に生かし、ポインタの重みだけを動かすこと——コードのコピーは1バイトも動いていない。

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