一个service可以认为是一个工程,service通过其根目录下的serverless.yml文件定义了service提供的lambda函数,触发lambda函数的events,以及lambda函数用到的各种resources.
可以使用serverless create命令使用模版创建一个service,详情请参考: AWS Serverless CLI命令参考2--Create&Install.
每个serverless.yml文件都会被翻译成一个AWS CloudFormation模版,在部署时会使用该模版创建一个CloudFormation stack.
可以使用serverless deploy命令对service进行部署,详情请参考: AWS Serverless CLI命令参考3--package&deploy
可以使用serverless remove命令对service进行部署,详情请参考: AWS Serverless CLI命令参考5--rollback&remove
通过在serverless.yml文件中指定frameworkVersion属性,可以对部署该service所需的serverless的版本进行限制.通过限制版本可以避免由serverless版本升级导致的错误.
如果制定了该属性, 在运行serverless命令时会检查serverless的版本与文件中定义的版本是否一致.
# serverless.yml
frameworkVersion: "=1.0.3"
service: users
provider:
name: aws
runtime: java8
memorySize: 512
#Version Range
# serverless.yml
frameworkVersion: ">=1.0.0 <2.0.0"
service: users
provider:
name: aws
runtime: java8
memorySize: 512
插件就是用于创建新的或者扩展原有的serverless framework命令的自定义的js代码.serverless framework本身由一组核心插件构成.
插件类型包括external plugins 和 core plugins.
external plugins需要为每个service单独安装,在service的根目录下执行如下命令即可:
npm install --save custom-serverless-plugin
在serverless.yml中的plugins属性中指定service需要使用的插件
plugins:
- plugin1
- plugin2
可以通过serverless.yml的custom属性配置plugin
plugins:
- custom-serverless-plugin
custom:
customkey: customvalue
用于指定服务提供商,以及lambda函数或其他资源用到的公共配置等,如果lambda函数没有对这些配置进行覆盖,则会使用provider中定义的配置.
custom:
configFile: ${file(config.yml)}
provider:
name: aws
region: ${self:custom.configFile.region}
stage: ${self:custom.configFile.stage}
variant: ${self:custom.configFile.variant}
runtime: java8
timeout: 30 # The default is 6 seconds. Note: API Gateway current maximum is 30 seconds
memorySize: 1024 # Overwrite the default memory size. Default is 1024. Increase by 64.
deploymentBucket: ${self:custom.configFile.deploymentBucket}
environment: ${file(config.yml)}
stackName: ${self:provider.stage}-${self:provider.variant}-${self:service}
versionFunctions: ${self:custom.configFile.versionFunctions}
aws的所有lambda函数都定义在functions属性下,provider中可以对所有的function进行权限全局配置,比如runtime, timeout,每个function可以对provider的配置进行重写.
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs12.x
memorySize: 512 # optional, in MB, default is 1024
timeout: 10 # optional, in seconds, default is 6
versionFunctions: false # optional, default is true
tracing:
lambda: true # optional, enables tracing for all functions (can be true (true equals 'Active') 'Active' or 'PassThrough')
functions:
hello:
handler: handler.hello # required, handler set in AWS Lambda
name: ${opt:stage, self:provider.stage, 'dev'}-lambdaName # optional, Deployed Lambda name
description: Description of what the lambda function does # optional, Description to publish to AWS
runtime: python2.7 # optional overwrite, default is provider runtime
memorySize: 512 # optional, in MB, default is 1024
timeout: 10 # optional, in seconds, default is 6
provisionedConcurrency: 3 # optional, Count of provisioned lambda instances
reservedConcurrency: 5 # optional, reserved concurrency limit for this function. By default, AWS uses account concurrency limit
tracing: PassThrough # optional, overwrite, can be 'Active' or 'PassThrough'
functions属性下可以定义多个function
service: myService
provider:
name: aws
runtime: nodejs12.x
functions:
functionOne:
handler: handler.functionOne
description: optional description for your Lambda
functionTwo:
handler: handler.functionTwo
functionThree:
handler: handler.functionThree
function 可以通过单独的ymal文件进行定义,并在serverless.yml文件中引入
# serverless.yml
---
functions:
- ${file(../foo-functions.yml)}
- ${file(../bar-functions.yml)}
# foo-functions.yml
getFoo:
handler: handler.foo
deleteFoo:
handler: handler.foo
lambda函数与其他aws资源进行交互时,需要具有访问被访问资源的权限,可以通过provider.iamRoleStatements
属性设置lambda函数的权限,也可以通过provider.role或者在定义function时指定role来配置函数权限.
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs12.x
iamRoleStatements: # permissions for all of your functions can be set here
- Effect: Allow
Action: # Gives permission to DynamoDB tables in a specific region
- dynamodb:DescribeTable
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: 'arn:aws:dynamodb:us-east-1:*:*'
- Effect: 'Allow'
Action:
- 's3:ListBucket'
# You can put CloudFormation syntax in here. No one will judge you.
# Remember, this all gets translated to CloudFormation.
Resource: { 'Fn::Join': ['', ['arn:aws:s3:::', { 'Ref': 'ServerlessDeploymentBucket' }]] }
- Effect: 'Allow'
Action:
- 's3:PutObject'
Resource:
Fn::Join:
- ''
- - 'arn:aws:s3:::'
- 'Ref': 'ServerlessDeploymentBucket'
- '/*'
functions:
functionOne:
handler: handler.functionOne
memorySize: 512
# serverless.yml
service: new-service
provider:
name: aws
role: arn:aws:iam::YourAccountNumber:role/IamRole1
functions:
# use role
functionOne:
handler: handler.functionOne
functionTwo:
handler: handler.functionTwo
role: arn:aws:iam::YourAccountNumber:role/IamRole2
可以通过在 lambda函数的配置中添加vpc属性配置来对特定的lambda函数进行vpc配置,也可以在provider中添加添加vpc属性配置来对所有的lambda函数进行vpc配置。两个都定义时,lambda函数的配置优先级高。
vpc配置必须包含 securityGroupIds
和subnetIds
属性。
# serverless.yml
service: service-name
provider:
name: aws
vpc:
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
functions:
hello: # this function will overwrite the service level vpc config above
handler: handler.hello
vpc:
securityGroupIds:
- securityGroupId1
- securityGroupId2
subnetIds:
- subnetId1
- subnetId2
users: # this function will inherit the service level vpc config above
handler: handler.users
使用vpc配置时必须保证lambda函数的执行权限包含 Elastic Network Interfaces (ENI)的创建,描述和删除权限。
参考:配置 Lambda 函数以访问 VPC 中的资源
默认配置下,当lambda函数在vpc内运行时,它会失去对Internet的访问权限,因此无法使用一些AWS资源。
为了使lambda函数能够访问S3和DynamoDB,需要创建一个VPC end point,参考 VPC Endpoint for Amazon S3。
为了使lambda函数能够Kinesisi streams,需要在运行lambda的子网内配置一个NAT Gateway,参考Enable Outgoing Internet Access within VPC。
可以通过在 lambda函数的配置中添加environment属性配置来对特定的lambda函数进行环境变量配置,也可以在provider中添加添加environment属性配置来对所有的lambda函数进行环境变量配置。两个都定义时,lambda函数的配置优先级高。
# serverless.yml
service: service-name
provider:
name: aws
environment:
SYSTEM_NAME: mySystem
TABLE_NAME: tableName1
functions:
hello:
# this function will have SYSTEM_NAME=mySystem and TABLE_NAME=tableName1 from the provider-level environment config above
handler: handler.hello
users:
# this function will have SYSTEM_NAME=mySystem from the provider-level environment config above
# but TABLE_NAME will be tableName2 because this more specific config will override the default above
handler: handler.users
environment:
TABLE_NAME: tableName2
可以使用整个yaml文件作为环境变量的源
# serverless.yml
service: service-name
provider:
name: aws
environment: ${file(environment.yml)}
可以通过在 lambda函数的配置中添加tags属性配置来对特定的lambda函数进行tag配置,也可以在provider中添加添加tags属性配置来对所有的lambda函数进行tag配置。两个都定义时,lambda函数的配置优先级高。
# serverless.yml
service: service-name
provider:
name: aws
tags:
foo: bar
baz: qux
functions:
hello:
# this function will inherit the service level tags config above
handler: handler.hello
users:
# this function will overwrite the foo tag and inherit the baz tag
handler: handler.users
tags:
foo: quux
通过layers属性可以对lambda函数使用的层进行配置,layer的配置请参考: Layers
functions:
hello:
handler: handler.hello
layers:
- arn:aws:lambda:region:XXXXXX:layer:LayerName:Y
默认情况下,lambda函数的log group无需手动创建,serverless framework会为lambda函数自动创建log group。
可以通过disableLogs属性禁用log group。
functions:
hello:
handler: handler.hello
disableLogs: true
默认情况下,serverless framework会为lambda函数的每次部署创建一个版本,可以通过versionFunctions属性进行配置。
provider:
versionFunctions: false
lambda函数执行失败时会进行重试,如果重试依然失败,aws通过死信队列对失败的函数进行保存,以便后续对执行失败的原因进行追踪和分析。
死信队列可是SNS和SQS.
可以通过onError配置属性和SNS的topic实现死信队列。
service: service
provider:
name: aws
runtime: nodejs12.x
functions:
hello:
handler: handler.hello
onError: arn:aws:sns:us-east-1:XXXXXX:test # Ref, Fn::GetAtt and Fn::ImportValue are supported as well
虽然lambda的死信队列支持SNS和SQS,但是目前onError
只支持SNS。
AWS Lambda使用KMS Keys对环境变量进行加密。
awsKmsKeyArn
属性用于指定使用哪个key来进行加密。
service:
name: service-name
awsKmsKeyArn: arn:aws:kms:us-east-1:XXXXXX:key/some-hash
provider:
name: aws
environment:
TABLE_NAME: tableName1
functions:
hello: # this function will OVERWRITE the service level environment config above
handler: handler.hello
awsKmsKeyArn: arn:aws:kms:us-east-1:XXXXXX:key/some-hash
environment:
TABLE_NAME: tableName2
goodbye: # this function will INHERIT the service level environment config above
handler: handler.goodbye
可以通过X-Ray对lambda函数的执行时间进行监控,通过配置tracing属性可以对监控进行开关。
# serverless.yml
service: myService
provider:
name: aws
runtime: nodejs12.x
tracing:
lambda: true # optional, enables tracing for all functions (can be true (true equals 'Active') 'Active' or 'PassThrough')
functions:
hello:
handler: handler.hello # required, handler set in AWS Lambda
name: ${opt:stage, self:provider.stage, 'dev'}-lambdaName # optional, Deployed Lambda name
tracing: PassThrough # optional, overwrite, can be 'Active' or 'PassThrough'
异步调用lambda的时候需要配置异步调用目标,异步调用目标可以是其他lambda函数,EventBridge,SQS或者SNS 。可为处理失败的事件和处理成功的事件配置单独的目标。
参考:配置异步调用目标
functions:
asyncHello:
handler: handler.asyncHello
destinations:
onSuccess: otherFunctionInService
onFailure: arn:aws:sns:us-east-1:xxxx:some-topic-name
events用于触发lambda函数。对于aws而言,events就是用于触发lambda函数的任意事件,比如 S3的文件上传,SNS topic,API Gateway创建的HTTP endpoints。
部署lambda函数时,serverless framework会自动创建event所需的资源,并且配置lambda函数对资源进行监听。
# 'functions' in serverless.yml
functions:
createUser: # Function name
handler: handler.users # Reference to file handler.js & exported function 'users'
events: # All events associated with this function
- http:
path: users/create
method: post
- http:
path: users/update
method: put
- http:
path: users/delete
method: delete
- http: #support path variable
path: users/{id}
method: get
用于对aws lambda layer进行配置。
layers属性中最多可以添加5个layer。
# serverless.yml
service: myService
provider:
name: aws
layers:
hello:
path: layer-dir # required, path to layer contents on disk
name: ${opt:stage, self:provider.stage, 'dev'}-layerName # optional, Deployed Lambda layer name
description: Description of what the lambda layer does # optional, Description to publish to AWS
compatibleRuntimes: # optional, a list of runtimes this layer is compatible with
- python3.8
licenseInfo: GPLv3 # optional, a string specifying license information
# allowedAccounts: # optional, a list of AWS account IDs allowed to access this layer.
# - '*'
# note: uncommenting this will give all AWS users access to this layer unconditionally.
retain: false # optional, false by default. If true, layer versions are not deleted as new ones are created
用于指定layer包含的内容所在的位置。
path与package:artifact必须设置一个。
# serverless.yml
service: myService
provider:
name: aws
layers:
layerOne:
package:
artifact: layerSource.zip
可以继承自权限的package属性也可以在layer中对全局的package属性进行覆盖
# serverless.yml
service: myService
provider:
name: aws
package:
exclude:
- layerSourceTarball1.tar.gz
layers:
layerOne:
path: layerOne
layerTwo:
path: layerTwo
package:
exclude:
- layerSourceTarball2.tar.gz
可以通过allowedAccounts对layer的访问权限进行配置。
# serverless.yml
service: myService
provider:
name: aws
layers:
layerOne:
path: layerOne
allowedAccounts:
- 111111111111 # a specific account ID
- 222222222222 # a different specific account ID
layerTwo:
path: layerTwo
allowedAccounts:
- '*' # ALL accounts!
可以通过layer的arn在lambda配置中指定使用哪一个layer,如果layer与lambda函数定义在同一个配置文件中,还可以使用CloudFormation Ref来指定使用哪一个layer。
# serverless.yml
service: myService
provider:
name: aws
layers:
layerOne:
path: layerOne
allowedAccounts:
- 111111111111 # a specific account ID
- 222222222222 # a different specific account ID
layerTwo:
path: layerTwo
allowedAccounts:
- '*' # ALL accounts!
functions:
hello1:
handler: handler.hello1
layers:
- arn:aws:lambda:region:XXXXXX:layer:LayerName:Y
hello2:
handler: handler.hello2
layers:
- { Ref: layerTwo}
使用原生的CloudFormation模板语法来定义resources。resources中可以使用Resources
和Outputs
属性。
normalizedFunctionName即为配置文件中指定的名字经过一下处理得到的字符串:
Underscore
对于如下lambda函数:
# serverless.yml
service: service-name
provider:
name: aws
functions:
hello-test1:
handler: handler.hello1
name: hello1
hello_test2:
handler: handler.hello2
name: hello2
在最终生成的CloudFormation模板中:
(注意资源名称并不是function配置中的name属性,资源名称是可以通过CloudFormation Ref进行引用的)
AWS Resource | Name Template | Example |
---|---|---|
S3::Bucket | S3Bucket{normalizedBucketName} | S3BucketMybucket |
IAM::Role | IamRoleLambdaExecution | IamRoleLambdaExecution |
Lambda::Function | {normalizedFunctionName}LambdaFunction | HelloLambdaFunction |
Lambda::Version | {normalizedFunctionName}LambdaVersion{sha256} | HelloLambdaVersionr3pgoTvv1xT4E4NiCL6JG02fl6vIyi7OS1aW0FwAI |
Logs::LogGroup | {normalizedFunctionName}LogGroup | HelloLogGroup |
Lambda::Permission |
|
|
Events::Rule |
|
|
AWS::Logs::SubscriptionFilter | {normalizedFunctionName}LogsSubscriptionFilterCloudWatchLog{SequentialID} | HelloLogsSubscriptionFilterCloudWatchLog1 |
AWS::IoT::TopicRule | {normalizedFunctionName}IotTopicRule{SequentialID} | HelloIotTopicRule1 |
ApiGateway::RestApi | ApiGatewayRestApi | ApiGatewayRestApi |
ApiGateway::Resource | ApiGatewayResource{normalizedPath} | ApiGatewayResourceUsers |
ApiGateway::Method | ApiGatewayMethod{normalizedPath}{normalizedMethod} | ApiGatewayMethodUsersGet |
ApiGateway::Authorizer | {normalizedFunctionName}ApiGatewayAuthorizer | HelloApiGatewayAuthorizer |
ApiGateway::Deployment | ApiGatewayDeployment{instanceId} | ApiGatewayDeployment12356789 |
ApiGateway::ApiKey | ApiGatewayApiKey{OptionalNormalizedName}{SequentialID} | ApiGatewayApiKeyFree1 |
ApiGateway::UsagePlan | ApiGatewayUsagePlan{OptionalNormalizedName} | ApiGatewayUsagePlanFree |
ApiGateway::UsagePlanKey | ApiGatewayUsagePlanKey{OptionalNormalizedName}{SequentialID} | ApiGatewayUsagePlanKeyFree1 |
ApiGateway::Stage | ApiGatewayStage | ApiGatewayStage |
SNS::Topic | SNSTopic{normalizedTopicName} | SNSTopicSometopic |
SNS::Subscription | {normalizedFunctionName}SnsSubscription{normalizedTopicName} | HelloSnsSubscriptionSomeTopic |
AWS::Lambda::EventSourceMapping |
|
|
Cognito::UserPool | CognitoUserPool{normalizedPoolId} | CognitoUserPoolPoolId |
可以通过在resources.extensions中定义与自动生成的资源属性名称相同的资源来对自动生成的资源的配置进行重写。
一下配置会将hello-test1生成的log group的保留时间设置为30天。
# serverless.yml
service: service-name
provider:
name: aws
functions:
hello-test1:
handler: handler.hello1
name: hello1
hello_test2:
handler: handler.hello2
name: hello2
resources:
extensions:
HelloDashTest1LogGroup:
Properties:
RetentionInDays: '30'
对不同的配置选项,重写规则不同,有的会覆盖默认配置,有的则与默认配置进行合并,具体参考下表:
Resource attribute | Operation |
---|---|
CreationPolicy |
Set to extension value if present. |
DeletionPolicy |
Set to extension value if present. |
DependsOn |
Merge. The extension value will be added to the resource's DependsOn list. |
Metadata |
Merge. If a metadata key with the same name exists in the resource, the value will be replaced with the extension value. |
Properties |
Merge. If a property with the same name exists in the resource, the value will be replaced with the extension value. |
UpdatePolicy |
Set to extension value if present. |
UpdateReplacePolicy |
Set to extension value if present. |
other | Not supported. An error will be thrown if you try to extend an unsupported attribute. |
在配置文件中使用${}
对变量进行引入。
serverless.yml
provider:
name: aws
stage: ${opt:stage, 'dev'}
environment:
MY_SECRET: ${file(../config.${opt:stage, self:provider.stage, 'dev'}.json):CREDS}
对于上述示例:
sls deploy --stage qa
命令对service进行部署时,opt:stage的value即为qa,因此MY_SECRET最终会被解析为${file(../config.qa.json):CREDS},即使用上层目录的config.qa.json文件中定义的CREDS属性的值作为MY_SECRETsls deploy
命令对service进行部署时,则provider.stage会使用默认值dev,因此MY_SECRET最终会被解析为${file(../config.dev.json):CREDS},即使用上层目录的config.qadev.json文件中定义的CREDS属性的值作为MY_SECRET可以使用${self:someProperty}对当前serverless文件中的属性进行引用
service: new-service
provider: aws
custom:
globalSchedule: rate(10 minutes)
newService: ${self:}
# the following will resolve identically in other serverless.yml files so long as they define
# `custom.newService: ${file(/serverless.yml)}`
exportName: ${self:custom.newService.service}-export
functions:
hello:
handler: handler.hello
events:
- schedule: ${self:custom.globalSchedule}
world:
handler: handler.world
events:
- schedule: ${self:custom.globalSchedule}
resources:
Outputs:
NewServiceExport:
Value: 'A Value To Export'
Export:
Name: ${self:custom.exportName}
Serverless initializes core variables 是Framework 内部使用的变量,这些变量会通过Serverless Variables暴露出来,可以通过 ${sls:}
进行引用。
目前可用的变量为:instanceId
instanceId是 Serverless CLI 运行时随机生成的。
service: new-service
provider: aws
functions:
func1:
name: function-1
handler: handler.func1
environment:
APIG_DEPLOYMENT_ID: ApiGatewayDeployment${sls:instanceId}
可以使用${env:SOME_VAR}
引用环境变量。
${env:}
表示引用所有的环境变量。
service: new-service
provider: aws
functions:
hello:
name: ${env:FUNC_PREFIX}-hello
handler: handler.hello
world:
name: ${env:FUNC_PREFIX}-world
handler: handler.world
可以使用 ${opt:some_option}
引用命令行参数。
${env:}
表示引用所有的命令行参数。
service: new-service
provider: aws
functions:
hello:
name: ${opt:stage}-hello
handler: handler.hello
world:
name: ${opt:stage}-world
handler: handler.world
在上述示例中使用serverless deploy --stage dev
命令对service进行部署时${opt:stage}的值即为dev。
通过${cf:stackName.outputKey
} 来对同一个region中的其他service的CloudFormation stack的导出属性进行引用.
service: new-service
provider:
name: aws
region: ap-northeast-1
functions:
hello:
name: ${cf:another-service-stack.prefix}-hello
handler: handler.hello
service: another-service
custom:
functionPrefix: 'my-prefix-'
provider:
name: aws
runtime: nodejs12.x
region: ap-northeast-1
memorySize: 512
stackName: ${self:service}-stack
functions:
hello:
name: ${self:custom.functionPrefix}hello
handler: handler.hello
resources:
Outputs:
prefix:
Value: ${self:custom.functionPrefix}
Export:
Name: functionPrefix
通过${cf.us-west-2:stackName.outputKey
} 来对其他region中的service的CloudFormation stack的导出属性进行引用.
service: new-service
provider:
name: aws
region: ap-southeast-1
functions:
hello:
name: ${cf.ap-northeast-1:another-service-stack.prefix}-hello
handler: handler.hello
通过CloudFormation stack的导出属性的name对属性值进行引用.
service: new-service
provider:
name: aws
region: ap-southeast-1
stage: develop
environment:
Table:
'Fn::ImportValue': 'DynamoDbTable-${self:provider.stage}'
prefix: 'Fn::ImportValue': 'functionPrefix'
functions
hello:
name: ${self:provider.functionPrefix}-hello
handler: handler.hello
service: another-service
custom:
functionPrefix: 'my-prefix-'
provider:
name: aws
region: ap-southeast-1
stage: develop
resources:
Resources:
DynamoDbTable:
Type: 'AWS::DynamoDB::Table'
......
Outputs:
DynamoDbTable:
Value:
"Ref": DynamoDbTable
Export:
Name: DynamoDbTable-${self:provider.stage}
prefix:
Value: ${self:custom.functionPrefix}
Export:
Name: functionPrefix
可以使用${s3:bucketName/key
}引入s3的值。
service: new-service
provider: aws
functions:
hello:
name: ${s3:myBucket/myKey}-hello
handler: handler.hello
上述示例中, ${s3:myBucket/myKey}的值会被替换为S3 的myBucket
中myKey
的value值。
可以使用${ssm:/path/to/param
}引入SSM 参数库的值。
service: ${ssm:/path/to/service/id}-service
provider:
name: aws
functions:
hello:
name: ${ssm:/path/to/service/myParam}-hello
handler: handler.hello
可以使用${ssm:/path/to/secureparam~true
}引入加密的SSM 参数库的值。
service: new-service
provider: aws
functions:
hello:
name: hello
handler: handler.hello
custom:
supersecret: ${ssm:/path/to/secureparam~true}
上述示例中,supersecret的值为解密后的value。
可以使用${ssm:/path/to/stringlistparam~split
}可以将SSM 参数库的值分割成array之后再引入。
service: new-service
provider: aws
functions:
hello:
name: hello
handler: handler.hello
custom:
myArrayVar: ${ssm:/path/to/stringlistparam~split}
可以使用${ ssm.REGION:/path/to/param
}引入其他region的SSM 参数库的值。
service: ${ssm.us-west-2:/path/to/service/id}-service
provider:
name: aws
functions:
hello:
name: ${ssm.ap-northeast-1:/path/to/service/myParam}-hello
handler: handler.hello
可以使用ssm语法${ ssm:/aws/reference/secretsmanager/secret_ID_in_Secrets_Manager~true
}对WS Secrets Manager中的变量进行引用。
service: new-service
provider: aws
functions:
hello:
name: hello
handler: handler.hello
custom:
supersecret: ${ssm:/aws/reference/secretsmanager/secret_ID_in_Secrets_Manager~true}
上述示例中,supersecret的值为解密后的value。
被引用的变量可以是字符串,也可以是object,因为AWS Secrets Manager不仅可存储string类型的value,也可以存储object的json。
如果被引用的变量是一个object
{
"num": 1,
"str": "secret",
"arr": [true, false]
}
则引入之后会被解析为如下形式:
service: new-service
provider: aws
functions:
hello:
name: hello
handler: handler.hello
custom:
supersecret:
num: 1
str: secret
arr:
- true
- false
可以在当前文件中使用引用其他YAML或者JSON文件中定义的变量:
${file(../myFile.yml):someProperty}
${file(../myFile.json):someProperty}
也可以使用${file(../myCustomFile.yml)}引用整个文件。
引用时需使用被引用文件相对当前文件的路径。
# myCustomFile.yml
globalSchedule: rate(10 minutes)
# serverless.yml
service: new-service
provider: aws
custom: ${file(../myCustomFile.yml)} # You can reference the entire file
functions:
hello:
handler: handler.hello
events:
- schedule: ${file(../myCustomFile.yml):globalSchedule} # Or you can reference a specific property
world:
handler: handler.world
events:
- schedule: ${self:custom.globalSchedule} # This would also work in this case
可以通过引用js文件中的变量来向配置文件中引入动态数据。
${file(../myFile.js):someModule}
对js文件中的命名导出数据进行引入 ${file(../myFile.js)}
对js文件中的未命名导出数据进行引入// scheduleConfig.js
module.exports.rate = 'rate(10 minutes)';
// config.js
module.exports = serverless => {
serverless.cli.consoleLog('You can access Serverless config and methods as well!');
return {
property1: 'some value',
property2: 'some other value',
};
};
# serverless.yml
service: new-service
provider: aws
custom: ${file(../config.js)}
functions:
hello:
handler: handler.hello
events:
- schedule: ${file(../scheduleConfig.js):rate} # Reference a specific module
引用导出的命名数据的特定属性:
# serverless.yml
service: new-service
provider: aws
functions:
scheduledFunction:
handler: handler.scheduledFunction
events:
- schedule: ${file(../myCustomFile.js):schedule.ten}
// myCustomFile.js
module.exports.schedule = () => {
// Code that generates dynamic data
return {
ten: 'rate(10 minutes)',
twenty: 'rate(20 minutes)',
thirty: 'rate(30 minutes)',
};
};
如果需要引入动态/异步数据,可以在js文件中导出Promise 。
# serverless.yml
service: new-service
provider: aws
functions:
scheduledFunction:
handler: handler.scheduledFunction
events:
- schedule: ${file(../myCustomFile.js):promised}
// myCustomFile.js
module.exports.promised = () => {
// Async code that fetches the rate config...
return Promise.resolve('rate(10 minutes)');
};
// myCustomFile.js
const { STS } = require('aws-sdk');
const sts = new STS();
module.exports.getAccountId = async () => {
// Checking AWS user details
const { Account } = await sts.getCallerIdentity().promise();
return Account;
};
# serverless.yml
service: new-service
provider: aws
custom:
accountId: ${file(../myCustomFile.js):getAccountId}
将多个配置文件引入到一个配置文件中,可以将配置文件模块化。
resources:
- Resources:
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
- ${file(resources/first-cf-resources.yml)}
- ${file(resources/second-cf-resources.yml)}
- Outputs:
CognitoUserPoolId:
Value:
Ref: CognitoUserPool
需要注意的是每个cloudformation 配置文件都必须以Resources开头。
Resources:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: some-bucket-name
service: new-service
provider: aws
custom:
myFlexibleArn: ${env:${opt:stage}_arn}
functions:
hello:
handler: handler.hello
Serverless framework 支持多参数引用,对于如下示例,当部署时没有指定任何命令行参数时:
Serverless framework 支持指定任意数量的引用参数,参数的来源和类型也可以任意指定。
service: new-service
provider:
name: aws
stage: dev
custom:
myStage: ${opt:stage, self:provider.stage}
myRegion: ${opt:region, 'us-west-1'}
myCfnRole: ${opt:role, false}
myLambdaMemory: ${opt:memory, 1024}
functions:
hello:
handler: handler.hello
通过设置provider.variableSyntax
property来自定变量引入语法。
以下示例使用 ${{}}代替
${}。
service: new-service
provider:
name: aws
runtime: nodejs12.x
variableSyntax: "\\${{([ ~:a-zA-Z0-9._@\\'\",\\-\\/\\(\\)]+?)}}" # notice the double quotes for yaml to ignore the escape characters!
# variableSyntax: "\\${((?!AWS)[ ~:a-zA-Z0-9._@'\",\\-\\/\\(\\)]+?)}" # Use this for allowing CloudFormation Pseudo-Parameters in your serverless.yml -- e.g. ${AWS::Region}. All other Serverless variables work as usual.
custom:
myStage: ${{opt:stage}}
参考: AWS Pseudo Parameters
目前支持的类型:
123456789012
。aws
。对于位于其他分区中的资源,则分区是 aws-
partitionname
。例如,中国(北京和宁夏)区域中的资源的分区为 aws-cn
,AWS GovCloud (US-West) 区域中的资源的分区为 aws-us-gov
。us-west-2
。aws cloudformation create-stack
命令指定的堆栈的 ID,如 arn:aws:cloudformation:us-west-2:123456789012:stack/teststack/51af3dc0-da77-11e4-872e-1234567db123
。aws cloudformation create-stack
命令指定的堆栈的名称,如 teststack
。Resources:
- 'Fn::Join':
- ':'
- - 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
在使用SSM variables等作为变量引入源时,boolean类型的变量可能会以string的形式进行返回,如果变量引入的地方需要使用boolean类型,则需要进行转化。
provider:
tracing:
apiGateway: ${strToBool(${ssm:API_GW_DEBUG_ENABLED})}
转化规则如下:
${strToBool(true)} => true
${strToBool(false)} => false
${strToBool(0)} => false
${strToBool(1)} => true
${strToBool(2)} => Error
${strToBool(null)} => Error
${strToBool(anything)} => Error
https://www.serverless.com/framework/docs/providers/aws/guide/services/
https://www.serverless.com/framework/docs/providers/aws/guide/functions/
https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/configuration-vpc.html
https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/invocation-async.html#invocation-async-destinations
https://www.serverless.com/framework/docs/providers/aws/guide/events/
https://www.serverless.com/framework/docs/providers/aws/guide/layers/
https://www.serverless.com/framework/docs/providers/aws/guide/resources/
https://www.serverless.com/framework/docs/providers/aws/guide/variables/
https://www.serverless.com/framework/docs/providers/aws/guide/iam/
https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/