在本地堆栈中部署一些基础设施,并在 Docker 容器中运行。特别是,有一个 lambda 函数和一个 RDS,通过
terraform
在下面定义。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
变量尝试了许多不同的组合:
由于“无法将主机名“[上述任何尝试]”翻译为地址:名称或服务未知”,所有这些都导致将数据添加到 RDS 时出现此错误。
不知道我做错了什么。
我敢打赌,RDS 端点必须是部署后 AWS 为实例提供的 FQDN。普通的 RDS 端点最终看起来像这样(您可以在端点下的 rds 控制台中看到这一点):
xxx-xxx-xxx-xxx-xxxx.c5gvcdmsmndh9l.ue-east-1.rds.amazonaws.com