Lambda 函数无法“翻译”RDS 端点,尽管直接指向它?

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

在本地堆栈中部署一些基础设施,并在 Docker 容器中运行。特别是,有一个 lambda 函数和一个 RDS,通过

terraform
在下面定义。
RDS.tf:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

provider "aws" {
  region                  = "us-east-1"
  access_key              = "test"
  secret_key              = "test"
  skip_credentials_validation = true
  skip_metadata_api_check = true
  skip_requesting_account_id = true
  endpoints {
    rds = "http://localhost:4566"  # LocalStack RDS endpoint
  }
}
resource "aws_db_instance" "main_RDS" {
  identifier        = "main-rds"
  allocated_storage = 20
  storage_type      = "gp2"
  engine            = "postgres"
  engine_version    = "14.1"  # Replace with the latest version supported by LocalStack
  instance_class    = "db.t3.micro"  # Adjust if needed
  name              = "veni_vidi_db"
  username          = "admin"
  password          = "admin123"
  skip_final_snapshot = true
}

output "db_instance_endpoint" {
    value = aws_db_instance.main_RDS.endpoint
}

请注意,其中的

terraform output
会生成“localhost.localstack.cloud:4510”,并且 localstack 浏览器 UI 类似地定义了此端点。 1. 为什么它不依赖于 terraform 中定义的端口 4566? 2. 如果我将 terraform 定义为
rds = "localhost.localstack.cloud:4510"
terraform apply
,则创建将无限地挂在“aws_db_instance.main_RDS:刷新状态... [id=main-rds]”上。

Lambda.tf:

provider "aws" {
  region                  = "us-east-1"
  access_key              = "test"
  secret_key              = "test"
  skip_credentials_validation = true
  skip_requesting_account_id = true

  endpoints {
    rds         = "http://localhost:4566"  # LocalStack RDS endpoint
    lambda      = "http://localhost:4566"
    iam         = "http://localhost:4566"
  }
}

resource "aws_iam_role" "lambda_execution_role" {
  name = "lambda_execution_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = "sts:AssumeRole",
        Effect = "Allow",
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      }
    ]
  })
}

resource "aws_iam_role_policy" "lambda_rds_access" {
  name   = "lambda_rds_access"
  role   = aws_iam_role.lambda_execution_role.id

  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = [
          "rds:*",
          "logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ],
        Effect   = "Allow",
        Resource = "*"
      },
      {
        Action   = "lambda:InvokeFunction",
        Effect   = "Allow",
        Resource = aws_lambda_function.add_user_post.arn
      }
    ]
  })
}

resource "aws_lambda_function" "add_user_post" {
  function_name = "AddUserPost"
  handler       = "addUserPostFunction.lambda_handler"
  runtime       = "python3.9"
  filename      = data.archive_file.lambda_function_add_user_post.output_path
  role          = aws_iam_role.lambda_execution_role.arn
  source_code_hash = filebase64sha256(data.archive_file.lambda_function_add_user_post.output_path)
  timeout       = 30


  layers = [aws_lambda_layer_version.psycopg2_layer.arn]

  environment {
    variables = {
      DB_ENDPOINT = "http://localhost:4566"  # Replace with your actual RDS endpoint
      DB_USER     = "admin"
      DB_PASSWORD = "admin123"
      DB_NAME     = "veni_vidi_db"
    }
  }
}

resource "aws_lambda_layer_version" "psycopg2_layer" {
  filename = "${path.module}/layer/psycopg2-layer.zip"
  layer_name = "psycopg2-layer"
  compatible_runtimes = ["python3.9"]
}

data "archive_file" "lambda_function_add_user_post" {
  type         = "zip"
  source_dir   = "${path.module}/Source"
  output_path  = "${path.module}/lambda_function_add_user_post.zip"
}

lambda.py 函数:

import os
import psycopg2

def lambda_handler(event, context):
    try:
        # Database connection details
        db_endpoint = os.environ['DB_ENDPOINT']
        db_user = os.environ['DB_USER']
        db_password = os.environ['DB_PASSWORD']
        db_name = os.environ['DB_NAME']

        # Establish a connection to the database
        conn = psycopg2.connect(
            dbname=db_name, user=db_user, password=db_password, host=db_endpoint
        )
        cur = conn.cursor()

        # Sample data to be added to the RDS table
        user_id = 1
        post_id = 1
        content = 'Yay!'

        # Insert data into the table
        cur.execute(
            "INSERT INTO user_posts_table (UserID, PostID, Content) VALUES (%s, %s, %s)",
            (user_id, post_id, content)
        )
        conn.commit()

        # Close the database connection
        cur.close()
        conn.close()

        return {
            'statusCode': 200,
            'body': 'Item added to RDS successfully',
        }
    except Exception as e:
        print('Error adding item to RDS:', e)

        # Ensure the connection is closed in case of error
        if 'conn' in locals() and conn is not None:
            conn.close()

        return {
            'statusCode': 500,
            'body': 'Error adding item to RDS',
        }

两个基础设施组件均已正确部署。但是,运行

awslocal lambda invoke --function-name AddUserPost output.txt
会导致本地堆栈日志中显示“将项目添加到 RDS 时出错:无法将主机名“http://localhost:4566”翻译为地址:名称或服务未知”。

我已经为 RDS.tf 和 lambda.tf 的

endpoints
中的值以及
DB_ENDPOINT
变量尝试了许多不同的组合:

  • “http://localhost:4510”
  • “localhost.localstack.cloud:4510”
  • “localhost.localstack.cloud:4566”
  • “http://localhost.localstack.cloud:4510”
  • “http://localhost.localstack.cloud:4566”

由于“无法将主机名“[上述任何尝试]”翻译为地址:名称或服务未知”,所有这些都导致将数据添加到 RDS 时出现此错误。

不知道我做错了什么。

aws-lambda terraform amazon-rds endpoint localstack
1个回答
0
投票

我敢打赌,RDS 端点必须是部署后 AWS 为实例提供的 FQDN。普通的 RDS 端点最终看起来像这样(您可以在端点下的 rds 控制台中看到这一点):

xxx-xxx-xxx-xxx-xxxx.c5gvcdmsmndh9l.ue-east-1.rds.amazonaws.com
© www.soinside.com 2019 - 2024. All rights reserved.