You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Terraform部署对接PostgreSQL的AWS Lambda 如何传递RDS主机名?

解决方案

1. 修正Terraform配置

1.1 修复Secrets Manager配置,写入动态生成的RDS信息

你之前用静态变量存储secrets内容的方式存在问题,RDS实例创建后会输出address、port等动态属性,直接引用这些属性写入Secrets Manager即可,不需要额外定义动态variable:

# 删掉原来的var.pgdb-secrets变量定义,直接在secret版本里引用动态值
resource "aws_secretsmanager_secret_version" "pgdb" {
  secret_id     = aws_secretsmanager_secret.pgdb.id
  secret_string = jsonencode({
    username = var.pgdb-username
    password = random_password.pgdb.result
    host     = aws_db_instance.bl-db.address
    port     = aws_db_instance.bl-db.port
    dbname   = aws_db_instance.bl-db.name
  })
}

1.2 修复RDS资源的配置错误

你原来的RDS用户名引用写法有误,var.pgdb-username是普通字符串变量,没有.result属性:

resource "aws_db_instance" "bl-db" {
  # 其他原有配置保留不变
  username = var.pgdb-username # 去掉末尾的.result
  password = random_password.pgdb.result # 该配置是正确的,random_password的输出属性为result
  # 其他原有配置保留不变
}

1.3 给Lambda角色添加Secrets Manager访问权限

当前的Lambda执行角色只有基础运行权限,没有读取Secrets的权限,需要挂载对应IAM策略:

resource "aws_iam_role_policy_attachment" "lambda_secrets_access" {
  role       = aws_iam_role.lambda-iam.name
  policy_arn = "arn:aws:iam::aws:policy/SecretsManagerReadWrite" 
  # 生产环境建议自定义策略,缩窄权限到仅允许访问该PG密钥,避免权限过大
}

1.4 (可选)通过Lambda环境变量传递非敏感配置

如果你不想把主机地址这类非敏感信息放到Secrets里,也可以直接通过Lambda的环境变量传递,代码中直接读取环境变量即可:

resource "aws_lambda_function" "lambda" {
  # 其他原有配置保留
  environment {
    variables = {
      PG_HOST = aws_db_instance.bl-db.address
      PG_PORT = aws_db_instance.bl-db.port
      PG_DB_NAME = aws_db_instance.bl-db.name
    }
  }
}

2. 修正Lambda Python代码

2.1 修复变量引用和逻辑问题

你原来的代码存在导入别名不一致、host_name未赋值、重复建表报错等问题,修正后代码如下:

#!env/bin/python
import json 
import os 
import random
import psycopg2 as pg
import awswrangler.secretsmanager as awssm 

# 方案1:直接从Secrets读取所有配置
pg_secrets = awssm.get_secret_json("postgres-database")
database_name = pg_secrets.get("dbname")
table_name = "cities"
username = pg_secrets.get("username")
password = pg_secrets.get("password")
port = pg_secrets.get("port")
host_name = pg_secrets.get("host")

# 方案2:如果使用了Lambda环境变量,可按以下方式读取
# database_name = os.environ.get("PG_DB_NAME")
# port = os.environ.get("PG_PORT")
# host_name = os.environ.get("PG_HOST")
# username = awssm.get_secret_json("postgres-database").get("username")
# password = awssm.get_secret_json("postgres-database").get("password")

def lambda_handler(event, context): 
    cxn = pg.connect(
        user=username, 
        password=password, 
        host=host_name, 
        port=port, 
        database=database_name
    )
    # 新增表存在性判断,避免重复建表报错
    with cxn.cursor() as csr:
        csr.execute("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'cities')")
        if not csr.fetchone()[0]:
            query_create_table = "create table cities ( ix serial primary key, names varchar(50) unique not null );"
            csr.execute(query_create_table) 
            query_insert_data = "insert into cities (names) values ('Washington'), ('Philadelphia'), ('New York'), ('Chicago'), ('Los Angeles'), ('Seattle'), ('Portland'), ('Dallas'), ('Miami'), ('Charlotte');"
            csr.execute(query_insert_data)
            cxn.commit()
        # 直接用SQL随机查询,写法更简洁
        csr.execute("SELECT names FROM cities ORDER BY RANDOM() LIMIT 1;")
        random_record = csr.fetchone()[0]
    
    cxn.close()
    return {"statusCode" : 200, 
            "body" : f"a random city is {random_record}" } 

额外优化建议

  • 生产环境不要开启RDS的公网访问,建议将Lambda和RDS都部署在同一个VPC的私有子网中,提升安全性
  • 可以为Lambda添加数据库连接池组件,避免每次冷启动都新建连接消耗RDS资源

内容的提问来源于stack exchange,提问作者Frank Burdell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 10:27:01