05.1 · AWS Lambda 版本(Version)详解:$LATEST、不可变快照与限定 ARN

🇬🇧 English version | 📦 GitHub: https://github.com/geekchow/aws-lambda-guide

背景: 本文选自开源学习指南《AWS Lambda 心智模型》(中英双语)。全书用一个贯穿示例串联:网店 ShopFast 的 checkout 函数,周四通过 prod 别名把 v7 金丝雀发布到 v8,周五黑五开售前把预置并发(PC,Provisioned Concurrency)提到 400;文中的"第 N 步"即指该示例中的步骤,完整场景见 04 贯穿示例。
你在这里: 第 5 阶段,深入 1 / 6。示例第 1 步(发布 v8),以及之后所有"运行 v8"的步骤。

读完本文你将知道: 版本到底冻结了什么、$LATEST 有何不同、限定 ARN(Amazon Resource Name,亚马逊资源名称)如何工作,以及版本相关的失败方式。


1. 角色回顾

负责: 把可变草稿 $LATEST 变成不可变、带编号的快照。出场于: 示例第 1 步(PublishVersion → v8);之后创建的每个环境都从这个快照启动。

2. 内部设计

2.1 $LATEST 与已发布版本

#mermaid-svg-83WokC7WpLGpoVNh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-83WokC7WpLGpoVNh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-83WokC7WpLGpoVNh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-83WokC7WpLGpoVNh .error-icon{fill:#552222;}#mermaid-svg-83WokC7WpLGpoVNh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-83WokC7WpLGpoVNh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-83WokC7WpLGpoVNh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-83WokC7WpLGpoVNh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-83WokC7WpLGpoVNh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-83WokC7WpLGpoVNh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-83WokC7WpLGpoVNh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-83WokC7WpLGpoVNh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-83WokC7WpLGpoVNh .marker.cross{stroke:#333333;}#mermaid-svg-83WokC7WpLGpoVNh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-83WokC7WpLGpoVNh p{margin:0;}#mermaid-svg-83WokC7WpLGpoVNh defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-83WokC7WpLGpoVNh g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-83WokC7WpLGpoVNh g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-83WokC7WpLGpoVNh g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-83WokC7WpLGpoVNh g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-83WokC7WpLGpoVNh g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-83WokC7WpLGpoVNh .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-83WokC7WpLGpoVNh .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-83WokC7WpLGpoVNh .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-83WokC7WpLGpoVNh .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-83WokC7WpLGpoVNh .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-83WokC7WpLGpoVNh .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-83WokC7WpLGpoVNh .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-83WokC7WpLGpoVNh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-83WokC7WpLGpoVNh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-83WokC7WpLGpoVNh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-83WokC7WpLGpoVNh .edgeLabel .label text{fill:#333;}#mermaid-svg-83WokC7WpLGpoVNh .label div .edgeLabel{color:#333;}#mermaid-svg-83WokC7WpLGpoVNh .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-83WokC7WpLGpoVNh .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-83WokC7WpLGpoVNh .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-83WokC7WpLGpoVNh .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-83WokC7WpLGpoVNh .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-83WokC7WpLGpoVNh .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-83WokC7WpLGpoVNh .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-83WokC7WpLGpoVNh #statediagram-barbEnd{fill:#333333;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-83WokC7WpLGpoVNh .cluster-label,#mermaid-svg-83WokC7WpLGpoVNh .nodeLabel{color:#131300;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-83WokC7WpLGpoVNh .note-edge{stroke-dasharray:5;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-note text{fill:black;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram-note .nodeLabel{color:black;}#mermaid-svg-83WokC7WpLGpoVNh .statediagram .edgeLabel{color:red;}#mermaid-svg-83WokC7WpLGpoVNh #dependencyStart,#mermaid-svg-83WokC7WpLGpoVNh #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-83WokC7WpLGpoVNh .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-83WokC7WpLGpoVNh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} CreateFunction
更新代码或配置
PublishVersion

(有变化时)
永久只读
带限定符删除
$LATEST(可变草稿)
版本 N(不可变)

图注:生命周期------只有 $LATEST 会变;发布就是把它复制成一个冻结的版本。

$LATEST 版本 N
可变? 是------每次代码/配置更新都落在这里 否------发布后永不改变
标识 checkout:$LATEST 或非限定 ARN checkout:8
能承载预置并发? 不能 能
能作为加权别名的目标? 不能 能
适合生产调用方? 不适合------部署会在他们脚下改变它 适合

2.2 版本冻结了什么

版本是创建执行环境的完整配方:

  • 代码 :位于内部 S3(Simple Storage Service,简单存储服务)的 zip,或 ECR(Elastic Container Registry,弹性容器镜像仓库)中容器镜像的摘要(digest)------是摘要而非标签,所以镜像不会漂移。
  • 配置:运行时、handler、内存、超时、环境变量、层(按版本 ARN)、执行角色、VPC(Virtual Private Cloud,虚拟私有云)配置、架构(x86_64/arm64)、临时存储、SnapStart 设置。

不被冻结------这些是函数级或按限定符的设置,仍可修改:预留并发(函数级)、预置并发(按别名/版本)、基于资源的策略语句、事件源映射、异步调用配置。

