Lambda 函数与 RDS 的连接超时(*仅限私有隔离子网,无 NAT 网关或 IGW)

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

有谁知道是否可以在同一 VPC 中通过隔离子网(其中两个资源位于同一子网中)将 Lambda 连接到 RDS?我已经摆弄和搜索了几天了。连GPT也搞不定。这更多的是“它实际上可以这样工作吗”,而不是一种固定的方法。

我试图避免使用 NAT 网关来规避每小时 0.045 美分的成本,而只使用免费的 RDS 实例进行开发。添加具有公共子网的 NAT 网关并具有私有的出口子网是可行的。但我想知道这对于没有 NAT 网关的完全隔离的子网是否可行。

这就是我现在的位置:

  • 与所有子网关联的路由表,并具有目标本地的 VPC CIDR 的目的地
  • 设置 NACL 以允许所有入站和出站流量(也尝试了特定子网 CIDR)。
  • VPC 和子网正确连接到 Lambda。
  • RDS 不公开
  • 相同的 VPC 和安全组以及附加到 RDS 实例的子网组。 (是的,我知道这对于产品来说并不理想。)我尝试让安全组引用本身,并尝试允许所有流量的安全组,甚至让 RDS 通过实际附加安全组的顾问连接到 Lambda。
  • lambda 层不是问题,超时设置也不太短。

这是 VPC 和安全组的 CDK 的样子。您可以看到 create lambda 函数相应地附加了它们。

非常感谢任何帮助。为了让它连接起来,我快把自己逼疯了。

# Create VPC non NAT Gateways & only private isolated subnets
vpc = ec2.Vpc(
    self,
    "VPCNoNat",
    cidr="10.0.0.0/24",
    nat_gateways=0,  # No NAT gateways
    subnet_configuration=[
        ec2.SubnetConfiguration(
            name="PrivateSubnetNoNat",
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
            cidr_mask=26,
        ),
    ],
)

# Create a Security Group for the RDS Cluster and Lambda
security_group = ec2.SecurityGroup(
    self,
    "cdk-securitygroupNoNat",
    vpc=vpc,
    security_group_name="cdk-security-group-no-nat",
)

# Allow traffic on port 5432 from within the VPC for RDS
security_group.add_ingress_rule(ec2.Peer.ipv4(vpc.vpc_cidr_block), ec2.Port.tcp(5432))

# Create a subnet group
subnet_group = rds.SubnetGroup(
    self,
    "cdkSubnetGroupNoNat",
    description="Subnet group for cdk no nat",
    vpc=vpc,
    vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
)

db_instance = rds.DatabaseInstance(
    self,
    "PostgresInstance1NoNat",
    engine=rds.DatabaseInstanceEngine.POSTGRES,
    instance_type=ec2.InstanceType.of(
        ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO
    ),
    credentials=rds.Credentials.from_generated_secret("postgres"),
    vpc=vpc,
    security_groups=[security_group],
    subnet_group=subnet_group,
    publicly_accessible=False,
)


# Create a Lambda function
def create_lambda_function(
    stack,
    lambda_id,
    handler,
    layers,
    vpc,
    security_group,
    role,
    runtime=_lambda.Runtime.PYTHON_3_9,
    timeout=Duration.seconds(15),
    extra_env_vars=None,
):
    # Default environment variables
    default_env_vars = {
        "SECRET_ARN": db_instance.secret.secret_arn,
        "DB_HOST": db_instance.db_instance_endpoint_address,
    }

    # Merge extra environment variables with the default ones
    environment_vars = {**default_env_vars, **(extra_env_vars or {})}

    return _lambda.Function(
        stack,
        lambda_id,
        handler=handler,
        runtime=runtime,
        environment=environment_vars,
        code=_lambda.Code.from_asset(handler),
        role=role,
        layers=layers,
        vpc=vpc,
        security_groups=[security_group],
        vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE_ISOLATED),
        timeout=timeout,
    )
amazon-web-services aws-lambda amazon-rds aws-cdk amazon-vpc
1个回答
0
投票

我强烈建议不要直接与安全组打交道。

来自 SecurityGroup

 上的 CDK 文档:

可以通过 addIngressRule 和 addEgressRule 直接操作安全组,但建议通过 .connections 对象进行更改。如果您以这种方式将两个构造与安全组对等,则将在两者中创建适当的规则。

它会大大简化你的代码:

vpc = ec2.Vpc(
    self,
    "VPCNoNat",
    cidr="10.0.0.0/24",
    nat_gateways=0,  # No NAT gateways
    subnet_configuration=ec2.Vpc.DEFAULT_SUBNETS_NO_NAT,
)

db_instance = rds.DatabaseInstance(
    self,
    "PostgresInstance1NoNat",
    engine=rds.DatabaseInstanceEngine.POSTGRES,
    instance_type=ec2.InstanceType.of(
        ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO
    ),
    credentials=rds.Credentials.from_generated_secret("postgres"),
    vpc=vpc,
    publicly_accessible=False,
)
function = _lambda.Function(
    self,
    "MyFunction",
    handler=handler,
    runtime=runtime,
    environment=environment_vars,
    code=_lambda.Code.from_asset(handler),
    layers=layers,
    vpc=vpc,
)

function.connections.allow_to_default_port(db_instance)

Connections.allow_to_default_port
将负责安全组规则。您不必自己创建安全组或子网组。

也就是说,如果您从函数内进行任何 AWS API 调用,则需要为您在 VPC 中使用的每个服务创建一个 VPC 终端节点。

© www.soinside.com 2019 - 2024. All rights reserved.