aws Lambda创建的ENI在删除堆栈时不删除 [英] aws Lambda created ENI not deleting while deletion of stack
问题描述
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屋!