@@ -15,8 +15,6 @@ package crds
15
15
16
16
import (
17
17
"context"
18
- "fmt"
19
- "strings"
20
18
"time"
21
19
22
20
"github.com/aws/amazon-vpc-resource-controller-k8s/apis/vpcresources/v1alpha1"
@@ -27,8 +25,8 @@ import (
27
25
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/utils"
28
26
"github.com/go-logr/logr"
29
27
"github.com/prometheus/client_golang/prometheus"
28
+ "golang.org/x/sync/semaphore"
30
29
v1 "k8s.io/api/core/v1"
31
- "k8s.io/apimachinery/pkg/api/errors"
32
30
apierrors "k8s.io/apimachinery/pkg/api/errors"
33
31
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34
32
"k8s.io/apimachinery/pkg/runtime"
@@ -79,6 +77,7 @@ type CNINodeReconciler struct {
79
77
clusterName string
80
78
vpcId string
81
79
finalizerManager k8s.FinalizerManager
80
+ deletePool * semaphore.Weighted
82
81
newResourceCleaner func (nodeID string , eC2Wrapper ec2API.EC2Wrapper , vpcID string , log logr.Logger ) cleanup.ResourceCleaner
83
82
}
84
83
@@ -92,6 +91,7 @@ func NewCNINodeReconciler(
92
91
clusterName string ,
93
92
vpcId string ,
94
93
finalizerManager k8s.FinalizerManager ,
94
+ maxConcurrentWorkers int ,
95
95
newResourceCleaner func (nodeID string , eC2Wrapper ec2API.EC2Wrapper , vpcID string , log logr.Logger ) cleanup.ResourceCleaner ,
96
96
) * CNINodeReconciler {
97
97
return & CNINodeReconciler {
@@ -104,6 +104,7 @@ func NewCNINodeReconciler(
104
104
clusterName : clusterName ,
105
105
vpcId : vpcId ,
106
106
finalizerManager : finalizerManager ,
107
+ deletePool : semaphore .NewWeighted (int64 (maxConcurrentWorkers )),
107
108
newResourceCleaner : newResourceCleaner ,
108
109
}
109
110
}
@@ -133,8 +134,8 @@ func (r *CNINodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
133
134
134
135
if cniNode .GetDeletionTimestamp ().IsZero () {
135
136
cniNodeCopy := cniNode .DeepCopy ()
136
- shouldPatch , err := r .ensureTagsAndLabels (cniNodeCopy , node , nodeFound )
137
- shouldPatch = r . ensureFinalizer (cniNodeCopy ) || shouldPatch
137
+ shouldPatch , err := r .ensureTagsAndLabels (cniNodeCopy , node )
138
+ shouldPatch = controllerutil . AddFinalizer (cniNodeCopy , config . NodeTerminationFinalizer ) || shouldPatch
138
139
139
140
if shouldPatch {
140
141
r .log .Info ("patching CNINode to add fields Tags, Labels and finalizer" , "cninode" , cniNode .Name )
@@ -147,24 +148,31 @@ func (r *CNINodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
147
148
}
148
149
}
149
150
return ctrl.Result {}, err
150
-
151
151
} else { // CNINode is marked for deletion
152
152
if ! nodeFound {
153
153
// node is also deleted, proceed with running the cleanup routine and remove the finalizer
154
-
155
154
// run cleanup for Linux nodes only
156
155
if val , ok := cniNode .ObjectMeta .Labels [config .NodeLabelOS ]; ok && val == config .OSLinux {
157
156
r .log .Info ("running the finalizer routine on cniNode" , "cniNode" , cniNode .Name )
158
157
// run cleanup when node id is present
159
158
if nodeID , ok := cniNode .Spec .Tags [config .NetworkInterfaceNodeIDKey ]; ok && nodeID != "" {
160
- if err := r . newResourceCleaner ( nodeID , r . eC2Wrapper , r . vpcId , r . log ). DeleteLeakedResources (); err != nil {
161
- r .log .Error ( err , "failed to cleanup resources during node termination " )
162
- ec2API . NodeTerminationENICleanupFailure . Inc ()
159
+ if ! r . deletePool . TryAcquire ( 1 ) {
160
+ r .log .Info ( "d, will requeue request " )
161
+ return ctrl. Result { RequeueAfter : 10 * time . Second }, nil
163
162
}
163
+ go func (nodeID string ) {
164
+ defer r .deletePool .Release (1 )
165
+ childCtx , cancel := context .WithTimeout (ctx , config .NodeTerminationTimeout )
166
+ defer cancel ()
167
+ if err := r .newResourceCleaner (nodeID , r .eC2Wrapper , r .vpcId , r .log ).DeleteLeakedResources (childCtx ); err != nil {
168
+ r .log .Error (err , "failed to cleanup resources during node termination" )
169
+ ec2API .NodeTerminationENICleanupFailure .Inc ()
170
+ }
171
+ }(nodeID )
164
172
}
165
173
}
166
174
167
- if err := r .removeFinalizers (ctx , cniNode , config .NodeTerminationFinalizer ); err != nil {
175
+ if err := r .removeFinalizer (ctx , cniNode , config .NodeTerminationFinalizer ); err != nil {
168
176
r .log .Error (err , "failed to remove finalizer on CNINode, will retry" , "cniNode" , cniNode .Name , "finalizer" , config .NodeTerminationFinalizer )
169
177
if apierrors .IsConflict (err ) {
170
178
return ctrl.Result {Requeue : true }, nil
@@ -188,7 +196,7 @@ func (r *CNINodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
188
196
Spec : cniNode .Spec ,
189
197
}
190
198
191
- if err := r .removeFinalizers (ctx , cniNode , config .NodeTerminationFinalizer ); err != nil {
199
+ if err := r .removeFinalizer (ctx , cniNode , config .NodeTerminationFinalizer ); err != nil {
192
200
r .log .Error (err , "failed to remove finalizer on CNINode, will retry" )
193
201
return ctrl.Result {}, err
194
202
}
@@ -233,7 +241,7 @@ func (r *CNINodeReconciler) waitTillCNINodeDeleted(nameSpacedCNINode types.Names
233
241
oldCNINode := & v1alpha1.CNINode {}
234
242
235
243
return wait .PollUntilContextTimeout (context .TODO (), 500 * time .Millisecond , time .Second * 3 , true , func (ctx context.Context ) (bool , error ) {
236
- if err := r .Client .Get (ctx , nameSpacedCNINode , oldCNINode ); err != nil && errors .IsNotFound (err ) {
244
+ if err := r .Client .Get (ctx , nameSpacedCNINode , oldCNINode ); err != nil && apierrors .IsNotFound (err ) {
237
245
return true , nil
238
246
}
239
247
return false , nil
@@ -248,17 +256,7 @@ func (r *CNINodeReconciler) createCNINodeFromObj(ctx context.Context, newCNINode
248
256
})
249
257
}
250
258
251
- func (r * CNINodeReconciler ) GetNodeID (node * v1.Node ) (string , error ) {
252
- if node .Spec .ProviderID == "" {
253
- return "" , fmt .Errorf ("provider ID is not set for node %s" , node .Name )
254
- }
255
- if idx := strings .LastIndex (node .Spec .ProviderID , "/" ); idx != - 1 && idx < len (node .Spec .ProviderID )- 1 {
256
- return node .Spec .ProviderID [idx + 1 :], nil
257
- }
258
- return "" , fmt .Errorf ("invalid provider ID format for node %s, with providerId" , node .Spec .ProviderID )
259
- }
260
-
261
- func (r * CNINodeReconciler ) ensureTagsAndLabels (cniNode * v1alpha1.CNINode , node * v1.Node , nodeFound bool ) (bool , error ) {
259
+ func (r * CNINodeReconciler ) ensureTagsAndLabels (cniNode * v1alpha1.CNINode , node * v1.Node ) (bool , error ) {
262
260
shouldPatch := false
263
261
var err error
264
262
if cniNode .Spec .Tags == nil {
@@ -269,11 +267,11 @@ func (r *CNINodeReconciler) ensureTagsAndLabels(cniNode *v1alpha1.CNINode, node
269
267
cniNode .Spec .Tags [config .VPCCNIClusterNameKey ] = r .clusterName
270
268
shouldPatch = true
271
269
}
272
- if nodeFound {
270
+ if node != nil {
273
271
var nodeID string
274
- nodeID , err = r .GetNodeID (node )
272
+ nodeID , err = utils .GetNodeID (node )
275
273
276
- if cniNode .Spec .Tags [config .NetworkInterfaceNodeIDKey ] != nodeID {
274
+ if nodeID != "" && cniNode .Spec .Tags [config .NetworkInterfaceNodeIDKey ] != nodeID {
277
275
cniNode .Spec .Tags [config .NetworkInterfaceNodeIDKey ] = nodeID
278
276
shouldPatch = true
279
277
}
@@ -290,28 +288,12 @@ func (r *CNINodeReconciler) ensureTagsAndLabels(cniNode *v1alpha1.CNINode, node
290
288
return shouldPatch , err
291
289
}
292
290
293
- func (r * CNINodeReconciler ) ensureFinalizer (cniNode * v1alpha1.CNINode ) bool {
294
- shouldPatch := false
295
- if ! controllerutil .ContainsFinalizer (cniNode , config .NodeTerminationFinalizer ) {
296
- r .log .Info ("adding finalizer" , "object" , cniNode .GetObjectKind ().GroupVersionKind ().Kind , "name" , cniNode .GetName (), "finalizer" , config .NodeTerminationFinalizer )
297
- controllerutil .AddFinalizer (cniNode , config .NodeTerminationFinalizer )
298
- shouldPatch = true
299
- }
300
- return shouldPatch
301
- }
302
-
303
- func (r * CNINodeReconciler ) removeFinalizers (ctx context.Context , cniNode * v1alpha1.CNINode , finalizer string ) error {
291
+ func (r * CNINodeReconciler ) removeFinalizer (ctx context.Context , cniNode * v1alpha1.CNINode , finalizer string ) error {
304
292
cniNodeCopy := cniNode .DeepCopy ()
305
- needsUpdate := false
306
293
307
- if controllerutil .ContainsFinalizer (cniNodeCopy , finalizer ) {
294
+ if controllerutil .RemoveFinalizer (cniNodeCopy , finalizer ) {
308
295
r .log .Info ("removing finalizer for cninode" , "name" , cniNode .GetName (), "finalizer" , finalizer )
309
- controllerutil .RemoveFinalizer (cniNodeCopy , finalizer )
310
- needsUpdate = true
311
- }
312
-
313
- if ! needsUpdate {
314
- return nil
296
+ return r .Client .Patch (ctx , cniNodeCopy , client .MergeFromWithOptions (cniNode , client.MergeFromWithOptimisticLock {}))
315
297
}
316
- return r . Client . Patch ( ctx , cniNodeCopy , client . MergeFromWithOptions ( cniNode , client. MergeFromWithOptimisticLock {}))
298
+ return nil
317
299
}
0 commit comments