Repository: kubernetes-sigs/cloud-provider-azure
Pull request #7696 (2024-11-27 06:23:26)

[release-1.31] Chores: move azure config struct to config package
This is an automated cherry-pick of #7667

/assign MartinForReal

```release-note
NONE
```

coveralls: 
[![Coverage Status](https://coveralls.io/builds/71076853/badge)](https://coveralls.io/builds/71076853)

coverage: 75.912% (-0.2%) from 76.089%
when pulling **e1c9cbe9c53b32969067ffa3cca43ff0b1e7bead on k8s-infra-cherrypick-robot:cherry-pick-7667-to-release-1.31**
into **b67c63f7ddff6c96c526f6f84158349cfec3ae90 on kubernetes-sigs:release-1.31**.

MartinForReal: /lgtm
/approve
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/cloud-provider-azure/pull/7696#" title="Author self-approved">k8s-infra-cherrypick-robot</a>*, *<a href="https://github.com/kubernetes-sigs/cloud-provider-azure/pull/7696#issuecomment-2503035210" title="Approved">MartinForReal</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fcloud-provider-azure).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubernetes-sigs/cloud-provider-azure/blob/release-1.31/OWNERS)~~ [MartinForReal]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
MartinForReal: /kind cleanup

Patch:
diff --git a/pkg/node/node.go b/pkg/node/node.go
index 4b705d1f0..5bd959a82 100644
--- a/pkg/node/node.go
+++ b/pkg/node/node.go
@@ -25,6 +25,7 @@ import (
 	"k8s.io/klog/v2"
 
 	azureprovider "sigs.k8s.io/cloud-provider-azure/pkg/provider"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 )
 
 // IMDSNodeProvider implements nodemanager.NodeProvider.
@@ -34,7 +35,7 @@ type IMDSNodeProvider struct {
 
 // NewIMDSNodeProvider creates a new IMDSNodeProvider.
 func NewIMDSNodeProvider(ctx context.Context) *IMDSNodeProvider {
-	az, err := azureprovider.NewCloud(ctx, nil, &azureprovider.Config{
+	az, err := azureprovider.NewCloud(ctx, nil, &config.Config{
 		UseInstanceMetadata: true,
 		VMType:              "vmss",
 	}, false)
diff --git a/pkg/provider/azure.go b/pkg/provider/azure.go
index 1d3fe4af5..d6241b12a 100644
--- a/pkg/provider/azure.go
+++ b/pkg/provider/azure.go
@@ -20,7 +20,6 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"io"
 	"net/http"
 	"os"
 	"strings"
@@ -33,7 +32,6 @@ import (
 	"github.com/Azure/go-autorest/autorest/azure"
 
 	v1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/informers"
@@ -48,7 +46,6 @@ import (
 	cloudnodeutil "k8s.io/cloud-provider/node/helpers"
 	nodeutil "k8s.io/component-helpers/node/util"
 	"k8s.io/klog/v2"
-	"sigs.k8s.io/yaml"
 
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader"
@@ -68,6 +65,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmsizeclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmssclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmssvmclient"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/privatelinkservice"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/routetable"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/securitygroup"
@@ -76,7 +74,7 @@ import (
 
 	azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
-	ratelimitconfig "sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
+	azureconfig "sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 	utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
 	"sigs.k8s.io/cloud-provider-azure/pkg/util/taints"
@@ -99,208 +97,6 @@ var (
 	}
 )
 
-// Config holds the configuration parsed from the --cloud-config flag
-// All fields are required unless otherwise specified
-// NOTE: Cloud config files should follow the same Kubernetes deprecation policy as
-// flags or CLIs. Config fields should not change behavior in incompatible ways and
-// should be deprecated for at least 2 release prior to removing.
-// See https://kubernetes.io/docs/reference/using-api/deprecation-policy/#deprecating-a-flag-or-cli
-// for more details.
-type Config struct {
-	ratelimitconfig.AzureClientConfig `json:",inline" yaml:",inline"`
-
-	// The cloud configure type for Azure cloud provider. Supported values are file, secret and merge.
-	CloudConfigType configloader.CloudConfigType `json:"cloudConfigType,omitempty" yaml:"cloudConfigType,omitempty"`
-
-	// The name of the resource group that the cluster is deployed in
-	ResourceGroup string `json:"resourceGroup,omitempty" yaml:"resourceGroup,omitempty"`
-	// The location of the resource group that the cluster is deployed in
-	Location string `json:"location,omitempty" yaml:"location,omitempty"`
-	// The name of site where the cluster will be deployed to that is more granular than the region specified by the "location" field.
-	// Currently only public ip, load balancer and managed disks support this.
-	ExtendedLocationName string `json:"extendedLocationName,omitempty" yaml:"extendedLocationName,omitempty"`
-	// The type of site that is being targeted.
-	// Currently only public ip, load balancer and managed disks support this.
-	ExtendedLocationType string `json:"extendedLocationType,omitempty" yaml:"extendedLocationType,omitempty"`
-	// The name of the VNet that the cluster is deployed in
-	VnetName string `json:"vnetName,omitempty" yaml:"vnetName,omitempty"`
-	// The name of the resource group that the Vnet is deployed in
-	VnetResourceGroup string `json:"vnetResourceGroup,omitempty" yaml:"vnetResourceGroup,omitempty"`
-	// The name of the subnet that the cluster is deployed in
-	SubnetName string `json:"subnetName,omitempty" yaml:"subnetName,omitempty"`
-	// The name of the security group attached to the cluster's subnet
-	SecurityGroupName string `json:"securityGroupName,omitempty" yaml:"securityGroupName,omitempty"`
-	// The name of the resource group that the security group is deployed in
-	SecurityGroupResourceGroup string `json:"securityGroupResourceGroup,omitempty" yaml:"securityGroupResourceGroup,omitempty"`
-	// (Optional in 1.6) The name of the route table attached to the subnet that the cluster is deployed in
-	RouteTableName string `json:"routeTableName,omitempty" yaml:"routeTableName,omitempty"`
-	// The name of the resource group that the RouteTable is deployed in
-	RouteTableResourceGroup string `json:"routeTableResourceGroup,omitempty" yaml:"routeTableResourceGroup,omitempty"`
-	// (Optional) The name of the availability set that should be used as the load balancer backend
-	// If this is set, the Azure cloudprovider will only add nodes from that availability set to the load
-	// balancer backend pool. If this is not set, and multiple agent pools (availability sets) are used, then
-	// the cloudprovider will try to add all nodes to a single backend pool which is forbidden.
-	// In other words, if you use multiple agent pools (availability sets), you MUST set this field.
-	PrimaryAvailabilitySetName string `json:"primaryAvailabilitySetName,omitempty" yaml:"primaryAvailabilitySetName,omitempty"`
-	// The type of azure nodes. Candidate values are: vmss, standard and vmssflex.
-	// If not set, it will be default to vmss.
-	VMType string `json:"vmType,omitempty" yaml:"vmType,omitempty"`
-	// The name of the scale set that should be used as the load balancer backend.
-	// If this is set, the Azure cloudprovider will only add nodes from that scale set to the load
-	// balancer backend pool. If this is not set, and multiple agent pools (scale sets) are used, then
-	// the cloudprovider will try to add all nodes to a single backend pool which is forbidden in the basic sku.
-	// In other words, if you use multiple agent pools (scale sets), and loadBalancerSku is set to basic, you MUST set this field.
-	PrimaryScaleSetName string `json:"primaryScaleSetName,omitempty" yaml:"primaryScaleSetName,omitempty"`
-	// Tags determines what tags shall be applied to the shared resources managed by controller manager, which
-	// includes load balancer, security group and route table. The supported format is `a=b,c=d,...`. After updated
-	// this config, the old tags would be replaced by the new ones.
-	// Because special characters are not supported in "tags" configuration, "tags" support would be removed in a future release,
-	// please consider migrating the config to "tagsMap".
-	Tags string `json:"tags,omitempty" yaml:"tags,omitempty"`
-	// TagsMap is similar to Tags but holds tags with special characters such as `=` and `,`.
-	TagsMap map[string]string `json:"tagsMap,omitempty" yaml:"tagsMap,omitempty"`
-	// SystemTags determines the tag keys managed by cloud provider. If it is not set, no tags would be deleted if
-	// the `Tags` is changed. However, the old tags would be deleted if they are neither included in `Tags` nor
-	// in `SystemTags` after the update of `Tags`.
-	SystemTags string `json:"systemTags,omitempty" yaml:"systemTags,omitempty"`
-	// Sku of Load Balancer and Public IP. Candidate values are: basic and standard.
-	// If not set, it will be default to basic.
-	LoadBalancerSku string `json:"loadBalancerSku,omitempty" yaml:"loadBalancerSku,omitempty"`
-	// LoadBalancerName determines the specific name of the load balancer user want to use, working with
-	// LoadBalancerResourceGroup
-	LoadBalancerName string `json:"loadBalancerName,omitempty" yaml:"loadBalancerName,omitempty"`
-	// LoadBalancerResourceGroup determines the specific resource group of the load balancer user want to use, working
-	// with LoadBalancerName
-	LoadBalancerResourceGroup string `json:"loadBalancerResourceGroup,omitempty" yaml:"loadBalancerResourceGroup,omitempty"`
-	// PreConfiguredBackendPoolLoadBalancerTypes determines whether the LoadBalancer BackendPool has been preconfigured.
-	// Candidate values are:
-	//   "": exactly with today (not pre-configured for any LBs)
-	//   "internal": for internal LoadBalancer
-	//   "external": for external LoadBalancer
-	//   "all": for both internal and external LoadBalancer
-	PreConfiguredBackendPoolLoadBalancerTypes string `json:"preConfiguredBackendPoolLoadBalancerTypes,omitempty" yaml:"preConfiguredBackendPoolLoadBalancerTypes,omitempty"`
-
-	// DisableAvailabilitySetNodes disables VMAS nodes support when "VMType" is set to "vmss".
-	DisableAvailabilitySetNodes bool `json:"disableAvailabilitySetNodes,omitempty" yaml:"disableAvailabilitySetNodes,omitempty"`
-	// EnableVmssFlexNodes enables vmss flex nodes support when "VMType" is set to "vmss".
-	EnableVmssFlexNodes bool `json:"enableVmssFlexNodes,omitempty" yaml:"enableVmssFlexNodes,omitempty"`
-	// DisableAzureStackCloud disables AzureStackCloud support. It should be used
-	// when setting AzureAuthConfig.Cloud with "AZURESTACKCLOUD" to customize ARM endpoints
-	// while the cluster is not running on AzureStack.
-	DisableAzureStackCloud bool `json:"disableAzureStackCloud,omitempty" yaml:"disableAzureStackCloud,omitempty"`
-	// Use instance metadata service where possible
-	UseInstanceMetadata bool `json:"useInstanceMetadata,omitempty" yaml:"useInstanceMetadata,omitempty"`
-
-	// Backoff exponent
-	CloudProviderBackoffExponent float64 `json:"cloudProviderBackoffExponent,omitempty" yaml:"cloudProviderBackoffExponent,omitempty"`
-	// Backoff jitter
-	CloudProviderBackoffJitter float64 `json:"cloudProviderBackoffJitter,omitempty" yaml:"cloudProviderBackoffJitter,omitempty"`
-
-	// ExcludeMasterFromStandardLB excludes master nodes from standard load balancer.
-	// If not set, it will be default to true.
-	ExcludeMasterFromStandardLB *bool `json:"excludeMasterFromStandardLB,omitempty" yaml:"excludeMasterFromStandardLB,omitempty"`
-	// DisableOutboundSNAT disables the outbound SNAT for public load balancer rules.
-	// It should only be set when loadBalancerSku is standard. If not set, it will be default to false.
-	DisableOutboundSNAT *bool `json:"disableOutboundSNAT,omitempty" yaml:"disableOutboundSNAT,omitempty"`
-
-	// Maximum allowed LoadBalancer Rule Count is the limit enforced by Azure Load balancer
-	MaximumLoadBalancerRuleCount int `json:"maximumLoadBalancerRuleCount,omitempty" yaml:"maximumLoadBalancerRuleCount,omitempty"`
-
-	// LoadBalancerBackendPoolConfigurationType defines how vms join the load balancer backend pools. Supported values
-	// are `nodeIPConfiguration`, `nodeIP` and `podIP`.
-	// `nodeIPConfiguration`: vm network interfaces will be attached to the inbound backend pool of the load balancer (default);
-	// `nodeIP`: vm private IPs will be attached to the inbound backend pool of the load balancer;
-	// `podIP`: pod IPs will be attached to the inbound backend pool of the load balancer (not supported yet).
-	LoadBalancerBackendPoolConfigurationType string `json:"loadBalancerBackendPoolConfigurationType,omitempty" yaml:"loadBalancerBackendPoolConfigurationType,omitempty"`
-	// PutVMSSVMBatchSize defines how many requests the client send concurrently when putting the VMSS VMs.
-	// If it is smaller than or equal to zero, the request will be sent one by one in sequence (default).
-	PutVMSSVMBatchSize int `json:"putVMSSVMBatchSize" yaml:"putVMSSVMBatchSize"`
-	// PrivateLinkServiceResourceGroup determines the specific resource group of the private link services user want to use
-	PrivateLinkServiceResourceGroup string `json:"privateLinkServiceResourceGroup,omitempty" yaml:"privateLinkServiceResourceGroup,omitempty"`
-
-	// EnableMigrateToIPBasedBackendPoolAPI uses the migration API to migrate from NIC-based to IP-based backend pool.
-	// The migration API can provide a migration from NIC-based to IP-based backend pool without service downtime.
-	// If the API is not used, the migration will be done by decoupling all nodes on the backend pool and then re-attaching
-	// node IPs, which will introduce service downtime. The downtime increases with the number of nodes in the backend pool.
-	EnableMigrateToIPBasedBackendPoolAPI bool `json:"enableMigrateToIPBasedBackendPoolAPI" yaml:"enableMigrateToIPBasedBackendPoolAPI"`
-
-	// MultipleStandardLoadBalancerConfigurations stores the properties regarding multiple standard load balancers.
-	// It will be ignored if LoadBalancerBackendPoolConfigurationType is nodeIPConfiguration.
-	// If the length is not 0, it is assumed the multiple standard load balancers mode is on. In this case,
-	// there must be one configuration named "<clustername>" or an error will be reported.
-	MultipleStandardLoadBalancerConfigurations []MultipleStandardLoadBalancerConfiguration `json:"multipleStandardLoadBalancerConfigurations,omitempty" yaml:"multipleStandardLoadBalancerConfigurations,omitempty"`
-
-	// RouteUpdateIntervalInSeconds is the interval for updating routes. Default is 30 seconds.
-	RouteUpdateIntervalInSeconds int `json:"routeUpdateIntervalInSeconds,omitempty" yaml:"routeUpdateIntervalInSeconds,omitempty"`
-	// LoadBalancerBackendPoolUpdateIntervalInSeconds is the interval for updating load balancer backend pool of local services. Default is 30 seconds.
-	LoadBalancerBackendPoolUpdateIntervalInSeconds int `json:"loadBalancerBackendPoolUpdateIntervalInSeconds,omitempty" yaml:"loadBalancerBackendPoolUpdateIntervalInSeconds,omitempty"`
-
-	// ClusterServiceLoadBalancerHealthProbeMode determines the health probe mode for cluster service load balancer.
-	// Supported values are `shared` and `servicenodeport`.
-	// `servicenodeport`: the health probe will be created against each port of each service by watching the backend application (default).
-	// `shared`: all cluster services shares one HTTP probe targeting the kube-proxy on the node (<nodeIP>/healthz:10256).
-	ClusterServiceLoadBalancerHealthProbeMode string `json:"clusterServiceLoadBalancerHealthProbeMode,omitempty" yaml:"clusterServiceLoadBalancerHealthProbeMode,omitempty"`
-	// ClusterServiceSharedLoadBalancerHealthProbePort defines the target port of the shared health probe. Default to 10256.
-	ClusterServiceSharedLoadBalancerHealthProbePort int32 `json:"clusterServiceSharedLoadBalancerHealthProbePort,omitempty" yaml:"clusterServiceSharedLoadBalancerHealthProbePort,omitempty"`
-	// ClusterServiceSharedLoadBalancerHealthProbePath defines the target path of the shared health probe. Default to `/healthz`.
-	ClusterServiceSharedLoadBalancerHealthProbePath string `json:"clusterServiceSharedLoadBalancerHealthProbePath,omitempty" yaml:"clusterServiceSharedLoadBalancerHealthProbePath,omitempty"`
-}
-
-// MultipleStandardLoadBalancerConfiguration stores the properties regarding multiple standard load balancers.
-type MultipleStandardLoadBalancerConfiguration struct {
-	// Name of the public load balancer. There will be an internal load balancer
-	// created if needed, and the name will be `<name>-internal`. The internal lb
-	// shares the same configurations as the external one. The internal lbs
-	// are not needed to be included in `MultipleStandardLoadBalancerConfigurations`.
-	// There must be a name of "<clustername>" in the load balancer configuration list.
-	Name string `json:"name" yaml:"name"`
-
-	MultipleStandardLoadBalancerConfigurationSpec
-
-	MultipleStandardLoadBalancerConfigurationStatus
-}
-
-// MultipleStandardLoadBalancerConfigurationSpec stores the properties regarding multiple standard load balancers.
-type MultipleStandardLoadBalancerConfigurationSpec struct {
-	// This load balancer can have services placed on it. Defaults to true,
-	// can be set to false to drain and eventually remove a load balancer.
-	// This only affects services that will be using the LB. For services
-	// that is currently using the LB, they will not be affected.
-	AllowServicePlacement *bool `json:"allowServicePlacement" yaml:"allowServicePlacement"`
-
-	// A string value that must specify the name of an existing vmSet.
-	// All nodes in the given vmSet will always be added to this load balancer.
-	// A vmSet can only be the primary vmSet for a single load balancer.
-	PrimaryVMSet string `json:"primaryVMSet" yaml:"primaryVMSet"`
-
-	// Services that must match this selector can be placed on this load balancer. If not supplied,
-	// services with any labels can be created on the load balancer.
-	ServiceLabelSelector *metav1.LabelSelector `json:"serviceLabelSelector" yaml:"serviceLabelSelector"`
-
-	// Services created in namespaces with the supplied label will be allowed to select that load balancer.
-	// If not supplied, services created in any namespaces can be created on that load balancer.
-	ServiceNamespaceSelector *metav1.LabelSelector `json:"serviceNamespaceSelector" yaml:"serviceNamespaceSelector"`
-
-	// Nodes matching this selector will be preferentially added to the load balancers that
-	// they match selectors for. NodeSelector does not override primaryAgentPool for node allocation.
-	NodeSelector *metav1.LabelSelector `json:"nodeSelector" yaml:"nodeSelector"`
-}
-
-// MultipleStandardLoadBalancerConfigurationStatus stores the properties regarding multiple standard load balancers.
-type MultipleStandardLoadBalancerConfigurationStatus struct {
-	// ActiveServices stores the services that are supposed to use the load balancer.
-	ActiveServices *utilsets.IgnoreCaseSet `json:"activeServices" yaml:"activeServices"`
-
-	// ActiveNodes stores the nodes that are supposed to be in the load balancer.
-	// It will be used in EnsureHostsInPool to make sure the given ones are in the backend pool.
-	ActiveNodes *utilsets.IgnoreCaseSet `json:"activeNodes" yaml:"activeNodes"`
-}
-
-// HasExtendedLocation returns true if extendedlocation prop are specified.
-func (config *Config) HasExtendedLocation() bool {
-	return config.ExtendedLocationName != "" && config.ExtendedLocationType != ""
-}
-
 var (
 	_ cloudprovider.Interface    = (*Cloud)(nil)
 	_ cloudprovider.Instances    = (*Cloud)(nil)
@@ -311,7 +107,7 @@ var (
 
 // Cloud holds the config and clients
 type Cloud struct {
-	Config
+	azureconfig.Config
 	Environment azure.Environment
 
 	SubnetsClient                   subnetclient.Interface
@@ -408,7 +204,7 @@ type Cloud struct {
 }
 
 // NewCloud returns a Cloud with initialized clients
-func NewCloud(ctx context.Context, clientBuilder cloudprovider.ControllerClientBuilder, config *Config, callFromCCM bool) (cloudprovider.Interface, error) {
+func NewCloud(ctx context.Context, clientBuilder cloudprovider.ControllerClientBuilder, config *azureconfig.Config, callFromCCM bool) (cloudprovider.Interface, error) {
 	az := &Cloud{
 		nodeNames:                  utilsets.NewString(),
 		nodeZones:                  map[string]*utilsets.IgnoreCaseSet{},
@@ -450,17 +246,17 @@ func NewCloudFromConfigFile(ctx context.Context, clientBuilder cloudprovider.Con
 		err   error
 	)
 
-	var configValue *Config
+	var configValue *azureconfig.Config
 	if configFilePath != "" {
-		var config *os.File
-		config, err = os.Open(configFilePath)
+		var configFile *os.File
+		configFile, err = os.Open(configFilePath)
 		if err != nil {
 			klog.Fatalf("Couldn't open cloud provider configuration %s: %#v",
 				configFilePath, err)
 		}
 
-		defer config.Close()
-		configValue, err = ParseConfig(config)
+		defer configFile.Close()
+		configValue, err = config.ParseConfig(configFile)
 		if err != nil {
 			klog.Fatalf("Failed to parse Azure cloud provider config: %v", err)
 		}
@@ -477,7 +273,7 @@ func NewCloudFromConfigFile(ctx context.Context, clientBuilder cloudprovider.Con
 }
 
 func NewCloudFromSecret(ctx context.Context, clientBuilder cloudprovider.ControllerClientBuilder, secretName, secretNamespace, cloudConfigKey string) (cloudprovider.Interface, error) {
-	config, err := configloader.Load[Config](ctx, &configloader.K8sSecretLoaderConfig{
+	config, err := configloader.Load[azureconfig.Config](ctx, &configloader.K8sSecretLoaderConfig{
 		K8sSecretConfig: configloader.K8sSecretConfig{
 			SecretName:      secretName,
 			SecretNamespace: secretNamespace,
@@ -498,7 +294,7 @@ func NewCloudFromSecret(ctx context.Context, clientBuilder cloudprovider.Control
 }
 
 // InitializeCloudFromConfig initializes the Cloud from config.
-func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config, fromSecret, callFromCCM bool) error {
+func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *config.Config, fromSecret, callFromCCM bool) error {
 	if config == nil {
 		// should not reach here
 		return fmt.Errorf("InitializeCloudFromConfig: cannot initialize from nil config")
@@ -574,13 +370,13 @@ func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config,
 		config.ClusterServiceSharedLoadBalancerHealthProbePath = consts.ClusterServiceLoadBalancerHealthProbeDefaultPath
 	}
 
-	env, err := ratelimitconfig.ParseAzureEnvironment(config.Cloud, config.ResourceManagerEndpoint, config.IdentitySystem)
+	env, err := azureconfig.ParseAzureEnvironment(config.Cloud, config.ResourceManagerEndpoint, config.IdentitySystem)
 	if err != nil {
 		return err
 	}
 
 	// Initialize rate limiting config options.
-	ratelimitconfig.InitializeCloudProviderRateLimitConfig(&config.CloudProviderRateLimitConfig)
+	azureconfig.InitializeCloudProviderRateLimitConfig(&config.CloudProviderRateLimitConfig)
 
 	resourceRequestBackoff := az.setCloudProviderBackoffDefaults(config)
 
@@ -619,19 +415,19 @@ func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config,
 		}
 	}
 
-	if az.isLBBackendPoolTypeNodeIPConfig() {
+	if az.IsLBBackendPoolTypeNodeIPConfig() {
 		az.LoadBalancerBackendPool = newBackendPoolTypeNodeIPConfig(az)
-	} else if az.isLBBackendPoolTypeNodeIP() {
+	} else if az.IsLBBackendPoolTypeNodeIP() {
 		az.LoadBalancerBackendPool = newBackendPoolTypeNodeIP(az)
 	}
 
-	if az.useMultipleStandardLoadBalancers() {
+	if az.UseMultipleStandardLoadBalancers() {
 		if err := az.checkEnableMultipleStandardLoadBalancers(); err != nil {
 			return err
 		}
 	}
-	servicePrincipalToken, err := ratelimitconfig.GetServicePrincipalToken(&config.AzureClientConfig, env, env.ServiceManagementEndpoint)
-	if errors.Is(err, ratelimitconfig.ErrorNoAuth) {
+	servicePrincipalToken, err := azureconfig.GetServicePrincipalToken(&config.AzureClientConfig, env, env.ServiceManagementEndpoint)
+	if errors.Is(err, azureconfig.ErrorNoAuth) {
 		// Only controller-manager would lazy-initialize from secret, and credentials are required for such case.
 		if fromSecret {
 			err := fmt.Errorf("no credentials provided for Azure cloud provider")
@@ -727,8 +523,8 @@ func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config,
 
 	// Common controller contains the function
 	// needed by both blob disk and managed disk controllers
-	qps := float32(ratelimitconfig.DefaultAtachDetachDiskQPS)
-	bucket := ratelimitconfig.DefaultAtachDetachDiskBucket
+	qps := float32(azureconfig.DefaultAtachDetachDiskQPS)
+	bucket := azureconfig.DefaultAtachDetachDiskBucket
 	if az.Config.AttachDetachDiskRateLimit != nil {
 		qps = az.Config.AttachDetachDiskRateLimit.CloudProviderRateLimitQPSWrite
 		bucket = az.Config.AttachDetachDiskRateLimit.CloudProviderRateLimitBucketWrite
@@ -745,14 +541,14 @@ func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config,
 		go az.routeUpdater.run(ctx)
 
 		// start backend pool updater.
-		if az.useMultipleStandardLoadBalancers() {
+		if az.UseMultipleStandardLoadBalancers() {
 			az.backendPoolUpdater = newLoadBalancerBackendPoolUpdater(az, time.Duration(az.LoadBalancerBackendPoolUpdateIntervalInSeconds)*time.Second)
 			go az.backendPoolUpdater.run(ctx)
 		}
 
 		// Azure Stack does not support zone at the moment
 		// https://docs.microsoft.com/en-us/azure-stack/user/azure-stack-network-differences?view=azs-2102
-		if !az.isStackCloud() {
+		if !az.IsStackCloud() {
 			// wait for the success first time of syncing zones
 			err = az.syncRegionZonesMap(ctx)
 			if err != nil {
@@ -767,17 +563,9 @@ func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config,
 	return nil
 }
 
-func (az *Cloud) useMultipleStandardLoadBalancers() bool {
-	return az.useStandardLoadBalancer() && len(az.MultipleStandardLoadBalancerConfigurations) > 0
-}
-
-func (az *Cloud) useSingleStandardLoadBalancer() bool {
-	return az.useStandardLoadBalancer() && len(az.MultipleStandardLoadBalancerConfigurations) == 0
-}
-
 // Multiple standard load balancer mode only supports IP-based load balancers.
 func (az *Cloud) checkEnableMultipleStandardLoadBalancers() error {
-	if az.isLBBackendPoolTypeNodeIPConfig() {
+	if az.IsLBBackendPoolTypeNodeIPConfig() {
 		return fmt.Errorf("multiple standard load balancers cannot be used with backend pool type %s", consts.LoadBalancerBackendPoolConfigurationTypeNodeIPConfiguration)
 	}
 
@@ -805,18 +593,6 @@ func (az *Cloud) checkEnableMultipleStandardLoadBalancers() error {
 	return nil
 }
 
-func (az *Cloud) isLBBackendPoolTypeNodeIPConfig() bool {
-	return strings.EqualFold(az.LoadBalancerBackendPoolConfigurationType, consts.LoadBalancerBackendPoolConfigurationTypeNodeIPConfiguration)
-}
-
-func (az *Cloud) isLBBackendPoolTypeNodeIP() bool {
-	return strings.EqualFold(az.LoadBalancerBackendPoolConfigurationType, consts.LoadBalancerBackendPoolConfigurationTypeNodeIP)
-}
-
-func (az *Cloud) getPutVMSSVMBatchSize() int {
-	return az.PutVMSSVMBatchSize
-}
-
 func (az *Cloud) initCaches() (err error) {
 	if az.Config.DisableAPICallCache {
 		klog.Infof("API call cache is disabled, ignore logs about cache operations")
@@ -847,7 +623,7 @@ func (az *Cloud) initCaches() (err error) {
 	return nil
 }
 
-func (az *Cloud) setLBDefaults(config *Config) error {
+func (az *Cloud) setLBDefaults(config *azureconfig.Config) error {
 	if config.LoadBalancerSku == "" {
 		config.LoadBalancerSku = consts.LoadBalancerSkuStandard
 	}
@@ -875,11 +651,11 @@ func (az *Cloud) getAuthTokenInMultiTenantEnv(_ *adal.ServicePrincipalToken, aut
 	var multiTenantOAuthToken adal.MultitenantOAuthTokenProvider
 	var networkResourceServicePrincipalToken adal.OAuthTokenProvider
 	if az.Config.UsesNetworkResourceInDifferentTenant() {
-		multiTenantOAuthToken, err = ratelimitconfig.GetMultiTenantServicePrincipalToken(&az.Config.AzureClientConfig, &az.Environment, authProvider)
+		multiTenantOAuthToken, err = azureconfig.GetMultiTenantServicePrincipalToken(&az.Config.AzureClientConfig, &az.Environment, authProvider)
 		if err != nil {
 			return nil, nil, err
 		}
-		networkResourceServicePrincipalToken, err = ratelimitconfig.GetNetworkResourceServicePrincipalToken(&az.Config.AzureClientConfig, &az.Environment, authProvider)
+		networkResourceServicePrincipalToken, err = azureconfig.GetNetworkResourceServicePrincipalToken(&az.Config.AzureClientConfig, &az.Environment, authProvider)
 		if err != nil {
 			return nil, nil, err
 		}
@@ -887,7 +663,7 @@ func (az *Cloud) getAuthTokenInMultiTenantEnv(_ *adal.ServicePrincipalToken, aut
 	return multiTenantOAuthToken, networkResourceServicePrincipalToken, nil
 }
 
-func (az *Cloud) setCloudProviderBackoffDefaults(config *Config) wait.Backoff {
+func (az *Cloud) setCloudProviderBackoffDefaults(config *azureconfig.Config) wait.Backoff {
 	// Conditionally configure resource request backoff
 	resourceRequestBackoff := wait.Backoff{
 		Steps: 1,
@@ -1031,45 +807,6 @@ func (az *Cloud) getAzureClientConfig(servicePrincipalToken *adal.ServicePrincip
 	return azClientConfig
 }
 
-// ParseConfig returns a parsed configuration for an Azure cloudprovider config file
-func ParseConfig(configReader io.Reader) (*Config, error) {
-	var config Config
-	if configReader == nil {
-		return nil, nil
-	}
-
-	configContents, err := io.ReadAll(configReader)
-	if err != nil {
-		return nil, err
-	}
-
-	err = yaml.Unmarshal(configContents, &config)
-	if err != nil {
-		return nil, err
-	}
-
-	// The resource group name may be in different cases from different Azure APIs, hence it is converted to lower here.
-	// See more context at https://github.com/kubernetes/kubernetes/issues/71994.
-	config.ResourceGroup = strings.ToLower(config.ResourceGroup)
-
-	// these environment variables are injected by workload identity webhook
-	if tenantID := os.Getenv("AZURE_TENANT_ID"); tenantID != "" {
-		config.TenantID = tenantID
-	}
-	if clientID := os.Getenv("AZURE_CLIENT_ID"); clientID != "" {
-		config.AADClientID = clientID
-	}
-	if federatedTokenFile := os.Getenv("AZURE_FEDERATED_TOKEN_FILE"); federatedTokenFile != "" {
-		config.AADFederatedTokenFile = federatedTokenFile
-		config.UseFederatedWorkloadIdentityExtension = true
-	}
-	return &config, nil
-}
-
-func (az *Cloud) isStackCloud() bool {
-	return strings.EqualFold(az.Config.Cloud, consts.AzureStackCloudName) && !az.Config.DisableAzureStackCloud
-}
-
 // Initialize passes a Kubernetes clientBuilder interface to the cloud provider
 func (az *Cloud) Initialize(clientBuilder cloudprovider.ControllerClientBuilder, _ <-chan struct{}) {
 	az.KubeClient = clientBuilder.ClientOrDie("azure-cloud-provider")
@@ -1100,7 +837,7 @@ func (az *Cloud) InstancesV2() (cloudprovider.InstancesV2, bool) {
 // DEPRECATED: Zones is deprecated in favor of retrieving zone/region information from InstancesV2.
 // This interface will not be called if InstancesV2 is enabled.
 func (az *Cloud) Zones() (cloudprovider.Zones, bool) {
-	if az.isStackCloud() {
+	if az.IsStackCloud() {
 		// Azure stack does not support zones at this point
 		// https://docs.microsoft.com/en-us/azure-stack/user/azure-stack-network-differences?view=azs-2102
 		return nil, false
diff --git a/pkg/provider/azure_fakes.go b/pkg/provider/azure_fakes.go
index 7aa9e2ba4..c04374653 100644
--- a/pkg/provider/azure_fakes.go
+++ b/pkg/provider/azure_fakes.go
@@ -78,7 +78,7 @@ func NewTestFlexScaleSet(ctrl *gomock.Controller) (*FlexScaleSet, error) {
 // GetTestCloud returns a fake azure cloud for unit tests in Azure related CSI drivers
 func GetTestCloud(ctrl *gomock.Controller) (az *Cloud) {
 	az = &Cloud{
-		Config: Config{
+		Config: config.Config{
 			AzureClientConfig: config.AzureClientConfig{
 				ARMClientConfig: azclient.ARMClientConfig{
 					TenantID: "TenantID",
diff --git a/pkg/provider/azure_loadbalancer.go b/pkg/provider/azure_loadbalancer.go
index 3b8fe1d8e..88ce01229 100644
--- a/pkg/provider/azure_loadbalancer.go
+++ b/pkg/provider/azure_loadbalancer.go
@@ -45,6 +45,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 	"sigs.k8s.io/cloud-provider-azure/pkg/log"
 	"sigs.k8s.io/cloud-provider-azure/pkg/metrics"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/loadbalancer"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 	"sigs.k8s.io/cloud-provider-azure/pkg/trace"
@@ -177,7 +178,7 @@ func (az *Cloud) reconcileService(ctx context.Context, clusterName string, servi
 
 	lbName := strings.ToLower(ptr.Deref(lb.Name, ""))
 	key := strings.ToLower(getServiceName(service))
-	if az.useMultipleStandardLoadBalancers() && isLocalService(service) {
+	if az.UseMultipleStandardLoadBalancers() && isLocalService(service) {
 		az.localServiceNameToServiceInfoMap.Store(key, newServiceInfo(getServiceIPFamily(service), lbName))
 		// There are chances that the endpointslice changes after EnsureHostsInPool, so
 		// need to check endpointslice for a second time.
@@ -488,7 +489,7 @@ func (az *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName stri
 		return err
 	}
 
-	if az.useMultipleStandardLoadBalancers() && isLocalService(service) {
+	if az.UseMultipleStandardLoadBalancers() && isLocalService(service) {
 		key := strings.ToLower(svcName)
 		az.localServiceNameToServiceInfoMap.Delete(key)
 	}
@@ -519,7 +520,7 @@ func (az *Cloud) shouldChangeLoadBalancer(service *v1.Service, currLBName, clust
 	// The load balancer can be changed in two cases:
 	// 1. Using multiple standard load balancers.
 	// 2. Migrate from multiple standard load balancers to single standard load balancer.
-	if az.useStandardLoadBalancer() {
+	if az.UseStandardLoadBalancer() {
 		if currLBName != expectedLBName {
 			klog.V(2).Infof("shouldChangeLoadBalancer(%s, %s, %s): change the LB to another one %s", service.Name, currLBName, clusterName, expectedLBName)
 			return true
@@ -826,7 +827,7 @@ func (az *Cloud) getServiceLoadBalancer(
 				ptr.Deref(existingLB.Name, ""),
 			)
 
-			if isLocalService(service) && az.useMultipleStandardLoadBalancers() {
+			if isLocalService(service) && az.UseMultipleStandardLoadBalancers() {
 				// No need for the endpoint slice informer to update the backend pool
 				// for the service because the main loop will delete the old backend pool
 				// and create a new one in the new load balancer.
@@ -854,7 +855,7 @@ func (az *Cloud) getServiceLoadBalancer(
 	// Service does not have a load balancer, select one.
 	// Single standard load balancer doesn't need this because
 	// all backends nodes should be added to same LB.
-	if wantLb && !az.useStandardLoadBalancer() {
+	if wantLb && !az.UseStandardLoadBalancer() {
 		// select new load balancer for service
 		selectedLB, exists, err := az.selectLoadBalancer(ctx, clusterName, service, existingLBs, nodes)
 		if err != nil {
@@ -881,7 +882,7 @@ func (az *Cloud) getServiceLoadBalancer(
 			Location:                     &az.Location,
 			LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{},
 		}
-		if az.useStandardLoadBalancer() {
+		if az.UseStandardLoadBalancer() {
 			defaultLB.Sku = &network.LoadBalancerSku{
 				Name: network.LoadBalancerSkuNameStandard,
 			}
@@ -929,7 +930,7 @@ func (az *Cloud) selectLoadBalancer(ctx context.Context, clusterName string, ser
 			// select this LB as this is a new LB and will have minimum rules
 			// create tmp lb struct to hold metadata for the new load-balancer
 			var loadBalancerSKU network.LoadBalancerSkuName
-			if az.useStandardLoadBalancer() {
+			if az.UseStandardLoadBalancer() {
 				loadBalancerSKU = network.LoadBalancerSkuNameStandard
 			} else {
 				loadBalancerSKU = network.LoadBalancerSkuNameBasic
@@ -1203,7 +1204,7 @@ func (az *Cloud) ensurePublicIPExists(ctx context.Context, service *v1.Service,
 			return nil, err
 		}
 
-		if az.useStandardLoadBalancer() {
+		if az.UseStandardLoadBalancer() {
 			pip.Sku = &network.PublicIPAddressSku{
 				Name: network.PublicIPAddressSkuNameStandard,
 			}
@@ -1277,7 +1278,7 @@ func (az *Cloud) reconcileIPSettings(pip *network.PublicIPAddress, service *v1.S
 			changed = true
 		}
 
-		if az.useStandardLoadBalancer() {
+		if az.UseStandardLoadBalancer() {
 			// standard sku must have static allocation method for ipv6
 			if !strings.EqualFold(string(pip.PublicIPAddressPropertiesFormat.PublicIPAllocationMethod), string(network.Static)) {
 				pip.PublicIPAddressPropertiesFormat.PublicIPAllocationMethod = network.Static
@@ -1688,7 +1689,7 @@ func (az *Cloud) reconcileMultipleStandardLoadBalancerConfigurations(
 	existingLBs *[]network.LoadBalancer,
 	nodes []*v1.Node,
 ) (err error) {
-	if !az.useMultipleStandardLoadBalancers() {
+	if !az.UseMultipleStandardLoadBalancers() {
 		return nil
 	}
 
@@ -1777,7 +1778,7 @@ func (az *Cloud) reconcileLoadBalancer(ctx context.Context, clusterName string,
 	// Delete backend pools for local service if:
 	// 1. the cluster is migrating from multi-slb to single-slb,
 	// 2. the service is changed from local to cluster.
-	if !az.useMultipleStandardLoadBalancers() || !isLocalService(service) {
+	if !az.UseMultipleStandardLoadBalancers() || !isLocalService(service) {
 		existingLBs, err = az.cleanupLocalServiceBackendPool(ctx, service, nodes, existingLBs, clusterName)
 		if err != nil {
 			klog.Errorf("reconcileLoadBalancer: failed to cleanup local service backend pool for service %q, error: %s", serviceName, err.Error())
@@ -1957,7 +1958,7 @@ func (az *Cloud) reconcileLoadBalancer(ctx context.Context, clusterName string,
 			_ = az.lbCache.Delete(lbName)
 		}()
 
-		if az.useMultipleStandardLoadBalancers() {
+		if az.UseMultipleStandardLoadBalancers() {
 			err := az.reconcileMultipleStandardLoadBalancerBackendNodes(ctx, clusterName, lbName, existingLBs, service, nodes, false)
 			if err != nil {
 				return nil, err
@@ -1970,7 +1971,7 @@ func (az *Cloud) reconcileLoadBalancer(ctx context.Context, clusterName string,
 		// change in one reconciliation loop.
 		var lbToReconcile []network.LoadBalancer
 		lbToReconcile = append(lbToReconcile, *lb)
-		if az.useMultipleStandardLoadBalancers() {
+		if az.UseMultipleStandardLoadBalancers() {
 			lbToReconcile = *existingLBs
 		}
 		lb, err = az.reconcileBackendPoolHosts(ctx, lb, lbToReconcile, service, nodes, clusterName, vmSetName, lbBackendPoolIDs)
@@ -2662,7 +2663,7 @@ func (az *Cloud) getFrontendZones(
 		if err != nil {
 			return err
 		}
-		if az.useStandardLoadBalancer() && len(zones) > 0 && !az.HasExtendedLocation() {
+		if az.UseStandardLoadBalancer() && len(zones) > 0 && !az.HasExtendedLocation() {
 			fipConfig.Zones = &zones
 		}
 	} else {
@@ -2826,7 +2827,7 @@ func (az *Cloud) getExpectedLBRules(
 	// In HA mode, lb forward traffic of all port to backend
 	// HA mode is only supported on standard loadbalancer SKU in internal mode
 	if consts.IsK8sServiceUsingInternalLoadBalancer(service) &&
-		az.useStandardLoadBalancer() &&
+		az.UseStandardLoadBalancer() &&
 		consts.IsK8sServiceHasHAModeEnabled(service) {
 
 		lbRuleName := az.getloadbalancerHAmodeRuleName(service, isIPv6)
@@ -2882,7 +2883,7 @@ func (az *Cloud) getExpectedLBRules(
 				klog.V(2).Infof("getExpectedLBRules lb name (%s) rule name (%s) no lb rule required", lbName, lbRuleName)
 				continue
 			}
-			if port.Protocol == v1.ProtocolSCTP && !(az.useStandardLoadBalancer() && consts.IsK8sServiceUsingInternalLoadBalancer(service)) {
+			if port.Protocol == v1.ProtocolSCTP && !(az.UseStandardLoadBalancer() && consts.IsK8sServiceUsingInternalLoadBalancer(service)) {
 				return expectedProbes, expectedRules, fmt.Errorf("SCTP is only supported on standard loadbalancer in internal mode")
 			}
 
@@ -2970,7 +2971,7 @@ func (az *Cloud) getExpectedLoadBalancingRulePropertiesForPort(
 		Protocol:            transportProto,
 		FrontendPort:        ptr.To(servicePort.Port),
 		BackendPort:         ptr.To(servicePort.Port),
-		DisableOutboundSnat: ptr.To(az.disableLoadBalancerOutboundSNAT()),
+		DisableOutboundSnat: ptr.To(az.DisableLoadBalancerOutboundSNAT()),
 		EnableFloatingIP:    ptr.To(true),
 		LoadDistribution:    loadDistribution,
 		FrontendIPConfiguration: &network.SubResource{
@@ -2981,7 +2982,7 @@ func (az *Cloud) getExpectedLoadBalancingRulePropertiesForPort(
 		},
 		IdleTimeoutInMinutes: lbIdleTimeout,
 	}
-	if strings.EqualFold(string(transportProto), string(network.TransportProtocolTCP)) && az.useStandardLoadBalancer() {
+	if strings.EqualFold(string(transportProto), string(network.TransportProtocolTCP)) && az.UseStandardLoadBalancer() {
 		props.EnableTCPReset = ptr.To(!consts.IsTCPResetDisabled(service.Annotations))
 	}
 
@@ -3663,7 +3664,7 @@ func ipInSubnet(ip string, subnet *network.Subnet) bool {
 // if anything else it returns the unique VM set names after trimming spaces.
 func (az *Cloud) getServiceLoadBalancerMode(service *v1.Service) (bool, bool, string) {
 	mode, hasMode := service.Annotations[consts.ServiceAnnotationLoadBalancerMode]
-	if az.useStandardLoadBalancer() && hasMode {
+	if az.UseStandardLoadBalancer() && hasMode {
 		klog.Warningf("single standard load balancer doesn't work with annotation %q, would ignore it", consts.ServiceAnnotationLoadBalancerMode)
 	}
 	mode = strings.TrimSpace(mode)
@@ -3909,14 +3910,14 @@ func (az *Cloud) getAzureLoadBalancerName(
 	// The LB name prefix is set to the name of the cluster when:
 	// 1. the LB belongs to the primary agent pool.
 	// 2. using the single SLB.
-	if strings.EqualFold(vmSetName, az.VMSet.GetPrimaryVMSetName()) || az.useSingleStandardLoadBalancer() {
+	if strings.EqualFold(vmSetName, az.VMSet.GetPrimaryVMSetName()) || az.UseSingleStandardLoadBalancer() {
 		lbNamePrefix = clusterName
 	}
 
 	// For multiple standard load balancers scenario:
 	// 1. Filter out the eligible load balancers.
 	// 2. Choose the most eligible load balancer.
-	if az.useMultipleStandardLoadBalancers() {
+	if az.UseMultipleStandardLoadBalancers() {
 		eligibleLBs, err := az.getEligibleLoadBalancersForService(ctx, service)
 		if err != nil {
 			return "", err
@@ -4008,7 +4009,7 @@ func (az *Cloud) getServiceCurrentLoadBalancerName(service *v1.Service) string {
 // 5. If there is no label/namespace selector on the LB, it can be a valid placement target if and only if the service has no other choice.
 func (az *Cloud) getEligibleLoadBalancersForService(ctx context.Context, service *v1.Service) ([]string, error) {
 	var (
-		eligibleLBs               []MultipleStandardLoadBalancerConfiguration
+		eligibleLBs               []config.MultipleStandardLoadBalancerConfiguration
 		eligibleLBNames           []string
 		lbSelectedByAnnotation    []string
 		lbFailedLabelSelector     []string
@@ -4159,7 +4160,7 @@ func (az *Cloud) getEligibleLoadBalancersForService(ctx context.Context, service
 	return eligibleLBNames, nil
 }
 
-func (az *Cloud) isLoadBalancerInUseByService(service *v1.Service, lbConfig MultipleStandardLoadBalancerConfiguration) bool {
+func (az *Cloud) isLoadBalancerInUseByService(service *v1.Service, lbConfig config.MultipleStandardLoadBalancerConfiguration) bool {
 	az.multipleStandardLoadBalancersActiveServicesLock.Lock()
 	defer az.multipleStandardLoadBalancersActiveServicesLock.Unlock()
 
diff --git a/pkg/provider/azure_loadbalancer_backendpool.go b/pkg/provider/azure_loadbalancer_backendpool.go
index 44ea68380..38364f0f6 100644
--- a/pkg/provider/azure_loadbalancer_backendpool.go
+++ b/pkg/provider/azure_loadbalancer_backendpool.go
@@ -411,7 +411,7 @@ func (bi *backendPoolTypeNodeIP) EnsureHostsInPool(ctx context.Context, service
 		numOfAdd, numOfDelete int
 		activeNodes           *utilsets.IgnoreCaseSet
 	)
-	if bi.useMultipleStandardLoadBalancers() {
+	if bi.UseMultipleStandardLoadBalancers() {
 		if !isLocalService(service) {
 			activeNodes = bi.getActiveNodesByLoadBalancerName(lbName)
 		} else {
@@ -463,7 +463,7 @@ func (bi *backendPoolTypeNodeIP) EnsureHostsInPool(ctx context.Context, service
 				nodePrivateIPsSet.Insert(privateIP)
 			}
 
-			if bi.useMultipleStandardLoadBalancers() {
+			if bi.UseMultipleStandardLoadBalancers() {
 				if activeNodes != nil && !activeNodes.Has(node.Name) {
 					klog.V(4).Infof("bi.EnsureHostsInPool: node %s should not be in load balancer %q", node.Name, lbName)
 					continue
@@ -487,7 +487,7 @@ func (bi *backendPoolTypeNodeIP) EnsureHostsInPool(ctx context.Context, service
 				nodeIPsToBeDeleted = append(nodeIPsToBeDeleted, ip)
 				changed = true
 				numOfDelete++
-			} else if bi.useMultipleStandardLoadBalancers() && activeNodes != nil {
+			} else if bi.UseMultipleStandardLoadBalancers() && activeNodes != nil {
 				nodeName, ok := bi.nodePrivateIPToNodeNameMap[ip]
 				if !ok {
 					klog.Warningf("bi.EnsureHostsInPool: cannot find node name for private IP %s", ip)
@@ -501,7 +501,7 @@ func (bi *backendPoolTypeNodeIP) EnsureHostsInPool(ctx context.Context, service
 				}
 			}
 		}
-		removeNodeIPAddressesFromBackendPool(backendPool, nodeIPsToBeDeleted, false, bi.useMultipleStandardLoadBalancers(), true)
+		removeNodeIPAddressesFromBackendPool(backendPool, nodeIPsToBeDeleted, false, bi.UseMultipleStandardLoadBalancers(), true)
 	}
 	if changed {
 		klog.V(2).Infof("bi.EnsureHostsInPool: updating backend pool %s of load balancer %s to add %d nodes and remove %d nodes", lbBackendPoolName, lbName, numOfAdd, numOfDelete)
@@ -872,7 +872,7 @@ func hasIPAddressInBackendPool(backendPool *network.BackendAddressPool, ipAddres
 func removeNodeIPAddressesFromBackendPool(
 	backendPool network.BackendAddressPool,
 	nodeIPAddresses []string,
-	removeAll, useMultipleStandardLoadBalancers, isNodeIP bool,
+	removeAll, UseMultipleStandardLoadBalancers, isNodeIP bool,
 ) bool {
 	changed := false
 	nodeIPsSet := utilsets.NewString(nodeIPAddresses...)
@@ -913,7 +913,7 @@ func removeNodeIPAddressesFromBackendPool(
 
 	// Allow the pool to be empty when EnsureHostsInPool for multiple standard load balancers clusters,
 	// or one node could occur in multiple backend pools.
-	if len(addresses) == 0 && !useMultipleStandardLoadBalancers {
+	if len(addresses) == 0 && !UseMultipleStandardLoadBalancers {
 		klog.V(2).Info("removeNodeIPAddressFromBackendPool: the pool is empty or will be empty after removing the unwanted IP addresses, skipping the removal")
 		changed = false
 	} else if changed {
diff --git a/pkg/provider/azure_loadbalancer_healthprobe.go b/pkg/provider/azure_loadbalancer_healthprobe.go
index ee3281294..281a8d94d 100644
--- a/pkg/provider/azure_loadbalancer_healthprobe.go
+++ b/pkg/provider/azure_loadbalancer_healthprobe.go
@@ -160,7 +160,7 @@ func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port
 	case strings.EqualFold(*protocol, string(network.ProtocolHTTPS)):
 		//HTTPS probe is only supported in standard loadbalancer
 		//For backward compatibility,when unsupported protocol is used, fall back to tcp protocol in basic lb mode instead
-		if !az.useStandardLoadBalancer() {
+		if !az.UseStandardLoadBalancer() {
 			properties.Protocol = network.ProbeProtocolTCP
 		} else {
 			properties.Protocol = network.ProbeProtocolHTTPS
diff --git a/pkg/provider/azure_loadbalancer_repo.go b/pkg/provider/azure_loadbalancer_repo.go
index 189b0c955..9141db1ff 100644
--- a/pkg/provider/azure_loadbalancer_repo.go
+++ b/pkg/provider/azure_loadbalancer_repo.go
@@ -109,7 +109,7 @@ func (az *Cloud) ListManagedLBs(ctx context.Context, service *v1.Service, nodes
 		}
 	}
 
-	if az.useMultipleStandardLoadBalancers() {
+	if az.UseMultipleStandardLoadBalancers() {
 		for _, multiSLBConfig := range az.MultipleStandardLoadBalancerConfigurations {
 			managedLBNames.Insert(multiSLBConfig.Name, fmt.Sprintf("%s%s", multiSLBConfig.Name, consts.InternalLoadBalancerNameSuffix))
 		}
diff --git a/pkg/provider/azure_local_services.go b/pkg/provider/azure_local_services.go
index f2b3aad82..0febc94ed 100644
--- a/pkg/provider/azure_local_services.go
+++ b/pkg/provider/azure_local_services.go
@@ -408,7 +408,7 @@ func getLocalServiceBackendPoolName(serviceName string, ipv6 bool) string {
 // getBackendPoolNameForService determine the expected backend pool name
 // by checking the external traffic policy of the service.
 func (az *Cloud) getBackendPoolNameForService(service *v1.Service, clusterName string, ipv6 bool) string {
-	if !isLocalService(service) || !az.useMultipleStandardLoadBalancers() {
+	if !isLocalService(service) || !az.UseMultipleStandardLoadBalancers() {
 		return getBackendPoolName(clusterName, ipv6)
 	}
 	return getLocalServiceBackendPoolName(getServiceName(service), ipv6)
@@ -417,7 +417,7 @@ func (az *Cloud) getBackendPoolNameForService(service *v1.Service, clusterName s
 // getBackendPoolNamesForService determine the expected backend pool names
 // by checking the external traffic policy of the service.
 func (az *Cloud) getBackendPoolNamesForService(service *v1.Service, clusterName string) map[bool]string {
-	if !isLocalService(service) || !az.useMultipleStandardLoadBalancers() {
+	if !isLocalService(service) || !az.UseMultipleStandardLoadBalancers() {
 		return getBackendPoolNames(clusterName)
 	}
 	return map[bool]string{
@@ -429,7 +429,7 @@ func (az *Cloud) getBackendPoolNamesForService(service *v1.Service, clusterName
 // getBackendPoolIDsForService determine the expected backend pool IDs
 // by checking the external traffic policy of the service.
 func (az *Cloud) getBackendPoolIDsForService(service *v1.Service, clusterName, lbName string) map[bool]string {
-	if !isLocalService(service) || !az.useMultipleStandardLoadBalancers() {
+	if !isLocalService(service) || !az.UseMultipleStandardLoadBalancers() {
 		return az.getBackendPoolIDs(clusterName, lbName)
 	}
 	return map[bool]string{
diff --git a/pkg/provider/azure_standard.go b/pkg/provider/azure_standard.go
index 6ec29f657..79b13824c 100644
--- a/pkg/provider/azure_standard.go
+++ b/pkg/provider/azure_standard.go
@@ -694,7 +694,7 @@ func (as *availabilitySet) getAgentPoolAvailabilitySets(vms []compute.VirtualMac
 // annotation would be ignored when using one SLB per cluster.
 func (as *availabilitySet) GetVMSetNames(ctx context.Context, service *v1.Service, nodes []*v1.Node) (availabilitySetNames *[]string, err error) {
 	hasMode, isAuto, serviceAvailabilitySetName := as.getServiceLoadBalancerMode(service)
-	if !hasMode || as.useStandardLoadBalancer() {
+	if !hasMode || as.UseStandardLoadBalancer() {
 		// no mode specified in service annotation or use single SLB mode
 		// default to PrimaryAvailabilitySetName
 		availabilitySetNames = &[]string{as.Config.PrimaryAvailabilitySetName}
@@ -825,7 +825,7 @@ func (as *availabilitySet) getPrimaryInterfaceWithVMSet(ctx context.Context, nod
 	//   don't check vmSet for it.
 	// - For multiple standard SKU load balancers, the behavior is similar to the basic LB.
 	needCheck := false
-	if !as.useStandardLoadBalancer() {
+	if !as.UseStandardLoadBalancer() {
 		// need to check the vmSet name when using the basic LB
 		needCheck = true
 	}
@@ -904,7 +904,7 @@ func (as *availabilitySet) EnsureHostInPool(ctx context.Context, service *v1.Ser
 		}
 	}
 	if !foundPool {
-		if as.useStandardLoadBalancer() && len(newBackendPools) > 0 {
+		if as.UseStandardLoadBalancer() && len(newBackendPools) > 0 {
 			// Although standard load balancer supports backends from multiple availability
 			// sets, the same network interface couldn't be added to more than one load balancer of
 			// the same type. Omit those nodes (e.g. masters) so Azure ARM won't complain
@@ -954,7 +954,7 @@ func (as *availabilitySet) EnsureHostsInPool(ctx context.Context, service *v1.Se
 	hostUpdates := make([]func() error, 0, len(nodes))
 	for _, node := range nodes {
 		localNodeName := node.Name
-		if as.useStandardLoadBalancer() && as.excludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
+		if as.UseStandardLoadBalancer() && as.ExcludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
 			klog.V(4).Infof("Excluding master node %q from load balancer backendpool %q", localNodeName, backendPoolID)
 			continue
 		}
diff --git a/pkg/provider/azure_vmss.go b/pkg/provider/azure_vmss.go
index 06222ab63..0db63e3e1 100644
--- a/pkg/provider/azure_vmss.go
+++ b/pkg/provider/azure_vmss.go
@@ -872,7 +872,7 @@ func (ss *ScaleSet) getAgentPoolScaleSets(ctx context.Context, nodes []*v1.Node)
 // for loadbalancer exists then return the eligible VMSet.
 func (ss *ScaleSet) GetVMSetNames(ctx context.Context, service *v1.Service, nodes []*v1.Node) (*[]string, error) {
 	hasMode, isAuto, serviceVMSetName := ss.getServiceLoadBalancerMode(service)
-	if !hasMode || ss.useStandardLoadBalancer() {
+	if !hasMode || ss.UseStandardLoadBalancer() {
 		// no mode specified in service annotation or use single SLB mode
 		// default to PrimaryScaleSetName
 		scaleSetNames := &[]string{ss.Config.PrimaryScaleSetName}
@@ -1069,7 +1069,7 @@ func (ss *ScaleSet) EnsureHostInPool(ctx context.Context, _ *v1.Service, nodeNam
 	//   don't check vmSet for it.
 	// - For multiple standard SKU load balancers, the behavior is similar to the basic load balancer
 	needCheck := false
-	if !ss.useStandardLoadBalancer() {
+	if !ss.UseStandardLoadBalancer() {
 		// need to check the vmSet name when using the basic LB
 		needCheck = true
 	}
@@ -1115,7 +1115,7 @@ func (ss *ScaleSet) EnsureHostInPool(ctx context.Context, _ *v1.Service, nodeNam
 		return "", "", "", nil, nil
 	}
 
-	if ss.useStandardLoadBalancer() && len(newBackendPools) > 0 {
+	if ss.UseStandardLoadBalancer() && len(newBackendPools) > 0 {
 		// Although standard load balancer supports backends from multiple scale
 		// sets, the same network interface couldn't be added to more than one load balancer of
 		// the same type. Omit those nodes (e.g. masters) so Azure ARM won't complain
@@ -1183,9 +1183,9 @@ func (ss *ScaleSet) ensureVMSSInPool(ctx context.Context, _ *v1.Service, nodes [
 
 	// the single standard load balancer supports multiple vmss in its backend while
 	// multiple standard load balancers and the basic load balancer doesn't
-	if ss.useStandardLoadBalancer() {
+	if ss.UseStandardLoadBalancer() {
 		for _, node := range nodes {
-			if ss.excludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
+			if ss.ExcludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
 				continue
 			}
 
@@ -1282,7 +1282,7 @@ func (ss *ScaleSet) ensureVMSSInPool(ctx context.Context, _ *v1.Service, nodes [
 			continue
 		}
 
-		if ss.useStandardLoadBalancer() && len(loadBalancerBackendAddressPools) > 0 {
+		if ss.UseStandardLoadBalancer() && len(loadBalancerBackendAddressPools) > 0 {
 			// Although standard load balancer supports backends from multiple scale
 			// sets, the same network interface couldn't be added to more than one load balancer of
 			// the same type. Omit those nodes (e.g. masters) so Azure ARM won't complain
@@ -1390,7 +1390,7 @@ func (ss *ScaleSet) ensureHostsInPool(ctx context.Context, service *v1.Service,
 	for _, node := range nodes {
 		localNodeName := node.Name
 
-		if ss.useStandardLoadBalancer() && ss.excludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
+		if ss.UseStandardLoadBalancer() && ss.ExcludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
 			klog.V(4).Infof("Excluding master node %q from load balancer backendpool %q", localNodeName, backendPoolID)
 			continue
 		}
@@ -1491,7 +1491,7 @@ func (ss *ScaleSet) EnsureHostsInPool(ctx context.Context, service *v1.Service,
 	for _, node := range nodes {
 		localNodeName := node.Name
 
-		if ss.useStandardLoadBalancer() && ss.excludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
+		if ss.UseStandardLoadBalancer() && ss.ExcludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
 			klog.V(4).Infof("Excluding master node %q from load balancer backendpool %q", localNodeName, backendPoolID)
 			continue
 		}
@@ -1516,7 +1516,7 @@ func (ss *ScaleSet) EnsureHostsInPool(ctx context.Context, service *v1.Service,
 		if vmManagementType == ManagedByAvSet {
 			// vm is managed by availability set.
 			// VMAS nodes should also be added to the SLB backends.
-			if ss.useStandardLoadBalancer() {
+			if ss.UseStandardLoadBalancer() {
 				vmasNodes = append(vmasNodes, node)
 				continue
 			}
@@ -1525,7 +1525,7 @@ func (ss *ScaleSet) EnsureHostsInPool(ctx context.Context, service *v1.Service,
 		}
 		if vmManagementType == ManagedByVmssFlex {
 			// vm is managed by vmss flex.
-			if ss.useStandardLoadBalancer() {
+			if ss.UseStandardLoadBalancer() {
 				vmssFlexNodes = append(vmssFlexNodes, node)
 				continue
 			}
@@ -1674,7 +1674,7 @@ func getScaleSetAndResourceGroupNameByIPConfigurationID(ipConfigurationID string
 }
 
 func (ss *ScaleSet) ensureBackendPoolDeletedFromVMSS(ctx context.Context, backendPoolIDs []string, vmSetName string) error {
-	if !ss.useStandardLoadBalancer() {
+	if !ss.UseStandardLoadBalancer() {
 		found := false
 
 		cachedUniform, err := ss.vmssCache.Get(ctx, consts.VMSSKey, azcache.CacheReadTypeDefault)
@@ -1733,7 +1733,7 @@ func (ss *ScaleSet) ensureBackendPoolDeletedFromVMSS(ctx context.Context, backen
 func (ss *ScaleSet) ensureBackendPoolDeletedFromVmssUniform(ctx context.Context, backendPoolIDs []string, vmSetName string) error {
 	vmssNamesMap := make(map[string]bool)
 	// the standard load balancer supports multiple vmss in its backend while the basic sku doesn't
-	if ss.useStandardLoadBalancer() {
+	if ss.UseStandardLoadBalancer() {
 		cachedUniform, err := ss.vmssCache.Get(ctx, consts.VMSSKey, azcache.CacheReadTypeDefault)
 		if err != nil {
 			klog.Errorf("ensureBackendPoolDeletedFromVMSS: failed to get vmss uniform from cache: %v", err)
@@ -1860,7 +1860,7 @@ func (ss *ScaleSet) ensureBackendPoolDeleted(ctx context.Context, service *v1.Se
 		var err error
 		if scaleSetName, err = extractScaleSetNameByProviderID(ipConfigurationID); err == nil {
 			// Only remove nodes belonging to specified vmSet to basic LB backends.
-			if !ss.useStandardLoadBalancer() && !strings.EqualFold(scaleSetName, vmSetName) {
+			if !ss.UseStandardLoadBalancer() && !strings.EqualFold(scaleSetName, vmSetName) {
 				continue
 			}
 		}
@@ -2313,7 +2313,7 @@ func (ss *ScaleSet) VMSSBatchSize(ctx context.Context, vmssName string) (int, er
 		return 0, fmt.Errorf("get vmss batch size: %w", err)
 	}
 	if _, ok := vmss.Tags[consts.VMSSTagForBatchOperation]; ok {
-		batchSize = ss.getPutVMSSVMBatchSize()
+		batchSize = ss.GetPutVMSSVMBatchSize()
 	}
 	klog.V(2).InfoS("Fetch VMSS batch size", "vmss", vmssName, "size", batchSize)
 	return batchSize, nil
diff --git a/pkg/provider/azure_vmssflex.go b/pkg/provider/azure_vmssflex.go
index 1e803a4c1..662eded7b 100644
--- a/pkg/provider/azure_vmssflex.go
+++ b/pkg/provider/azure_vmssflex.go
@@ -135,7 +135,7 @@ func (fs *FlexScaleSet) GetAgentPoolVMSetNames(ctx context.Context, nodes []*v1.
 // annotation would be ignored when using one SLB per cluster.
 func (fs *FlexScaleSet) GetVMSetNames(ctx context.Context, service *v1.Service, nodes []*v1.Node) (*[]string, error) {
 	hasMode, isAuto, serviceVMSetName := fs.getServiceLoadBalancerMode(service)
-	if !hasMode || fs.useStandardLoadBalancer() {
+	if !hasMode || fs.UseStandardLoadBalancer() {
 		// no mode specified in service annotation or use single SLB mode
 		// default to PrimaryScaleSetName
 		vmssFlexNames := &[]string{fs.Config.PrimaryScaleSetName}
@@ -459,7 +459,7 @@ func (fs *FlexScaleSet) EnsureHostInPool(ctx context.Context, service *v1.Servic
 	//   don't check vmSet for it.
 	// - For multiple standard SKU load balancers, return nil if the node's scale set is mismatched with vmSetNameOfLB
 	needCheck := false
-	if !fs.useStandardLoadBalancer() {
+	if !fs.UseStandardLoadBalancer() {
 		return "", "", "", nil, fmt.Errorf("EnsureHostInPool: VMSS Flex does not support Basic Load Balancer")
 	}
 	if vmSetNameOfLB != "" && needCheck && !strings.EqualFold(vmSetNameOfLB, vmssFlexName) {
@@ -508,7 +508,7 @@ func (fs *FlexScaleSet) EnsureHostInPool(ctx context.Context, service *v1.Servic
 		return "", "", "", nil, nil
 	}
 
-	if fs.useStandardLoadBalancer() && len(newBackendPools) > 0 {
+	if fs.UseStandardLoadBalancer() && len(newBackendPools) > 0 {
 		// Although standard load balancer supports backends from multiple availability
 		// sets, the same network interface couldn't be added to more than one load balancer of
 		// the same type. Omit those nodes (e.g. masters) so Azure ARM won't complain
@@ -556,15 +556,15 @@ func (fs *FlexScaleSet) ensureVMSSFlexInPool(ctx context.Context, _ *v1.Service,
 	klog.V(2).Infof("ensureVMSSFlexInPool: ensuring VMSS Flex with backendPoolID %s", backendPoolID)
 	vmssFlexIDsMap := make(map[string]bool)
 
-	if !fs.useStandardLoadBalancer() {
+	if !fs.UseStandardLoadBalancer() {
 		return fmt.Errorf("ensureVMSSFlexInPool: VMSS Flex does not support Basic Load Balancer")
 	}
 
 	// the single standard load balancer supports multiple vmss in its backend while
 	// multiple standard load balancers doesn't
-	if fs.useStandardLoadBalancer() {
+	if fs.UseStandardLoadBalancer() {
 		for _, node := range nodes {
-			if fs.excludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
+			if fs.ExcludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
 				continue
 			}
 
@@ -649,7 +649,7 @@ func (fs *FlexScaleSet) ensureVMSSFlexInPool(ctx context.Context, _ *v1.Service,
 			continue
 		}
 
-		if fs.useStandardLoadBalancer() && len(loadBalancerBackendAddressPools) > 0 {
+		if fs.UseStandardLoadBalancer() && len(loadBalancerBackendAddressPools) > 0 {
 			// Although standard load balancer supports backends from multiple scale
 			// sets, the same network interface couldn't be added to more than one load balancer of
 			// the same type. Omit those nodes (e.g. masters) so Azure ARM won't complain
@@ -719,7 +719,7 @@ func (fs *FlexScaleSet) EnsureHostsInPool(ctx context.Context, service *v1.Servi
 	hostUpdates := make([]func() error, 0, len(nodes))
 	for _, node := range nodes {
 		localNodeName := node.Name
-		if fs.useStandardLoadBalancer() && fs.excludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
+		if fs.UseStandardLoadBalancer() && fs.ExcludeMasterNodesFromStandardLB() && isControlPlaneNode(node) {
 			klog.V(4).Infof("Excluding master node %q from load balancer backendpool %q", localNodeName, backendPoolID)
 			continue
 		}
@@ -755,7 +755,7 @@ func (fs *FlexScaleSet) EnsureHostsInPool(ctx context.Context, service *v1.Servi
 
 func (fs *FlexScaleSet) ensureBackendPoolDeletedFromVmssFlex(ctx context.Context, backendPoolIDs []string, vmSetName string) error {
 	vmssNamesMap := make(map[string]bool)
-	if fs.useStandardLoadBalancer() {
+	if fs.UseStandardLoadBalancer() {
 		cached, err := fs.vmssFlexCache.Get(ctx, consts.VmssFlexKey, azcache.CacheReadTypeDefault)
 		if err != nil {
 			klog.Errorf("ensureBackendPoolDeletedFromVmssFlex: failed to get vmss flex from cache: %v", err)
@@ -904,7 +904,7 @@ func (fs *FlexScaleSet) EnsureBackendPoolDeleted(ctx context.Context, service *v
 		}
 		// only vmsses in the resource group same as it's in azure config are included
 		if strings.EqualFold(resourceGroupName, fs.ResourceGroup) {
-			if fs.useStandardLoadBalancer() {
+			if fs.UseStandardLoadBalancer() {
 				vmssFlexVMNameMap[nodeName] = nicName
 			} else {
 				if strings.EqualFold(vmssFlexName, vmSetName) {
diff --git a/pkg/provider/azure_wrap.go b/pkg/provider/azure_wrap.go
index 614c01233..054fd24fa 100644
--- a/pkg/provider/azure_wrap.go
+++ b/pkg/provider/azure_wrap.go
@@ -50,22 +50,6 @@ func checkResourceExistsFromError(err *retry.Error) (bool, *retry.Error) {
 	return false, err
 }
 
-func (az *Cloud) useStandardLoadBalancer() bool {
-	return strings.EqualFold(az.LoadBalancerSku, consts.LoadBalancerSkuStandard)
-}
-
-func (az *Cloud) excludeMasterNodesFromStandardLB() bool {
-	return az.ExcludeMasterFromStandardLB != nil && *az.ExcludeMasterFromStandardLB
-}
-
-func (az *Cloud) disableLoadBalancerOutboundSNAT() bool {
-	if !az.useStandardLoadBalancer() || az.DisableOutboundSNAT == nil {
-		return false
-	}
-
-	return *az.DisableOutboundSNAT
-}
-
 // IsNodeUnmanaged returns true if the node is not managed by Azure cloud provider.
 // Those nodes includes on-prem or VMs from other clouds. They will not be added to load balancer
 // backends. Azure routes and managed disks are also not supported for them.
diff --git a/pkg/provider/azure_zones.go b/pkg/provider/azure_zones.go
index 8e05dd944..b5f030613 100644
--- a/pkg/provider/azure_zones.go
+++ b/pkg/provider/azure_zones.go
@@ -73,7 +73,7 @@ func (az *Cloud) updateRegionZonesMap(zones map[string][]string) {
 }
 
 func (az *Cloud) getRegionZonesBackoff(ctx context.Context, region string) ([]string, error) {
-	if az.isStackCloud() {
+	if az.IsStackCloud() {
 		// Azure Stack does not support zone at the moment
 		// https://docs.microsoft.com/en-us/azure-stack/user/azure-stack-network-differences?view=azs-2102
 		klog.V(3).Infof("getRegionZonesMapWrapper: Azure Stack does not support Zones at the moment, skipping")
diff --git a/pkg/provider/config/azure.go b/pkg/provider/config/azure.go
new file mode 100644
index 000000000..c643234da
--- /dev/null
+++ b/pkg/provider/config/azure.go
@@ -0,0 +1,216 @@
+/*
+Copyright 2024 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package config
+
+import (
+	"strings"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader"
+	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
+)
+
+// Config holds the configuration parsed from the --cloud-config flag
+// All fields are required unless otherwise specified
+// NOTE: Cloud config files should follow the same Kubernetes deprecation policy as
+// flags or CLIs. Config fields should not change behavior in incompatible ways and
+// should be deprecated for at least 2 release prior to removing.
+// See https://kubernetes.io/docs/reference/using-api/deprecation-policy/#deprecating-a-flag-or-cli
+// for more details.
+type Config struct {
+	AzureClientConfig `json:",inline" yaml:",inline"`
+
+	// The cloud configure type for Azure cloud provider. Supported values are file, secret and merge.
+	CloudConfigType configloader.CloudConfigType `json:"cloudConfigType,omitempty" yaml:"cloudConfigType,omitempty"`
+
+	// The name of the resource group that the cluster is deployed in
+	ResourceGroup string `json:"resourceGroup,omitempty" yaml:"resourceGroup,omitempty"`
+	// The location of the resource group that the cluster is deployed in
+	Location string `json:"location,omitempty" yaml:"location,omitempty"`
+	// The name of site where the cluster will be deployed to that is more granular than the region specified by the "location" field.
+	// Currently only public ip, load balancer and managed disks support this.
+	ExtendedLocationName string `json:"extendedLocationName,omitempty" yaml:"extendedLocationName,omitempty"`
+	// The type of site that is being targeted.
+	// Currently only public ip, load balancer and managed disks support this.
+	ExtendedLocationType string `json:"extendedLocationType,omitempty" yaml:"extendedLocationType,omitempty"`
+	// The name of the VNet that the cluster is deployed in
+	VnetName string `json:"vnetName,omitempty" yaml:"vnetName,omitempty"`
+	// The name of the resource group that the Vnet is deployed in
+	VnetResourceGroup string `json:"vnetResourceGroup,omitempty" yaml:"vnetResourceGroup,omitempty"`
+	// The name of the subnet that the cluster is deployed in
+	SubnetName string `json:"subnetName,omitempty" yaml:"subnetName,omitempty"`
+	// The name of the security group attached to the cluster's subnet
+	SecurityGroupName string `json:"securityGroupName,omitempty" yaml:"securityGroupName,omitempty"`
+	// The name of the resource group that the security group is deployed in
+	SecurityGroupResourceGroup string `json:"securityGroupResourceGroup,omitempty" yaml:"securityGroupResourceGroup,omitempty"`
+	// (Optional in 1.6) The name of the route table attached to the subnet that the cluster is deployed in
+	RouteTableName string `json:"routeTableName,omitempty" yaml:"routeTableName,omitempty"`
+	// The name of the resource group that the RouteTable is deployed in
+	RouteTableResourceGroup string `json:"routeTableResourceGroup,omitempty" yaml:"routeTableResourceGroup,omitempty"`
+	// (Optional) The name of the availability set that should be used as the load balancer backend
+	// If this is set, the Azure cloudprovider will only add nodes from that availability set to the load
+	// balancer backend pool. If this is not set, and multiple agent pools (availability sets) are used, then
+	// the cloudprovider will try to add all nodes to a single backend pool which is forbidden.
+	// In other words, if you use multiple agent pools (availability sets), you MUST set this field.
+	PrimaryAvailabilitySetName string `json:"primaryAvailabilitySetName,omitempty" yaml:"primaryAvailabilitySetName,omitempty"`
+	// The type of azure nodes. Candidate values are: vmss, standard and vmssflex.
+	// If not set, it will be default to vmss.
+	VMType string `json:"vmType,omitempty" yaml:"vmType,omitempty"`
+	// The name of the scale set that should be used as the load balancer backend.
+	// If this is set, the Azure cloudprovider will only add nodes from that scale set to the load
+	// balancer backend pool. If this is not set, and multiple agent pools (scale sets) are used, then
+	// the cloudprovider will try to add all nodes to a single backend pool which is forbidden in the basic sku.
+	// In other words, if you use multiple agent pools (scale sets), and loadBalancerSku is set to basic, you MUST set this field.
+	PrimaryScaleSetName string `json:"primaryScaleSetName,omitempty" yaml:"primaryScaleSetName,omitempty"`
+	// Tags determines what tags shall be applied to the shared resources managed by controller manager, which
+	// includes load balancer, security group and route table. The supported format is `a=b,c=d,...`. After updated
+	// this config, the old tags would be replaced by the new ones.
+	// Because special characters are not supported in "tags" configuration, "tags" support would be removed in a future release,
+	// please consider migrating the config to "tagsMap".
+	Tags string `json:"tags,omitempty" yaml:"tags,omitempty"`
+	// TagsMap is similar to Tags but holds tags with special characters such as `=` and `,`.
+	TagsMap map[string]string `json:"tagsMap,omitempty" yaml:"tagsMap,omitempty"`
+	// SystemTags determines the tag keys managed by cloud provider. If it is not set, no tags would be deleted if
+	// the `Tags` is changed. However, the old tags would be deleted if they are neither included in `Tags` nor
+	// in `SystemTags` after the update of `Tags`.
+	SystemTags string `json:"systemTags,omitempty" yaml:"systemTags,omitempty"`
+	// Sku of Load Balancer and Public IP. Candidate values are: basic and standard.
+	// If not set, it will be default to basic.
+	LoadBalancerSku string `json:"loadBalancerSku,omitempty" yaml:"loadBalancerSku,omitempty"`
+	// LoadBalancerName determines the specific name of the load balancer user want to use, working with
+	// LoadBalancerResourceGroup
+	LoadBalancerName string `json:"loadBalancerName,omitempty" yaml:"loadBalancerName,omitempty"`
+	// LoadBalancerResourceGroup determines the specific resource group of the load balancer user want to use, working
+	// with LoadBalancerName
+	LoadBalancerResourceGroup string `json:"loadBalancerResourceGroup,omitempty" yaml:"loadBalancerResourceGroup,omitempty"`
+	// PreConfiguredBackendPoolLoadBalancerTypes determines whether the LoadBalancer BackendPool has been preconfigured.
+	// Candidate values are:
+	//   "": exactly with today (not pre-configured for any LBs)
+	//   "internal": for internal LoadBalancer
+	//   "external": for external LoadBalancer
+	//   "all": for both internal and external LoadBalancer
+	PreConfiguredBackendPoolLoadBalancerTypes string `json:"preConfiguredBackendPoolLoadBalancerTypes,omitempty" yaml:"preConfiguredBackendPoolLoadBalancerTypes,omitempty"`
+
+	// DisableAvailabilitySetNodes disables VMAS nodes support when "VMType" is set to "vmss".
+	DisableAvailabilitySetNodes bool `json:"disableAvailabilitySetNodes,omitempty" yaml:"disableAvailabilitySetNodes,omitempty"`
+	// EnableVmssFlexNodes enables vmss flex nodes support when "VMType" is set to "vmss".
+	EnableVmssFlexNodes bool `json:"enableVmssFlexNodes,omitempty" yaml:"enableVmssFlexNodes,omitempty"`
+	// DisableAzureStackCloud disables AzureStackCloud support. It should be used
+	// when setting AzureAuthConfig.Cloud with "AZURESTACKCLOUD" to customize ARM endpoints
+	// while the cluster is not running on AzureStack.
+	DisableAzureStackCloud bool `json:"disableAzureStackCloud,omitempty" yaml:"disableAzureStackCloud,omitempty"`
+	// Use instance metadata service where possible
+	UseInstanceMetadata bool `json:"useInstanceMetadata,omitempty" yaml:"useInstanceMetadata,omitempty"`
+
+	// Backoff exponent
+	CloudProviderBackoffExponent float64 `json:"cloudProviderBackoffExponent,omitempty" yaml:"cloudProviderBackoffExponent,omitempty"`
+	// Backoff jitter
+	CloudProviderBackoffJitter float64 `json:"cloudProviderBackoffJitter,omitempty" yaml:"cloudProviderBackoffJitter,omitempty"`
+
+	// ExcludeMasterFromStandardLB excludes master nodes from standard load balancer.
+	// If not set, it will be default to true.
+	ExcludeMasterFromStandardLB *bool `json:"excludeMasterFromStandardLB,omitempty" yaml:"excludeMasterFromStandardLB,omitempty"`
+	// DisableOutboundSNAT disables the outbound SNAT for public load balancer rules.
+	// It should only be set when loadBalancerSku is standard. If not set, it will be default to false.
+	DisableOutboundSNAT *bool `json:"disableOutboundSNAT,omitempty" yaml:"disableOutboundSNAT,omitempty"`
+
+	// Maximum allowed LoadBalancer Rule Count is the limit enforced by Azure Load balancer
+	MaximumLoadBalancerRuleCount int `json:"maximumLoadBalancerRuleCount,omitempty" yaml:"maximumLoadBalancerRuleCount,omitempty"`
+
+	// LoadBalancerBackendPoolConfigurationType defines how vms join the load balancer backend pools. Supported values
+	// are `nodeIPConfiguration`, `nodeIP` and `podIP`.
+	// `nodeIPConfiguration`: vm network interfaces will be attached to the inbound backend pool of the load balancer (default);
+	// `nodeIP`: vm private IPs will be attached to the inbound backend pool of the load balancer;
+	// `podIP`: pod IPs will be attached to the inbound backend pool of the load balancer (not supported yet).
+	LoadBalancerBackendPoolConfigurationType string `json:"loadBalancerBackendPoolConfigurationType,omitempty" yaml:"loadBalancerBackendPoolConfigurationType,omitempty"`
+	// PutVMSSVMBatchSize defines how many requests the client send concurrently when putting the VMSS VMs.
+	// If it is smaller than or equal to zero, the request will be sent one by one in sequence (default).
+	PutVMSSVMBatchSize int `json:"putVMSSVMBatchSize" yaml:"putVMSSVMBatchSize"`
+	// PrivateLinkServiceResourceGroup determines the specific resource group of the private link services user want to use
+	PrivateLinkServiceResourceGroup string `json:"privateLinkServiceResourceGroup,omitempty" yaml:"privateLinkServiceResourceGroup,omitempty"`
+
+	// EnableMigrateToIPBasedBackendPoolAPI uses the migration API to migrate from NIC-based to IP-based backend pool.
+	// The migration API can provide a migration from NIC-based to IP-based backend pool without service downtime.
+	// If the API is not used, the migration will be done by decoupling all nodes on the backend pool and then re-attaching
+	// node IPs, which will introduce service downtime. The downtime increases with the number of nodes in the backend pool.
+	EnableMigrateToIPBasedBackendPoolAPI bool `json:"enableMigrateToIPBasedBackendPoolAPI" yaml:"enableMigrateToIPBasedBackendPoolAPI"`
+
+	// MultipleStandardLoadBalancerConfigurations stores the properties regarding multiple standard load balancers.
+	// It will be ignored if LoadBalancerBackendPoolConfigurationType is nodeIPConfiguration.
+	// If the length is not 0, it is assumed the multiple standard load balancers mode is on. In this case,
+	// there must be one configuration named "<clustername>" or an error will be reported.
+	MultipleStandardLoadBalancerConfigurations []MultipleStandardLoadBalancerConfiguration `json:"multipleStandardLoadBalancerConfigurations,omitempty" yaml:"multipleStandardLoadBalancerConfigurations,omitempty"`
+
+	// RouteUpdateIntervalInSeconds is the interval for updating routes. Default is 30 seconds.
+	RouteUpdateIntervalInSeconds int `json:"routeUpdateIntervalInSeconds,omitempty" yaml:"routeUpdateIntervalInSeconds,omitempty"`
+	// LoadBalancerBackendPoolUpdateIntervalInSeconds is the interval for updating load balancer backend pool of local services. Default is 30 seconds.
+	LoadBalancerBackendPoolUpdateIntervalInSeconds int `json:"loadBalancerBackendPoolUpdateIntervalInSeconds,omitempty" yaml:"loadBalancerBackendPoolUpdateIntervalInSeconds,omitempty"`
+
+	// ClusterServiceLoadBalancerHealthProbeMode determines the health probe mode for cluster service load balancer.
+	// Supported values are `shared` and `servicenodeport`.
+	// `servicenodeport`: the health probe will be created against each port of each service by watching the backend application (default).
+	// `shared`: all cluster services shares one HTTP probe targeting the kube-proxy on the node (<nodeIP>/healthz:10256).
+	ClusterServiceLoadBalancerHealthProbeMode string `json:"clusterServiceLoadBalancerHealthProbeMode,omitempty" yaml:"clusterServiceLoadBalancerHealthProbeMode,omitempty"`
+	// ClusterServiceSharedLoadBalancerHealthProbePort defines the target port of the shared health probe. Default to 10256.
+	ClusterServiceSharedLoadBalancerHealthProbePort int32 `json:"clusterServiceSharedLoadBalancerHealthProbePort,omitempty" yaml:"clusterServiceSharedLoadBalancerHealthProbePort,omitempty"`
+	// ClusterServiceSharedLoadBalancerHealthProbePath defines the target path of the shared health probe. Default to `/healthz`.
+	ClusterServiceSharedLoadBalancerHealthProbePath string `json:"clusterServiceSharedLoadBalancerHealthProbePath,omitempty" yaml:"clusterServiceSharedLoadBalancerHealthProbePath,omitempty"`
+}
+
+// HasExtendedLocation returns true if extendedlocation prop are specified.
+func (az *Config) HasExtendedLocation() bool {
+	return az.ExtendedLocationName != "" && az.ExtendedLocationType != ""
+}
+
+func (az *Config) IsLBBackendPoolTypeNodeIPConfig() bool {
+	return strings.EqualFold(az.LoadBalancerBackendPoolConfigurationType, consts.LoadBalancerBackendPoolConfigurationTypeNodeIPConfiguration)
+}
+
+func (az *Config) IsLBBackendPoolTypeNodeIP() bool {
+	return strings.EqualFold(az.LoadBalancerBackendPoolConfigurationType, consts.LoadBalancerBackendPoolConfigurationTypeNodeIP)
+}
+
+func (az *Config) GetPutVMSSVMBatchSize() int {
+	return az.PutVMSSVMBatchSize
+}
+
+func (az *Config) UseStandardLoadBalancer() bool {
+	return strings.EqualFold(az.LoadBalancerSku, consts.LoadBalancerSkuStandard)
+}
+
+func (az *Config) ExcludeMasterNodesFromStandardLB() bool {
+	return az.ExcludeMasterFromStandardLB != nil && *az.ExcludeMasterFromStandardLB
+}
+
+func (az *Config) DisableLoadBalancerOutboundSNAT() bool {
+	if !az.UseStandardLoadBalancer() || az.DisableOutboundSNAT == nil {
+		return false
+	}
+
+	return *az.DisableOutboundSNAT
+}
+
+func (az *Config) UseMultipleStandardLoadBalancers() bool {
+	return az.UseStandardLoadBalancer() && len(az.MultipleStandardLoadBalancerConfigurations) > 0
+}
+
+func (az *Config) UseSingleStandardLoadBalancer() bool {
+	return az.UseStandardLoadBalancer() && len(az.MultipleStandardLoadBalancerConfigurations) == 0
+}
+
+func (az *Config) IsStackCloud() bool {
+	return strings.EqualFold(az.Cloud, consts.AzureStackCloudName) && !az.DisableAzureStackCloud
+}
diff --git a/pkg/provider/config/env.go b/pkg/provider/config/env.go
new file mode 100644
index 000000000..e57f3d6f2
--- /dev/null
+++ b/pkg/provider/config/env.go
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package config
+
+import (
+	"io"
+	"os"
+	"strings"
+
+	"sigs.k8s.io/yaml"
+)
+
+// ParseConfig returns a parsed configuration for an Azure cloudprovider config file
+func ParseConfig(configReader io.Reader) (*Config, error) {
+	var config Config
+	if configReader == nil {
+		return nil, nil
+	}
+
+	configContents, err := io.ReadAll(configReader)
+	if err != nil {
+		return nil, err
+	}
+
+	err = yaml.Unmarshal(configContents, &config)
+	if err != nil {
+		return nil, err
+	}
+
+	// The resource group name may be in different cases from different Azure APIs, hence it is converted to lower here.
+	// See more context at https://github.com/kubernetes/kubernetes/issues/71994.
+	config.ResourceGroup = strings.ToLower(config.ResourceGroup)
+
+	// these environment variables are injected by workload identity webhook
+	if tenantID := os.Getenv("AZURE_TENANT_ID"); tenantID != "" {
+		config.TenantID = tenantID
+	}
+	if clientID := os.Getenv("AZURE_CLIENT_ID"); clientID != "" {
+		config.AADClientID = clientID
+	}
+	if federatedTokenFile := os.Getenv("AZURE_FEDERATED_TOKEN_FILE"); federatedTokenFile != "" {
+		config.AADFederatedTokenFile = federatedTokenFile
+		config.UseFederatedWorkloadIdentityExtension = true
+	}
+	return &config, nil
+}
diff --git a/pkg/provider/config/multi_slb.go b/pkg/provider/config/multi_slb.go
new file mode 100644
index 000000000..079d4afb1
--- /dev/null
+++ b/pkg/provider/config/multi_slb.go
@@ -0,0 +1,73 @@
+/*
+Copyright 2024 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package config
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
+)
+
+// MultipleStandardLoadBalancerConfiguration stores the properties regarding multiple standard load balancers.
+type MultipleStandardLoadBalancerConfiguration struct {
+	// Name of the public load balancer. There will be an internal load balancer
+	// created if needed, and the name will be `<name>-internal`. The internal lb
+	// shares the same configurations as the external one. The internal lbs
+	// are not needed to be included in `MultipleStandardLoadBalancerConfigurations`.
+	// There must be a name of "<clustername>" in the load balancer configuration list.
+	Name string `json:"name" yaml:"name"`
+
+	MultipleStandardLoadBalancerConfigurationSpec
+
+	MultipleStandardLoadBalancerConfigurationStatus
+}
+
+// MultipleStandardLoadBalancerConfigurationSpec stores the properties regarding multiple standard load balancers.
+type MultipleStandardLoadBalancerConfigurationSpec struct {
+	// This load balancer can have services placed on it. Defaults to true,
+	// can be set to false to drain and eventually remove a load balancer.
+	// This only affects services that will be using the LB. For services
+	// that is currently using the LB, they will not be affected.
+	AllowServicePlacement *bool `json:"allowServicePlacement" yaml:"allowServicePlacement"`
+
+	// A string value that must specify the name of an existing vmSet.
+	// All nodes in the given vmSet will always be added to this load balancer.
+	// A vmSet can only be the primary vmSet for a single load balancer.
+	PrimaryVMSet string `json:"primaryVMSet" yaml:"primaryVMSet"`
+
+	// Services that must match this selector can be placed on this load balancer. If not supplied,
+	// services with any labels can be created on the load balancer.
+	ServiceLabelSelector *metav1.LabelSelector `json:"serviceLabelSelector" yaml:"serviceLabelSelector"`
+
+	// Services created in namespaces with the supplied label will be allowed to select that load balancer.
+	// If not supplied, services created in any namespaces can be created on that load balancer.
+	ServiceNamespaceSelector *metav1.LabelSelector `json:"serviceNamespaceSelector" yaml:"serviceNamespaceSelector"`
+
+	// Nodes matching this selector will be preferentially added to the load balancers that
+	// they match selectors for. NodeSelector does not override primaryAgentPool for node allocation.
+	NodeSelector *metav1.LabelSelector `json:"nodeSelector" yaml:"nodeSelector"`
+}
+
+// MultipleStandardLoadBalancerConfigurationStatus stores the properties regarding multiple standard load balancers.
+type MultipleStandardLoadBalancerConfigurationStatus struct {
+	// ActiveServices stores the services that are supposed to use the load balancer.
+	ActiveServices *utilsets.IgnoreCaseSet `json:"activeServices" yaml:"activeServices"`
+
+	// ActiveNodes stores the nodes that are supposed to be in the load balancer.
+	// It will be used in EnsureHostsInPool to make sure the given ones are in the backend pool.
+	ActiveNodes *utilsets.IgnoreCaseSet `json:"activeNodes" yaml:"activeNodes"`
+}


Test patch:
diff --git a/pkg/provider/azure_instance_metadata_test.go b/pkg/provider/azure_instance_metadata_test.go
index f79312897..d5f6c066b 100644
--- a/pkg/provider/azure_instance_metadata_test.go
+++ b/pkg/provider/azure_instance_metadata_test.go
@@ -25,6 +25,8 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 )
 
 // TestFillNetInterfacePublicIPs tests if IPv6 IPs from imds load balancer are
@@ -110,7 +112,7 @@ func TestGetPlatformSubFaultDomain(t *testing.T) {
 	} {
 		t.Run(testCase.description, func(t *testing.T) {
 			cloud := &Cloud{
-				Config: Config{
+				Config: config.Config{
 					Location:            "eastus",
 					UseInstanceMetadata: true,
 				},
diff --git a/pkg/provider/azure_loadbalancer_backendpool_test.go b/pkg/provider/azure_loadbalancer_backendpool_test.go
index 72155935a..2675786e4 100644
--- a/pkg/provider/azure_loadbalancer_backendpool_test.go
+++ b/pkg/provider/azure_loadbalancer_backendpool_test.go
@@ -36,6 +36,7 @@ import (
 
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/loadbalancerclient/mockloadbalancerclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 	utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
 )
@@ -107,7 +108,7 @@ func TestEnsureHostsInPoolNodeIP(t *testing.T) {
 	testcases := []struct {
 		desc                string
 		backendPool         network.BackendAddressPool
-		multiSLBConfigs     []MultipleStandardLoadBalancerConfiguration
+		multiSLBConfigs     []config.MultipleStandardLoadBalancerConfiguration
 		local               bool
 		notFound            bool
 		skip                bool
@@ -214,10 +215,10 @@ func TestEnsureHostsInPoolNodeIP(t *testing.T) {
 					},
 				},
 			},
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "kubernetes",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("vmss-2"),
 					},
 				},
@@ -255,10 +256,10 @@ func TestEnsureHostsInPoolNodeIP(t *testing.T) {
 					},
 				},
 			},
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "kubernetes",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("vmss-2"),
 					},
 				},
@@ -282,7 +283,7 @@ func TestEnsureHostsInPoolNodeIP(t *testing.T) {
 			desc:     "local service without service info",
 			local:    true,
 			notFound: true,
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "kubernetes",
 				},
@@ -292,7 +293,7 @@ func TestEnsureHostsInPoolNodeIP(t *testing.T) {
 			desc:  "local service with another load balancer",
 			local: true,
 			skip:  true,
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "kubernetes",
 				},
@@ -307,7 +308,7 @@ func TestEnsureHostsInPoolNodeIP(t *testing.T) {
 					LoadBalancerBackendAddresses: &[]network.LoadBalancerBackendAddress{},
 				},
 			},
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "kubernetes",
 				},
@@ -343,7 +344,7 @@ func TestEnsureHostsInPoolNodeIP(t *testing.T) {
 					LoadBalancerBackendAddresses: &[]network.LoadBalancerBackendAddress{},
 				},
 			},
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "kubernetes",
 				},
@@ -942,7 +943,7 @@ func TestReconcileBackendPoolsNodeIPConfigToIPWithMigrationAPI(t *testing.T) {
 	az.LoadBalancerClient = mockLBClient
 	az.EnableMigrateToIPBasedBackendPoolAPI = true
 	az.LoadBalancerSku = "standard"
-	az.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{{Name: "kubernetes"}}
+	az.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{{Name: "kubernetes"}}
 
 	bi := newBackendPoolTypeNodeIP(az)
 	svc := getTestService("test", v1.ProtocolTCP, nil, false, 80)
diff --git a/pkg/provider/azure_loadbalancer_repo_test.go b/pkg/provider/azure_loadbalancer_repo_test.go
index 85da86606..6b2b84431 100644
--- a/pkg/provider/azure_loadbalancer_repo_test.go
+++ b/pkg/provider/azure_loadbalancer_repo_test.go
@@ -35,6 +35,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/publicipclient/mockpublicipclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/cache"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 )
 
@@ -58,7 +59,7 @@ func TestListManagedLBs(t *testing.T) {
 		existingLBs     []network.LoadBalancer
 		expectedLBs     *[]network.LoadBalancer
 		callTimes       int
-		multiSLBConfigs []MultipleStandardLoadBalancerConfiguration
+		multiSLBConfigs []config.MultipleStandardLoadBalancerConfiguration
 		clientErr       *retry.Error
 		expectedErr     error
 	}{
@@ -94,7 +95,7 @@ func TestListManagedLBs(t *testing.T) {
 				{Name: ptr.To("lb1-internal")},
 				{Name: ptr.To("lb2")},
 			},
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{Name: "kubernetes"},
 				{Name: "lb1"},
 			},
diff --git a/pkg/provider/azure_loadbalancer_test.go b/pkg/provider/azure_loadbalancer_test.go
index 3385b3072..6b0fb9e1d 100644
--- a/pkg/provider/azure_loadbalancer_test.go
+++ b/pkg/provider/azure_loadbalancer_test.go
@@ -51,6 +51,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/subnetclient/mocksubnetclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmssclient/mockvmssclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/privatelinkservice"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/zone"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
@@ -1729,7 +1730,7 @@ func TestGetServiceLoadBalancerMultiSLB(t *testing.T) {
 		existingPIPs    []network.PublicIPAddress
 		service         v1.Service
 		local           bool
-		multiSLBConfigs []MultipleStandardLoadBalancerConfiguration
+		multiSLBConfigs []config.MultipleStandardLoadBalancerConfiguration
 		expectedLB      *network.LoadBalancer
 		expectedLBs     *[]network.LoadBalancer
 		expectedError   error
@@ -1756,13 +1757,13 @@ func TestGetServiceLoadBalancerMultiSLB(t *testing.T) {
 				},
 			},
 			service: getInternalTestService("test1"),
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
 				},
 				{
 					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveServices: utilsets.NewString("default/test1"),
 					},
 				},
@@ -1837,13 +1838,13 @@ func TestGetServiceLoadBalancerMultiSLB(t *testing.T) {
 			},
 			service: getTestService("test1", v1.ProtocolTCP, nil, false, 80),
 			local:   true,
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
 				},
 				{
 					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveServices: utilsets.NewString("default/test1"),
 					},
 				},
@@ -6906,9 +6907,9 @@ func TestSafeDeleteLoadBalancer(t *testing.T) {
 		desc                          string
 		expectedDeleteCall            bool
 		expectedDecoupleErr           error
-		multiSLBConfigs               []MultipleStandardLoadBalancerConfiguration
+		multiSLBConfigs               []config.MultipleStandardLoadBalancerConfiguration
 		nodesWithCorrectVMSet         *utilsets.IgnoreCaseSet
-		expectedMultiSLBConfigs       []MultipleStandardLoadBalancerConfiguration
+		expectedMultiSLBConfigs       []config.MultipleStandardLoadBalancerConfiguration
 		expectedNodesWithCorrectVMSet *utilsets.IgnoreCaseSet
 		expectedErr                   *retry.Error
 	}{
@@ -6929,31 +6930,31 @@ func TestSafeDeleteLoadBalancer(t *testing.T) {
 		{
 			desc:               "should cleanup active nodes when using multi-slb",
 			expectedDeleteCall: true,
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "test",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node1", "node2"),
 					},
 				},
 				{
 					Name: "test2",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node3"),
 					},
 				},
 			},
 			nodesWithCorrectVMSet: utilsets.NewString("node1", "node2", "node3"),
-			expectedMultiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			expectedMultiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "test",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString(),
 					},
 				},
 				{
 					Name: "test2",
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node3"),
 					},
 				},
@@ -7048,7 +7049,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 
 	for _, tc := range []struct {
 		description string
-		lbConfigs   []MultipleStandardLoadBalancerConfiguration
+		lbConfigs   []config.MultipleStandardLoadBalancerConfiguration
 		svc         v1.Service
 		namespace   *v1.Namespace
 		labels      map[string]string
@@ -7058,14 +7059,14 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should respect service annotation",
 			svc:         getTestService("test", v1.ProtocolTCP, map[string]string{consts.ServiceAnnotationLoadBalancerConfigurations: "A ,b"}, false),
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 			},
 			expectedLBs: []string{"a"},
@@ -7073,14 +7074,14 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should report an error if a service selects a load balancer that is not defined in the configuration",
 			svc:         getTestService("test", v1.ProtocolTCP, map[string]string{consts.ServiceAnnotationLoadBalancerConfigurations: "b"}, false),
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 			},
 			expectedErr: errors.New(`service "test" selects 1 load balancers by annotation, but none of them is defined in cloud provider configuration`),
@@ -7088,10 +7089,10 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should respect namespace selector",
 			svc:         getTestService("test", v1.ProtocolTCP, nil, false),
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
@@ -7099,7 +7100,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "b",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
 						},
@@ -7107,7 +7108,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 			},
 			namespace: &v1.Namespace{
@@ -7122,10 +7123,10 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 			description: "should respect label selector",
 			svc:         getTestService("test", v1.ProtocolTCP, nil, false),
 			labels:      map[string]string{"k2": "v2", "k3": "v3"},
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
@@ -7133,7 +7134,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "b",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
 						},
@@ -7141,7 +7142,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 			},
 			expectedLBs: []string{"b"},
@@ -7156,10 +7157,10 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 					Labels: map[string]string{"k1": "v1"},
 				},
 			},
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "fails to match service label",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
@@ -7167,7 +7168,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "fails to match service namespace",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
 						},
@@ -7175,7 +7176,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "empty",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 			},
 			expectedLBs: []string{"empty"},
@@ -7184,10 +7185,10 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 			description: "should return the intersection of annotation, namespace and label selector",
 			svc:         getTestService("test", v1.ProtocolTCP, map[string]string{consts.ServiceAnnotationLoadBalancerConfigurations: "a,b"}, false),
 			labels:      map[string]string{"k2": "v2"},
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
@@ -7195,7 +7196,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "b",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchExpressions: []metav1.LabelSelectorRequirement{
 								{
@@ -7218,7 +7219,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
 						},
@@ -7236,10 +7237,10 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should return an error if there is no matching lb config",
 			svc:         getTestService("test", v1.ProtocolTCP, map[string]string{consts.ServiceAnnotationLoadBalancerConfigurations: "a,b,c"}, false),
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
@@ -7247,7 +7248,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "b",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchExpressions: []metav1.LabelSelectorRequirement{
 								{
@@ -7261,7 +7262,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v3"},
 						},
@@ -7269,13 +7270,13 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 				},
 				{
 					Name: "d",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						AllowServicePlacement: ptr.To(false),
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
 						},
 					},
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveServices: utilsets.NewString("default/test"),
 					},
 				},
@@ -7292,10 +7293,10 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should report an error if failed to convert label selector as a selector",
 			svc:         getTestService("test", v1.ProtocolTCP, nil, false),
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchExpressions: []metav1.LabelSelectorRequirement{
 								{
@@ -7314,10 +7315,10 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should report an error if failed to convert namespace selector as a selector",
 			svc:         getTestService("test", v1.ProtocolTCP, nil, false),
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchExpressions: []metav1.LabelSelectorRequirement{
 								{
@@ -7336,27 +7337,27 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should respect allowServicePlacement flag",
 			svc:         getTestService("test", v1.ProtocolTCP, map[string]string{consts.ServiceAnnotationLoadBalancerConfigurations: "a,c"}, false),
-			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
+			lbConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						AllowServicePlacement: ptr.To(false),
 					},
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveServices: utilsets.NewString("default/test"),
 					},
 				},
 				{
 					Name: "b",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 				{
 					Name: "d",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{},
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{},
 				},
 			},
 			expectedLBs: []string{"a", "c"},
@@ -7398,7 +7399,7 @@ func TestGetAzureLoadBalancerName(t *testing.T) {
 		useStandardLB     bool
 		clusterName       string
 		lbName            string
-		multiSLBConfigs   []MultipleStandardLoadBalancerConfiguration
+		multiSLBConfigs   []config.MultipleStandardLoadBalancerConfiguration
 		serviceAnnotation map[string]string
 		serviceLabel      map[string]string
 		expected          string
@@ -7471,10 +7472,10 @@ func TestGetAzureLoadBalancerName(t *testing.T) {
 			description:   "should select the most eligible load balancer when using multi-slb",
 			vmSet:         primary,
 			useStandardLB: true,
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
@@ -7482,7 +7483,7 @@ func TestGetAzureLoadBalancerName(t *testing.T) {
 				},
 				{
 					Name: "b",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchExpressions: []metav1.LabelSelectorRequirement{
 								{
@@ -7496,7 +7497,7 @@ func TestGetAzureLoadBalancerName(t *testing.T) {
 				},
 				{
 					Name: "c",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceNamespaceSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
 						},
@@ -7512,10 +7513,10 @@ func TestGetAzureLoadBalancerName(t *testing.T) {
 			description:   "should report an error if failed to select eligible load balancers",
 			vmSet:         primary,
 			useStandardLB: true,
-			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			multiSLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						ServiceLabelSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
@@ -7758,12 +7759,12 @@ func TestReconcileMultipleStandardLoadBalancerConfigurations(t *testing.T) {
 
 			if tc.useMultipleLB {
 				az.LoadBalancerBackendPool = newBackendPoolTypeNodeIP(az)
-				az.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
+				az.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{
 					{Name: "lb1"},
 					{Name: "lb2"},
 				}
 				if !tc.noPrimaryConfig {
-					az.MultipleStandardLoadBalancerConfigurations = append(az.MultipleStandardLoadBalancerConfigurations, MultipleStandardLoadBalancerConfiguration{Name: "kubernetes"})
+					az.MultipleStandardLoadBalancerConfigurations = append(az.MultipleStandardLoadBalancerConfigurations, config.MultipleStandardLoadBalancerConfiguration{Name: "kubernetes"})
 				}
 			}
 
@@ -8235,7 +8236,7 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 		description          string
 		lbName               string
 		init                 bool
-		existingLBConfigs    []MultipleStandardLoadBalancerConfiguration
+		existingLBConfigs    []config.MultipleStandardLoadBalancerConfiguration
 		existingNodes        []*v1.Node
 		existingLBs          []network.LoadBalancer
 		expectedPutLBTimes   int
@@ -8243,22 +8244,22 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 	}{
 		{
 			description: "should remove unwanted nodes and arrange existing nodes with primary vmSet as expected",
-			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			existingLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-1",
 					},
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node1", "node2"),
 					},
 				},
 				{
 					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 					},
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node3", "node4"),
 					},
 				},
@@ -8331,34 +8332,34 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 		{
 			description: "should respect node selector",
 			lbName:      "lb2-internal",
-			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			existingLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-1",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
 					},
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node1", "node2"),
 					},
 				},
 				{
 					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
 						},
 					},
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node3", "node4"),
 					},
 				},
 				{
 					Name: "lb3",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
@@ -8367,7 +8368,7 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 				},
 				{
 					Name: "lb4",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 					},
 				},
@@ -8436,16 +8437,16 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 		},
 		{
 			description: "should remove the node on the lb if it is no longer eligible",
-			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			existingLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-1",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
 						},
 					},
-					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+					MultipleStandardLoadBalancerConfigurationStatus: config.MultipleStandardLoadBalancerConfigurationStatus{
 						ActiveNodes: utilsets.NewString("node1", "node2"),
 					},
 				},
@@ -8459,10 +8460,10 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 		},
 		{
 			description: "should skip lbs that do not exist or will not be created",
-			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			existingLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-1",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
@@ -8471,7 +8472,7 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 				},
 				{
 					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
@@ -8480,7 +8481,7 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 				},
 				{
 					Name: "lb3",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k3": "v3"},
@@ -8527,10 +8528,10 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 		},
 		{
 			description: "should skip lbs that do not exist or will not be created when no lb is selected by node selector",
-			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			existingLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-1",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k1": "v1"},
@@ -8539,7 +8540,7 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 				},
 				{
 					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k2": "v2"},
@@ -8548,7 +8549,7 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 				},
 				{
 					Name: "lb3",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 						NodeSelector: &metav1.LabelSelector{
 							MatchLabels: map[string]string{"k3": "v3"},
@@ -8586,16 +8587,16 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 		{
 			description: "should record current node distributions after restarting the controller",
 			init:        true,
-			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+			existingLBConfigs: []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-1",
 					},
 				},
 				{
 					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+					MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 						PrimaryVMSet: "vmss-2",
 					},
 				},
diff --git a/pkg/provider/azure_local_services_test.go b/pkg/provider/azure_local_services_test.go
index bbfa6d739..f24846799 100644
--- a/pkg/provider/azure_local_services_test.go
+++ b/pkg/provider/azure_local_services_test.go
@@ -39,6 +39,7 @@ import (
 
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/loadbalancerclient/mockloadbalancerclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 	utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
 )
@@ -485,7 +486,7 @@ func TestEndpointSlicesInformer(t *testing.T) {
 			cloud.serviceLister = informerFactory.Core().V1().Services().Lister()
 			cloud.LoadBalancerBackendPoolUpdateIntervalInSeconds = 1
 			cloud.LoadBalancerSku = consts.LoadBalancerSkuStandard
-			cloud.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
+			cloud.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
 				},
@@ -529,7 +530,7 @@ func TestGetBackendPoolNamesAndIDsForService(t *testing.T) {
 	defer ctrl.Finish()
 
 	cloud := GetTestCloud(ctrl)
-	cloud.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
+	cloud.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{
 		{},
 	}
 	svc := getTestService("test", v1.ProtocolTCP, nil, false)
@@ -564,7 +565,7 @@ func TestCheckAndApplyLocalServiceBackendPoolUpdates(t *testing.T) {
 			cloud.serviceLister = informerFactory.Core().V1().Services().Lister()
 			cloud.LoadBalancerBackendPoolUpdateIntervalInSeconds = 1
 			cloud.LoadBalancerSku = consts.LoadBalancerSkuStandard
-			cloud.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
+			cloud.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "lb1",
 				},
diff --git a/pkg/provider/azure_routes_test.go b/pkg/provider/azure_routes_test.go
index 719dff4f1..4704fa736 100644
--- a/pkg/provider/azure_routes_test.go
+++ b/pkg/provider/azure_routes_test.go
@@ -32,6 +32,7 @@ import (
 	cloudprovider "k8s.io/cloud-provider"
 	"k8s.io/utils/ptr"
 
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/routetable"
 	utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
 )
@@ -44,7 +45,7 @@ func TestDeleteRoute(t *testing.T) {
 	mockRTRepo := routetable.NewMockRepository(ctrl)
 	cloud := &Cloud{
 		routeTableRepo: mockRTRepo,
-		Config: Config{
+		Config: config.Config{
 			RouteTableResourceGroup: "foo",
 			RouteTableName:          "bar",
 			Location:                "location",
@@ -122,7 +123,7 @@ func TestDeleteRouteDualStack(t *testing.T) {
 	mockRTRepo := routetable.NewMockRepository(ctrl)
 	cloud := &Cloud{
 		routeTableRepo: mockRTRepo,
-		Config: Config{
+		Config: config.Config{
 			RouteTableResourceGroup: "foo",
 			RouteTableName:          "bar",
 			Location:                "location",
@@ -318,7 +319,7 @@ func TestCreateRoute(t *testing.T) {
 			cloud := &Cloud{
 				routeTableRepo: mockRTRepo,
 				VMSet:          mockVMSet,
-				Config: Config{
+				Config: config.Config{
 					RouteTableResourceGroup: "foo",
 					RouteTableName:          "bar",
 					Location:                "location",
@@ -397,7 +398,7 @@ func TestCreateRouteTable(t *testing.T) {
 	mockRTRepo := routetable.NewMockRepository(ctrl)
 	cloud := &Cloud{
 		routeTableRepo: mockRTRepo,
-		Config: Config{
+		Config: config.Config{
 			RouteTableResourceGroup: "foo",
 			RouteTableName:          "bar",
 			Location:                "location",
@@ -600,7 +601,7 @@ func TestListRoutes(t *testing.T) {
 	cloud := &Cloud{
 		routeTableRepo: mockRTRepo,
 		VMSet:          mockVMSet,
-		Config: Config{
+		Config: config.Config{
 			RouteTableResourceGroup: "foo",
 			RouteTableName:          "bar",
 			Location:                "location",
diff --git a/pkg/provider/azure_test.go b/pkg/provider/azure_test.go
index 88cb4f8a2..6e6d9c4a8 100644
--- a/pkg/provider/azure_test.go
+++ b/pkg/provider/azure_test.go
@@ -53,6 +53,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/subnetclient/mocksubnetclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmclient/mockvmclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	providerconfig "sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/privatelinkservice"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/zone"
@@ -2254,12 +2255,12 @@ func validateConfig(t *testing.T, config string) { //nolint
 	}
 }
 
-func getCloudFromConfig(t *testing.T, config string) *Cloud {
+func getCloudFromConfig(t *testing.T, configContent string) *Cloud {
 	ctrl := gomock.NewController(t)
 	defer ctrl.Finish()
 
-	configReader := strings.NewReader(config)
-	c, err := ParseConfig(configReader)
+	configReader := strings.NewReader(configContent)
+	c, err := config.ParseConfig(configReader)
 	assert.NoError(t, err)
 
 	zoneMock := zone.NewMockRepository(ctrl)
@@ -2787,15 +2788,15 @@ func TestInitializeCloudFromConfig(t *testing.T) {
 	err := az.InitializeCloudFromConfig(context.Background(), nil, false, true)
 	assert.Equal(t, fmt.Errorf("InitializeCloudFromConfig: cannot initialize from nil config"), err)
 
-	config := Config{
+	azureconfig := config.Config{
 		DisableAvailabilitySetNodes: true,
 		VMType:                      consts.VMTypeStandard,
 	}
-	err = az.InitializeCloudFromConfig(context.Background(), &config, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), &azureconfig, false, true)
 	expectedErr := fmt.Errorf("disableAvailabilitySetNodes true is only supported when vmType is 'vmss'")
 	assert.Equal(t, expectedErr, err)
 
-	config = Config{
+	azureconfig = config.Config{
 		AzureClientConfig: providerconfig.AzureClientConfig{
 			ARMClientConfig: azclient.ARMClientConfig{
 				Cloud: "AZUREPUBLICCLOUD",
@@ -2803,19 +2804,19 @@ func TestInitializeCloudFromConfig(t *testing.T) {
 		},
 		CloudConfigType: configloader.CloudConfigTypeFile,
 	}
-	err = az.InitializeCloudFromConfig(context.Background(), &config, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), &azureconfig, false, true)
 	expectedErr = fmt.Errorf("useInstanceMetadata must be enabled without Azure credentials")
 	assert.Equal(t, expectedErr, err)
 
-	config = Config{
+	azureconfig = config.Config{
 		LoadBalancerBackendPoolConfigurationType: "invalid",
 	}
-	err = az.InitializeCloudFromConfig(context.Background(), &config, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), &azureconfig, false, true)
 	expectedErr = errors.New("loadBalancerBackendPoolConfigurationType invalid is not supported, supported values are")
 	assert.Contains(t, err.Error(), expectedErr.Error())
 
-	config = Config{}
-	err = az.InitializeCloudFromConfig(context.Background(), &config, false, true)
+	azureconfig = config.Config{}
+	err = az.InitializeCloudFromConfig(context.Background(), &azureconfig, false, true)
 	assert.NoError(t, err)
 	assert.Equal(t, az.Config.LoadBalancerBackendPoolConfigurationType, consts.LoadBalancerBackendPoolConfigurationTypeNodeIPConfiguration)
 }
@@ -2825,7 +2826,7 @@ func TestSetLBDefaults(t *testing.T) {
 	defer ctrl.Finish()
 	az := GetTestCloud(ctrl)
 
-	config := &Config{}
+	config := &config.Config{}
 	_ = az.setLBDefaults(config)
 	assert.Equal(t, config.LoadBalancerSku, consts.LoadBalancerSkuStandard)
 }
@@ -2836,22 +2837,22 @@ func TestCheckEnableMultipleStandardLoadBalancers(t *testing.T) {
 	az := GetTestCloud(ctrl)
 	az.LoadBalancerBackendPoolConfigurationType = consts.LoadBalancerBackendPoolConfigurationTypeNodeIP
 
-	az.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
+	az.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{
 		{
 			Name: "kubernetes",
-			MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+			MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 				PrimaryVMSet: "vmss-0",
 			},
 		},
 		{
 			Name: "lb1",
-			MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+			MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 				PrimaryVMSet: "vmss-1",
 			},
 		},
 		{
 			Name: "kubernetes",
-			MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+			MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 				PrimaryVMSet: "vmss-2",
 			},
 		},
@@ -2860,10 +2861,10 @@ func TestCheckEnableMultipleStandardLoadBalancers(t *testing.T) {
 	err := az.checkEnableMultipleStandardLoadBalancers()
 	assert.Equal(t, "duplicated multiple standard load balancer configuration name kubernetes", err.Error())
 
-	az.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
+	az.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{
 		{
 			Name: "kubernetes",
-			MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+			MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 				PrimaryVMSet: "vmss-0",
 			},
 		},
@@ -2875,22 +2876,22 @@ func TestCheckEnableMultipleStandardLoadBalancers(t *testing.T) {
 	err = az.checkEnableMultipleStandardLoadBalancers()
 	assert.Equal(t, "multiple standard load balancer configuration lb1 must have primary VMSet", err.Error())
 
-	az.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
+	az.MultipleStandardLoadBalancerConfigurations = []config.MultipleStandardLoadBalancerConfiguration{
 		{
 			Name: "kubernetes",
-			MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+			MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 				PrimaryVMSet: "vmss-0",
 			},
 		},
 		{
 			Name: "lb1",
-			MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+			MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 				PrimaryVMSet: "vmss-2",
 			},
 		},
 		{
 			Name: "lb2",
-			MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+			MultipleStandardLoadBalancerConfigurationSpec: config.MultipleStandardLoadBalancerConfigurationSpec{
 				PrimaryVMSet: "vmss-2",
 			},
 		},
diff --git a/pkg/provider/azure_zones_test.go b/pkg/provider/azure_zones_test.go
index 6d9eea2f9..7c160c0a0 100644
--- a/pkg/provider/azure_zones_test.go
+++ b/pkg/provider/azure_zones_test.go
@@ -33,6 +33,7 @@ import (
 	"k8s.io/utils/ptr"
 
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmclient/mockvmclient"
+	"sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 	"sigs.k8s.io/cloud-provider-azure/pkg/provider/zone"
 	utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
 )
@@ -44,7 +45,7 @@ const (
 func TestIsAvailabilityZone(t *testing.T) {
 	location := "eastus"
 	az := &Cloud{
-		Config: Config{
+		Config: config.Config{
 			Location: location,
 		},
 	}
@@ -70,7 +71,7 @@ func TestIsAvailabilityZone(t *testing.T) {
 func TestGetZoneID(t *testing.T) {
 	location := "eastus"
 	az := &Cloud{
-		Config: Config{
+		Config: config.Config{
 			Location: location,
 		},
 	}
@@ -95,7 +96,7 @@ func TestGetZoneID(t *testing.T) {
 
 func TestGetZone(t *testing.T) {
 	cloud := &Cloud{
-		Config: Config{
+		Config: config.Config{
 			Location:            "eastus",
 			UseInstanceMetadata: true,
 		},