Lambda 无法访问 RDS,尽管它们位于同一 VPC 中

Lambda can not access RDS though those are in the same VPC

我用下面的 CloudFormation 创建了 VPCRDS

Resources:
  TestVpc:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: "10.0.0.0/16"
      EnableDnsSupport: true
      EnableDnsHostnames: true
  TestSubnetA:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: "10.0.0.0/20"
      VpcId: !Ref TestVpc
  TestSubnetB:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1d"
      CidrBlock: "10.0.16.0/20"
      VpcId: !Ref TestVpc
  TestSubnetC:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: "10.0.32.0/20"
      VpcId: !Ref TestVpc
  TestSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "Test security group with cloduformation"
      SecurityGroupIngress:
        - CidrIp: "10.0.0.0/16"
          IpProtocol: "tcp"
          FromPort: 0
          ToPort: 65535
      SecurityGroupEgress:
        - CidrIp: "0.0.0.0/0"
          FromPort: 0
          ToPort: 65535
          IpProtocol: "tcp"
      VpcId: !Ref TestVpc

  TestSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupDescription: "TestSubnetGroupDesc"
      SubnetIds:
        - !Ref TestSubnetA
        - !Ref TestSubnetB
        - !Ref TestSubnetC

  TestRDS:
    Type: "AWS::RDS::DBInstance"
    Properties:
      DBInstanceClass: "db.t2.micro"
      DBInstanceIdentifier: "rekog-moderation"
      DBName: "rekog"

      Engine: "postgres"
      EngineVersion: "10.4"

      MasterUsername: "rekog"
      MasterUserPassword: "passwd"
      AllocatedStorage: "20"

      DBSubnetGroupName: !Ref TestSubnetGroup
      VPCSecurityGroups:
        - !Ref TestSecurityGroup

RDS的结果


Lambda 设置


Lambda 尝试使用域名 rekog-moderation.cokqwd6ixsnc.ap-northeast-1.rds.amazonaws.com 访问时,在连接到 RDS 时出现 returns 超时错误。

我错过了什么?

您需要在入口规则中添加安全组自引用,以允许安全组中的所有成员相互通信。类似于:

"TestSecurityGroupIngress": {
  "Type": "AWS::EC2::SecurityGroupIngress",
  "Properties": {
    "GroupId": { "Ref": "TestSecurityGroup" },
    "IpProtocol": "tcp",
    "FromPort": "0",
    "ToPort": "65535",
    "SourceSecurityGroupId": { "Ref": "TestSecurityGroup" }
  }
}

您可以在 AWS forum

上找到有关 CF 中自引用安全组的更多信息

除了@caldazar 的回答:

我在使用 mysql npm 包时遇到了类似的问题。在调试过程中,我试图查看主机名解析到的 IP 地址:

const { lookup: lc } = require('dns');
const { promisify } = require('util');

const lookup = promisify(lc);
const { address } = await lookup('<my-hostname.com>');

然后我检查了 IP 地址在为 RDS 实例和子网指定的范围内,并且它与可用区匹配。

问题是 mysql 可能试图从 public DNS 解析主机名。因此,我没有传递主机名,而是将已解析的 IP 地址传递给 mysql 的初始化并且它起作用了。