2.3 编号与幂等

  • 编号从 1 开始单调递增。已删除的编号永不复用:删掉 v3 后下次发布仍是 v9 而不是 v3。这让"v8"在日志和仪表盘中成为永久、无歧义的名字。
  • PublishVersion 只在 $LATEST 自上次发布以来有变化时(比较 CodeSha256 + 配置)才创建新版本,否则返回现有的最新版本------流水线里调用两次也安全。
  • 乐观并发控制:传入 --code-sha256 或 --revision-id,如果期间有人改了 $LATEST,发布就会失败。

2.4 ARN 的几种形式

复制代码
arn:aws:lambda:us-east-1:111122223333:function:checkout          # 非限定 → $LATEST
arn:aws:lambda:us-east-1:111122223333:function:checkout:$LATEST  # 显式草稿
arn:aws:lambda:us-east-1:111122223333:function:checkout:8        # 版本限定
arn:aws:lambda:us-east-1:111122223333:function:checkout:prod     # 别名限定(见 05.2)

末尾部分称为限定符(qualifier)。每次调用在运行前都会被解析为恰好一个版本。

3. 交互

邻居 契约
CI/CD(Continuous Integration / Continuous Delivery,持续集成/持续交付)流水线 调用 UpdateFunctionCode → 等待 LastUpdateStatus=Successful → PublishVersion。
别名路由(05.2) 别名引用版本号;被别名引用的版本不能删除。
PC 管理器(05.3) PC 挂在某个版本上(直接或经由别名);$LATEST 会被拒绝。
放置服务 / 环境(05.5、05.6) 每个环境都由恰好一个版本的制品 + 配置构建。v7 和 v8 的环境从不混用。

4. ⚓ 回到示例------第 1 步,周四 14:00

流水线执行:

bash 复制代码
# 1. 更新草稿
aws lambda update-function-code \
  --function-name checkout \
  --zip-file fileb://checkout-v8.zip

aws lambda wait function-updated-v2 --function-name checkout

# 2. 冻结。--code-sha256 防止期间有人并发修改 $LATEST
aws lambda publish-version \
  --function-name checkout \
  --description "coupons (git a1b2c3d)" \
  --code-sha256 "Y2hlY2tvdXQtdjgtc2hhMjU2LWV4YW1wbGU="

响应(节选):

json 复制代码
{
  "FunctionArn": "arn:aws:lambda:us-east-1:111122223333:function:checkout:8",
  "Version": "8",
  "CodeSha256": "Y2hlY2tvdXQtdjgtc2hhMjU2LWV4YW1wbGU=",
  "Runtime": "nodejs22.x",
  "MemorySize": 1024,
  "Timeout": 10,
  "State": "Active"
}

从这一刻起,"v8"就固定了。周五放置服务启动 400 个环境时(第 6 步),以及 Bob 冷启动时(第 8 步),每个环境都由这份 zip、这套 1,024 MB / 10 秒配置构建------即便周五早上有人改了 $LATEST 也不受影响。代码中 process.env.AWS_LAMBDA_FUNCTION_VERSION 读到的是 "8"。

5. 失败行为

失败 会发生什么 设计应对
更新进行中时发布 ResourceConflictException 先等待 function-updated-v2。
有缺陷的代码被发布为 v8 v8 永久存在,但只有别名指向它时才接流量 别名保持在 v7;发布修复后的 v9。版本很便宜;修改在设计上就不可能。
旧版本过多 所有版本都计入每个 Region 的代码存储限额(默认 75 GB) 清理未被别名引用的版本(例如保留最近 10 个)。
有人在生产中调用 $LATEST 拿到未经测试的草稿代码 只授权调用方访问别名 ARN(基于资源的策略带 Qualifier)。

下一篇 → 05.2 别名 · 返回 03 概念地图


📚 返回专栏目录

相关推荐
DolitD8 小时前
UE像素流与云渲染技术方案对比分析
3d·云原生·ue5·云计算·图形渲染
天府云创9 小时前
面向 Personal Agent 增强长期记忆与个性化能力,阿里云升级Memory 服务
阿里云·云计算·memory·agent智能体·长期记忆·personal agent
yunlaodacom10 小时前
AWS亚马逊云代理商:WAF登录接口请求洪泛,限速阈值怎么设置?
云计算·aws
长不大的杨瑞杰11 小时前
OpenCode v2 配置工程实战:Config 优先级、JSONC、变量替换与多环境治理
人工智能·安全·云计算·软件工程·devops
longzhizhui92612 小时前
Ubuntu 全版本 CVE-2026-98432 内核安全升级操作手册
ubuntu·网络安全·云计算·bash
yunlaodacom17 小时前
做异地灾备,华为云国际站 OBS 跨地域复制该怎么配置?
安全·华为云·云计算
Elastic 中国社区官方博客17 小时前
AgentHack Shanghai|基于阿里云AI搜索 Elasticsearch x Qoder 构建AI Agent应用
大数据·人工智能·elasticsearch·搜索引擎·阿里云·云计算·全文检索
知已难寻1 天前
03 · OpenStack的计算管理 Nova
运维·服务器·开发语言·云原生·云计算·openstack·开源软件
会议咨询2 天前
2027年云计算、机电一体化与电子通信国际会议(CMEC 2027)
云计算·机电一体化·电子通信
云老大-阿里云国际站代理商2 天前
阿里云国际站服务代理商:CDN出现404,ECS源站正常怎么排查?
阿里云·云计算