Change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: If computer name prefix does not match VMSS name, then Azure cloud provider will use VMSS API instead of using metadata service data. This leads to throttling, because every affected kubelet is making API requests. What you expected to happen: Azure cloud provider should use metadata service data instead of calling VMSS API when instance is current. How to reproduce it (as minimally and precisely as possible): Set computer name prefix of the VMSS to something different than default. You should observe Azure provider making requests to the VMSS API rather than using metadata service, which leads to throttling if you have multiple kubelets with this bug. Anything else we need to know?: This is bug was introduced by - returns false even if instance is current, because it expects node name to match VMSS name + instance id, however node name is derived from the computer-name-prefix which can be different than VMSS name. Node name should be matched against , not against . Environment: Kubernetes version (use ): 1.18.x and higher Cloud provider or hardware configuration: azure /sig cloud-provider
/sig cloud-provider
/area provider/azure
CC
/remove-sig cloud-provider /sig cloud-provider (trying to remove the label)
/sig cloud-provider
Thanks for the reporting. Unfortunately, computer name prefix is not included in IMDS, so it can't be used without VMSS API for constructing the NodeName. Would check what could we do to workaround the issue.
Can you memorize the computer name prefix in the first request to the Azure API and then use it for the isCurrentInstance check?
opened to fix the issue. Would you like to have a look?
I can confirm that your change should fix the problem I reported. Do you know if your fix will be to 1.18.x?
is working on the cherry pick
Thank you for quick fix!

Discussion:
import ( "context" "fmt" <del> "strconv" </del> <ins> "os" </ins> "strings" v1 "k8s.io/api/core/v1"

vmPowerStateStopped      = "stopped" vmPowerStateDeallocated  = "deallocated" vmPowerStateDeallocating = "deallocating" <ins> // nodeNameEnvironmentName is the environment variable name for getting node name. // It is only used for out-of-tree cloud provider. nodeNameEnvironmentName = "NODE_NAME" </ins> ) var (

} func (az *Cloud) isCurrentInstance(name types.NodeName, metadataVMName string) (bool, error) { <ins> var err error </ins> nodeName := mapNodeNameToVMName(name) <ins> // VMSS vmName is not same with hostname, use hostname instead. </ins> if az.VMType == vmTypeVMSS { <del> // VMSS vmName is not same with hostname, construct the node name "{computer-name-prefix}{base-36-instance-id}". // Refer https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-instance-ids#scale-set-vm-computer-name. if ssName, instanceID, err := extractVmssVMName(metadataVMName); err == nil { instance, err := strconv.ParseInt(instanceID, 10, 64) if err != nil { return false, fmt.Errorf("failed to parse VMSS instanceID %q: %v", instanceID, err) } metadataVMName = fmt.Sprintf("%s%06s", ssName, strconv.FormatInt(instance, 36)) </del> <ins> metadataVMName, err = os.Hostname() if err != nil { return false, err } // Use name from env variable "NODE_NAME" if it is set. nodeNameEnv := os.Getenv(nodeNameEnvironmentName) if nodeNameEnv != "" { metadataVMName = nodeNameEnv </ins> } }

expectedErrMsg:      fmt.Errorf("failure of getting instance metadata"), }, { <del> name:                "NodeAddresses should report error if VMSS instanceID is invalid", nodeName:            "vm123456", metadataName:        "vmss_$123", vmType:              vmTypeVMSS, useInstanceMetadata: true, expectedErrMsg:      fmt.Errorf("failed to parse VMSS instanceID %q: strconv.ParseInt: parsing %q: invalid syntax", "$123", "$123"), }, { </del> name:                "NodeAddresses should report error if cloud.vmSet is nil", nodeName:            "vm1", vmType:              vmTypeStandard,

expectedErrMsg:      fmt.Errorf("getError"), }, { <del> name:                "NodeAddresses should report error if VMSS instanceID is invalid", nodeName:            "vm123456", metadataName:        "vmss_$123", vmType:              vmTypeVMSS, useInstanceMetadata: true, expectedErrMsg:      fmt.Errorf("failed to parse VMSS instanceID %q: strconv.ParseInt: parsing %q: invalid syntax", "$123", "$123"), }, { </del> name:                "NodeAddresses should report error if cloud.vmSet is nil", nodeName:            "vm1", vmType:              vmTypeStandard,

expectedErrMsg:      fmt.Errorf("getError"), }, { <del> name:                "InstanceMetadataByProviderID should report error if VMSS instanceID is invalid", metadataName:        "vmss_$123", providerID:          providerID, vmType:              vmTypeVMSS, useInstanceMetadata: true, expectedErrMsg:      fmt.Errorf("failed to parse VMSS instanceID %q: strconv.ParseInt: parsing %q: invalid syntax", "$123", "$123"), }, { </del> name:         "InstanceMetadataByProviderID should get metadata from Azure API if cloud.UseInstanceMetadata is false", metadataName: "vm1", providerID:   providerID,

func TestIsCurrentInstance(t *testing.T) { cloud := &Cloud{ Config: Config{ <del> VMType: vmTypeVMSS, </del> <ins> VMType: vmTypeStandard, </ins> }, } testcases := []struct {

metadataVMName: "node2", expected:       false, }, <del> { nodeName:       "vmss000001", metadataVMName: "vmss_1", expected:       true, }, { nodeName:       "vmss_2", metadataVMName: "vmss000000", expected:       false, }, { nodeName:       "vmss123456", metadataVMName: "vmss_$123", expected:       false, expectedErrMsg: fmt.Errorf("failed to parse VMSS instanceID %q: strconv.ParseInt: parsing %q: invalid syntax", "$123", "$123"), }, </del> } for _, test := range testcases {

useCustomImsCache: true, expectedErrMsg:    fmt.Errorf("getError"), }, <del> { name:           "NodeAddresses should report error if VMSS instanceID is invalid", nodeName:       "vm123456", metadataName:   "vmss_$123", providerID:     "azure:///subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/vm1", vmType:         vmTypeVMSS, expectedErrMsg: fmt.Errorf("failed to parse VMSS instanceID %q: strconv.ParseInt: parsing %q: invalid syntax", "$123", "$123"), }, </del> } for _, test := range testcases {