CloudFormation创建Lambda函数。执行该功能时,由lambda自动配置ENI。在执行函数后,ENI似乎仍然存在,以加速后续的函数执行。 CloudFormation删除lambda函数。 EN
仍然落后。尝试删除VPC CloudFormation stack
时,由于ENI使用security group and subnet
,堆栈删除失败。
在我的lambda role
delete permission
中。
"效果":"允许","行动":[" ec2:CreateNetworkInterface"," ec2:DeleteNetworkInterface&# 34;," ec2:DescribeNetworkInterfaces" ],"资源":" *"
我正在使用自定义资源从CloudFormation模板运行lambda,因此lambda将被称为堆栈创建和删除。 ENI将用于创建堆栈和删除堆栈。现在如何处理eni删除?
答案 0 :(得分:20)
在VPC中使用Lambda函数时存在一个已知问题,如Configuring a Lambda Function to Access Resources in an Amazon VPC中所述:
Lambda函数执行和ENI删除之间存在延迟。如果您在执行函数后立即删除了该角色,则您有责任删除ENI。
文档没有详细说明此“延迟”的确切时间,但forum post by Richard@AWS表明它可以持续 6小时(!)。 (在我使用AWS CloudTrail的观察中,Lambda执行和ENI删除之间的延迟大约是一小时。)
在AWS进一步解决此问题之前,您可以通过在删除Lambda函数和删除关联的安全组和子网之间分离和删除剩余的ENI来解决此问题。这就是Terraform目前handles在其框架中issue的方式。
您可以通过将VPC / Subnet / SG层和Lambda功能层分离为两个不同的CloudFormation堆栈来手动执行此操作,也可以通过实施自定义资源以使用AWS SDK删除ENI来自动执行此操作。
这是一个完整的工作示例,它创建了一个VPC-Lambda自定义资源,在使用VPCDestroyENI
自定义资源删除时清理其ENI:
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 template。