Repository: kubernetes-sigs/cloud-provider-azure (go)

Issue:
Add "k8s-azure-" prefix for cloud provider managed tags
<!-- Feature requests are unlikely to make progress as an issue.

Instead, please suggest enhancements by engaging with SIGs on slack and mailing lists.

A proposal that works through the design along with the implications of the change can be opened as a KEP:
https://git.k8s.io/enhancements/keps#kubernetes-enhancement-proposals-keps
-->

#### What would you like to be added:

As lots of customers are using Azure Policy to apply their own tags on various Azure resources, to avoid conflicts with them, cloud provider should add "k8s-azure-" prefix for all its managed tags. A list of tags should also be published as well.

Legacy Tag | New Tag | Comment
-- | -- | --
service | k8s-azure-service | Applied on public IP
kubernetes-cluster-name | k8s-azure-cluster-name | Applied on public IP
kubernetes-dns-label-service | k8s-azure-dns-label-service | Applied on public IP
created-by | k8s-azure-created-by | Applied on azure disk (value is kubernetes-azure-dd) and storage account (value is azure)
user-specified tags in azure.json | same as user specified tags | Applied on Public IP, LoadBalancer and Routetable



#### Why is this needed:

/milestone v1.2

Pull request:
feat: add prefix 'k8s-azure-' for cloud provider managed tags
<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide/first-contribution.md#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
5. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

#### What type of PR is this?

<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature
/kind design

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

/kind feature

#### What this PR does / why we need it:

feat: add prefix 'k8s-azure-' for cloud provider managed tags

Legacy Tag | New Tag | Comment
-- | -- | --
service | k8s-azure-service | Applied on public IP
kubernetes-cluster-name | k8s-azure-cluster-name | Applied on public IP
kubernetes-dns-label-service | k8s-azure-dns-label-service | Applied on public IP


#### Which issue(s) this PR fixes:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #788

#### Special notes for your reviewer:

#### Does this PR introduce a user-facing change?
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".

For more information on release notes see: https://git.k8s.io/community/contributors/guide/release-notes.md
-->
```release-note
Prefix 'k8s-azure-' has been added to the following tags:

Legacy Tag | New Tag | Comment
-- | -- | --
service | k8s-azure-service | Applied on public IP
kubernetes-cluster-name | k8s-azure-cluster-name | Applied on public IP
kubernetes-dns-label-service | k8s-azure-dns-label-service | Applied on public IP

To keep backward compability, the legacy tags on existing public IP would not be removed, but newly created public IPs would only get the new tags.
```

#### Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

<!--
This section can be blank if this pull request does not require a release note.

When adding links which point to resources within git repositories, like
KEPs or supporting documentation, please reference a specific commit and avoid
linking directly to the master branch. This ensures that links reference a
specific point in time, rather than a document that may change over time.

See here for guidance on getting permanent links to files: https://help.github.com/en/articles/getting-permanent-links-to-files

Please use the following format for linking documentation:
- [KEP]: <link>
- [Usage]: <link>
- [Other doc]: <link>
-->
```docs

```


