@@ -155,7 +155,12 @@ func (cnc *CloudNodeController) UpdateNodeStatus(ctx context.Context) {
155
155
}
156
156
157
157
for i := range nodes .Items {
158
- cnc .updateNodeAddress (ctx , & nodes .Items [i ])
158
+ instanceMetadata , err := cnc .getInstanceNodeAddresses (ctx , & nodes .Items [i ])
159
+ if err != nil {
160
+ klog .Errorf ("Error getting instance metadata for node addresses: %v" , err )
161
+ continue
162
+ }
163
+ cnc .updateNodeAddress (ctx , & nodes .Items [i ], instanceMetadata )
159
164
}
160
165
161
166
for _ , node := range nodes .Items {
@@ -217,42 +222,15 @@ func (cnc *CloudNodeController) reconcileNodeLabels(nodeName string) error {
217
222
}
218
223
219
224
// UpdateNodeAddress updates the nodeAddress of a single node
220
- func (cnc * CloudNodeController ) updateNodeAddress (ctx context.Context , node * v1.Node ) {
225
+ func (cnc * CloudNodeController ) updateNodeAddress (ctx context.Context , node * v1.Node , instanceMetadata * cloudprovider. InstanceMetadata ) {
221
226
// Do not process nodes that are still tainted
222
227
cloudTaint := getCloudTaint (node .Spec .Taints )
223
228
if cloudTaint != nil {
224
229
klog .V (5 ).Infof ("This node %s is still tainted. Will not process." , node .Name )
225
230
return
226
231
}
227
232
228
- instanceMetadataGetter := func (providerID string , node * v1.Node ) (* cloudprovider.InstanceMetadata , error ) {
229
- if instancesV2 , ok := cnc .cloud .InstancesV2 (); instancesV2 != nil && ok {
230
- return instancesV2 .InstanceMetadata (ctx , node )
231
- }
232
-
233
- // If InstancesV2 not implement, use Instances.
234
- instances , ok := cnc .cloud .Instances ()
235
- if ! ok {
236
- return nil , fmt .Errorf ("failed to get instances from cloud provider" )
237
- }
238
-
239
- nodeAddresses , err := getNodeAddressesByProviderIDOrName (ctx , instances , node .Spec .ProviderID , node .Name )
240
- if err != nil {
241
- klog .Errorf ("Error getting node addresses for node %q: %v" , node .Name , err )
242
- return nil , err
243
- }
244
- return & cloudprovider.InstanceMetadata {
245
- NodeAddresses : nodeAddresses ,
246
- }, nil
247
- }
248
-
249
- instanceMeta , err := instanceMetadataGetter (node .Spec .ProviderID , node )
250
- if err != nil {
251
- utilruntime .HandleError (err )
252
- return
253
- }
254
-
255
- nodeAddresses := instanceMeta .NodeAddresses
233
+ nodeAddresses := instanceMetadata .NodeAddresses
256
234
if len (nodeAddresses ) == 0 {
257
235
klog .V (5 ).Infof ("Skipping node address update for node %q since cloud provider did not return any" , node .Name )
258
236
return
@@ -363,9 +341,19 @@ func (cnc *CloudNodeController) initializeNode(ctx context.Context, node *v1.Nod
363
341
return
364
342
}
365
343
366
- // TODO: getNodeModifiersFromCloudProvider and updateNodeAddress both call cloud api to get instanceMetadata,
367
- // get instanceMetadata and pass it to getNodeModifiersFromCloudProvider and updateNodeAddress which reduces api calls.
368
- nodeModifiers , err := cnc .getNodeModifiersFromCloudProvider (ctx , curNode )
344
+ providerID , err := cnc .getProviderID (ctx , curNode )
345
+ if err != nil {
346
+ utilruntime .HandleError (fmt .Errorf ("failed to get provider ID for node %s at cloudprovider: %v" , node .Name , err ))
347
+ return
348
+ }
349
+
350
+ instanceMetadata , err := cnc .getInstanceMetadata (ctx , providerID , curNode )
351
+ if err != nil {
352
+ utilruntime .HandleError (fmt .Errorf ("failed to get instance metadata for node %s: %v" , node .Name , err ))
353
+ return
354
+ }
355
+
356
+ nodeModifiers , err := cnc .getNodeModifiersFromCloudProvider (ctx , providerID , curNode , instanceMetadata )
369
357
if err != nil {
370
358
utilruntime .HandleError (fmt .Errorf ("failed to initialize node %s at cloudprovider: %v" , node .Name , err ))
371
359
return
@@ -392,7 +380,7 @@ func (cnc *CloudNodeController) initializeNode(ctx context.Context, node *v1.Nod
392
380
393
381
// After adding, call UpdateNodeAddress to set the CloudProvider provided IPAddresses
394
382
// So that users do not see any significant delay in IP addresses being filled into the node
395
- cnc .updateNodeAddress (ctx , curNode )
383
+ cnc .updateNodeAddress (ctx , curNode , instanceMetadata )
396
384
397
385
klog .Infof ("Successfully initialized node %s with cloud provider" , node .Name )
398
386
return nil
@@ -407,86 +395,16 @@ func (cnc *CloudNodeController) initializeNode(ctx context.Context, node *v1.Nod
407
395
// a node object with provider-specific information.
408
396
// All of the returned functions are idempotent, because they are used in a retry-if-conflict
409
397
// loop, meaning they could get called multiple times.
410
- func (cnc * CloudNodeController ) getNodeModifiersFromCloudProvider (ctx context.Context , node * v1.Node ) ([]nodeModifier , error ) {
411
- var (
412
- nodeModifiers []nodeModifier
413
- providerID string
414
- err error
415
- )
416
-
417
- if node .Spec .ProviderID == "" {
418
- providerID , err = cloudprovider .GetInstanceProviderID (ctx , cnc .cloud , types .NodeName (node .Name ))
419
- if err == nil {
420
- nodeModifiers = append (nodeModifiers , func (n * v1.Node ) {
421
- if n .Spec .ProviderID == "" {
422
- n .Spec .ProviderID = providerID
423
- }
424
- })
425
- } else if err == cloudprovider .NotImplemented {
426
- // if the cloud provider being used does not support provider IDs,
427
- // we can safely continue since we will attempt to set node
428
- // addresses given the node name in getNodeAddressesByProviderIDOrName
429
- klog .Warningf ("cloud provider does not set node provider ID, using node name to discover node %s" , node .Name )
430
- } else {
431
- // if the cloud provider being used supports provider IDs, we want
432
- // to propagate the error so that we re-try in the future; if we
433
- // do not, the taint will be removed, and this will not be retried
434
- return nil , err
435
- }
436
- } else {
437
- providerID = node .Spec .ProviderID
438
- }
439
-
440
- instanceMetadataGetter := func (providerID string , nodeName string , node * v1.Node ) (* cloudprovider.InstanceMetadata , error ) {
441
- if instancesV2 , ok := cnc .cloud .InstancesV2 (); instancesV2 != nil && ok {
442
- return instancesV2 .InstanceMetadata (ctx , node )
443
- }
444
-
445
- // If InstancesV2 not implement, use Instances.
446
- instances , ok := cnc .cloud .Instances ()
447
- if ! ok {
448
- return nil , fmt .Errorf ("failed to get instances from cloud provider" )
449
- }
450
-
451
- nodeAddresses , err := getNodeAddressesByProviderIDOrName (ctx , instances , providerID , nodeName )
452
- if err != nil {
453
- return nil , err
454
- }
455
-
456
- instanceType , err := getInstanceTypeByProviderIDOrName (ctx , instances , providerID , nodeName )
457
- if err != nil {
458
- return nil , err
459
- }
460
-
461
- instanceMetadata := & cloudprovider.InstanceMetadata {
462
- InstanceType : instanceType ,
463
- NodeAddresses : nodeAddresses ,
464
- }
465
-
466
- zones , ok := cnc .cloud .Zones ()
467
- if ! ok {
468
- return instanceMetadata , nil
469
- }
470
-
471
- zone , err := getZoneByProviderIDOrName (ctx , zones , providerID , node .Name )
472
- if err != nil {
473
- return nil , fmt .Errorf ("failed to get zone from cloud provider: %v" , err )
474
- }
475
-
476
- if zone .FailureDomain != "" {
477
- instanceMetadata .Zone = zone .FailureDomain
478
- }
479
-
480
- if zone .Region != "" {
481
- instanceMetadata .Region = zone .Region
482
- }
398
+ func (cnc * CloudNodeController ) getNodeModifiersFromCloudProvider (
399
+ ctx context.Context ,
400
+ providerID string ,
401
+ node * v1.Node ,
402
+ instanceMeta * cloudprovider.InstanceMetadata ,
403
+ ) ([]nodeModifier , error ) {
483
404
484
- return instanceMetadata , nil
485
- }
486
-
487
- instanceMeta , err := instanceMetadataGetter (providerID , node .Name , node )
488
- if err != nil {
489
- return nil , err
405
+ var nodeModifiers []nodeModifier
406
+ if node .Spec .ProviderID == "" && providerID != "" {
407
+ nodeModifiers = append (nodeModifiers , func (n * v1.Node ) { n .Spec .ProviderID = providerID })
490
408
}
491
409
492
410
// If user provided an IP address, ensure that IP address is found
@@ -533,6 +451,94 @@ func (cnc *CloudNodeController) getNodeModifiersFromCloudProvider(ctx context.Co
533
451
return nodeModifiers , nil
534
452
}
535
453
454
+ func (cnc * CloudNodeController ) getProviderID (ctx context.Context , node * v1.Node ) (string , error ) {
455
+ if node .Spec .ProviderID != "" {
456
+ return node .Spec .ProviderID , nil
457
+ }
458
+
459
+ providerID , err := cloudprovider .GetInstanceProviderID (ctx , cnc .cloud , types .NodeName (node .Name ))
460
+ if err == cloudprovider .NotImplemented {
461
+ // if the cloud provider being used does not support provider IDs,
462
+ // we can safely continue since we will attempt to set node
463
+ // addresses given the node name in getNodeAddressesByProviderIDOrName
464
+ klog .Warningf ("cloud provider does not set node provider ID, using node name to discover node %s" , node .Name )
465
+ return "" , nil
466
+ }
467
+
468
+ // if the cloud provider being used supports provider IDs, we want
469
+ // to propagate the error so that we re-try in the future; if we
470
+ // do not, the taint will be removed, and this will not be retried
471
+ return providerID , err
472
+ }
473
+
474
+ // getInstanceMetadata get instance type and nodeAddresses, use Instances if InstancesV2 is off.
475
+ func (cnc * CloudNodeController ) getInstanceMetadata (ctx context.Context , providerID string , node * v1.Node ) (* cloudprovider.InstanceMetadata , error ) {
476
+ if instancesV2 , ok := cnc .cloud .InstancesV2 (); instancesV2 != nil && ok {
477
+ return instancesV2 .InstanceMetadata (ctx , node )
478
+ }
479
+
480
+ // If InstancesV2 not implement, use Instances.
481
+ instances , ok := cnc .cloud .Instances ()
482
+ if ! ok {
483
+ return nil , fmt .Errorf ("failed to get instances from cloud provider" )
484
+ }
485
+ nodeAddresses , err := getNodeAddressesByProviderIDOrName (ctx , instances , providerID , node .Name )
486
+ if err != nil {
487
+ return nil , err
488
+ }
489
+ instanceType , err := getInstanceTypeByProviderIDOrName (ctx , instances , providerID , node .Name )
490
+ if err != nil {
491
+ return nil , err
492
+ }
493
+
494
+ instanceMetadata := & cloudprovider.InstanceMetadata {
495
+ InstanceType : instanceType ,
496
+ NodeAddresses : nodeAddresses ,
497
+ }
498
+
499
+ zones , ok := cnc .cloud .Zones ()
500
+ if ! ok {
501
+ return instanceMetadata , nil
502
+ }
503
+
504
+ zone , err := getZoneByProviderIDOrName (ctx , zones , providerID , node .Name )
505
+ if err != nil {
506
+ return nil , fmt .Errorf ("failed to get zone from cloud provider: %v" , err )
507
+ }
508
+
509
+ if zone .FailureDomain != "" {
510
+ instanceMetadata .Zone = zone .FailureDomain
511
+ }
512
+
513
+ if zone .Region != "" {
514
+ instanceMetadata .Region = zone .Region
515
+ }
516
+
517
+ return instanceMetadata , nil
518
+ }
519
+
520
+ // getInstanceAddresses returns InstanceMetadata.NodeAddresses. If InstancesV2 not supported, it won't get instanceType
521
+ // which avoid an api call compared with getInstanceMetadata.
522
+ func (cnc * CloudNodeController ) getInstanceNodeAddresses (ctx context.Context , node * v1.Node ) (* cloudprovider.InstanceMetadata , error ) {
523
+ if instancesV2 , ok := cnc .cloud .InstancesV2 (); instancesV2 != nil && ok {
524
+ return instancesV2 .InstanceMetadata (ctx , node )
525
+ }
526
+
527
+ // If InstancesV2 not implement, use Instances.
528
+ instances , ok := cnc .cloud .Instances ()
529
+ if ! ok {
530
+ return nil , fmt .Errorf ("failed to get instances from cloud provider" )
531
+ }
532
+ nodeAddresses , err := getNodeAddressesByProviderIDOrName (ctx , instances , node .Spec .ProviderID , node .Name )
533
+ if err != nil {
534
+ return nil , err
535
+ }
536
+
537
+ return & cloudprovider.InstanceMetadata {
538
+ NodeAddresses : nodeAddresses ,
539
+ }, nil
540
+ }
541
+
536
542
func getCloudTaint (taints []v1.Taint ) * v1.Taint {
537
543
for _ , taint := range taints {
538
544
if taint .Key == cloudproviderapi .TaintExternalCloudProvider {
0 commit comments