Lambda 部署在概念上是最簡單的無伺服器 (serverless) 操作,卻是 Pro 等級最不容易做對的事情。DOP-C02 考試期望考生熟練掌握 Lambda 的版本模型 (versioning)、基於別名 (alias) 的流量轉移、CodeDeploy 對金絲雀 (canary) 與線性 (linear) 部署的整合、AWS SAM 的 DeploymentPreference 縮寫語法、基於警示的自動回滾,以及部署期間預先佈建並行能力 (provisioned concurrency) 的隱藏陷阱。與 EC2 或 ECS 不同 —— Lambda 沒有執行個體 (instance) 或任務 (task) 需要排空 (drain) —— 流量轉移發生在別名層 (alias layer),因此整個部署敘事其實就是「把別名指向另一個(或加權的)版本」。
本指南從 version 與 alias 開始建立 Lambda 部署的心智模型。內容涵蓋何時使用原生 alias 更新、何時改用 CodeDeploy 託管的流量轉移、SAM 的 DeploymentPreference 如何簡化 CodeDeploy 配線、PreTraffic 與 PostTraffic hook 如何插入驗證流程、基於警示的自動回滾如何運作,以及預先佈建並行能力與版本汰換之間的微妙互動。讀完之後,你應該能看到任何 Lambda 部署情境題就立刻判斷答案是「用 alias」、「用 CodeDeploy 搭配金絲雀組態」或「用 SAM AutoPublishAlias 加 DeploymentPreference」。
為什麼 Lambda 部署需要 Pro 等級的思維
Lambda 部署在三個關鍵面向與 EC2 / ECS 不同。第一,版本不可變 (immutability at the version):每個已發佈的版本都是不可變的,這讓回滾變成只改 metadata 的操作(把 alias 指回舊版本)—— 不需重新部署程式碼。第二,alias 即路由層 (alias-as-routing-layer):alias 可同時對兩個版本進行加權路由(例如 90% 到 v5、10% 到 v6),完全不需動到基礎設施。第三,叫用端整合 (invocation-time integration):API Gateway、EventBridge、S3 事件、SNS、SQS 與其他叫用者都指向 alias,而非函數名稱本身;alias 是穩定的位址。
這三個特性合起來,使 Lambda 的部署模型特別適合金絲雀部署 —— 你就是調整 alias 權重而已。複雜度來自自動化:CodeDeploy 搭配警示式回滾把手動調權重變成全自動的金絲雀或線性部署,而 SAM 的 DeploymentPreference 把 CodeDeploy 設定濃縮成兩行 YAML。
DOP-C02 的題目傾向測試:(1) CodeDeploy 比原生 alias 更新多了什麼價值、(2) CodeDeploy Lambda 組態的逐字名稱、(3) PreTraffic 與 PostTraffic hook 的語義,以及 (4) alias 更新與預先佈建並行能力的互動。
- Lambda version:函數程式碼與設定的不可變快照;以數字版本 (例如
1、2) 或$LATEST(未發佈版本)識別。 - Lambda alias:指向某個版本(或加權版本對)的具名指標,叫用者可指向 alias 而非
$LATEST;常見名稱:prod、staging、live。 - 加權 alias (Weighted alias):透過
RoutingConfig.AdditionalVersionWeights將第二個版本映射到一個分數權重 (0.0–1.0) 的 alias 設定。 - CodeDeploy Lambda 部署組態 (Deployment configuration):控制流量轉移排程的具名政策(例如
LambdaCanary10Percent5Minutes、LambdaLinear10PercentEvery1Minute)。 - PreTraffic hook:CodeDeploy 在轉移流量「之前」叫用的 Lambda 函數,用於驗證;非零回傳會中止部署。
- PostTraffic hook:CodeDeploy 在流量完全轉移「之後」叫用的 Lambda 函數,用於部署後驗證。
- AutoPublishAlias (SAM):SAM 的屬性,每次程式碼更新會自動發佈新版本,並把指定的 alias 指向該版本。
- DeploymentPreference (SAM):SAM 的屬性,宣告函數的 CodeDeploy 組態 (Type、Hooks、Alarms、Role)。
- 預先佈建並行能力 (Provisioned concurrency):預先暖機好的 Lambda 執行環境;綁定特定版本或 alias,部署期間有微妙互動。
- 參考:https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html
白話文解釋 Lambda 部署
Lambda 部署的感覺與其他運算平台不太一樣,因為沒有機群可管理。以下三個跨領域的類比可以讓「基於 alias 的流量轉移模型」變得直觀。
類比 1:電話轉接服務
想像一間小公司有一個公開電話號碼,會自動轉接到當班的員工。公開電話號碼就是 alias —— 印在名片、電話簿上、給 API Gateway 與 EventBridge 用。特定員工的直撥分機就是 version —— 不可變,雇用時就固定。更新 alias 就是改轉接規則 —— 瞬時、原子性、來電者完全感受不到。
加權 alias 是通話路由魔法:90% 來電進到資深員工 (v5),10% 轉到新進員工 (v6) 接受評估。一週評估後若新人通話品質達標,路由切換到 100% 給新人。回滾就是把規則改回資深員工 —— 一次電話系統設定變更,不需要重新培訓或重新招人。
CodeDeploy 搭配金絲雀組態是自動電話路由管理員:它按排程調整百分比(10% 維持 5 分鐘,然後 100%),監控客訴指標,若客訴飆升就自動把路由切回資深員工。PreTraffic hook 是面試篩選 —— 在任何真實顧客的來電進到新人之前,主管會先做模擬電話(合成測試);若新人連模擬都搞砸,就完全不會把真實流量轉過去。
類比 2:餐廳品嚐菜單試菜
高級餐廳要推出新菜。公開菜單上列出菜名(alias seared scallops)。後台,主廚有兩個食譜 —— v5 食譜(已驗證的做法)和 v6 食譜(新技術)。廚房進行金絲雀試菜:接下來的 10 份 seared scallops 訂單中,1 份用 v6(新技術),9 份用 v5(已驗證)。若 v6 的菜完美回到桌上,主廚下一輪服務把 v6 提高到 25%,然後 50%、最後 100%。
PreTraffic hook 是主廚試吃 —— 任何顧客拿到新食譜之前,主廚必須先試菜並確認過關。PostTraffic hook 是服務後回顧 —— 新食譜完全推開之後,主廚會檢視整個服務時段的顧客回饋,確認接受度。
類比 3:軟體 Beta 測試計畫
消費型軟體公司推出新功能 beta 計畫。產品 (alias) 在 App Store 上是單一個體。內部,version 是不可變的釋出版本 —— v5 是當前生產版,v6 是 beta。公司的推送系統第一天把 1% 使用者導到 v6、第二天 5%、第三天 20%、第四天 100%。當機回報就是 CloudWatch 警示 —— 若 v6 的當機率比 v5 多超過某個門檻,推送系統幾分鐘內就自動把所有人退回 100% v5。完全不需要工程師介入。
電話轉接類比最直接對應 alias 更新,對第一次接觸的學習者最直觀。餐廳類比最適合理解 hook 的語義。軟體 beta 類比最適合考題強調「百分比漸進部署 + 警示驅動回滾」的情境。參考:https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html
Version 與 Alias —— 一切的基礎
每個 Lambda 函數都從一個版本開始:$LATEST。它是可變的 —— 每次程式碼更新都覆寫它。發佈版本 (PublishVersion API 或 aws lambda publish-version) 會用當前的 $LATEST 做快照,建立一個不可變的數字版本(1、2、3...)。
Alias 是解析到某個版本的具名指標。一個 prod alias 可能指向版本 5;把 alias 更新到版本 6 就改變了 prod 進來的請求會打到哪份程式碼。Alias 支援加權路由:prod alias 可以指向版本 5,並用 AdditionalVersionWeights: {6: 0.10} 將 10% 的叫用送到版本 6、90% 留在版本 5。
關鍵慣例:叫用者一律指向 alias,絕不直接指向 $LATEST。API Gateway 整合、EventBridge 規則、S3 事件通知、SNS 訂閱、SQS 事件來源都應該參考 function-name:prod,而不是 function-name(意義等同 $LATEST)。這讓 alias 更新成為唯一的釋出控制點。
CodeDeploy Lambda 部署組態
CodeDeploy 自動化「隨時間調整 alias 權重」。組態決定排程:
CodeDeployDefault.LambdaAllAtOnce:一次轉移 100%。等同原生 alias 更新;CodeDeploy 在這裡只多了 hook 與回滾。CodeDeployDefault.LambdaCanary10Percent5Minutes:10% 維持 5 分鐘,然後 100%。CodeDeployDefault.LambdaCanary10Percent10Minutes:10% 維持 10 分鐘,然後 100%。CodeDeployDefault.LambdaCanary10Percent15Minutes:10% 維持 15 分鐘,然後 100%。CodeDeployDefault.LambdaCanary10Percent30Minutes:10% 維持 30 分鐘,然後 100%。CodeDeployDefault.LambdaLinear10PercentEvery1Minute:每 1 分鐘加 10%(共 10 分鐘)。CodeDeployDefault.LambdaLinear10PercentEvery2Minutes:每 2 分鐘加 10%。CodeDeployDefault.LambdaLinear10PercentEvery3Minutes:每 3 分鐘加 10%。CodeDeployDefault.LambdaLinear10PercentEvery10Minutes:每 10 分鐘加 10%。
自訂部署組態 (Custom deployment configuration) 可定義非標準 SLA 所需的任意金絲雀或線性排程。
考題有時會給部分組態名稱讓你判斷是 canary 還是 linear。Canary 名稱永遠是 Canary{percent}Percent{minutes}Minutes(一個起始百分比,然後跳到 100)。Linear 名稱永遠是 Linear{percent}PercentEvery{minutes}Minute(s)(整段時間內均勻遞增)。掌握命名邏輯,就算沒背全部變體也能答對。參考:https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-configurations.html
SAM AutoPublishAlias 與 DeploymentPreference
AWS SAM 把整套 Lambda 金絲雀配線壓縮成兩個屬性:
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./src
Handler: app.handler
Runtime: nodejs18.x
AutoPublishAlias: live
DeploymentPreference:
Type: Canary10Percent5Minutes
Hooks:
PreTraffic: !Ref PreTrafficHookFunction
PostTraffic: !Ref PostTrafficHookFunction
Alarms:
- !Ref ErrorRateAlarm
Role: !GetAtt CodeDeployRole.Arn
AutoPublishAlias: live 告訴 SAM (1) 每次程式碼變更時自動發佈一個新版本,並 (2) 確保 live 這個 alias 存在,且指向最新發佈的版本。
DeploymentPreference 宣告 CodeDeploy 組態:Type 選擇排程 (Canary10Percent5Minutes、Linear10PercentEvery1Minute 等),Hooks 列出 pre/post traffic Lambda 函數,Alarms 列出用於自動回滾的 CloudWatch 警示,Role 是 CodeDeploy 服務角色。
幕後,SAM 會把 CodeDeploy 應用程式、部署群組與部署組態以 CloudFormation 資源產出。考題很愛測:DeploymentPreference 只存在於 SAM,原生 CloudFormation AWS::Lambda::Function 沒有 —— 純 CFN 必須自己宣告 CodeDeploy 資源。
PreTraffic 與 PostTraffic Hook
Hook 是 CodeDeploy 在部署生命週期中叫用的 Lambda 函數,由部署帳號按標準 Lambda 費率付費。
PreTraffic hook 在新版本發佈完、但流量還沒轉移之前執行。用來對新版本做合成叫用(帶測試 payload),驗證基本功能。Hook 函數必須呼叫 aws codedeploy put-lifecycle-event-hook-execution-status --status Succeeded (或 Failed),告訴 CodeDeploy 是否要繼續。
PostTraffic hook 在部署完成(alias 完全指向新版本)之後執行。用來做端到端驗證 —— 合成 API 呼叫、整合測試、跨依賴服務的 smoke test。狀態通報模式相同。
典型的 PreTraffic hook 會用已知良好的測試事件直接叫用新版本並驗證回應格式;PostTraffic hook 則呼叫位於函數前端的 API Gateway 端點並驗證 happy-path 回應。
Hook 函數即使成功執行完,只要沒呼叫 PutLifecycleEventHookExecutionStatus,最終會超時(過了部署 timeout 之後),CodeDeploy 就會把它標記為 Failed。許多考生以為「hook 正常 return 就夠了」 —— 不夠。Hook 函數必須明確呼叫 CodeDeploy API 來回報狀態。參考:https://docs.aws.amazon.com/lambda/latest/dg/services-codedeploy.html
基於警示的自動回滾
CodeDeploy 可以在部署期間 CloudWatch 警示進入 ALARM 狀態時,自動把 alias 回滾。透過 DeploymentPreference.Alarms (SAM) 或 alarmConfiguration (原生 CodeDeploy) 設定。
最佳實踐警示:
- 函數錯誤率:
Errors / Invocations > 1%(1 分鐘內)。 - 函數執行時間:高優先函數
Average Duration > 1000ms。 - API Gateway 5xx 錯誤率:可捕捉到 Lambda 程式碼問題對下游的影響。
- 來自 EMF 的自訂指標:透過嵌入式指標格式 (embedded metric format) 在日誌中嵌入的業務層級信號。
當警示在金絲雀或線性部署期間觸發,CodeDeploy 會停止排程並把 alias 回滾到舊版本 —— 因為只是 metadata 變更,所以是瞬時回滾。
預先佈建並行能力 (Provisioned Concurrency) 的互動
預先佈建並行能力會讓執行環境保持暖機狀態。它綁定到特定 version 或 alias,是部署期間微妙互動的來源。
如果預先佈建並行能力綁在 alias,權重轉移會按比例切分預先佈建容量。Alias 上有 100 PC、金絲雀 10% 到 v6 的情境,會變成 v6 有 10 PC、v5 有 90 PC。CodeDeploy 自動處理重新平衡。
如果預先佈建並行能力綁在特定 version,那個版本不論 alias 怎麼更新都保留自己的 PC。常見的部署模式:在流量轉移開始前先在新版本上預先配置 PC,這樣金絲雀流量就不會碰到冷啟動。SAM 的 ProvisionedConcurrencyConfig 可以綁到 alias 以取得這種自動平衡。
一個微妙的陷阱:部署一個 PC 綁在特定版本上的函數,但沒有在新版本上重新配置 PC,會讓新版本承受流量時冷啟動。除非有特別理由,否則永遠把 PC 綁到 alias。
綁到 alias 的 PC 會在金絲雀過程中自動重新平衡;綁到固定 version 的 PC 不會遷移到新版本。考題情境是「金絲雀部署導致使用者看到冷啟動」 —— 解法是把 PC 從 version 移到 alias。參考:https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html
比較 —— 原生 Alias 更新 vs CodeDeploy
Lambda 部署有三種做法,依自動化程度排序:
1. 原生 alias 更新 (UpdateAlias API):從舊版本瞬間切到新版本。沒有加權轉移、沒有 hook、沒有自動回滾。適用於非關鍵函數,回滾可接受是手動操作。
2. 手動加權 alias 更新:設定 RoutingConfig.AdditionalVersionWeights 並隨時間手動調整。能取得金絲雀語義,但需要操作員自己排程。在生產環境很少見。
3. CodeDeploy 搭配 DeploymentPreference:完整自動化,有排程流量轉移、hook、警示。生產環境的標準做法。
任何有明確 SLA、影響客戶、或需要警示式回滾的函數,預設選 3。內部自動化、排程批次作業或 ops 指令稿用 1。
CloudFormation 部署考量
透過原生 CloudFormation (AWS::Lambda::Function) 部署 Lambda 函數時,程式碼更新會就地取代 $LATEST。要取得版本語義,必須明確建立 AWS::Lambda::Version 資源 —— 但這些是不可變的,所以每次更新都需要一個新的邏輯資源 ID。
這就是 SAM 的 AutoPublishAlias 自動化掉的事情。沒有 SAM 的話,標準的原生 CFN 模式是把函數程式碼的 S3 物件版本編碼進 AWS::Lambda::Version 的邏輯 ID,強迫 CloudFormation 在每次程式碼變更時建立新的版本資源。
對 DOP-C02 而言,知道「Lambda CI/CD 偏好用 SAM」就夠了;你很少需要從零寫原生 CFN 模式。
常見陷阱模式
陷阱一:用 LambdaAllAtOnce 卻期待自動回滾接住問題。AllAtOnce 給你回滾機制但沒有金絲雀期 —— 警示觸發時,所有流量早已打到新版本。
陷阱二:API Gateway 整合指向 $LATEST 而非 alias。更新 $LATEST 會立即影響生產,沒有回滾路徑。
陷阱三:PreTraffic hook 沒呼叫 PutLifecycleEventHookExecutionStatus。Hook 靜默超時並讓部署失敗。
陷阱四:警示打在 alias 的指標上 —— CloudWatch 預設指標是每函數發出,不是每 alias。要對 alias 層級指標告警,要啟用 per-alias metric 或用 embedded metric format。
陷阱五:忘記在金絲雀流量轉移之前對新版本配置預先佈建並行能力;PC 綁在舊版本意味著金絲雀期間新版本會冷啟動。
CodeDeploy 自動回滾在相關警示進入 ALARM 時觸發。如果一個全新警示資料點不足(還沒任何資料點),它會維持在 INSUFFICIENT_DATA —— CodeDeploy 把這視為健康。對於剛建立的函數或警示,要確保基準指標已存在,再依賴警示式回滾。考題情境是「警示因為資料不足而沒觸發」。參考:https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-configurations.html
端到端 Lambda Pipeline 模式
DOP-C02 標準的 Lambda pipeline 組合長這樣。Source 在 CodeCommit。Build 在 CodeBuild 跑 sam build、跑單元測試、產出 packaged.yaml 與壓縮過的程式碼上傳到 S3。部署到 staging 透過 CloudFormation deploy action 對 SAM stack 設 DeploymentPreference: AllAtOnce。Approval action 暫停等發佈經理簽核。部署到生產用同樣的 CFN deploy action 對生產 stack 設 DeploymentPreference: Canary10Percent5Minutes,PreTraffic hook 跑合成測試、PostTraffic hook 跑整合測試,警示打在函數錯誤率、執行時間及 API Gateway 5xx。
把這個模式背下來 —— 這是考題會出無數變體的參考架構。
任何 Lambda 部署題,都用這四件套定錨:
- Version 與 alias:叫用者指向 alias;alias 指向一個版本(或加權版本對)。
- CodeDeploy 組態:AllAtOnce(無金絲雀)、Canary{percent}Percent{minutes}Minutes(單一金絲雀步)、或 Linear{percent}PercentEvery{minutes}Minute(s)(均勻遞增)。
- Hook:PreTraffic(轉移前驗證)、PostTraffic(轉移後驗證);兩者都必須呼叫
PutLifecycleEventHookExecutionStatus。 - 警示:綁函數錯誤率、執行時間、下游 API Gateway 5xx;進入 ALARM 觸發自動回滾。
SAM 的 AutoPublishAlias 加 DeploymentPreference 把 1–4 都包成兩個 YAML 屬性。參考:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-deploymentpreference.html
常考陷阱
- 叫用
$LATEST而非 alias —— 每次程式碼更新都立即影響生產且無回滾路徑;生產叫用者必須一律指向 alias。 - PreTraffic hook 漏呼叫
PutLifecycleEventHookExecutionStatus—— 即使執行成功,hook 會超時並讓部署失敗。 - 預先佈建並行能力綁在固定 version —— 金絲雀期間不會遷移到新版本;流量轉移時出現冷啟動尖峰。把 PC 綁到 alias 才會自動重新平衡。
- 警示處於 INSUFFICIENT_DATA 狀態 —— 自動回滾只在 ALARM 觸發;剛建立的警示如果沒資料點就不會發出。
- 用
LambdaAllAtOnce卻期待金絲雀安全性 —— AllAtOnce 立即轉移所有流量;警示仍會觸發回滾,但每位使用者早已碰過壞版本。
FAQ
Q1:什麼時候 CodeDeploy 比原生 alias 更新值得? 任何時候部署需要加權流量轉移、警示式自動回滾或 hook。原生 alias 更新適合 ops 指令稿和內部 Lambda。CodeDeploy 是面對客戶、有 SLA 的生產函數的預設選擇。
Q2:可以不用 SAM、單獨用 CodeDeploy 給 Lambda 嗎?
可以。在 CloudFormation 裡宣告 AWS::CodeDeploy::Application、AWS::CodeDeploy::DeploymentGroup,並手動連結到函數的 alias。SAM 把這些樣板隱藏起來;底層的 CodeDeploy 機制完全相同。
Q3:Lambda 部署期間,進行中的叫用會發生什麼事? 它們會用「叫用當下 alias 解析到的版本」執行完畢。Lambda 不會在流量轉移期間強制中止正在執行的呼叫。長時間執行的叫用可能在金絲雀開始之後才在舊版本上結束。
Q4:如何把 Lambda alias 回滾到指定的舊版本?
手動回滾:aws lambda update-alias --name prod --function-version 5 --routing-config AdditionalVersionWeights={}。CodeDeploy 回滾則是重新建立部署,用前一個成功 task-set 的版本作為目標。
Q5:CodeDeploy 是否支援 Lambda 的 EC2 式藍綠部署? Lambda 服務沒有多個「機群」 —— Lambda 的藍綠就是「版本之間的 alias 加權流量轉移」。概念上是藍綠(舊版本與新版本並存),但機制上是 alias 路由。
Q6:什麼時候應該選 LambdaLinear10PercentEvery1Minute 而不是 LambdaCanary10Percent5Minutes?
Linear 在整個部署窗口逐步遞增(Linear10PercentEvery1Minute 是 10 分鐘)。Canary 維持 10% 五分鐘後跳到 100%。Linear 對緩慢顯現的問題更安全;Canary 較快,足以對付快速失敗的 bug。
Q7:如何把 Lambda 函數部署與下游 DynamoDB schema 變更同步? 兩階段部署。(1) 先更新 DynamoDB 表(新增欄位、雙寫程式碼)。(2) 部署 Lambda 函數讀新欄位。(3) 回填舊資料。(4) Lambda 後續部署移除雙寫。用 Step Functions 狀態機包成編排;CodeDeploy 本身無法處理跨資源的序列化。
Q8:可以讓多個 Lambda 函數共用同一個部署組態嗎? 可以。一個 CodeDeploy 應用程式可有多個部署群組,每個指向不同函數的 alias。同一個自訂或預設部署組態可被多個群組參考。這是 monorepo serverless 應用(有大量函數)的標準模式。