postgresql - 使用 PostgreSQL 对 AWS Lambda 进行地形改造——如何将主机名传递给 lambda?
问题描述
AWS 环境——从 RDS/PostgreSQL 实例中提取并通过 API 网关推送的 Lamdba 函数。
SecretsManager 可以轻松地将用户名和密码等静态数据传递给 Lambda 函数。然而,Terraform 禁止在其variable
资源中使用动态变量。因此,Terraform 无法定义主机并通过 SecretsManager 将主机传递给 Lambda 函数。
我考虑在 Terraform 脚本的末尾将变量导出到环境中。但这不会导出到运行 Lambda 的同一台机器上,对吗?无论如何,SecretsManager 显然是一种被黑的方式。在创建 RDS 实例和 Lambda 函数期间,我发现的所有资源似乎都有一些手册。
提前谢谢你。
地形:
### Variables
variable "pgdb-username" {
default = "frank"
}
resource "random_password" "pgdb" {
length = 16
}
variable "pgdb-secrets" {
default = {
"username" = ""
"password" = ""
}
}
# Secrets
resource "aws_secretsmanager_secret" "pgdb" {
name = "postgres-database"
}
resource "aws_secretsmanager_secret_version" "pgdb" {
secret_id = aws_secretsmanager_secret.pgdb.id
secret_string = jsonencode(var.pgdb-secrets)
}
### General
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "> 3.5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
### Lambda
data "archive_file" "lambda-zip" {
type = "zip"
source_dir = "lambda"
output_path = "lambda.zip"
}
resource "aws_iam_role" "lambda-iam" {
name = "lambda-iam"
assume_role_policy = jsonencode({
"Version" = "2012-10-17"
"Statement" = {
"Action" = "sts:AssumeRole"
"Principal" = {
"Service" = "lambda.amazonaws.com"
}
"Effect" = "Allow"
"Sid" = ""
}
})
}
resource "aws_lambda_function" "lambda" {
filename = "lambda.zip"
function_name = "lambda-function"
role = aws_iam_role.lambda-iam.arn
handler = "lambda.lambda_handler"
source_code_hash = data.archive_file.lambda-zip.output_base64sha256
runtime = "python3.8"
}
### API
resource "aws_apigatewayv2_api" "lambda-api" {
name = "v2-http-api"
protocol_type = "HTTP"
}
resource "aws_apigatewayv2_stage" "lambda-stage" {
api_id = aws_apigatewayv2_api.lambda-api.id
name = "$default"
auto_deploy = true
}
resource "aws_apigatewayv2_integration" "lambda-integration" {
api_id = aws_apigatewayv2_api.lambda-api.id
integration_type = "AWS_PROXY"
integration_method = "POST"
integration_uri = aws_lambda_function.lambda.invoke_arn
passthrough_behavior = "WHEN_NO_MATCH"
}
resource "aws_apigatewayv2_route" "lambda_route" {
api_id = aws_apigatewayv2_api.lambda-api.id
route_key = "GET /{proxy+}"
target = "integrations/${aws_apigatewayv2_integration.lambda-integration.id}"
}
resource "aws_lambda_permission" "api-gw" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda.arn
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.lambda-api.execution_arn}/*/*/*"
}
### RDS
resource "aws_db_instance" "bl-db" {
allocated_storage = 1 # gigabytes
backup_retention_period = 7 # in days
engine = "postgres"
engine_version = "9.5.4"
identifier = "main"
name = "main"
instance_class = "db.r3.large"
multi_az = false
username = var.pgdb-username.result
password = random_password.pgdb.result
port = 5432
publicly_accessible = true
storage_encrypted = true
storage_type = "gp2"
}
Python 中的 Lambda:
#!env/bin/python
import json
import os
import random
import psycopg2 as pg
import awswrangler.secretsmanager as awssm
database_name = "main"
table_name = "cities"
username = sm.get_secret_json( "postgres-database" ).get( "username" )
password = sm.get_secret_json( "postgres-database" ).get( "password" )
port = "5432"
host_name =
def lambda_handler(event, context):
cxn = pg.connect( user=username,
password=password,
host=host_name,
port=port,
database=database_name)
query_create_table = f"create table cities ( ix serial primary key, names varchar(50) unique not null );"
query_insert_data = f"insert into {table_name} (city) values ('Washington'), ('Philadelphia'), ('New York'), ('Chicago'), ('Los Angeles'), ('Seattle'), ('Portland'), ('Dallas'), ('Miami'), ('Charlotte');"
csr = cxn.cursor()
csr.execute( query_create_table )
csr.execute( query_insert_data )
cxn.commit()
len_table = csr.rowcount
random_record = random.randint(1, len_table)
query_random_data = f"select names from cities where ix = {random_record};"
cxn.execute( query_random_data )
random_record = cxn.fetchall()
print( f"{len_table} rows inserted sucessfully" )
return {"statusCode" : 200,
"body" : f"a random city is {random_record}" }
解决方案
您可以通过 terraform 使用 lambda 环境变量将 db 实例地址传递给 lambda 函数。
resource "aws_lambda_function" "test_lambda" {
...
environment {
variables = {
DB_INSTANCE_ADDRESS = aws_db_instance.bl-db.address
}
}
}
然后在您的 lambda 处理程序代码中读取环境变量。
DB_INSTANCE_ADDRESS = os.getenv('DB_INSTANCE_ADDRESS')
推荐阅读
- ignite - 点燃内核状态总是显示停止
- flutter - Flutter sqflite 不适用于真实设备 android
- windows - 环境变量扩展不再适用于 Windows 上的 npm run
- php - PHP8将0与空字符串进行比较,其背后的逻辑是什么
- jenkins - 构建触发器不会保存在 Jenkins 中
- python - 遍历 pandas df 返回所有与正则表达式不匹配的值
- powershell - 如何使用 PowerShell 解析文件夹和文件?
- python - 如何计算已登录的客户端扭曲?
- reactjs - AsyncStorage 不存储数据,随后不检索数据
- javascript - 使用更高分辨率的javascript将画布图表下载为PNG图像