in pkg/aws/ec2/api/cleanup/eni_cleanup.go [113:205]
func (e *ENICleaner) DeleteLeakedResources() error {
var errors []error
availableENIs := make(map[string]struct{})
vpcrcAvailableCount := 0
vpccniAvailableCount := 0
leakedENICount := 0
defer e.Manager.UpdateCleanupMetrics(&vpcrcAvailableCount, &vpccniAvailableCount, &leakedENICount)
filters := append(CommonNetworkInterfaceFilters, []ec2types.Filter{
{
Name: aws.String("vpc-id"),
Values: []string{e.VpcId},
},
}...)
// only apply extra filters when the controller is enabled which provides cninode resources
var OrFilters []ec2types.Filter
var err error
var networkInterfaces []*ec2types.NetworkInterface
if !e.ControllerDisabled {
// get cleaner specific filters
OrFilters = e.Manager.GetENITagFilters()
for _, OrFilter := range OrFilters {
filterCopy := append([]ec2types.Filter{}, filters...)
filterCopy = append(filterCopy, OrFilter)
describeNetworkInterfaceIp := &ec2.DescribeNetworkInterfacesInput{
Filters: filterCopy,
}
tempNetworkInterfaces, err := e.EC2Wrapper.DescribeNetworkInterfacesPagesWithRetry(describeNetworkInterfaceIp)
if err != nil {
e.Log.Error(err, "failed to describe network interfaces, cleanup will be retried in next cycle")
return err
}
networkInterfaces = append(networkInterfaces, tempNetworkInterfaces...)
}
} else {
describeNetworkInterfaceIp := &ec2.DescribeNetworkInterfacesInput{
Filters: filters,
}
networkInterfaces, err = e.EC2Wrapper.DescribeNetworkInterfacesPagesWithRetry(describeNetworkInterfaceIp)
if err != nil {
e.Log.Error(err, "failed to describe network interfaces, cleanup will be retried in next cycle")
return err
}
}
for _, nwInterface := range networkInterfaces {
if e.Manager.ShouldDeleteENI(nwInterface.NetworkInterfaceId) {
tagMap := utils.GetTagKeyValueMap(nwInterface.TagSet)
if val, ok := tagMap[config.NetworkInterfaceOwnerTagKey]; ok {
// Increment promethues metrics for number of leaked ENIs cleaned up
switch val {
case config.NetworkInterfaceOwnerTagValue:
vpcrcAvailableCount += 1
case config.NetworkInterfaceOwnerVPCCNITagValue:
vpccniAvailableCount += 1
default:
// We should not hit this case as we only filter for relevant tag values, log error and continue if unexpected ENIs found
e.Log.Error(fmt.Errorf("found available ENI not created by VPC-CNI/VPC-RC"), "eniID", *nwInterface.NetworkInterfaceId)
continue
}
}
_, err := e.EC2Wrapper.DeleteNetworkInterface(&ec2.DeleteNetworkInterfaceInput{
NetworkInterfaceId: nwInterface.NetworkInterfaceId,
})
if err != nil {
if !strings.Contains(err.Error(), ec2Errors.NotFoundInterfaceID) { // ignore InvalidNetworkInterfaceID.NotFound error
// append err and continue, we will retry deletion in the next period/reconcile
leakedENICount += 1
errors = append(errors, fmt.Errorf("failed to delete leaked network interface %v:%v", *nwInterface.NetworkInterfaceId, err))
e.Log.Error(err, "failed to delete the leaked network interface",
"id", *nwInterface.NetworkInterfaceId)
}
continue
}
// It is possible for eni attachment to be nil, if it was never attached to instance
instanceID := ""
if nwInterface.Attachment != nil && nwInterface.Attachment.InstanceId != nil {
instanceID = aws.ToString(nwInterface.Attachment.InstanceId)
}
e.Log.Info("deleted leaked ENI successfully", "eni id", *nwInterface.NetworkInterfaceId, "instance id", instanceID)
} else {
// Seeing the ENI for the first time, add it to the new list of available network interfaces
availableENIs[*nwInterface.NetworkInterfaceId] = struct{}{}
e.Log.Info("adding eni to to the map of available ENIs, will be removed if present in "+
"next run too", "id", *nwInterface.NetworkInterfaceId)
}
}
e.Manager.UpdateAvailableENIsIfNeeded(&availableENIs)
return kerrors.NewAggregate(errors)
}