Code change:
For external cloud provider - Kubelet setting the TaintExternalCloudProvider taint: The results in calling function in cloud node-controller: This (in a healthy case) sends 4 GCE API calls to: node addresses: (as part of getNodeModifier call) instance type: (as part of getNodeModifiers call) instance: (as part of updateNodeAddresses call) node addresses (again): (as part of updateNodeAddresses call) All those requests are read requests and could be replaced by a single call. We could do that by introducing a simple struct like: and adding a method (or rather replacing the existing InstanceTypeByProviderID which is used only for this purpose) to Instances cloud-provider interface; With that change, we would be able to replace all that 4 calls with just a single API call. This would be useful especially for creating large clusters (like 5k nodes), which may saturate the quota for API calls for quite some time. This is quite significant size of refactoring, though it should be relatively mechanical task to do. /sig cloud-provider /sig scalability /priority important-longterm /help-wanted - FYI
The InstanceMetadataByProviderID would be to every cloud provider, such as aws, azure, etc. right ?
/assign Hi , if you're interested in it, I can work with you.
Yes - we need to do that (which is why I wrote it's quite significant refectoring). It also makes reviews harder, because we will need to ask maintainers of all cloud-providers. So it would be good to separate changes to different cloud providers into separate commits.
I have one question: and first query by providerID, if failed then query by nodeName. While the logic in is converse(if providerID is nil, get providerID by nodeName, then ensure its existence by providerID). If we merge these three method into , how to deal with the query sequence of nodeName and providerID?
I bet it's a consequence of different people adding different code paths. Those conceptually seem to be the same to me. Unifying this will be additional benefit from this change imho. So I would say that choose whatever is easier to implement.
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
/remove-lifecycle stale
I think and are the only PRs left for this. One other optimization that can be made is to cache the instance metadata but I think that's a provider specific implementation
Plus enabling it for GCE if we decide to remove it from the first PR. But yeah, in general I agree.
- can you please address ?
Yes, I have seen that.
I think this issue has been resolved, feel free to reopen it. /close
Closing this issue. <detailsIn response to : I think this issue has been resolved, feel free to reopen it. Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

Related discussion:
text: return true, nil } <ins> // InstanceExists returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (g *Cloud) InstanceExists(ctx context.Context, node *v1.Node) (bool, error) { providerID := node.Spec.ProviderID if providerID == "" { var err error if providerID, err = g.InstanceID(ctx, types.NodeName(node.Name)); err != nil { return false, err } } return g.InstanceExistsByProviderID(ctx, providerID) } // InstanceMetadata returns metadata of the specified instance. func (g *Cloud) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error) { timeoutCtx, cancel := context.WithTimeout(ctx, 1*time.Hour) defer cancel() providerID := node.Spec.ProviderID if providerID == "" { var err error if providerID, err = g.InstanceID(ctx, types.NodeName(node.Name)); err != nil { return nil, err } } _, zone, name, err := splitProviderID(providerID) if err != nil { return nil, err } region, err := GetGCERegion(zone) if err != nil { return nil, err } instance, err := g.c.Instances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(name), zone)) if err != nil { return nil, fmt.Errorf("error while querying for providerID %q: %v", providerID, err) } addresses, err := nodeAddressesFromInstance(instance) if err != nil { return nil, err } return &cloudprovider.InstanceMetadata{ ProviderID:    providerID, InstanceType:  lastComponent(instance.MachineType), NodeAddresses: addresses, Zone:          zone, Region:        region, }, nil } </ins> // InstanceID returns the cloud provider ID of the node with the specified NodeName. func (g *Cloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) { instanceName := mapNodeNameToInstanceName(nodeName)