121. Lambdaのカナリアは重み付きエイリアスでできている — 確率でトラフィックを割り、アラームで引き返す
Lambda編で「バージョン=イミュータブルなスナップショット、エイリアス=可変なポインタ」と学びました。この回はその答え合わせ——1つのポインタの重みだけを動かして新旧を同時に生かす「カナリア」の仕組みを、下から上への確率の流れとして図で追っていきます。
① 1つのエイリアスは最大2バージョンを「重み」で指す
- 公式: 「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つの資格」がある
- 公式: 「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・両方公開済み)が急所。
③ 振り分けは「単純な確率モデル」——だから低トラフィックではブレる
- 公式: 「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行の公式例: 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 は「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が時間を追って重みを機械的に上げていく。
⑥ 設定名は「そのまま仕様」——読み方を覚えれば暗記はいらない
- 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層——アラーム(自動で引き返す)とフック(前後で検証)
- 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段構え」——移行元がなければ段階シフトできない
- 公式: 「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バイトも動いていない。