作者:薛峰
背景介绍
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 模板提供了一套简化的语法,我们先来看一个简单的例子:
Java
最上面是模板格式的版本号和 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,看下面这个片段。
Java
这里我们声明了一个 Lambda 环境变量,变量名是 MyEnvironment。它的属性都可以顾名思义,类型是字符串,默认值是 testing,可取值是 testing、staging 和 prod。最后还有一个描述。我们建议给各种变量和资源添加描述,以清楚说明它们具体的使用情况。
Java
然后在声明 Lambda 函数时在 Variables: 段声明一个环境变量 S3_BUCKET,它的值使用 CloudFormatioin 内置函数!Ref 读取 SAM 模板中的环境变量 MyEnvironment。
Java
相应地,在我们的 Lambda 函数代码中,index.js 中上述这段就可以通过全局变量 process.env 获取到 S3_BUCKET 这个环境变量值了。
用 CloudFormation 部署 SAM 模板
我们还使用上述 Lambda 环境变量这个例子,具体介绍一下 CloudFormation 部署的方法。
以下操作流程使用 AWS CLI 命令执行。准备环境及了解 AWS CLI 基本功能请参见 https://aws.amazon.com/cn/cli/ 。
请先从以下 git 库下载源码。
https://github.com/xfsnow/serverless/tree/master/sam/parameters
把下面命令中的等变量值替换成你的具体的值。
在当前目录下执行以下命令,把文件上传到 S3 并打包成可用于 CloudFormation 的模板文件。
Java
确认已经生成 packaged_parameters.yaml 文件。
执行以下命令。–parameter-overrides MyEnvironment=prod 表示部署时为 CloudFormation 的模板参数指定值为 prod。
Java
顺利地话,会看到逐渐输出的返回结果。
Java
这时到 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
Java
等待执行完毕后,刷新刚才的调用 URL,可以看到内容已经更新成了
{“bucketName”:”testing”}
这个例子演示了我们在 SAM 模板中定义的环境变量在具体部署时可以灵活赋成不同的值,然后部署出相应的效果。
小结
今天我们介绍了 AWS 无服务器应用模型和 SAM 模板的基本功能和特性,并带领大家用一个实例体验了通过 CloudFormation 部署 SAM 模板。随着无服务器应用开发逐渐复杂,规模越来越大,涉及的服务和资源也会越来越多,SAM 确实为我们提供了一种使用 AWS 服务进行统一管理的方法,希望大家多多体验。
下一篇中,我们将进一步为大家讲解使用 AWS CodeBuild 构建 Lambda 函数以及使用 AWS CodePipeline 实现自动化持续集成。
作者介绍:
薛峰,亚马逊 AWS 解决方案架构师,AWS 的云计算方案架构的咨询和设计,同时致力于 AWS 云服务在国内和全球的应用和推广,在大规模并发应用架构、移动应用以及无服务器架构等方面有丰富的实践经验。在加入 AWS 之前曾长期从事互联网应用开发,先后在新浪、唯品会等公司担任架构师、技术总监等职位。对跨平台多终端的互联网应用架构和方案有深入的研究。
本文转载自 AWS 技术博客。
原文链接:
https://amazonaws-china.com/cn/blogs/china/getting-started-with-a-serverless-application-model/
评论