带有 RDS Postgresql 的 AWS Lambda - 未知问题
AWS Lambda with RDS Postgresql - Unknown Issue
我已经为这个问题苦苦思索了 3 天,无法弄清楚问题出在哪里。我在 Lambda 函数中将所有登录凭据设置为环境变量。我的 RDS 实例对公众开放,安全组也打开传入和传出端口。
我的 PostgresQL 代码有很多变体,最新的一个来自这个
我当前的 lambda 代码
const pg = require('pg')
const pool = new pg.Pool()
async function query (q) {
const client = await pool.connect()
let res
try {
await client.query('BEGIN')
try {
res = await client.query(q)
await client.query('COMMIT')
} catch (err) {
await client.query('ROLLBACK')
throw err
}
} finally {
client.release()
}
return res
}
exports.handler = async (event, context, callback) => {
try {
const { rows } = await query("select 'thaison' as ")
console.log(JSON.stringify(rows[0]))
var response = {
"statusCode": 200,
"headers": {
"Content-Type" : "application/json"
},
"body": JSON.stringify(rows),
"isBase64Encoded": false
};
callback(null, response);
} catch (err) {
console.log('Database ' + err)
callback(null, 'Database ' + err);
}
};
我可以在pool.connect()
前后成功地做一个console.log
。我也可以在 client.query()
之前 console.log
但不能在之后。问题是在 client.query()
之后,没有任何反应。我检查了 Cloudwatch 日志和指标,日志上没有任何内容,也没有任何错误报告。代码必须在某处失败,但我无法弄清楚在哪里。响应为空,查询后我无法记录任何内容,甚至在 catch(err)
块中也没有。我做的最后一件事是将 PG 端点更改为甚至不存在的东西,但我仍然没有收到任何错误。这东西就默默的失败了。
我做错了什么?
由于您使用的是 Publicly Available = Yes
,数据库的 DNS 名称将解析为 public IP 地址。这意味着 Lambda 函数 需要 Internet 访问权限 。
这可以通过 NOT 将 Lambda 函数附加到 VPC 或通过将 Lambda 函数附加到 私有子网 来完成然后在 public 子网中使用 NAT 网关 来提供对 Internet 的访问。安全组应允许来自 0.0.0.0/0
的访问(这对安全性非常不利)。
配置此类系统的更多 'secure' 方法是:
- 使用
Publicly Available = No
,这只会将 RDS 数据库的 DNS 名称解析为 私有 IP 地址
- 将 Lambda 函数附加到与 RDS 数据库位于同一 VPC 中的子网
- 将安全组附加到允许默认“允许所有”出站访问的 Lambda 函数 (
Lambda-SG
)
- 将安全组附加到 RDS 数据库 (
RDS-SG
),允许使用 Source = Lambda-SG
在端口 5432 (PostgreSQL) 上进行入站访问
也就是说,RDS-SG
在其入站规则中特别引用了 Lambda-SG
。这将允许 Lambda 函数访问 RDS 数据库。
但是,请注意,RDS 数据库只能从 VPC 内部访问。您将无法从您自己的 Internet 计算机连接到它(因为它现在更安全)。如果需要,您可以使用带有端口转发的 跳转框 进行连接。
我已经为这个问题苦苦思索了 3 天,无法弄清楚问题出在哪里。我在 Lambda 函数中将所有登录凭据设置为环境变量。我的 RDS 实例对公众开放,安全组也打开传入和传出端口。
我的 PostgresQL 代码有很多变体,最新的一个来自这个
我当前的 lambda 代码
const pg = require('pg')
const pool = new pg.Pool()
async function query (q) {
const client = await pool.connect()
let res
try {
await client.query('BEGIN')
try {
res = await client.query(q)
await client.query('COMMIT')
} catch (err) {
await client.query('ROLLBACK')
throw err
}
} finally {
client.release()
}
return res
}
exports.handler = async (event, context, callback) => {
try {
const { rows } = await query("select 'thaison' as ")
console.log(JSON.stringify(rows[0]))
var response = {
"statusCode": 200,
"headers": {
"Content-Type" : "application/json"
},
"body": JSON.stringify(rows),
"isBase64Encoded": false
};
callback(null, response);
} catch (err) {
console.log('Database ' + err)
callback(null, 'Database ' + err);
}
};
我可以在pool.connect()
前后成功地做一个console.log
。我也可以在 client.query()
之前 console.log
但不能在之后。问题是在 client.query()
之后,没有任何反应。我检查了 Cloudwatch 日志和指标,日志上没有任何内容,也没有任何错误报告。代码必须在某处失败,但我无法弄清楚在哪里。响应为空,查询后我无法记录任何内容,甚至在 catch(err)
块中也没有。我做的最后一件事是将 PG 端点更改为甚至不存在的东西,但我仍然没有收到任何错误。这东西就默默的失败了。
我做错了什么?
由于您使用的是 Publicly Available = Yes
,数据库的 DNS 名称将解析为 public IP 地址。这意味着 Lambda 函数 需要 Internet 访问权限 。
这可以通过 NOT 将 Lambda 函数附加到 VPC 或通过将 Lambda 函数附加到 私有子网 来完成然后在 public 子网中使用 NAT 网关 来提供对 Internet 的访问。安全组应允许来自 0.0.0.0/0
的访问(这对安全性非常不利)。
配置此类系统的更多 'secure' 方法是:
- 使用
Publicly Available = No
,这只会将 RDS 数据库的 DNS 名称解析为 私有 IP 地址 - 将 Lambda 函数附加到与 RDS 数据库位于同一 VPC 中的子网
- 将安全组附加到允许默认“允许所有”出站访问的 Lambda 函数 (
Lambda-SG
) - 将安全组附加到 RDS 数据库 (
RDS-SG
),允许使用Source = Lambda-SG
在端口 5432 (PostgreSQL) 上进行入站访问
也就是说,RDS-SG
在其入站规则中特别引用了 Lambda-SG
。这将允许 Lambda 函数访问 RDS 数据库。
但是,请注意,RDS 数据库只能从 VPC 内部访问。您将无法从您自己的 Internet 计算机连接到它(因为它现在更安全)。如果需要,您可以使用带有端口转发的 跳转框 进行连接。