一直在尝试让启用 HTTP 的 Lambda 连接到 RDS 数据库,获取结果并返回给调用者。我遇到了各种超时问题,这让我抓狂不已。我从未真正处理过基础设施方面的问题,所以我所说的一些内容可能没有切中要害。
当我尝试在没有任何 VPC 的情况下创建 Lambda 和 Postgres 数据库时,Lambda 无法连接到 Postgres - 那里超时了。
当我尝试创建一个基本 VPC 并将 Lambda 和数据库放入其中时,Lambda 连接并获取行,但 Lambda 本身无法退出 VPC 并超时。
我尝试通过 CloudFormation 执行此操作,这样我就不必太担心回溯我的步骤。到目前为止,我有这个。它应该会创建
- 一个 VPC
- 我所在地区的三个子网
- 我的数据库的子网
- 我的功能的安全组
- 我的数据库的安全组
我认为我需要以某种方式将这些功能的群组公开,但我不知道该怎么做。有人能给我指点迷津吗?
ServerlessVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: "10.0.0.0/16"
ServerlessSubnetA:
DependsOn: ServerlessVPC
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: ServerlessVPC
AvailabilityZone: ${self:provider.region}a
CidrBlock: "10.0.0.0/24"
ServerlessSubnetB:
DependsOn: ServerlessVPC
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: ServerlessVPC
AvailabilityZone: ${self:provider.region}b
CidrBlock: "10.0.1.0/24"
ServerlessSubnetC:
DependsOn: ServerlessVPC
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: ServerlessVPC
AvailabilityZone: ${self:provider.region}c
CidrBlock: "10.0.2.0/24"
ServerlessSecurityGroup:
DependsOn: ServerlessVPC
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: SecurityGroup for Serverless Functions
VpcId:
Ref: ServerlessVPC
ServerlessStorageSecurityGroup:
DependsOn: ServerlessVPC
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Ingress for RDS Instance
VpcId:
Ref: ServerlessVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '5432'
ToPort: '5432'
SourceSecurityGroupId:
Ref: ServerlessSecurityGroup
- IpProtocol: tcp
FromPort: '11211'
ToPort: '11211'
SourceSecurityGroupId:
Ref: ServerlessSecurityGroup
SecurityGroupEgress:
ServerlessRDSSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: "RDS Subnet Group"
SubnetIds:
- Ref: ServerlessSubnetA
- Ref: ServerlessSubnetB
- Ref: ServerlessSubnetC
ServerlessRDSCluster:
DependsOn: ServerlessStorageSecurityGroup
Type: "AWS::RDS::DBInstance"
Properties:
DBName: ${self:custom.database_name}
AllocatedStorage: 10
DBInstanceClass: "db.t2.micro"
Engine: "postgres"
EngineVersion: "9.6.2"
MasterUsername: ${self:custom.env.DATABASE_USER}
MasterUserPassword: ${self:custom.env.DATABASE_PASSWORD}
VPCSecurityGroups:
- "Fn::GetAtt": ServerlessStorageSecurityGroup.GroupId
DBSubnetGroupName:
Ref: ServerlessRDSSubnetGroup
DeletionPolicy: "Snapshot"
答案1
为了使您的 Lambda 函数能够 (a) 访问您的 RDS 实例,以及 (b) 访问外部世界,您需要将您的 Lambda 函数放在您的 VPC 中,并向您的 VPC 添加 NAT 以供外部世界访问。
请执行下列操作:
- 将您的 Lambda 函数放入私人的您的 VPC 中的子网。
- 在民众子网。
- 确保您的私有子网的路由表允许访问 RDS 实例。
- 确保您的私有子网的路由表将出站流量引导至 NAT。
- 如果 Lambda 函数支持安全组,请确保您的 RDS 实例的安全组允许访问您的 Lambda 函数的安全组。如果 Lambda 函数不支持安全组,请确保您的 RDS 实例的安全组允许从您的私有子网或 VPC 的 CIDR 块进行访问。
答案2
在您的 cloudformation 模板中,我没有看到任何公共子网,也没有看到 Internet 或 NAT 网关。我不使用 CloudFormation 或 Lambda,因此它们中可能存在一些神奇之处,使其变得不必要,但对于 VPC 而言,如果您希望私有子网中的某些东西能够与外界通信,则需要一个 NAT 网关(最好每个 AZ 一个)、一个 NAT 网关所在的公共子网、一个 NAT 网关用于通信的 Internet 网关,以及通过 NAT 网关在您的私有子网中建立默认路由。
如果您查看帐户中的默认 VPC,并追踪其附加的所有位,您将看到需要设置的结构类型。