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: Node external IP of azure VMSS cannot be obtained when cloud-controller-manager is enabled. Corresponding logs are shown as follows:
/sig azure
/milestone v1.16

Discussion:
CreateOrUpdate(ctx context.Context, resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress) (resp *http.Response, err error) Delete(ctx context.Context, resourceGroupName string, publicIPAddressName string) (resp *http.Response, err error) Get(ctx context.Context, resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) <ins> GetVirtualMachineScaleSetPublicIPAddress(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, IPConfigurationName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) </ins> List(ctx context.Context, resourceGroupName string) (result []network.PublicIPAddress, err error) }

return } <ins> func (az *azPublicIPAddressesClient) GetVirtualMachineScaleSetPublicIPAddress(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, IPConfigurationName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) { if !az.rateLimiterReader.TryAccept() { err = createRateLimitErr(false, "VMSSPublicIPGet") return } klog.V(10).Infof("azPublicIPAddressesClient.GetVirtualMachineScaleSetPublicIPAddress(%q,%q): start", resourceGroupName, publicIPAddressName) defer func() { klog.V(10).Infof("azPublicIPAddressesClient.GetVirtualMachineScaleSetPublicIPAddress(%q,%q): end", resourceGroupName, publicIPAddressName) }() mc := newMetricContext("vmss_public_ip_addresses", "get", resourceGroupName, az.client.SubscriptionID, "") result, err = az.client.GetVirtualMachineScaleSetPublicIPAddress(ctx, resourceGroupName, virtualMachineScaleSetName, virtualmachineIndex, networkInterfaceName, IPConfigurationName, publicIPAddressName, expand) mc.Observe(err) return } </ins> func (az *azPublicIPAddressesClient) List(ctx context.Context, resourceGroupName string) ([]network.PublicIPAddress, error) { if !az.rateLimiterReader.TryAccept() { return nil, createRateLimitErr(false, "PublicIPList")

} return result, autorest.DetailedError{ StatusCode: http.StatusNotFound, <del> Message:    "Not such PIP", </del> <ins> Message:    "No such PIP", } } func (fAPC *fakeAzurePIPClient) GetVirtualMachineScaleSetPublicIPAddress(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, IPConfigurationName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) { fAPC.mutex.Lock() defer fAPC.mutex.Unlock() if _, ok := fAPC.FakeStore[resourceGroupName]; ok { if entity, ok := fAPC.FakeStore[resourceGroupName][publicIPAddressName]; ok { return entity, nil } } return result, autorest.DetailedError{ StatusCode: http.StatusNotFound, Message:    "No such PIP", </ins> } }

// ErrorNotVmssInstance indicates an instance is not belongint to any vmss. ErrorNotVmssInstance = errors.New("not a vmss instance") <del> scaleSetNameRE        = regexp.MustCompile(`.*/subscriptions/(?:.*)/Microsoft.Compute/virtualMachineScaleSets/(.+)/virtualMachines(?:.*)`) resourceGroupRE       = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Compute/virtualMachineScaleSets/(?:.*)/virtualMachines(?:.*)`) vmssMachineIDTemplate = "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%s" vmssIPConfigurationRE = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Compute/virtualMachineScaleSets/(.+)/virtualMachines/(.+)/networkInterfaces(?:.*)`) </del> <ins> scaleSetNameRE         = regexp.MustCompile(`.*/subscriptions/(?:.*)/Microsoft.Compute/virtualMachineScaleSets/(.+)/virtualMachines(?:.*)`) resourceGroupRE        = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Compute/virtualMachineScaleSets/(?:.*)/virtualMachines(?:.*)`) vmssMachineIDTemplate  = "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%s" vmssIPConfigurationRE  = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Compute/virtualMachineScaleSets/(.+)/virtualMachines/(.+)/networkInterfaces(?:.*)`) vmssPIPConfigurationRE = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Compute/virtualMachineScaleSets/(.+)/virtualMachines/(.+)/networkInterfaces/(.+)/ipConfigurations/(.+)/publicIPAddresses/(.+)`) </ins> ) // scaleSet implements VMSet interface for Azure scale set.

publicIP := "" if ipConfig.PublicIPAddress != nil && ipConfig.PublicIPAddress.ID != nil { pipID := *ipConfig.PublicIPAddress.ID <del> pipName, err := getLastSegment(pipID) if err != nil { return "", "", fmt.Errorf("failed to get publicIP name for node %q with pipID %q", nodeName, pipID) </del> <ins> matches := vmssPIPConfigurationRE.FindStringSubmatch(pipID) if len(matches) == 7 { resourceGroupName := matches[1] virtualMachineScaleSetName := matches[2] virtualmachineIndex := matches[3] networkInterfaceName := matches[4] IPConfigurationName := matches[5] publicIPAddressName := matches[6] pip, existsPip, err := ss.getVMSSPublicIPAddress(resourceGroupName, virtualMachineScaleSetName, virtualmachineIndex, networkInterfaceName, IPConfigurationName, publicIPAddressName) if err != nil { klog.Errorf("ss.getVMSSPublicIPAddress() failed with error: %v", err) return "", "", err } if existsPip && pip.IPAddress != nil { publicIP = *pip.IPAddress } } else { klog.Warningf("Failed to get VMSS Public IP with ID %s", pipID) </ins> } <ins> } </ins> <del> resourceGroup, err := ss.GetNodeResourceGroup(nodeName) if err != nil { return "", "", err } </del> <ins> return internalIP, publicIP, nil } </ins> <del> pip, existsPip, err := ss.getPublicIPAddress(resourceGroup, pipName) if err != nil { return "", "", err } if existsPip { publicIP = *pip.IPAddress } </del> <ins> func (ss *scaleSet) getVMSSPublicIPAddress(resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, IPConfigurationName string, publicIPAddressName string) (pip network.PublicIPAddress, exists bool, err error) { var realErr error var message string ctx, cancel := getContextWithCancel() defer cancel() pip, err = ss.PublicIPAddressesClient.GetVirtualMachineScaleSetPublicIPAddress(ctx, resourceGroupName, virtualMachineScaleSetName, virtualmachineIndex, networkInterfaceName, IPConfigurationName, publicIPAddressName, "") exists, message, realErr = checkResourceExistsFromError(err) if realErr != nil { return pip, false, realErr </ins> } <del> return internalIP, publicIP, nil </del> <ins> if !exists { klog.V(2).Infof("Public IP %q not found with message: %q", publicIPAddressName, message) return pip, false, nil } return pip, exists, err </ins> } // returns a list of private ips assigned to node