Patch:
diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go
index 12b04a1fb..7f926ef6a 100644
--- a/pkg/consts/consts.go
+++ b/pkg/consts/consts.go
@@ -271,11 +271,14 @@ const (
 	ServiceAnnotationAdditionalPublicIPs = "service.beta.kubernetes.io/azure-additional-public-ips"
 
 	// ServiceTagKey is the service key applied for public IP tags.
-	ServiceTagKey = "service"
+	ServiceTagKey       = "k8s-azure-service"
+	LegacyServiceTagKey = "service"
 	// ClusterNameKey is the cluster name key applied for public IP tags.
-	ClusterNameKey = "kubernetes-cluster-name"
+	ClusterNameKey       = "k8s-azure-cluster-name"
+	LegacyClusterNameKey = "kubernetes-cluster-name"
 	// ServiceUsingDNSKey is the service name consuming the DNS label on the public IP
-	ServiceUsingDNSKey = "kubernetes-dns-label-service"
+	ServiceUsingDNSKey       = "k8s-azure-dns-label-service"
+	LegacyServiceUsingDNSKey = "kubernetes-dns-label-service"
 
 	// DefaultLoadBalancerSourceRanges is the default value of the load balancer source ranges
 	DefaultLoadBalancerSourceRanges = "0.0.0.0/0"
diff --git a/pkg/provider/azure_loadbalancer.go b/pkg/provider/azure_loadbalancer.go
index 026b72094..8c519063b 100644
--- a/pkg/provider/azure_loadbalancer.go
+++ b/pkg/provider/azure_loadbalancer.go
@@ -990,8 +990,7 @@ func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domai
 
 		// return if pip exist and dns label is the same
 		if strings.EqualFold(getDomainNameLabel(&pip), domainNameLabel) {
-			if existingServiceName, ok := pip.Tags[consts.ServiceUsingDNSKey]; ok &&
-				strings.EqualFold(*existingServiceName, serviceName) {
+			if existingServiceName := getServiceFromPIPDNSTags(pip.Tags); existingServiceName != "" && strings.EqualFold(existingServiceName, serviceName) {
 				klog.V(6).Infof("ensurePublicIPExists for service(%s): pip(%s) - "+
 					"the service is using the DNS label on the public IP", serviceName, pipName)
 
@@ -1146,10 +1145,8 @@ func (az *Cloud) reconcileIPSettings(pip *network.PublicIPAddress, service *v1.S
 func reconcileDNSSettings(pip *network.PublicIPAddress, domainNameLabel, serviceName, pipName string) (bool, error) {
 	var changed bool
 
-	if existingServiceName, ok := pip.Tags[consts.ServiceUsingDNSKey]; ok {
-		if !strings.EqualFold(to.String(existingServiceName), serviceName) {
-			return false, fmt.Errorf("ensurePublicIPExists for service(%s): pip(%s) - there is an existing service %s consuming the DNS label on the public IP, so the service cannot set the DNS label annotation with this value", serviceName, pipName, *existingServiceName)
-		}
+	if existingServiceName := getServiceFromPIPDNSTags(pip.Tags); existingServiceName != "" && !strings.EqualFold(existingServiceName, serviceName) {
+		return false, fmt.Errorf("ensurePublicIPExists for service(%s): pip(%s) - there is an existing service %s consuming the DNS label on the public IP, so the service cannot set the DNS label annotation with this value", serviceName, pipName, existingServiceName)
 	}
 
 	if len(domainNameLabel) == 0 {
@@ -1172,8 +1169,7 @@ func reconcileDNSSettings(pip *network.PublicIPAddress, domainNameLabel, service
 			}
 		}
 
-		if svc, ok := pip.Tags[consts.ServiceUsingDNSKey]; !ok ||
-			!strings.EqualFold(to.String(svc), serviceName) {
+		if svc := getServiceFromPIPDNSTags(pip.Tags); svc == "" || !strings.EqualFold(svc, serviceName) {
 			pip.Tags[consts.ServiceUsingDNSKey] = &serviceName
 			changed = true
 		}
@@ -1182,6 +1178,48 @@ func reconcileDNSSettings(pip *network.PublicIPAddress, domainNameLabel, service
 	return changed, nil
 }
 
+func getServiceFromPIPDNSTags(tags map[string]*string) string {
+	v, ok := tags[consts.ServiceUsingDNSKey]
+	if ok && v != nil {
+		return *v
+	}
+
+	v, ok = tags[consts.LegacyServiceUsingDNSKey]
+	if ok && v != nil {
+		return *v
+	}
+
+	return ""
+}
+
+func getServiceFromPIPServiceTags(tags map[string]*string) string {
+	v, ok := tags[consts.ServiceTagKey]
+	if ok && v != nil {
+		return *v
+	}
+
+	v, ok = tags[consts.LegacyServiceTagKey]
+	if ok && v != nil {
+		return *v
+	}
+
+	return ""
+}
+
+func getClusterFromPIPClusterTags(tags map[string]*string) string {
+	v, ok := tags[consts.ClusterNameKey]
+	if ok && v != nil {
+		return *v
+	}
+
+	v, ok = tags[consts.LegacyClusterNameKey]
+	if ok && v != nil {
+		return *v
+	}
+
+	return ""
+}
+
 type serviceIPTagRequest struct {
 	IPTagsRequestedByAnnotation bool
 	IPTags                      *[]network.IPTag
@@ -2641,14 +2679,14 @@ func shouldReleaseExistingOwnedPublicIP(existingPip *network.PublicIPAddress, lb
 
 	// Check whether the public IP is being referenced by other service.
 	// The owned public IP can be released only when there is not other service using it.
-	if existingPip.Tags[consts.ServiceTagKey] != nil {
+	if serviceTag := getServiceFromPIPServiceTags(existingPip.Tags); serviceTag != "" {
 		// case 1: there is at least one reference when deleting the PIP
-		if !lbShouldExist && len(parsePIPServiceTag(existingPip.Tags[consts.ServiceTagKey])) > 0 {
+		if !lbShouldExist && len(parsePIPServiceTag(&serviceTag)) > 0 {
 			return false
 		}
 
 		// case 2: there is at least one reference from other service
-		if lbShouldExist && len(parsePIPServiceTag(existingPip.Tags[consts.ServiceTagKey])) > 1 {
+		if lbShouldExist && len(parsePIPServiceTag(&serviceTag)) > 1 {
 			return false
 		}
 	}
@@ -2683,11 +2721,11 @@ func (az *Cloud) ensurePIPTagged(service *v1.Service, pip *network.PublicIPAddre
 
 	// include the cluster name and service names tags when comparing
 	var clusterName, serviceNames *string
-	if v, ok := pip.Tags[consts.ClusterNameKey]; ok {
-		clusterName = v
+	if v := getClusterFromPIPClusterTags(pip.Tags); v != "" {
+		clusterName = &v
 	}
-	if v, ok := pip.Tags[consts.ServiceTagKey]; ok {
-		serviceNames = v
+	if v := getServiceFromPIPServiceTags(pip.Tags); v != "" {
+		serviceNames = &v
 	}
 	if clusterName != nil {
 		configTags[consts.ClusterNameKey] = clusterName
@@ -3113,32 +3151,30 @@ func serviceOwnsPublicIP(service *v1.Service, pip *network.PublicIPAddress, clus
 	serviceName := getServiceName(service)
 
 	if pip.Tags != nil {
-		serviceTag := pip.Tags[consts.ServiceTagKey]
-		clusterTag := pip.Tags[consts.ClusterNameKey]
+		serviceTag := getServiceFromPIPServiceTags(pip.Tags)
+		clusterTag := getClusterFromPIPClusterTags(pip.Tags)
 
 		// if there is no service tag on the pip, it is user-created pip
-		if to.String(serviceTag) == "" {
+		if serviceTag == "" {
 			return strings.EqualFold(to.String(pip.IPAddress), service.Spec.LoadBalancerIP), true
 		}
 
-		if serviceTag != nil {
-			// if there is service tag on the pip, it is system-created pip
-			if isSVCNameInPIPTag(*serviceTag, serviceName) {
-				// Backward compatible for clusters upgraded from old releases.
-				// In such case, only "service" tag is set.
-				if clusterTag == nil {
-					return true, false
-				}
+		// if there is service tag on the pip, it is system-created pip
+		if isSVCNameInPIPTag(serviceTag, serviceName) {
+			// Backward compatible for clusters upgraded from old releases.
+			// In such case, only "service" tag is set.
+			if clusterTag == "" {
+				return true, false
+			}
 
-				// If cluster name tag is set, then return true if it matches.
-				if *clusterTag == clusterName {
-					return true, false
-				}
-			} else {
-				// if the service is not included in te tags of the system-created pip, check the ip address
-				// this could happen for secondary services
-				return strings.EqualFold(to.String(pip.IPAddress), service.Spec.LoadBalancerIP), false
+			// If cluster name tag is set, then return true if it matches.
+			if clusterTag == clusterName {
+				return true, false
 			}
+		} else {
+			// if the service is not included in te tags of the system-created pip, check the ip address
+			// this could happen for secondary services
+			return strings.EqualFold(to.String(pip.IPAddress), service.Spec.LoadBalancerIP), false
 		}
 	}
 
@@ -3158,7 +3194,7 @@ func isSVCNameInPIPTag(tag, svcName string) bool {
 }
 
 func parsePIPServiceTag(serviceTag *string) []string {
-	if serviceTag == nil {
+	if serviceTag == nil || len(*serviceTag) == 0 {
 		return []string{}
 	}
 
@@ -3188,7 +3224,7 @@ func bindServicesToPIP(pip *network.PublicIPAddress, incomingServiceNames []stri
 		pip.Tags = map[string]*string{consts.ServiceTagKey: to.StringPtr("")}
 	}
 
-	serviceTagValue := pip.Tags[consts.ServiceTagKey]
+	serviceTagValue := to.StringPtr(getServiceFromPIPServiceTags(pip.Tags))
 	serviceTagValueSet := make(map[string]struct{})
 	existingServiceNames := parsePIPServiceTag(serviceTagValue)
 	addedNew := false
@@ -3232,7 +3268,7 @@ func unbindServiceFromPIP(pip *network.PublicIPAddress, service *v1.Service, ser
 	}
 
 	// skip removing tags for user assigned pips
-	serviceTagValue := pip.Tags[consts.ServiceTagKey]
+	serviceTagValue := to.StringPtr(getServiceFromPIPServiceTags(pip.Tags))
 	existingServiceNames := parsePIPServiceTag(serviceTagValue)
 	var found bool
 	for i := len(existingServiceNames) - 1; i >= 0; i-- {
@@ -3250,10 +3286,8 @@ func unbindServiceFromPIP(pip *network.PublicIPAddress, service *v1.Service, ser
 		return err
 	}
 
-	if existingServiceName, ok := pip.Tags[consts.ServiceUsingDNSKey]; ok {
-		if strings.EqualFold(*existingServiceName, serviceName) {
-			pip.Tags[consts.ServiceUsingDNSKey] = to.StringPtr("")
-		}
+	if existingServiceName := getServiceFromPIPDNSTags(pip.Tags); existingServiceName != "" && strings.EqualFold(existingServiceName, serviceName) {
+		pip.Tags[consts.ServiceUsingDNSKey] = to.StringPtr("")
 	}
 
 	return nil
diff --git a/pkg/provider/azure_utils.go b/pkg/provider/azure_utils.go
index 1ea88e23f..ebc025bb1 100644
--- a/pkg/provider/azure_utils.go
+++ b/pkg/provider/azure_utils.go
@@ -100,8 +100,12 @@ func convertMapToMapPointer(origin map[string]string) map[string]*string {
 }
 
 func parseTags(tags string) map[string]*string {
-	kvs := strings.Split(tags, consts.TagsDelimiter)
 	formatted := make(map[string]*string)
+	if len(tags) == 0 {
+		return formatted
+	}
+
+	kvs := strings.Split(tags, consts.TagsDelimiter)
 	for _, kv := range kvs {
 		res := strings.Split(kv, consts.TagKeyValueDelimiter)
 		if len(res) != 2 {


Test patch:
diff --git a/pkg/provider/azure_loadbalancer_test.go b/pkg/provider/azure_loadbalancer_test.go
index 9445514fb..7d314bb8c 100644
--- a/pkg/provider/azure_loadbalancer_test.go
+++ b/pkg/provider/azure_loadbalancer_test.go
@@ -693,7 +693,7 @@ func TestShouldReleaseExistingOwnedPublicIP(t *testing.T) {
 	existingPipWithNoPublicIPAddressFormatProperties := network.PublicIPAddress{
 		ID:                              to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/testPIP"),
 		Name:                            to.StringPtr("testPIP"),
-		Tags:                            map[string]*string{"service": to.StringPtr("default/test2")},
+		Tags:                            map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test2")},
 		PublicIPAddressPropertiesFormat: nil,
 	}
 
@@ -2916,7 +2916,7 @@ func TestReconcilePublicIP(t *testing.T) {
 			existingPIPs: []network.PublicIPAddress{
 				{
 					Name: to.StringPtr("pip1"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
@@ -2934,11 +2934,11 @@ func TestReconcilePublicIP(t *testing.T) {
 			existingPIPs: []network.PublicIPAddress{
 				{
 					Name: to.StringPtr("pip1"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 				},
 				{
 					Name: to.StringPtr("pip2"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 				},
 			},
 			expectedError:               true,
@@ -2952,21 +2952,21 @@ func TestReconcilePublicIP(t *testing.T) {
 			existingPIPs: []network.PublicIPAddress{
 				{
 					Name: to.StringPtr("pip1"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
 				},
 				{
 					Name: to.StringPtr("pip2"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
 				},
 				{
 					Name: to.StringPtr("testPIP"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
@@ -2975,7 +2975,7 @@ func TestReconcilePublicIP(t *testing.T) {
 			expectedPIP: &network.PublicIPAddress{
 				ID:   to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/testPIP"),
 				Name: to.StringPtr("testPIP"),
-				Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+				Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 				PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 					PublicIPAddressVersion: network.IPVersionIPv4,
 					IPAddress:              to.StringPtr("1.2.3.4"),
@@ -2991,21 +2991,21 @@ func TestReconcilePublicIP(t *testing.T) {
 			existingPIPs: []network.PublicIPAddress{
 				{
 					Name: to.StringPtr("pip1"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
 				},
 				{
 					Name: to.StringPtr("pip2"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1,default/test2")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1,default/test2")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
 				},
 				{
 					Name: to.StringPtr("testPIP"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
@@ -3014,7 +3014,7 @@ func TestReconcilePublicIP(t *testing.T) {
 			expectedPIP: &network.PublicIPAddress{
 				ID:   to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/testPIP"),
 				Name: to.StringPtr("testPIP"),
-				Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+				Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 				PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 					PublicIPAddressVersion: network.IPVersionIPv4,
 					IPAddress:              to.StringPtr("1.2.3.4"),
@@ -3033,21 +3033,21 @@ func TestReconcilePublicIP(t *testing.T) {
 			existingPIPs: []network.PublicIPAddress{
 				{
 					Name: to.StringPtr("pip1"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
 				},
 				{
 					Name: to.StringPtr("pip2"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
 				},
 				{
 					Name: to.StringPtr("testPIP"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
@@ -3056,7 +3056,7 @@ func TestReconcilePublicIP(t *testing.T) {
 			expectedPIP: &network.PublicIPAddress{
 				ID:   to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/testPIP"),
 				Name: to.StringPtr("testPIP"),
-				Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+				Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 				PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 					PublicIPAddressVersion:   network.IPVersionIPv4,
 					PublicIPAllocationMethod: network.IPAllocationMethodStatic,
@@ -3081,7 +3081,7 @@ func TestReconcilePublicIP(t *testing.T) {
 			existingPIPs: []network.PublicIPAddress{
 				{
 					Name: to.StringPtr("testPIP"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						PublicIPAddressVersion:   network.IPVersionIPv4,
 						PublicIPAllocationMethod: network.IPAllocationMethodStatic,
@@ -3098,7 +3098,7 @@ func TestReconcilePublicIP(t *testing.T) {
 			expectedPIP: &network.PublicIPAddress{
 				ID:   to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/testPIP"),
 				Name: to.StringPtr("testPIP"),
-				Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+				Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 				PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 					PublicIPAddressVersion:   network.IPVersionIPv4,
 					PublicIPAllocationMethod: network.IPAllocationMethodStatic,
@@ -3127,7 +3127,7 @@ func TestReconcilePublicIP(t *testing.T) {
 				},
 				{
 					Name: to.StringPtr("pip2"),
-					Tags: map[string]*string{"service": to.StringPtr("default/test1")},
+					Tags: map[string]*string{consts.ServiceTagKey: to.StringPtr("default/test1")},
 					PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
 						IPAddress: to.StringPtr("1.2.3.4"),
 					},
@@ -3559,8 +3559,8 @@ func TestEnsurePublicIPExistsWithExtendedLocation(t *testing.T) {
 			ProvisioningState:        "",
 		},
 		Tags: map[string]*string{
-			"service":                 to.StringPtr("default/test1"),
-			"kubernetes-cluster-name": to.StringPtr(""),
+			consts.ServiceTagKey:  to.StringPtr("default/test1"),
+			consts.ClusterNameKey: to.StringPtr(""),
 		},
 	}
 	mockPIPsClient := az.PublicIPAddressesClient.(*mockpublicipclient.MockInterface)
@@ -4642,3 +4642,90 @@ func TestReconcileSharedLoadBalancer(t *testing.T) {
 		})
 	}
 }
+
+func TestGetServiceFromPIPDNSTags(t *testing.T) {
+	tests := []struct {
+		desc     string
+		tags     map[string]*string
+		expected string
+	}{
+		{
+			desc: "Empty string should be returned when tags are empty",
+		},
+		{
+			desc: "Empty string should be returned when tags don't contain dns label tag",
+		},
+		{
+			desc:     "Expected service should be returned when tags contain dns label tag",
+			tags:     map[string]*string{consts.ServiceUsingDNSKey: to.StringPtr("test-service")},
+			expected: "test-service",
+		},
+		{
+			desc:     "Expected service should be returned when tags contain legacy dns label tag",
+			tags:     map[string]*string{consts.LegacyServiceUsingDNSKey: to.StringPtr("test-service")},
+			expected: "test-service",
+		},
+	}
+	for i, c := range tests {
+		actual := getServiceFromPIPDNSTags(c.tags)
+		assert.Equal(t, actual, c.expected, "TestCase[%d]: %s", i, c.desc)
+	}
+}
+
+func TestGetServiceFromPIPServiceTags(t *testing.T) {
+	tests := []struct {
+		desc     string
+		tags     map[string]*string
+		expected string
+	}{
+		{
+			desc: "Empty string should be returned when tags are empty",
+		},
+		{
+			desc: "Empty string should be returned when tags don't contain service tag",
+		},
+		{
+			desc:     "Expected service should be returned when tags contain service tag",
+			tags:     map[string]*string{consts.ServiceTagKey: to.StringPtr("test-service")},
+			expected: "test-service",
+		},
+		{
+			desc:     "Expected service should be returned when tags contain legacy service tag",
+			tags:     map[string]*string{consts.LegacyServiceTagKey: to.StringPtr("test-service")},
+			expected: "test-service",
+		},
+	}
+	for i, c := range tests {
+		actual := getServiceFromPIPServiceTags(c.tags)
+		assert.Equal(t, actual, c.expected, "TestCase[%d]: %s", i, c.desc)
+	}
+}
+
+func TestGetClusterFromPIPClusterTags(t *testing.T) {
+	tests := []struct {
+		desc     string
+		tags     map[string]*string
+		expected string
+	}{
+		{
+			desc: "Empty string should be returned when tags are empty",
+		},
+		{
+			desc: "Empty string should be returned when tags don't contain cluster name tag",
+		},
+		{
+			desc:     "Expected service should be returned when tags contain cluster name tag",
+			tags:     map[string]*string{consts.ClusterNameKey: to.StringPtr("test-cluster")},
+			expected: "test-cluster",
+		},
+		{
+			desc:     "Expected service should be returned when tags contain legacy cluster name tag",
+			tags:     map[string]*string{consts.LegacyClusterNameKey: to.StringPtr("test-cluster")},
+			expected: "test-cluster",
+		},
+	}
+	for i, c := range tests {
+		actual := getClusterFromPIPClusterTags(c.tags)
+		assert.Equal(t, actual, c.expected, "TestCase[%d]: %s", i, c.desc)
+	}
+}
diff --git a/tests/e2e/network/service_annotations.go b/tests/e2e/network/service_annotations.go
index 9e0c630b1..c900b1e24 100644
--- a/tests/e2e/network/service_annotations.go
+++ b/tests/e2e/network/service_annotations.go
@@ -502,8 +502,8 @@ func waitComparePIPTags(tc *utils.AzureTestClient, expectedTags map[string]*stri
 			return false, err
 		}
 		tags := pip.Tags
-		delete(tags, "kubernetes-cluster-name")
-		delete(tags, "service")
+		delete(tags, consts.ClusterNameKey)
+		delete(tags, consts.ServiceTagKey)
 		utils.Logf("\ntags: %v\nexpectedTags: %v", tags, expectedTags)
 		return reflect.DeepEqual(tags, expectedTags), nil
 	})