如何通过CloudFormation实现VPC内Lambda公网访问与RDS远程管理
解决方案:同时实现Lambda公网访问与PostgreSQL RDS远程管理
核心问题分析
你的两次配置尝试的问题根源:
- 第一次配置:RDS部署在私有子网,虽开启
PubliclyAccessible: true,但私有子网未关联带Internet Gateway(IGW)的路由表,AWS无法为RDS生成可路由的公网DNS解析路径,导致本地无法连接;而Lambda通过NAT网关正常访问公网。 - 第二次配置:把私有子网关联到带IGW的路由表,RDS获得公网访问路径,但公有子网关联到私有路由表,NAT网关失去公网访问能力,导致Lambda无法通过NAT网关出站访问公网。
正确架构设计
要同时满足需求,需遵循VPC子网标准安全架构:
- 私有子网(2个,跨可用区):部署Lambda和RDS,关联私有路由表(默认路由指向NAT网关,实现出站公网访问,无入站公网直接访问)
- 公有子网(至少1个):部署NAT网关,关联公有路由表(默认路由指向IGW,为NAT网关提供公网访问能力)
- RDS通过
PubliclyAccessible: true获得公网DNS端点,配合安全组放行本地IP,实现远程管理;Lambda通过私有子网的NAT网关实现出站公网访问。
CloudFormation模板调整要点
以下是修正后的核心资源配置,关键修改已标注:
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: MyVPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: '10.0.0.0/16' EnableDnsSupport: true # 必须开启,保证VPC内DNS解析 EnableDnsHostnames: true # 必须开启,保证RDS能生成公网DNS MyInternetGateway: Type: 'AWS::EC2::InternetGateway' AttachGateway: Type: 'AWS::EC2::VPCGatewayAttachment' Properties: VpcId: !Ref MyVPC InternetGatewayId: !Ref MyInternetGateway # 公有路由表:关联公有子网,默认路由指向IGW MyPublicRouteTable: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref MyVPC MyPublicRoute: Type: 'AWS::EC2::Route' DependsOn: AttachGateway Properties: RouteTableId: !Ref MyPublicRouteTable DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref MyInternetGateway # 私有子网A/B:Lambda和RDS部署在这里,无公网IP自动分配 MySubnetA: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref MyVPC CidrBlock: '10.0.1.0/24' AvailabilityZone: !Select [0, !GetAZs ''] MapPublicIpOnLaunch: false MySubnetB: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref MyVPC CidrBlock: '10.0.2.0/24' AvailabilityZone: !Select [1, !GetAZs ''] MapPublicIpOnLaunch: false # 公有子网:部署NAT网关,自动分配公网IP MyPublicSubnet: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref MyVPC CidrBlock: '10.0.3.0/24' AvailabilityZone: !Select [0, !GetAZs ''] MapPublicIpOnLaunch: true MyDBSubnetGroup: Type: 'AWS::RDS::DBSubnetGroup' Properties: SubnetIds: - !Ref MySubnetA - !Ref MySubnetB # 安全组:补充出站规则确保Lambda能访问公网 MySecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref MyVPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 5433 ToPort: 5433 CidrIp: 10.0.0.0/16 # 允许VPC内Lambda访问RDS - IpProtocol: tcp FromPort: 5433 ToPort: 5433 CidrIp: 'X.X.X.X/32' # 替换为你的本地公网IP,允许远程管理RDS SecurityGroupEgress: - IpProtocol: '-1' # 允许所有出站流量(Lambda公网访问需求) CidrIp: '0.0.0.0/0' MyDBInstance: Type: 'AWS::RDS::DBInstance' Properties: Engine: postgres Port: '5433' DBSubnetGroupName: !Ref MyDBSubnetGroup VPCSecurityGroups: - !Ref MySecurityGroup PubliclyAccessible: true # 必须开启,生成公网DNS端点 # 需补充:DBInstanceClass、MasterUsername、MasterUserPassword等必填配置 MyEIP: Type: 'AWS::EC2::EIP' Properties: Domain: vpc MyNatGateway: Type: 'AWS::EC2::NatGateway' Properties: AllocationId: !GetAtt MyEIP.AllocationId SubnetId: !Ref MyPublicSubnet # 私有路由表:关联私有子网,默认路由指向NAT网关 MyPrivateRouteTable: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref MyVPC MyPrivateRoute: Type: 'AWS::EC2::Route' DependsOn: MyNatGateway Properties: RouteTableId: !Ref MyPrivateRouteTable DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref MyNatGateway # 子网与路由表正确绑定 SubnetARouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref MySubnetA RouteTableId: !Ref MyPrivateRouteTable SubnetBRouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref MySubnetB RouteTableId: !Ref MyPrivateRouteTable PublicSubnetRouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref MyPublicSubnet RouteTableId: !Ref MyPublicRouteTable SenderFunction: Type: AWS::Serverless::Function Properties: PackageType: Image VpcConfig: SubnetIds: - !Ref MySubnetA - !Ref MySubnetB SecurityGroupIds: - !Ref MySecurityGroup # 需补充:Timeout、MemorySize等配置
关键调整说明
- 路由表命名规范:将原有
MyRouteTable改为MyPublicRouteTable,明确区分公有/私有路由表,避免混淆 - 安全组出站规则:添加全量出站规则,确保Lambda能发起公网请求
- 子网路由绑定:严格遵循:
- 私有子网(A/B)绑定到私有路由表(走NAT网关出公网)
- 公有子网绑定到公有路由表(走IGW出公网,为NAT网关提供公网能力)
- RDS配置确认:保留
PubliclyAccessible: true,同时VPC开启DNS支持,确保RDS的公网DNS能被正确解析
验证步骤
- Lambda公网访问验证:在Lambda代码中添加访问公网API的逻辑(比如调用
https://api.ipify.org获取公网IP),执行测试并确认返回结果正常 - RDS远程访问验证:在本地机器使用
psql命令连接RDS的公网端点:
输入密码后确认能正常连接并执行SQL命令psql -h <RDS公网端点> -p 5433 -U <数据库用户名> -d <数据库名>
内容的提问来源于stack exchange,提问作者Ilan Chemla
相关产品推荐
相关产品推荐

