如何将CloudFormation模板与在RDS中的Aurora PostgreSQL实例上创建新数据库的Lambda函



我希望你能帮忙!

目标

我正在尝试在AWS上配置以下szenario:

  1. 在AWC CLI:调用CloudFormation Template以创建新堆栈
  2. 在模板中:调用Lambda函数
  3. 在Lambda函数中:通过pg模块连接RDS中的Aurora PostgreSQL实例
  4. 在PostgresSQL中:创建一个新数据库

短篇小说

一旦我将我的Lambda函数添加到默认的VPC,它就无法再向CloudFormation发送响应,并且堆栈被困在CREATE_IN_PROGRESS中。当我从Lambda功能的配置中删除VPC时,它就起作用了。但是我不能再连接到RDS数据库实例这样的组件了。如何处理?

长话短说

为了让它发挥作用,我的第一步是手动连接到PostgreSQL并创建一个新数据库:

  1. 已配置默认安全组以允许所有入站和所有出站流量。不用担心,只用于测试。我稍后会更改
  2. 在RDS实例中增加了安全组,接受来自同一VPC内其他组件的流量。步骤3所必需的
  3. 创建了一个Cloud9环境,可以访问VPC中的一个终端。连接到PostgreSQL数据库并创建数据库是可行的

现在我的目标是通过Lambda函数创建一个新的数据库:

  1. 手动创建了一个新的Lambda函数,其中包括一个具有基本Lambda授权的新角色。还向角色添加了AdministratorAccess。不用担心,再次只是为了测试。Lambda函数在Node.js 12.x上运行,超时15秒
  2. 将我的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;
};
  1. 通过aws lambda invoke从Cloud9调用Lambda脚本会导致超时。这是预期的行为,因为Lambda函数与RDS数据库实例不在同一VPC中
  2. 在Lambda Function配置中添加了带有三个默认子网和默认安全组的默认VPC。瞧,数据库创建了!我们正在步入正轨

现在我尝试调用Lambda函数,并从基本的CloudFormation模板创建数据库:

  1. 创建了包含自定义资源的模板:
{
"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函数得到响应。

  1. 更改Lambda函数以从CloudFormation接收事件并发回响应。我可以使用cfc响应模块,但决定将它的代码复制到我的Lambda函数中,看看引擎盖下发生了什么。请单击上面的链接并向下滚动到模块源代码以查看源代码

我还更改了获取输入参数的方式,如下所示:

var customerName = event.ResourceProperties.CustomerName;
var dbSuperUser = event.ResourceProperties.DBSuperUser;
var dbSuperPassword = event.ResourceProperties.DBSuperPassword; 

并向CloudFormation发送这样的响应:

responseData = {Id: '1234567890'};
send(event, context, SUCCESS, responseData);
  1. 通过AWS CLI命令aws cloudformation create-stack运行模板会导致堆栈卡在CREATE_IN_PROGRESS中。但是数据库成功创建了!

  2. 当我从Lambda函数中删除VPC配置时,问题就消失了。CloudFormation成功地接收到来自函数的响应,并尝试创建EC2示例实例。但是现在Lambda函数不能再访问RDS来创建数据库了。

这导致了以下问题:

  • Lambda函数中的VPC配置是否会导致与CloudFormation模板的连接出现问题
  • 如果是,我该如何解决
  • 网络配置是否合适?还是我必须更改我的编码

我检查过的其他东西:

  • 我比较了两次运行(成功响应和失败响应)中Lambda脚本的以下变量和对象:eventcontextresponseBodyparsedUrloptionsrequest。它们是相同的(除了某些Id等)

期待您的想法!

干杯

您发布的代码是一个简单的Lambda,不会按照CloudFormation自定义资源的要求报告其状态。所以,第一步是确保您遵循要求。

如果是这样,并且在向S3报告状态时代码被阻止,那么最有可能的原因是您在既没有NAT也没有S3端点的子网中运行。如果您不需要NAT,S3端点是免费的,因此将是最好的解决方案。如果您已经有NAT,请确保Lambda在NAT可用的子网中运行。

最新更新