对预签名 S3 URL 的 Lambda HTTP 请求超时

Lambda HTTP request to presigned S3 URL timing out

我有一个自定义 Lambda 资源,它初始化我的数据库,然后应该在完成后调用预签名的 S3 url。它正在正确启动数据库,但在调用 S3 时超时。我的猜测是我在我的 CloudFormation 模板中做错了什么,这是由于我有限的网络知识导致的。将不胜感激任何帮助。提前致谢!

精简 YAML:

AWSTemplateFormatVersion: 2010-09-09
Transform: "AWS::Serverless-2016-10-31"
Resources:
  InternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-InternetGateway
  VPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VPC
  VPCGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  NATGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt ElasticIPAddress.AllocationId
      SubnetId: !Ref PublicSubnet1
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-NATGateway
  ElasticIPAddress:
    Type: AWS::EC2::EIP
    Properties:
      Domain: VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-EIP
  PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Public
  PublicRoute1:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTable
      GatewayId: !Ref InternetGateway
      DestinationCidrBlock: 0.0.0.0/0
    DependsOn:
      - InternetGateway
  PublicSubnet1:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: !Select [0, !GetAZs ]
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-PublicSubnet1
  CreateRDSDatabaseLambdaSG:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupDescription: Allow Lambda to access RDS in same VPC
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-CreateRDSDatabaseLambdaSG
  LambdaRDSCFNInit:
    Type: AWS::Serverless::Function
    DependsOn:
      - InternetGateway
      - VPC
      - VPCGatewayAttachment
      - NATGateway
      - ElasticIPAddress
      - PublicRouteTable
      - PublicRoute1
      - PublicSubnet1
      - CreateRDSDatabaseLambdaSG
    Properties:
      CodeUri: CreateRDSDatabase/
      Description: "Lambda function which will execute when this CFN template is created, updated or deleted"
      Handler: app.createRDSDatabase
      Runtime: nodejs12.x
      Timeout: 300
      VpcConfig:
        SecurityGroupIds:
          - !Ref CreateRDSDatabaseLambdaSG
        SubnetIds:
          - !Ref PublicSubnet1
      Environment:
        Variables:
          RDS_ENDPOINT: !GetAtt RDSCluster.Endpoint.Address
          RDS_DB_NAME: !Ref RDSDBName
          RDS_USERNAME: !Ref RDSUserName
          RDS_PASSWORD: !Ref RDSPassword

  LambdaRDSCFNTrigger:
    Type: Custom::ProvisionRDS
    DependsOn: LambdaRDSCFNInit
    Version: 1.0
    Properties:
      ServiceToken: !GetAtt LambdaRDSCFNInit.Arn

您正在将 lambda 放在 PublicSubnet1 中。因此,尽管有 NAT 或 Internet 网关,您的 lambda 将无法连接到 Internet。您需要将您的函数放在 私有子网 中,并配置您的私有子网以使用 NAT 网关。来自 docs:

To access private resources, connect your function to private subnets. If your function needs internet access, use network address translation (NAT). Connecting a function to a public subnet doesn't give it internet access or a public IP address.

或者,使用 S3 VPC gateway endpoint 并将其与 public 子网的路由表相关联。这样您的函数将使用网关而不是互联网访问 s3。 在这种情况下不需要 NAT 或私有子网