- 后端
- 云原生
- IaC
【免费下载链接】serverless-application-model
The AWS Serverless Application Model (AWS SAM) transform is a AWS CloudFormation macro that transforms SAM templates into CloudFormation templates.
AWS SAM(Serverless Application Model)transform 是 AWS CloudFormation 的一个宏(macro),它把简洁的 SAM 模板(如AWS::Serverless::Function)在部署前自动展开为完整的 CloudFormation 模板。本文以当前开源仓库serverless-application-model的 README.md 为核心,带你从快速上手、转换原理、插件机制到源码级实现细节,全面掌握 SAM transform 的使用方式与底层工作机制。
什么是 AWS SAM transform
SAM transform 本质上是一个AWS CloudFormation macro:当 CloudFormation 在部署模板时遇到宏,会先把模板交给宏处理,再把宏产出的结果作为真正的 CloudFormation 模板执行。这个仓库就是该宏的开源实现——它将开发者编写的SAM 模板(遵循 SAM 规范)转换为等价的CloudFormation 模板。
使用方式非常简单:在 CloudFormation 模板的Transform部分声明宏名称即可:
Transform: AWS::Serverless-2016-10-31只要模板声明了这个 Transform,CloudFormation 就会自动调用本仓库实现的宏逻辑,把模板中所有AWS::Serverless::*资源逐一翻译成对应的原生 CloudFormation 资源(AWS::Lambda::Function、AWS::IAM::Role、AWS::ApiGateway::*等)。
使用 SAM transform 的三个核心收益
README 明确了使用 SAM transform 的三点价值:
- 内置最佳实践与合理默认值(Built-in best practices and sane defaults):例如,为一个
AWS::Serverless::Function声明函数时,transform 会自动生成配套的 IAM 执行角色、标签、事件源权限等,开发者无需手写这些样板资源。 - 本地测试与调试(Local testing and debugging with the AWS SAM CLI):SAM CLI(
aws-sam-cli)在本地模拟 Lambda 与 API Gateway 环境,基于同一套模板规范,实现"本地与云端行为一致"。 - 扩展 CloudFormation 模板语法(Extension of the CloudFormation template syntax):SAM 提供
Globals、Connectors、DeploymentPreference等 CloudFormation 原生不具备的高级抽象,让模板更简短、更易维护。
快速上手:五分钟写出第一个 SAM 应用
README 给出了一个可直接落地的入门示例。将下面的内容保存为template.yaml:
Transform: AWS::Serverless-2016-10-31 Resources: MyFunction: Type: AWS::Serverless::Function Properties: Runtime: nodejs24.x Handler: index.handler InlineCode: | exports.handler = async (event) => { console.log(event); }然后使用 SAM CLI 直接同步部署:
sam sync --stack-name sam-app这个模板声明了一个AWS::Serverless::Function资源,transform 会把它展开为一个记录(打印)所收到事件的 AWS Lambda 函数。InlineCode直接内联函数源码,适合快速验证;生产场景更常用CodeUri指向 S3 或本地代码目录(打包后上传)。
转换后长什么样
README 特别给出了转换结果的 YAML 等价形式,理解它有助于把握 transform 的"魔法"所在——一个简洁的函数声明,被展开为一个 Lambda 函数外加一个 IAM 角色:
Resources: MyFunction: Type: AWS::Lambda::Function Properties: Code: ZipFile: | exports.handler = async (event) => { console.log(event); } Handler: index.handler Role: !GetAtt MyFunctionRole.Arn Runtime: nodejs24.x Tags: - Key: lambda:createdBy Value: SAM MyFunctionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Tags: - Key: lambda:createdBy Value: SAM注意输出中的几个关键点,它们正是"内置最佳实践"的体现:
- 角色自动生成:
MyFunctionRole是 transform 自动创建的 IAM 角色,信任策略(AssumeRolePolicyDocument)仅允许lambda.amazonaws.com服务代入; - 最小权限托管策略:默认附加
AWSLambdaBasicExecutionRole(CloudWatch Logs 写入权限),而非AdministratorAccess之类的宽泛策略; - 溯源标签:自动给函数和角色打上
lambda:createdBy: SAM标签,便于在 AWS 控制台识别由 SAM 创建的资源。
深入原理:源码视角的转换全流程
README 只描述了"做了什么",而转换"如何发生"需要深入源码。整个转换的入口位于 samtranslator/translator/transform.py 的transform()函数,其调用链如下:
transform(input_fragment, parameter_values, managed_policy_loader, feature_toggle, passthrough_metadata)是唯一入口:input_fragment是待转换的 SAM 模板字典,parameter_values是用户提供的模板参数值(可能为空字典)。- 调用
to_py27_compatible_template做 Python 2/3 哈希兼容处理(samtranslator/utils/py27hash_fix.py),保证新旧环境生成一致的逻辑 ID。 - 构造
Parser与Translator,执行translator.translate(...)完成真正的转换,最后用undo_mark_unicode_str_in_template还原输出。
Translator.translate:转换主流程
核心逻辑在 samtranslator/translator/translator.py 的Translator.translate()方法中,大致分四个阶段:
阶段一:参数准备与插件安装。SamParameterValues负责补全模板参数:先注入用户未提供的默认值,再注入伪参数(如AWS::Region、AWS::AccountId,依赖可选的boto_session)。随后prepare_plugins装配插件链(见下文"插件系统"一节)。
阶段二:模板校验。Parser 的validate_datatypes检查模板骨架:Resources部分必须存在且为字典,每个资源必须是对象(YAML 缩进错误会在此暴露),每个 SAM 资源的Properties必须是 map。
阶段三:逐资源翻译。这是核心循环(translator.py 的 translate 主循环)。ResourceTypeResolver根据资源Type找到对应的 SAM 宏类(如SamFunction),调用to_cloudformation()生成一个或多个原生 CloudFormation 资源,随后从原模板删除 SAM 资源、写入翻译结果。翻译过程中还维护了changed_logical_ids(逻辑 ID 变更追踪)与supported_resource_refs(资源引用收集),用于最后统一修正跨资源引用。
阶段四:收尾处理。若启用了部署偏好(DeploymentPreference),生成 CodeDeploy 应用、IAM 角色与部署组;执行after_transform_template生命周期钩子;删除Transform声明;通过ResolveDependsOn与IntrinsicsResolver修复DependsOn和资源引用;最后汇总所有错误——只要存在任意InvalidResourceException等文档级错误,整个转换就以InvalidDocumentException失败。
资源处理顺序:为什么 API 要排在函数后面
转换循环并非按模板书写顺序进行。_get_resources_to_iterate规定了处理优先级:
AWS::Serverless::Function(函数的事件可能修改对应 API 的 Swagger 定义);AWS::Serverless::StateMachine(原因同上);AWS::Serverless::Api/HttpApi/WebSocketApi(必须在所有 Swagger 修改完成后解析);- 其他 SAM 资源;
AWS::Serverless::Connector(连接器 profile 只作用于纯 CloudFormation 资源)。
这个顺序保证了"函数事件先改写 API 定义、API 再据此生成"的依赖关系成立。
插件系统:SAM 高级语法从何而来
Globals、隐式 API、策略模板等 SAM 高级特性并非硬编码在翻译循环里,而是由插件系统(Plugin)实现的。在 translator.py 的 prepare_plugins 中,每次转换都会装配以下"必需插件":
| 插件 | 职责 | 源码位置 |
|---|---|---|
ServerlessAppPlugin | 处理AWS::Serverless::Application(嵌套应用) | samtranslator/plugins/application/serverless_app_plugin.py |
DefaultDefinitionBodyPlugin | 为 API 生成默认 OpenAPI/Swagger 定义体 | samtranslator/plugins/api/default_definition_body_plugin.py |
ImplicitRestApiPlugin | 为函数事件自动创建隐式 REST API | samtranslator/plugins/api/implicit_rest_api_plugin.py |
ImplicitHttpApiPlugin | 为函数事件自动创建隐式 HTTP API | samtranslator/plugins/api/implicit_http_api_plugin.py |
GlobalsPlugin | 实现Globals节:向所有资源合并全局默认值 | samtranslator/plugins/globals/globals_plugin.py |
PolicyTemplatesForResourcePlugin | 展开 SAM 策略模板(如SQSPollerPolicy) | samtranslator/plugins/policies/policy_templates_plugin.py |
插件沿before_transform_template→ 翻译循环 →after_transform_template生命周期事件参与转换,用户自定义插件会先于内置插件执行(顺序对ServerlessAppPlugin等依赖方至关重要)。这也解释了 README 中"扩展 CloudFormation 模板语法"的能力来源。
源码级细节:SAM 函数是如何被"翻译"的
AWS::Serverless::Function是使用率最高的 SAM 资源,其定义位于 samtranslator/model/sam_resources.py 的SamFunction类。它声明了近 40 个属性(property_types),包括Handler、Runtime、CodeUri、InlineCode、Policies、Events、DeploymentPreference、AutoPublishAlias、SnapStart等。其中值得注意的几点:
1. IAM 角色按需扩权
前文示例默认只附加AWSLambdaBasicExecutionRole。查看 SamFunction._construct_role 可知,角色策略是按属性动态叠加的:
- 启用
Tracing(且非Disabled)时追加 X-Ray 托管策略(samtranslator/model/xray_utils.py); - 配置了
VpcConfig时追加AWSLambdaVPCAccessExecutionRole; - 配置了
DeadLetterQueue时生成对应的死信队列策略(sqs:SendMessage等); EventInvokeConfig指向 SQS/SNS/EventBridge 等目标时,追加sqs:SendMessage、sns:Publish、events:PutEvents等最小权限策略;Policies属性支持字符串、策略文档或托管策略 ARN 列表,经ResourcePolicies统一解析。
2. PackageType 的严格校验
_validate_package_type([samtranslator/model/sam_resources.py#L927-L967))区分两种打包方式:ZIP(需Runtime+Handler,且不得携带ImageUri/ImageConfig)与IMAGE(需ImageUri,且不得携带Runtime/Handler/Layers)。规则不满足时抛出InvalidResourceException,这正是 README 示例必须同时给出Runtime与Handler的原因。
3. 溯源标签的实现位置
lambda:createdBy: SAM标签的键名常量定义在 samtranslator/model/init.py(_SAM_KEY),由标签生成工具 samtranslator/model/tags/resource_tagging.py 统一注入函数及自动生成的默认角色。
4. 特性开关(Feature Toggle)
转换行为还受 samtranslator/feature_toggle/feature_toggle.py 控制。FeatureToggle根据stage、account_id、region三级配置决定某个新特性是否启用(支持toggle与account-percentile两种拨号策略),用于生产环境的灰度发布;本地默认实现FeatureToggleDefaultConfigProvider对所有查询返回 False,保证开源环境行为确定。
本地开发与测试:从源码构建
README 的 Contributing 部分给出了参与该仓库开发的标准流程,也适用于想从源码运行 transform 的读者。前提是Python 3.8+:
# 1. 创建并激活虚拟环境 python3 -m venv .venv source .venv/bin/activate # 2. 安装依赖(等价于 pip install -e '.[dev]') make init # 3. 提交 PR 前的完整校验:格式检查 + lint + 单测 + 覆盖率 make prmake pr实际串起了 Makefile 中的多项任务:format-check(含 schema 一致性校验、black 格式检查、JSON/YAML 规范检查)、lint(ruff + mypy 严格类型检查 + cfn-lint 校验生成的 CloudFormation 是否合法)、init与dev(pytest 单测,要求samtranslator包覆盖率 ≥ 95%)。此外还有make integ-test运行集成测试、make schema重新生成 samtranslator/schema/schema.json 等目标,详见 Makefile 与 DEVELOPMENT_GUIDE.md。
测试体系:如何验证转换正确性
这个仓库对转换正确性的验证投入非常大,是理解 transform 行为边界的绝佳入口:
- 翻译单元测试:
tests/translator/input/存放数百个 SAM 输入模板(覆盖 API、函数、状态机、连接器、策略模板、DeploymentPreference 等几乎全部特性),tests/translator/output/存放对应的期望 CloudFormation JSON 输出,由 tests/translator/test_translator.py 驱动逐一对拍; - 错误用例:
tests/translator/input/error_*.yaml系列验证各类非法模板能抛出准确的错误信息; - 插件与模型单测:
tests/plugins/、tests/model/分别覆盖插件与资源生成器的行为; - 集成测试:
integration/目录下的用例会真实调用 AWS 服务验证端到端行为(需要 companion stack,见 INTEGRATION_TESTS.md)。
总结
AWS SAM transform 是连接"简洁的 SAM 模板"与"完整的 CloudFormation 模板"之间的桥梁:通过声明Transform: AWS::Serverless-2016-10-31,开发者得以用几十行的模板描述函数、API、事件源与权限,由宏在部署前自动补齐 IAM 角色、托管策略、溯源标签等最佳实践。本文既演示了 README 中的快速上手路径,也从 transform.py、translator.py、sam_resources.py 等源码揭示了其翻译主流程、插件机制与校验细节,帮助你既会"用",也懂"理"。如需深入,可继续阅读仓库内的 docs/faq.rst、docs/policy_templates.rst 与 docs/safe_lambda_deployments.rst。
- 后端
- 云原生
- IaC
【免费下载链接】serverless-application-model
The AWS Serverless Application Model (AWS SAM) transform is a AWS CloudFormation macro that transforms SAM templates into CloudFormation templates.
相关推荐
Chalice 的 AWS CloudFormation 部署支持:从 `chalice package` 到 SAM 模板合并与 AWS CLI 部署
Chalice 的 AWS CloudFormation 部署支持:从 chalice package 到 SAM 模板合并与 AWS CLI 部署 本文基于当
后端云原生AWS SAM CLI模板验证:确保CloudFormation模板正确性的终极指南
AWS SAM CLI模板验证:确保CloudFormation模板正确性的终极指南 AWS SAM CLI模板验证是Serverless应用开发中不可或缺的关
开发工具云原生DevOpsAWS Serverless 新手第一课:serverless-application-model 完全指南,从 SAM 模板到 CloudFormation
AWS Serverless 新手第一课:serverless application model 完全指南,从 SAM 模板到 CloudFormation
后端云原生IaC
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考