我正在编写一个 lambda 来更新 RDS 实例。显然,RDS 实例必须在 VPC 中,并且 lambda 必须在 VPC 中,以便它可以访问 RDS。那好吧。所以我将 lambda 配置为在 VPC 中,然后它没有权限在 EC2 上打开网络接口,所以我必须给 lambda 一个具有这些权限的角色。
这是我的 serverless.yml:
service: users-to-rds
plugins:
- serverless-plugin-typescript
provider:
name: aws
runtime: nodejs6.10
stage: dev
timeout: 30
region: ap-southeast-2
iamRoleStatements:
- Effect: Allow
Action:
- "S3:*"
Resource: arn:aws:s3:::*
- Effect: Allow
Action:
- "rds:*"
Resource: "*"
vpc:
securityGroupIds:
- sg-stuff
subnetIds:
- subnet-stuff
- subnet-stuff
- subnet-stuff
functions:
writeToDB:
handler: write-users-to-rds.writeToDB
events:
- sns: userlists
role:
Fn::GetAtt: [ "doStuffFromInsideVPC", "Arn" ]
Resources:
SNSInvokeLambdaPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: "lambda:InvokeFunction"
Principal: "sns.amazonaws.com"
SourceArn:
Ref: UserListNotification
FunctionName:
Fn::GetAtt: [ "UserListToRDS", "Arn" ]
doStuffFromInsideVPC:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: '2017'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: doStuffFromInsideVPCPolicy
PolicyDocument:
Version: '2017'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- 'Fn::Join':
- ':'
- - 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
- Effect: Allow
Action:
- ec2:CreateNetworkInterface
- ec2:DescribeNetworkInterfaces
- ec2:DetachNetworkInterface
- ec2:DeleteNetworkInterface
Resource: "*"
当我进行无服务器部署时,它会生成上传到 AWS 的 zip,然后我被告知:
CloudFormation 模板无效:模板错误:Fn::GetAtt 实例引用未定义资源 doStuffFromInsideVPC
这当然完全是胡说八道。它就在那里。显然,曾经有一个错误,CloudFormation 没有及时创建角色资源,因此更新了无服务器以添加一个 DependsOn,这导致它等待角色存在。看着 .serverless/cloudformation-template-update-stack.json 它似乎在需要它的地方有一个 DependsOn。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "The AWS CloudFormation template for this Serverless application",
"Resources": {
"ServerlessDeploymentBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"AccelerateConfiguration": {
"AccelerationStatus": "Suspended"
}
}
},
"WriteToDBLogGroup": {
"Type": "AWS::Logs::LogGroup",
"Properties": {
"LogGroupName": "/aws/lambda/users-to-rds-dev-writeToDB"
}
},
"WriteToDBLambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Ref": "ServerlessDeploymentBucket"
},
"S3Key": "serverless/users-to-rds/dev/1515307801502-2018-01-07T06:50:01.502Z/users-to-rds.zip"
},
"FunctionName": "users-to-rds-dev-writeToDB",
"Handler": "write-users-to-rds.writeToDB",
"MemorySize": 1024,
"Role": {
"Fn::GetAtt": [
"doStuffFromInsideVPC",
"Arn"
]
},
"Runtime": "nodejs6.10",
"Timeout": 30,
"VpcConfig": {
"SecurityGroupIds": [
"sg-stuff"
],
"SubnetIds": [
"subnet-stuff",
"subnet-stuff",
"subnet-stuff"
]
}
},
"DependsOn": [
"WriteToDBLogGroup",
"doStuffFromInsideVPC"
]
},
"WriteToDBLambdaVersionAOwtYsOPCw4hVAkxPXSzE66bZXvdbu2xQUzGAe58E": {
"Type": "AWS::Lambda::Version",
"DeletionPolicy": "Retain",
"Properties": {
"FunctionName": {
"Ref": "WriteToDBLambdaFunction"
},
"CodeSha256": "7gOzejhkEn37BviNCIVy1lw32IwPs9/oyeaPBQjlqVA="
}
},
"SNSTopicUserlists": {
"Type": "AWS::SNS::Topic",
"Properties": {
"TopicName": "userlists",
"DisplayName": "",
"Subscription": [
{
"Endpoint": {
"Fn::GetAtt": [
"WriteToDBLambdaFunction",
"Arn"
]
},
"Protocol": "lambda"
}
]
}
},
"WriteToDBLambdaPermissionUserlistsSNS": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName": {
"Fn::GetAtt": [
"WriteToDBLambdaFunction",
"Arn"
]
},
"Action": "lambda:InvokeFunction",
"Principal": "sns.amazonaws.com",
"SourceArn": {
"Fn::Join": [
"",
[
"arn:aws:sns:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
"userlists"
]
]
}
}
}
},
"Outputs": {
"ServerlessDeploymentBucketName": {
"Value": {
"Ref": "ServerlessDeploymentBucket"
}
},
"WriteToDBLambdaFunctionQualifiedArn": {
"Description": "Current Lambda function version",
"Value": {
"Ref": "WriteToDBLambdaVersionAOwtYsOPCw4hVAkxPXSzE66bZXvdbu2xQUzGAe58E"
}
}
}
}
任何想法,任何人?谢谢你。