AWS 自定义资源无法识别成功或失败信号

问题描述 投票:0回答:1

我正在尝试在堆栈中设置自定义资源,以在堆栈创建期间实现一些数据库初始化步骤。然而,虽然自定义资源代码似乎运行良好,但 CloudFormation 无法识别自定义资源发回的 SUCCESS 信号,并且它会陷入

CREATE_IN_PROGRESS
状态长达 1 小时的超时。然后,当然,当我尝试手动删除堆栈时,它又卡在了一个小时
DELETE_IN_PROGRESS
等待删除信号。

我已经对我的环境进行了最小程度的重现,并表现出相同的行为。这是我的 lambda 代码:

const { put } = require('axios');

const SUCCESS = 'SUCCESS';
const FAILED = 'FAILED';

// CloudFormation Custom Resource Response Handler
let Responder = (event, context) => async (status, data={}) => {
    let body = {
        Status: status,
        Reason: data.Reason ?? data.Error ?? "",
        PhysicalResourceId: `${event.LogicalResourceId}-${event.RequestId}`,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        Data: (({Reason, Error, ...etc}) => etc)(data)
    };
    console.log("Custom Resource body:", body);
    let request = put(event.ResponseURL, body);
    console.log("Response sent");
    context.done();
    console.log("Context discontinued");
    let response = await request;
    console.log("Custom Resource response:", response);
}

exports.lambdaHandler = async (event, context) => {
    console.info("event:", event);

    let responder = Responder(event, context);
    try {
        if (event.RequestType === "Delete") {
            console.log("Custom resource deleting!");
            // delete resource
            await responder(SUCCESS);
        } else {
            console.log("Custom resource creating!");
            // create resource
            await responder(SUCCESS);
        }
    } catch (err) {
        console.error(err);
        await responder(FAILED, err);
    }
};

这是我的 SAM 模板:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:

  RDSVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.10.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref RDSVPC
      CidrBlock: 10.10.1.0/24
      AvailabilityZone: !Select 
        - 0
        - !GetAZs 
          Ref: 'AWS::Region'
  
  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref RDSVPC
      CidrBlock: 10.10.2.0/24
      AvailabilityZone: !Select 
        - 1
        - !GetAZs 
          Ref: 'AWS::Region'

  InternetGateway:
    Type: AWS::EC2::InternetGateway
  
  InternetGatewayAttachment:
    DependsOn: InternetGateway
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref RDSVPC
      InternetGatewayId: !Ref InternetGateway

  RouteTable:
    DependsOn: InternetGatewayAttachment
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref RDSVPC
  
  RouteTableAttachement:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref RouteTable

  RouteTableAttachement2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref RouteTable

  EIP:
    DependsOn: InternetGatewayAttachment
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  NAT:
    DependsOn: RDSVPC
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt EIP.AllocationId
      SubnetId: !Ref InternetSubnet
      ConnectivityType: public

  NATRoute:
    DependsOn: 
      - NAT
      - RouteTable
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NAT

  InternetSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref RDSVPC
      CidrBlock: 10.10.3.0/24
      AvailabilityZone: !Select 
        - 2
        - !GetAZs 
          Ref: 'AWS::Region'
  
  InternetRouteTable:
    DependsOn: InternetGatewayAttachment
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref RDSVPC
  
  InternetRouteTableAttachement:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref InternetSubnet
      RouteTableId: !Ref InternetRouteTable

  InternetRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref InternetRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  LambdaSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Lambda SG
      VpcId: !Ref RDSVPC
      SecurityGroupEgress: 
        - CidrIp: "0.0.0.0/0"
          IpProtocol: "-1"

  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      Timeout: 3
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs14.x
      Architectures:
        - x86_64
      VpcConfig:
        SecurityGroupIds:
          - !Ref LambdaSecurityGroup
        SubnetIds:
          - !Ref PublicSubnet1
          - !Ref PublicSubnet2

  HelloWorldCustomResource:
    DependsOn: 
      - HelloWorldFunction
      - InternetRoute
      - NATRoute
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt HelloWorldFunction.Arn

CloudWatch Log 输出示例(匿名):

