无服务器应用模型入门

阅读数:155 2019 年 11 月 11 日 08:00

无服务器应用模型入门

作者:薛峰

背景介绍

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

复制代码
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
GetHtmlFunction:
Type:
AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/todo_list.zip
Handler:
index.gethtml
Runtime:
nodejs4.3
Policies:
AmazonDynamoDBReadOnlyAccess
Events:
GetHtml:
Type: Api
Properties:
Path:
/{proxy+}
Method: ANY
ListTable:
Type:
AWS::Serverless::SimpleTable

最上面是模板格式的版本号和 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

复制代码
Parameters:
MyEnvironment:
Type: String
Default: testing
AllowedValues:
- testing
- staging
- prod
Description: Environment of this stack of resources

这里我们声明了一个 Lambda 环境变量,变量名是 MyEnvironment。它的属性都可以顾名思义,类型是字符串,默认值是 testing,可取值是 testing、staging 和 prod。最后还有一个描述。我们建议给各种变量和资源添加描述,以清楚说明它们具体的使用情况。

Java

复制代码
ApiHelloFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs6.10
Environment:
Variables:
S3_BUCKET: !Ref MyEnvironment

然后在声明 Lambda 函数时在 Variables: 段声明一个环境变量 S3_BUCKET,它的值使用 CloudFormatioin 内置函数!Ref 读取 SAM 模板中的环境变量 MyEnvironment。

Java

复制代码
var bucketName = process.env.S3_BUCKET;

相应地,在我们的 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

复制代码
aws cloudformation package \
--template-file parameters.yaml \
--s3-bucket <bucket-name> \
--output-template-file packaged_parameters.yaml

确认已经生成 packaged_parameters.yaml 文件。

执行以下命令。–parameter-overrides MyEnvironment=prod 表示部署时为 CloudFormation 的模板参数指定值为 prod。

Java

复制代码
aws cloudformation deploy \
--template-file output_parameters.yaml \
--stack-name parameters \
--capabilities CAPABILITY_IAM \
--parameter-overrides MyEnvironment=prod

顺利地话,会看到逐渐输出的返回结果。

Java

复制代码
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - lambdaProxy

这时到 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

复制代码
aws cloudformation deploy \
--template-file output_parameters.yaml \
--stack-name parameters \
--capabilities CAPABILITY_IAM \
--parameter-overrides MyEnvironment=testing

等待执行完毕后,刷新刚才的调用 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/

欲了解 AWS 的更多信息,请访问【AWS 技术专区】

评论

发布