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

同VPC内AWS Lambda连接Postgres RDS的SSL连接问题排查

问题背景

我在AWS搭建了以下架构:API Gateway -> Lambda -> RDS(Postgres),Lambda与RDS实例处于同一VPC,安全组已配置为允许所有入站和出站流量。

初始错误表现

通过API Gateway触发Lambda时,CloudWatch日志显示:

INIT_REPORT Init Duration: 3002.41 ms   Phase: invoke   Status: error   Error Type: Runtime.Unknown
INIT_REPORT Init Duration: 3002.41 ms Phase: invoke Status: error Error Type: Runtime.Unknown

初始Postgres连接字符串配置:

host=%s port=%s user=%s dbname=%s sslmode=verify-full sslrootcert=us-east-2-bundle.pem password=%s

我下载了对应区域的证书,RDS实例使用rds-ca-rsa2048-g1作为CA。

修改连接字符串后的错误

将连接字符串改为sslmode=disable后,日志错误变为:

failed to connect to `host=myHOST user=postgres database=api`: server error (FATAL: no pg_hba.conf entry for host "172.2.0.12", user "postgres", database "api", no encryption (SQLSTATE 28000))

这个错误说明问题不在IAM/安全组/权限上,必须配置SSL验证。

代码细节

建立数据库连接的Go代码(使用gORM):

func OpenDB(DbUser, DbPassword, DbPort, DbHost, DbName string) (*gorm.DB, error) {
    DBURL := fmt.Sprintf("host=%s port=%s user=%s dbname=%s sslmode=verify-full sslrootcert=us-east-2-bundle.pem password=%s", DbHost, DbPort, DbUser, DbName, DbPassword)

    return gorm.Open(postgres.Open(DBURL), &gorm.Config{})
}

后续更新

Runtime.Unknown实际是由初始化超时导致:

INIT_REPORT Init Duration: 10007.03 ms Phase: init Status: timeout

已尝试将Lambda超时设置为10秒、30秒,也换用了全局证书包,但问题依旧。代码连接本地Postgres正常,但因RDS所在VPC无互联网访问,无法本地测试RDS连接。


解决方案

1. 确认证书文件路径正确

Lambda运行时找不到指定的证书文件是高频触发问题的原因:

  • 打包Lambda代码时,务必将证书文件放在代码根目录,或在连接字符串中指定正确的相对/绝对路径
  • 检查部署包结构,确保证书文件和Go二进制文件在同一层级

2. 调整SSL模式适配RDS配置

针对rds-ca-rsa2048-g1 CA,推荐调整SSL模式:

  • 用sslmode=verify-ca替代verify-full:verify-full要求主机名与证书CN严格匹配,RDS端点证书可能不满足该条件,容易导致连接超时;verify-ca仅验证CA合法性,更适配RDS场景
  • 调整后的连接字符串示例:
    host=%s port=%s user=%s dbname=%s sslmode=verify-ca sslrootcert=us-east-2-bundle.pem password=%s
    

3. 优化Lambda初始化性能

初始化超时10秒说明连接建立耗时过长,可通过以下方式优化:

  • 将数据库连接初始化放在Lambda全局作用域(而非处理函数内部),利用Lambda执行环境复用特性,避免每次调用都重新建立连接
  • 修改后的代码示例:
    import (
        "log"
        "os"
        "context"
        "github.com/aws/aws-lambda-go/events"
        "gorm.io/driver/postgres"
        "gorm.io/gorm"
    )
    
    var db *gorm.DB
    
    func init() {
        var err error
        DBURL := fmt.Sprintf("host=%s port=%s user=%s dbname=%s sslmode=verify-ca sslrootcert=us-east-2-bundle.pem password=%s", 
            os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_USER"), os.Getenv("DB_NAME"), os.Getenv("DB_PASSWORD"))
        db, err = gorm.Open(postgres.Open(DBURL), &gorm.Config{})
        if err != nil {
            log.Fatalf("Failed to initialize DB: %v", err)
        }
    }
    
    func Handler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
        // 使用全局db对象操作数据库
        return events.APIGatewayProxyResponse{StatusCode: 200}, nil
    }
    

4. 检查RDS参数组配置

确认RDS参数组的SSL相关设置:

  • 查看rds.force_ssl参数是否设为1(强制SSL连接,这也是之前禁用SSL后报错的原因)
  • 若需临时允许非SSL连接(仅调试用),可修改参数组中的pg_hba.conf规则,但生产环境不建议这么做

5. 验证VPC内部网络连通性

即使安全组配置了全量流量,仍需确认:

  • Lambda所在子网与RDS子网的路由表配置正确(同一VPC内默认路由即可,但要排除自定义路由的阻断情况)
  • 在Lambda中添加调试代码,执行nslookup <RDS端点>,确认RDS私有DNS能被正常解析

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:23:21