aws Lambda创建的ENI在删除堆栈时不删除 [英] aws Lambda created ENI not deleting while deletion of stack

查看:117
本文介绍了aws Lambda创建的ENI在删除堆栈时不删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CloudFormation创建Lambda函数。执行该功能时,lambda会自动设置一个ENI。 ENI似乎在函数执行后仍然存在,以加快后续函数执行的速度。 CloudFormation删除lambda函数。 EN 仍然落后。尝试删除 VPC CloudFormation堆栈时,由于ENI使用安全组和子网,堆栈删除失败。 / p>在我的 lambda角色中的

那里有删除权限


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


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

解决方案

在VPC中使用Lambda函数时存在一个已知问题,如< a href = http://docs.aws.amazon.com/lambda/latest/dg/vpc.html#vpc-configuring rel = noreferrer>配置Lambda函数以访问Amazon VPC中的资源:


在执行Lambda函数与删除ENI之间存在延迟。如果确实在函数执行后立即删除了角色,则您有责任删除ENI。


文档没有确切说明如何这个延迟将持续很长时间,但Richard @ AWS的

 说明:创建VPC-Lambda自定义资源,删除后清除ENI。 
参数:
VPCId:
描述:VPC ID
类型:AWS :: EC2 :: VPC :: Id
SubnetId:
描述:专用子网Id
类型:AWS :: EC2 ::子网:: Id
资源:
安全组:
类型:AWS :: EC2 :: SecurityGroup
属性:
组描述:Lambda VPC安全组
VpcId:!Ref VPCId
LambdaExecutionRole:
类型:AWS :: IAM :: Role
属性:
AssumeRolePolicyDocument:
版本: 2012-10-17
声明:
-效果:允许
委托人:{服务:[lambda.amazonaws.com]} ​​
操作:[' sts:AssumeRole']
路径: /
ManagedPolicyArns:
-arn:aws:iam :: aws:policy / service-role / AWSLambdaVPCAccessExecutionRole
策略:
-PolicyName:DetachNetworkInterface
PolicyDocument:
版本:2012-10-17
声明:
-效果:允许
操作:['ec2:DetachNetworkInterface']
资源:'*'
AppendTest:
类型:自定义:: Split
依赖于:VPCDestroyENI
属性:
ServiceToken:!GetAtt AppendItemToListFunction.Arn
列表:[1、2、3]
AppendedItem:4
AppendItemToListFunction:
类型:AWS :: Lambda :: Function
属性:
处理程序:index.handler
角色:!GetAtt LambdaExecutionRole.Arn
代码:
ZipFile:!Sub |
var response = require(‘cfn-response’);
exports.handler =函数(事件,上下文){
var responseData = {值:event.ResourceProperties.List};
responseData.Value.push(event.ResourceProperties.AppendedItem);
response.send(事件,上下文,response.SUCCESS,responseData);
};
超时:30
运行时:nodejs4.3
VpcConfig:
SecurityGroupIds:[!Ref SecurityGroup]
SubnetIds:[!Ref SubnetId]
VPCDestroyENI功能:
类型:AWS :: Lambda :: Function
属性:
处理程序:index.handler
角色:!GetAtt LambdaExecutionRole.Arn
代码:
ZipFile :!Sub |
var response = require(‘cfn-response’);
var AWS = require('aws-sdk');
exports.handler =函数(事件,上下文){
console.log( REQUEST RECEIVED:\n,JSON.stringify(event));
if(event.RequestType!='Delete'){
response.send(event,context,response.SUCCESS,{});
的回报;
}
var ec2 = new AWS.EC2();
var params = {
过滤器:[
{
名称:'group-id',
值:event.ResourceProperties.SecurityGroups
},
{
名称:'description',
值:['AWS Lambda VPC ENI:*']
}
]
};
console.log(正在删除附件!);
//分离所有网络接口附件
ec2.describeNetworkInterfaces(params).promise()。then(function(data){
console.log( Got Interfaces:\n ,JSON.stringify(data));
返回Promise.all(data.NetworkInterfaces.map(function(networkInterface){
var networkInterfaceId = networkInterface.NetworkInterfaceId;
var attachmentId = networkInterface.Attachment .AttachmentId;
返回ec2.detachNetworkInterface({AttachmentId:attachmentId})。promise()。then(function(data){
return ec2.waitFor('networkInterfaceAvailable',{NetworkInterfaceIds:[networkInterfaceId]} ).promise();
})。then(function(data){
console.log( Detached Interface,delete:\n,networkInterfaceId);
返回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(事件,上下文,响应。失败,{});
});
};
超时:300
运行时:nodejs4.3
VPCDestroyENI:
类型:自定义:: VPCDestroyENI
属性:
ServiceToken:!GetAtt VPCDestroyENIFunction.Arn
SecurityGroups:[!Ref SecurityGroup]
输出:
输出:
描述:输出
值:!Join [,,!GetAtt AppendTest.Value]

注意:要创建上例中所需的VPC和专用子网,可以使用< a href = https://aws.amazon.com/quickstart/ rel = noreferrer> AWS快速入门 Amazon VPC架构 模板


CloudFormation creates Lambda function. When the function is executed an ENI is provisioned automatically by lambda. The ENI seems to be left in existence after function execution for to speed up subsequent function execution. CloudFormation deletes the lambda function. TheEN remains behind. When attempting to delete the VPC CloudFormation stack, stack deletion fails as the ENI is using a security group and subnet.

in my lambda role the delete permission are there.

"Effect": "Allow", "Action": [ "ec2:CreateNetworkInterface", "ec2:DeleteNetworkInterface", "ec2:DescribeNetworkInterfaces" ], "Resource": "*"

I am using custom resource to run the lambda from CloudFormation template, so lambda will be called both stack creation and deletion. The ENI will be used in creation of stack and deletion of stack. Now how to handle the eni deletion?

解决方案

There is a known issue when using Lambda Functions in a VPC, as documented in Configuring a Lambda Function to Access Resources in an Amazon VPC:

There is a delay between the time your Lambda function executes and ENI deletion. If you do delete the role immediately after function execution, you are responsible for deleting the ENIs.

The documentation doesn't specify exactly how long this "delay" will be, but a forum post by Richard@AWS suggests it can last up to 6 hours(!). (In my observations using AWS CloudTrail, the delay between Lambda execution and ENI deletion was around one hour.)

Until AWS addresses this issue further, you can workaround the issue by detaching and deleting the leftover ENIs in between deleting the Lambda function and deleting the associated Security Group(s) and Subnet(s). This is how Terraform currently handles this issue in its framework.

You can do this manually by separating the VPC/Subnet/SG layer and the Lambda-function layer into two different CloudFormation Stacks, or you can automate it by implementing a Custom Resource to delete the ENIs using the AWS SDK.

Here's a complete working example that creates a VPC-Lambda Custom Resource, cleaning up its ENIs when deleted using the VPCDestroyENI Custom Resource:

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]

Note: To create the VPC and Private Subnet required in the above example, you can use the AWS Quick Start Amazon VPC Architecture template.

这篇关于aws Lambda创建的ENI在删除堆栈时不删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