亚马逊AWS官方博客
用无服务器应用模型部署无服务器应用 (一)无服务器应用模型入门
作者:薛峰
背景介绍
AWS无服务器架构也涉及到多个AWS服务,如AWS Lambda、Amazon API Gateway、Amazon DynamoDB等。如何把这些服务资源方便地管理起来呢?今天我们介绍的AWS 无服务器应用模型(AWS Serverless Application Model,以下简称AWS SAM)就是一种解决方案,它是一个开源的模型,结合AWS自动运维相关的服务如AWS CloudFormation 和AWS CodePipeline,统一管理多种资源,实现我们的无服务器应用的持续集成和部署。
我们从SAM开始,用几个具体例子为大家介绍使用AWS服务实现持续集成的具体方法,帮助大家快速上手,体验其强大和便捷。
SAM 简介
松鼠SAM是AWS Lamba和无服务器应用模型的吉祥物,寓意轻便、灵活、敏捷。它头顶的头盔上是希腊字母 lambda ,代表了AWS无服务器核心服务 Lambda。
SAM是 AWS 2016年11月发布的一个应用架构模型。遵循开源协议,是一个开放的说明文档。通过开源协议方式发布,也体现了AWS推动开源流动的努力。
官方的github地址如下:
https://github.com/awslabs/serverless-application-model
SAM实质上是一个AWS CloudFormation 的扩展,基于AWS CloudFormation 并且为无服务器做了优化,它简化了无服务器资源的管理,增加了无服务器相关的新资源类型。
SAM模板简介
AWS CloudFormation标准模板语法比较复杂,SAM模板提供了一套简化的语法,我们先来看一个简单的例子:
最上面是模板格式的版本号和Transform声明。Transform声明告诉 CloudFormation这是一个 SAM 模板,需要转换成标准模板再执行。它的值取固定值,这里是 AWS::Serverless-2016-10-31,告诉CloudFormation这个模板里的声明都是无服务器应用的描述,以及进行相应的转换。
其余的两段其实都是 Resources 节点的子节点。这2段就是具体资源的声明:
GetHtmlFunction 段,Type: AWS::Serverless::Function,意思是创建一个Lambda函数,它有若干属性,如CodeUri指定函数的代码在S3的URL,Runtime 指定运行时的语言和版本,Policies 指定它的 IAM策略,以赋给它处理下游资源的权限。
Events 段,声明Lambda函数要响应的事件源。这里只有一个事件源,即创建一个 API Gateway 的 API,它有几个 API 相关的属性,比如路径、请求方式。
ListTable 这个资源Type是 AWS::Serverless::SimpleTable ,现在实际上是创建一个DynamoDB 表格。这里没有额外属性,就是以默认的容量规模创建,DynamoDB表容量默认值是每秒5次读写。
SAM 模板功能特性
可以和其它非SAM CloudFormation资源混用在同一个模板里 。SAM模板只增加了3种新资源,Lambda函数、API 和 SimpleTable,我们还可以使用其它标准CloudFormation资源,比如 S3 桶, Kinesis流,Step Function等等。
其它CloudFormation的标准功能SAM模板都支持,比如使用参数、映射和输出等,允许我们在CloudFormation执行时动态传入参数等, CloudFormation的内置函数我们在SAM也都可以使用,如连接字符串、拆分字符串等等。ImportValue也可使用,允许我们从现有架构中直接调取参数值,可以不再使用参数、映射等方式。总之这些标准功能使SAM模板可以和CloudFormation模板一样享受动态化的便利。
SAM 基于 CloudFormation,所以也是支持YAML 和JSON两种格式。
SAM 模板特有资源类型
SAM 模板新增3个特有资源类型,前面的简单例子已经展示了 ,即:AWS::Serverless::Function,AWS::Serverless::Api,AWS::Serverless::SimpleTable。这是当前Transform版本为 AWS::Serverless-2016-10-31所支持的特有资源类型。将来还有可能增加更多资源类型,到时请注意升级换用相应的Transform版本号。
第1个特有资源AWS::Serverless::Function 就是声明Lambda函数,模板中的包括Lambda函数所有的属性,如Handler、运行时、代码地址、描述等等。Events用来声明事件源,同一函数可以支持多个事件源。 Policies 声明IAM策略。Environment 可以声明环境变量,可用于传递给 Lambda函数。另外还有 Tags声明标签,这是 AWS 管理资源的通用功能,比如用于资源分组,账单和成本分解等。
第2个特有资源是 AWS::Serverless::Api,用于声明 API Gateway,关于API的详细定义,在 DefinitionUri 指定的swagger.yml里。其余的属性不多,主要是:StageName 阶段名称、CacheClusterEnabled 是否启用API Gateway的缓存,以及 CacheClusterSize缓存的容量。最后的Variables是传递给API 的参数,比如阶段参数,也是用来灵活部署的。
第3个特有资源是AWS::Serverless::SimpleTable,用于创建 DynamoDb 表。我们需要做的就是声明一下主键、类型,以及配置的容量规模。
AWS::Serverless::Function 事件源
在SAM模板中AWS::Serverless::Function资源下 Events 节点声明事件源。我们知道AWS Lambda 是事件驱动的无服务器函数服务,所以事件源也是部署Lambda函数的重要属性。事件源可以有很多种,大体分为3类:
- 数据状态变化,如S3对象的新增、删除。
- 请求端点,这里主要指的是通过 API Gateway 暴露为对外服务的 HTTP API 接口。
- 资源状态变化,如EC2实例的启动、停止等状态。
具体产生的事件源来自这些服务:S3、SNS、Kinesis、DynamoDB、Schedule、CloudWatchEvent、AlexaSkill。各事件源的各种事件及属性全部支持。具体这里不再赘述,大家可以参考各服务的事件部分相关文档。
Lambda环境变量
Lambda环境变量是可以动态传递给我们的函数的键值对,比如IAM的验证凭据,API的密钥等等。Lambda环境变量是Lambda服务本身的功能,在无服务器应用模型SAM里,我们可以方便地把环境变量管理起来。在SAM模板中以 Parameters 节点来声明环境变量。可以通过标准环境变量API使用,如 Node.js 的process.env 或 Python的os.environ,即Lambda的环境变量会添加到Node.js 的process.env 里,方便咱们开发时使用。下面我们看一个环境变量的具体例子。
使用SAM模板管理Lambda环境变量
请先从以下git库下载源码。
https://github.com/xfsnow/serverless/tree/master/sam/parameters
我们打开 parameters.yaml,看下面这个片段。
这里我们声明了一个Lambda环境变量,变量名是MyEnvironment。它的属性都可以顾名思义,类型是字符串,默认值是testing,可取值是testing、staging和 prod。最后还有一个描述。我们建议给各种变量和资源添加描述,以清楚说明它们具体的使用情况。
然后在声明Lambda函数时在 Variables: 段声明一个环境变量S3_BUCKET,它的值使用CloudFormatioin内置函数!Ref读取SAM模板中的环境变量MyEnvironment。
相应地,在我们的Lambda函数代码中,index.js 中上述这段就可以通过全局变量process.env 获取到S3_BUCKET这个环境变量值了。
用CloudFormation部署SAM模板
我们还使用上述Lambda环境变量这个例子,具体介绍一下CloudFormation部署的方法。
以下操作流程使用 AWS CLI 命令执行。准备环境及了解 AWS CLI 基本功能请参见 https://thinkwithwp.com/cn/cli/ 。
请先从以下git库下载源码。
https://github.com/xfsnow/serverless/tree/master/sam/parameters
把下面命令中的 <bucket-name> 等变量值替换成你的具体的值。
在当前目录下执行以下命令,把文件上传到S3并打包成可用于 CloudFormation 的模板文件。
确认已经生成 packaged_parameters.yaml 文件。
执行以下命令。–parameter-overrides MyEnvironment=prod 表示部署时为 CloudFormation 的模板参数指定值为 prod。
顺利地话,会看到逐渐输出的返回结果。
这时到 CloudFormation 的控制台已经创建出一个 lambdaProxy,整个过程大约持续 1 到 2 分钟。 然后到 API Gateway 控制台,可以看到创建出的 lambdaProxy 的 API,点击其 Stages 下的 Prod 链接,可以看到形如下面的调用 URL: Invoke URL: https://xxxxxxxxx.execute-api.my-region.amazonaws.com/Prod
点击它,打开一个新窗口,显示
{“bucketName”:”prod”}
表示已经部署成功。
再执行一次 aws cloudformation deploy,把 MyEnvironment 参数变成 testing
等待执行完毕后,刷新刚才的调用 URL,可以看到内容已经更新成了
{“bucketName”:”testing”}
这个例子演示了我们在SAM模板中定义的环境变量在具体部署时可以灵活赋成不同的值,然后部署出相应的效果。
小结
今天我们介绍了AWS 无服务器应用模型和SAM模板的基本功能和特性,并带领大家用一个实例体验了通过CloudFormation部署SAM模板。随着无服务器应用开发逐渐复杂,规模越来越大,涉及的服务和资源也会越来越多,SAM确实为我们提供了一种使用AWS服务进行统一管理的方法,希望大家多多体验。
下一篇中,我们将进一步为大家讲解使用AWS CodeBuild 构建 Lambda函数以及使用AWS CodePipeline实现自动化持续集成。
作者介绍:
薛峰,亚马逊AWS解决方案架构师,AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内和全球的应用和推广,在大规模并发应用架构、移动应用以及无服务器架构等方面有丰富的实践经验。在加入AWS之前曾长期从事互联网应用开发,先后在新浪、唯品会等公司担任架构师、技术总监等职位。对跨平台多终端的互联网应用架构和方案有深入的研究。