START RequestId: b7f45954-f5e9-4dd3-8404-c2117c8e8718 Version: $LATEST
2021-12-22T18:22:52.726Z    b7f45954-f5e9-4dd3-8404-c2117c8e8718    INFO    event: {
  RequestType: 'Create',
  ServiceToken: 'arn:aws:lambda:us-east-2:<userid>:function:custom-resource-test-2-HelloWorldFunction-DZYI8GLlnI0j',
  ResponseURL: 'https://cloudformation-custom-resource-response-useast2.s3.us-east-2.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-2%3A<userid>%3Astack/custom-resource-test-2/1820acc0-6354-11ec-b638-061066120c32%7CHelloWorldCustomResource%7C1311ae33-9ac4-461c-a118-433bc29e1671?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211222T182252Z&X-Amz-SignedHeaders=host&X-Amz-Expires=7200&X-Amz-Credential=AKIAVRFIPK6PKAFALJ4V%2F20211222%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=0190bb01d874ce33cf7d8559c060df5ffb171053b95279e9318cb556ff0f91e0',
  StackId: 'arn:aws:cloudformation:us-east-2:<userid>:stack/custom-resource-test-2/1820acc0-6354-11ec-b638-061066120c32',
  RequestId: '1311ae33-9ac4-461c-a118-433bc29e1671',
  LogicalResourceId: 'HelloWorldCustomResource',
  ResourceType: 'AWS::CloudFormation::CustomResource',
  ResourceProperties: {
    ServiceToken: 'arn:aws:lambda:us-east-2:<userid>:function:custom-resource-test-2-HelloWorldFunction-DZYI8GLlnI0j'
  }
}
2021-12-22T18:22:52.726Z    b7f45954-f5e9-4dd3-8404-c2117c8e8718    INFO    Custom resource creating!
2021-12-22T18:22:52.726Z    b7f45954-f5e9-4dd3-8404-c2117c8e8718    INFO    Custom Resource body: {
  Status: 'SUCCESS',
  Reason: '',
  PhysicalResourceId: 'HelloWorldCustomResource-1311ae33-9ac4-461c-a118-433bc29e1671',
  StackId: 'arn:aws:cloudformation:us-east-2:<userid>:stack/custom-resource-test-2/1820acc0-6354-11ec-b638-061066120c32',
  RequestId: '1311ae33-9ac4-461c-a118-433bc29e1671',
  LogicalResourceId: 'HelloWorldCustomResource',
  Data: {}
}
2021-12-22T18:22:52.996Z    b7f45954-f5e9-4dd3-8404-c2117c8e8718    INFO    Response sent
2021-12-22T18:22:53.016Z    b7f45954-f5e9-4dd3-8404-c2117c8e8718    INFO    Context discontinued
END RequestId: b7f45954-f5e9-4dd3-8404-c2117c8e8718
REPORT RequestId: b7f45954-f5e9-4dd3-8404-c2117c8e8718  Duration: 314.99 ms Billed Duration: 315 ms Memory Size: 128 MB Max Memory Used: 63 MB  Init Duration: 195.58 ms    

如您所见,除了自定义资源之外,所有资源都已成功创建: cloudformation stack output

更新:向 lambda 安全组添加完整的入口允许规则...

  LambdaSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Lambda SG
      VpcId: !Ref RDSVPC
      SecurityGroupEgress: 
        - CidrIp: "0.0.0.0/0"
          IpProtocol: "-1"
      SecurityGroupIngress:
        - CidrIp: "0.0.0.0/0"
          IpProtocol: "-1"

...put请求成功,自定义资源创建成功。然而,这并不是一个真正的解决方案。我不能只是为了解决这个问题而简单地允许我的 lambda 完全进入互联网。我可以设置更具体的入口规则以允许通信正常工作吗?

javascript amazon-web-services aws-cloudformation aws-sam aws-cloudformation-custom-resource
1个回答
0
投票

我认为

event.ResponseURL
是一个对象,它包含一些项目。您可以使用
event.ResponseURL
中提交的 href。或者您可以使用帖子名和路径字段等

当然你可以查看

cfn-response
源代码并在此基础上实现你自己的源代码。

© www.soinside.com 2019 - 2024. All rights reserved.