我正在使用 AWS CloudFormation 模板来部署无服务器应用程序,该应用程序需要具有 Internet 访问权限的 Lambda 函数和我需要远程访问以进行管理的 PostgreSQL RDS 实例。在修改我的子网和路由表关联以增强安全性后,我的 Lambda 失去了互联网访问权限,并且我无法远程连接到我的 RDS 实例。我正在寻找有关如何调整 CloudFormation 模板以满足这些要求的指导。
我的要求: AWS Lambda 函数需要访问 Internet 才能发出出站请求。 需要从我的本地计算机访问以进行管理的 PostgreSQL RDS 实例。
下面是我的 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
EnableDnsHostnames: true
MyInternetGateway:
Type: 'AWS::EC2::InternetGateway'
DependsOn: "MyVPC"
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref MyVPC
InternetGatewayId: !Ref MyInternetGateway
MyRouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref MyVPC
MyRoute:
Type: 'AWS::EC2::Route'
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref MyRouteTable
DestinationCidrBlock: '0.0.0.0/0'
GatewayId: !Ref MyInternetGateway
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
MyDBSubnetGroup:
Type: 'AWS::RDS::DBSubnetGroup'
Properties:
SubnetIds:
- !Ref MySubnetA
- !Ref MySubnetB
MySecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
VpcId: !Ref MyVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 5433
ToPort: 5433
CidrIp: 10.0.0.0/16 # VPC internal
- IpProtocol: tcp
FromPort: 5433
ToPort: 5433
CidrIp: 'X.X.X.X/32' # MYLOCALIP
MyDBInstance:
Type: 'AWS::RDS::DBInstance'
Properties:
Engine: postgres
Port: '5433'
DBSubnetGroupName: !Ref MyDBSubnetGroup
VPCSecurityGroups:
- !Ref MySecurityGroup
PubliclyAccessible: true
MyEIP:
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
MyPublicSubnet:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref MyVPC
CidrBlock: '10.0.3.0/24'
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
MyNatGateway:
Type: 'AWS::EC2::NatGateway'
Properties:
AllocationId: !GetAtt MyEIP.AllocationId
SubnetId: !Ref MyPublicSubnet
MyPrivateRouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref MyVPC
PrivateRoute:
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 MyRouteTable
SenderFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
VpcConfig:
SubnetIds:
- !Ref MySubnetA
- !Ref MySubnetB
SecurityGroupIds:
- !Ref MySecurityGroup
问题: 我的 Lambda 具有外部内部访问权限,但我无法从本地主机访问我的 RDS。
我尝试切换协会:
SubnetARouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref MySubnetA
RouteTableId: !Ref MyRouteTable
SubnetBRouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref MySubnetB
RouteTableId: !Ref MyRouteTable
PublicSubnetRouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref MyPublicSubnet
RouteTableId: !Ref MyPrivateRouteTable
结果是我可以远程访问我的 RDS,但随后我在 Lambda 中失去了互联网访问权限。
我也尝试询问ChatGPT,但他没有成功帮助! :D
我的问题: 如何调整我的 CloudFormation 模板以确保我的 Lambda 函数可以访问互联网,同时还保持对我的 RDS 实例的远程访问?
任何有关如何构建我的 VPC、子网、路由表或任何其他配置以实现这些目标的建议,我们将不胜感激。
您需要创建公共子网(具有到 Internet 网关的路由的子网)来放置 RDS 实例。RDS 实例必须位于公共子网中,以便您可以直接从本地主机访问它。 NAT 网关还需要位于公共子网中。
Lambda 函数必须位于私有子网(具有到 NAT 网关的路由的子网)中。
因此,您需要至少两个公有子网(用于 RDS)和至少两个私有子网(用于 Lambda 函数)。
这样配置后,Lambda函数将能够访问VPC中的所有资源(例如RDS实例)以及Internet上的资源(通过NAT网关)。