【发布时间】:2020-06-16 00:39:13
【问题描述】:
希望你能帮上忙!
目标
我正在尝试在 AWS 上配置以下场景:
- 在 AWC CLI 中:调用 CloudFormation 模板以创建新堆栈。
- 在模板中:调用Lambda 函数。
- 在 Lambda 函数中:通过 pg 模块连接到 RDS 中的 Aurora PostgreSQL 实例。
- 在 PostgresSQL 中:创建一个新数据库。
短篇小说
一旦我将我的 Lambda 函数添加到默认 VPC,它就无法再将响应发送回 CloudFormation 并且堆栈卡在 CREATE_IN_PROGRESS 中。当我从 Lambda 函数的配置中删除 VPC 时,它可以工作。但是后来我不能再连接到像 RDS 数据库实例这样的另一个组件了。如何处理?
长篇大论
为了让它工作,我的第一步是手动连接到 PostgreSQL 并创建一个新数据库:
- 将默认安全组配置为允许所有入站和所有出站流量。不用担心,仅用于测试。我稍后会更改它。
- 将安全组添加到 RDS 实例以接受来自同一 VPC 中其他组件的流量。第 3 步所必需的。
- 创建了Cloud9 环境以访问 VPC 中的终端。连接到 PostgreSQL 数据库并创建数据库即可!
现在我的目标是通过 Lambda 函数创建一个新数据库:
- 手动创建了一个新的 Lambda 函数,包括一个具有基本 Lambda 授权的新角色。还向角色添加了
AdministratorAccess。不用担心,再次仅用于测试。 Lambda 函数在 Node.js 12.x 上运行,超时时间为 15 秒。 - 将我的 Lambda 脚本和 pg 模块打包到一个 zip 文件中并上传。脚本如下所示:
const { Client } = require('pg');
exports.handler = async (event, context) => {
var databaseName = event.DatabaseName;
var dbSuperUser = event.DBSuperUser;
var dbSuperPassword = event.DBSuperPassword;
const dbClient = new Client({
host: "<Database Instance Endpoint>",
port: 5432,
database: "postgres",
user: dbSuperUser,
password: dbSuperPassword
});
await dbClient.connect();
await dbClient.query("CREATE DATABASE " + databaseName);
await dbClient.end();
var response = {status: 'SUCCESS'};
return response;
};
- 通过
aws lambda invoke从 Cloud9 调用 Lambda 脚本会导致超时。这是预期行为,因为 Lambda 函数与 RDS 数据库实例不在同一个 VPC 中。 - 将具有三个默认子网和默认安全组的默认 VPC 添加到 Lambda 函数配置。瞧,数据库被创建了!我们走上了正轨。
现在我尝试调用 Lambda 函数并从基本 CloudFormation 模板创建数据库:
- 创建了包含Custom Ressource的模板:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"DatabaseName": {"Type": "String"}
},
"Resources": {
"SampleInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"InstanceType": "t1.micro",
"ImageId": {"Fn::GetAtt": ["CreateDatabase", "Id"]}
}
},
"CreateDatabase": {
"Type": "Custom::CreateDatabase",
"Properties": {
"ServiceToken": "<Lambda Function ARN>",
"DBSuperUser": "<DBSuperUser>",
"DBSuperPassword": "<DBSuperPassword>",
"DatabaseName": {"Ref": "DatabaseName"}
}
}
}
}
EC2 实例只是一个示例,无论如何都无法创建,因为 ImageId 无效。它只是用来测试我是否从 Lambda 函数中得到响应。
- 更改了 Lambda 函数以从 CloudFormation 接收事件并发回响应。我可以使用 cfc-response 模块,但决定将其代码复制到我的 Lambda 函数中,以查看幕后情况。请点击上面的链接并向下滚动到 Module Source Code 以查看源代码。
我也改变了像这样获取输入参数:
var customerName = event.ResourceProperties.CustomerName;
var dbSuperUser = event.ResourceProperties.DBSuperUser;
var dbSuperPassword = event.ResourceProperties.DBSuperPassword;
然后像这样向 CloudFormation 发送响应:
responseData = {Id: '1234567890'};
send(event, context, SUCCESS, responseData);
通过 AWS CLI 命令
aws cloudformation create-stack运行模板会导致堆栈卡在CREATE_IN_PROGRESS中。但是数据库成功创建了!我从 Lambda 函数中删除 VPC 配置后,问题就消失了。 CloudFormation 成功接收到来自函数的响应并尝试创建 EC2 示例实例。但是现在 Lambda 函数不能再访问 RDS 来创建数据库了。
这会导致以下问题:
- Lambda 函数中的 VPC 配置是否会导致与 CloudFormation 模板的连接出现问题?
- 如果是,我该如何解决?
- 网络配置是否正确?还是我必须更改我的编码?
我检查过的其他事项:
- 我在两次运行(成功和失败响应)中比较了 Lambda 脚本的以下变量和对象:
event、context、responseBody、parsedUrl、options、request。它们是相同的(某些 ID 等除外)。
期待您对此的看法!
干杯
【问题讨论】:
标签: postgresql amazon-web-services aws-lambda amazon-cloudformation amazon-vpc