首页 文章

aws Lambda在删除堆栈时创建了ENI而不删除

提问于
浏览
7

CloudFormation创建Lambda函数 . 执行该功能时,由lambda自动配置ENI . 在执行函数后,ENI似乎仍然存在,以加速后续的函数执行 . CloudFormation删除lambda函数 . EN 仍然落后 . 尝试删除 VPC CloudFormation stack 时,堆栈删除失败,因为ENI正在使用 security group and subnet .

在我的 lambda roledelete permission 在那里 .

“效果”:“允许”,“操作”:[“ec2:CreateNetworkInterface”,“ec2:DeleteNetworkInterface”,“ec2:DescribeNetworkInterfaces”],“资源”:“*”

我正在使用自定义资源从CloudFormation模板运行lambda,因此lambda将被称为堆栈创建和删除 . ENI将用于创建堆栈和删除堆栈 . 现在如何处理eni删除?

1 回答

  • 14

    在VPC中使用Lambda函数时存在一个已知问题,如Configuring a Lambda Function to Access Resources in an Amazon VPC中所述:

    Lambda函数执行和ENI删除之间存在延迟 . 如果您在执行功能后立即删除了该角色,则您有责任删除ENI .

    该文档没有详细说明"delay"的确切时间,但forum post by Richard@AWS建议它可以持续 6 hours (!) . (在我使用AWS CloudTrail的观察中,Lambda执行和ENI删除之间的延迟大约是 one hour . )

    在AWS进一步解决此问题之前,您可以通过在删除Lambda函数和删除关联的安全组和子网之间分离和删除剩余的ENI来解决此问题 . 这就是Terraform目前handles这个issue在它的框架中 .

    您可以通过将VPC / Subnet / SG层和Lambda函数层分离为两个不同的CloudFormation堆栈来手动执行此操作,也可以通过使用AWS SDK实现自定义资源来删除ENI来自动执行此操作 .

    这是一个完整的工作示例,它创建了一个VPC-Lambda自定义资源,在使用 VPCDestroyENI 自定义资源删除时清理其ENI:

    Launch Stack

    Description: Creates a VPC-Lambda Custom Resource, cleaning up ENIs when deleted.
    Parameters:
      VPCId:
        Description: VPC Id
        Type: AWS::EC2::VPC::Id
      SubnetId:
        Description: Private Subnet Id
        Type: AWS::EC2::Subnet::Id
    Resources:
      SecurityGroup:
        Type: AWS::EC2::SecurityGroup
        Properties:
          GroupDescription: Lambda VPC security group
          VpcId: !Ref VPCId
      LambdaExecutionRole:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Version: '2012-10-17'
            Statement:
            - Effect: Allow
              Principal: {Service: [lambda.amazonaws.com]}
              Action: ['sts:AssumeRole']
          Path: "/"
          ManagedPolicyArns:
          - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
          Policies:
          - PolicyName: DetachNetworkInterface
            PolicyDocument:
              Version: 2012-10-17
              Statement:
              - Effect: Allow
                Action: ['ec2:DetachNetworkInterface']
                Resource: '*'
      AppendTest:
        Type: Custom::Split
        DependsOn: VPCDestroyENI
        Properties:
          ServiceToken: !GetAtt AppendItemToListFunction.Arn
          List: [1, 2, 3]
          AppendedItem: 4
      AppendItemToListFunction:
        Type: AWS::Lambda::Function
        Properties:
          Handler: index.handler
          Role: !GetAtt LambdaExecutionRole.Arn
          Code:
            ZipFile: !Sub |
              var response = require('cfn-response');
              exports.handler = function(event, context) {
                 var responseData = {Value: event.ResourceProperties.List};
                 responseData.Value.push(event.ResourceProperties.AppendedItem);
                 response.send(event, context, response.SUCCESS, responseData);
              };
          Timeout: 30
          Runtime: nodejs4.3
          VpcConfig:
            SecurityGroupIds: [!Ref SecurityGroup]
            SubnetIds: [!Ref SubnetId]
      VPCDestroyENIFunction:
        Type: AWS::Lambda::Function
        Properties:
          Handler: index.handler
          Role: !GetAtt LambdaExecutionRole.Arn
          Code:
            ZipFile: !Sub |
              var response = require('cfn-response');
              var AWS = require('aws-sdk');
              exports.handler = function(event, context) {
                console.log("REQUEST RECEIVED:\n", JSON.stringify(event));
                if (event.RequestType != 'Delete') {
                  response.send(event, context, response.SUCCESS, {});
                  return;
                }
                var ec2 = new AWS.EC2();
                var params = {
                  Filters: [
                    {
                      Name: 'group-id',
                      Values: event.ResourceProperties.SecurityGroups
                    },
                    {
                      Name: 'description',
                      Values: ['AWS Lambda VPC ENI: *']
                    }
                  ]
                };
                console.log("Deleting attachments!");
                // Detach all network-interface attachments
                ec2.describeNetworkInterfaces(params).promise().then(function(data) {
                  console.log("Got Interfaces:\n", JSON.stringify(data));
                  return Promise.all(data.NetworkInterfaces.map(function(networkInterface) {
                    var networkInterfaceId = networkInterface.NetworkInterfaceId;
                    var attachmentId = networkInterface.Attachment.AttachmentId;
                    return ec2.detachNetworkInterface({AttachmentId: attachmentId}).promise().then(function(data) {
                      return ec2.waitFor('networkInterfaceAvailable', {NetworkInterfaceIds: [networkInterfaceId]}).promise();
                    }).then(function(data) {
                      console.log("Detached Interface, deleting:\n", networkInterfaceId);
                      return ec2.deleteNetworkInterface({NetworkInterfaceId: networkInterfaceId}).promise();
                    });
                  }));
                }).then(function(data) {
                  console.log("Success!");
                  response.send(event, context, response.SUCCESS, {});
                }).catch(function(err) {
                  console.log("Failure:\n", JSON.stringify(err));
                  response.send(event, context, response.FAILED, {});
                });
              };
          Timeout: 300
          Runtime: nodejs4.3
      VPCDestroyENI:
        Type: Custom::VPCDestroyENI
        Properties:
          ServiceToken: !GetAtt VPCDestroyENIFunction.Arn
          SecurityGroups: [!Ref SecurityGroup]
    Outputs:
      Output:
        Description: output
        Value: !Join [",", !GetAtt AppendTest.Value]
    

    注意:要创建上例中所需的VPC和专用子网,您可以使用AWS Quick Start Amazon VPC Architecture模板 .

相关问题