在Go中连接AWS Lambda到RDS

问题描述 投票:0回答:1

我正在尝试使用 API Gateway、Lambda(Go 中)和 RDS 设置一个简单的 API。我已经让 API 网关和 lambda 函数正常通信,但是我不知道如何从 Go 代码内部访问我的数据库。我正在使用 Terraform 创建基础设施。

这是我的 RDS 设置(硬编码的用户名和密码只是为了本文的简单起见):

resource "aws_db_instance" "bl-db" {
  allocated_storage       = 5 # gigabytes
  engine                  = "postgres"
  engine_version          = "16.4"
  identifier              = "main"
  instance_class          = "db.t3.micro"
  username                = "myname"
  password                = "mypassword"
  publicly_accessible     = false
}

这是我的 lambda IAM 角色:

resource "aws_iam_role" "hello" {
  name               = "hello"
  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": {
    "Action": "sts:AssumeRole",
    "Principal": {
      "Service": "lambda.amazonaws.com"
    },
    "Effect": "Allow"
  }
}
POLICY
}

对于我的 lambda 代码,这就是我目前所拥有的,但我假设我还很遥远。

package main

import (
    "fmt"
    "net/http"
    "log"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
)

// The input type and the output type are defined by the API Gateway.
func handleRequest(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    db, err := sqlx.Connect("postgres", "user=postgres dbname=main sslmode=disable password=mypassword host=myhost")
    if err != nil {
        log.Fatalln(err)
    }
  
    defer db.Close()

    // Test the connection to the database
    if err := db.Ping(); err != nil {
        log.Fatal(err)
    } else {
        log.Println("Successfully Connected")
    }

    db.Queryx("some sql query")

    res := events.APIGatewayProxyResponse{
        StatusCode: http.StatusOK,
        Headers:    map[string]string{"Content-Type": "text/plain; charset=utf-8"},
        Body:       fmt.Sprintf("Hello!\n"),
    }
    return res, nil
}

func main() {
    lambda.Start(handleRequest)
}
amazon-web-services go lambda terraform amazon-rds
1个回答
0
投票

由于您的 RDS 实例不可公开访问

(publicly_accessible = false)
,您的 Lambda 函数需要与 RDS 实例位于同一 VPC 中。
Lambda 位于 VPC 内部的 Terraform 配置示例

  resource "aws_lambda_function" "my_lambda" {
  function_name = "my_lambda"
  role          = aws_iam_role.hello.arn
  handler       = "main"
  runtime       = "go1.x"
  filename      = "main.zip"
  
  vpc_config {
    subnet_ids         = ["subnet-12345678"] # replace with your subnet IDs
    security_group_ids = ["sg-12345678"] # replace with your security group IDs
  }
}

更新 Go 代码中的连接字符串。主机应该是 VPC 内 RDS 实例的私有 DNS 名称
db, err := sqlx.Connect("postgres", "host=<RDS-ENDPOINT> port=5432 user=myname dbname=main password=mypassword sslmode=disable")

确保您的 Lambda 的 IAM 角色具有访问 RDS(如果需要)和登录 CloudWatch 所需的权限。这通常意味着附加诸如“AWSLambdaVPCAccessExecutionRole”之类的策略以进行 VPC 访问。
package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
)

func handleRequest(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    db, err := sqlx.Connect("postgres", "host=<RDS-ENDPOINT> port=5432 user=myname dbname=main password=mypassword sslmode=disable")
    if err != nil {
        log.Fatalln("Error connecting to the database:", err)
    }
    defer db.Close()

    if err := db.Ping(); err != nil {
        log.Fatal("Error pinging the database:", err)
    } else {
        log.Println("Successfully Connected to the database")
    }

    rows, err := db.Queryx("SELECT * FROM your_table_name")
    if err != nil {
        log.Fatal("Error executing query:", err)
    }
    defer rows.Close()

    res := events.APIGatewayProxyResponse{
        StatusCode: http.StatusOK,
        Headers:    map[string]string{"Content-Type": "text/plain; charset=utf-8"},
        Body:       fmt.Sprintf("Hello!\n"),
    }
    return res, nil
}

func main() {
    lambda.Start(handleRequest)
}

动态引用 RDS 端点
output "rds_endpoint" {
  value = aws_db_instance.bl-db.endpoint
}
© www.soinside.com 2019 - 2024. All rights reserved.