Repository: kubernetes-sigs/cloud-provider-azure
Pull request #2875 (2022-12-08 03:28:33)

cleanup: set context as parameter in cloud provider functions
<!--  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 cleanup

#### What this PR does / why we need it:
cleanup: set context as parameter in cloud provider functions
#### 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 #

#### 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
none
```

#### 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
none
```


k8s-ci-robot: @umagnus: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
k8s-ci-robot: Hi @umagnus. Thanks for your PR.

I'm waiting for a [kubernetes-sigs](https://github.com/orgs/kubernetes-sigs/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fcloud-provider-azure).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/cloud-provider-azure/pull/2875#" title="Author self-approved">umagnus</a>*
**Once this PR has been reviewed and has the lgtm label**, please assign jwtty for approval by writing `/assign @jwtty` in a comment. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

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).

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

- **[OWNERS](https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/OWNERS)**

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":["jwtty"]} -->
coveralls: 
[![Coverage Status](https://coveralls.io/builds/54960704/badge)](https://coveralls.io/builds/54960704)

Coverage decreased (-0.007%) to 79.545% when pulling **7faa0b2261cfa275151ea5b8c939283d951a46ca on umagnus:set_context** into **2f0e8ad2f9d16eb7066548052148b36ce1ba8aa9 on kubernetes-sigs:master**.

andyzhangx: /ok-to-test
k8s-ci-robot: @umagnus: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-cloud-provider-azure-e2e-ccm-vmssflex-capz | 7faa0b2261cfa275151ea5b8c939283d951a46ca | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/2875/pull-cloud-provider-azure-e2e-ccm-vmssflex-capz/1600722698965618688) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmssflex-capz`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cloud-provider-azure&pr=2875). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Aumagnus). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cloud-provider-azure/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
deleted file mode 100644
index d68b3da4f..000000000
--- a/.github/workflows/lint.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Code Lint
-
-on:
-  workflow_dispatch:
-  push:
-  pull_request:
-
-jobs:
-  Lint:
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v3
-      - name: Setup Golang
-        uses: actions/setup-go@v3
-        with:
-          go-version-file: go.mod
-      - name: Lint
-        run: |
-          make lint
diff --git a/.golangci.yml b/.golangci.yml
index 3855f5efd..e10f54519 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,40 +1,26 @@
 run:
-  timeout: 30m
+  deadline: 30m
+  concurrency: 2
   go: '1.18'
-  tests: true
-  skip-dirs:
+  allow-serial-runners: true
+skip-dirs:
     - vendor
 linters:
   disable-all: true
   enable:
-    - errcheck
-    - goconst
-    - gofmt
-    - goimports
-    - revive
-    - gosec
-    - gosimple
-    - govet
-    - ineffassign
-    - misspell
-    - nakedret
-    - staticcheck
-    - typecheck
-    - unconvert
-    - unused
+    - LINTER_TO_RUN
+  # Run with --fast=false for more extensive checks
   fast: false
+  govet:
+    # Report about shadowed variables.
+    # Default: false
+    check-shadowing: true
 issues:
   exclude-rules:
     - path: tests/e2e
       linters:
         - revive
+  #include:
+  #  - EXC0002 # include "missing comments" issues from golint
   max-issues-per-linter: 0
   max-same-issues: 0
-linters-settings:
-  staticcheck:
-    checks: ["all", "-SA1019"]
-  gosec:
-    excludes:
-      - G114
-  govet:
-    check-shadowing: false
diff --git a/Makefile b/Makefile
index b9a53c168..c378a1b36 100644
--- a/Makefile
+++ b/Makefile
@@ -317,11 +317,11 @@ ifdef JUNIT
 endif
 
 .PHONY: test-check
-test-check: test-boilerplate test-helm verify-vendor-licenses ## Run all static checks.
+test-check: test-lint test-boilerplate test-helm verify-vendor-licenses ## Run all static checks.
 
-.PHONY: lint
-lint: golangci-lint ## Run golangci-lint against code.
-	$(LINTER) run -v
+.PHONY: test-lint
+test-lint: ## Run golint test.
+	hack/verify-golint.sh
 
 .PHONY: test-boilerplate
 test-boilerplate: ## Run boilerplate test.
@@ -400,12 +400,3 @@ endif
 .PHONY: deploy-cluster
 deploy-cluster:
 	hack/deploy-cluster-capz.sh
-
-##@ Tools
-
-LINTER = $(shell pwd)/bin/golangci-lint
-LINTER_VERSION = v1.50.1
-.PHONY: golangci-lint
-golangci-lint:  ## Download golangci-lint locally if necessary.
-	@echo "Installing golangci-lint"
-	@test -s $(LINTER) || curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/$(LINTER_VERSION)/install.sh | sh -s -- -b $(shell pwd)/bin $(LINTER_VERSION)
diff --git a/cmd/cloud-controller-manager/app/controllermanager.go b/cmd/cloud-controller-manager/app/controllermanager.go
index 9804f09cb..a1d4b5e23 100644
--- a/cmd/cloud-controller-manager/app/controllermanager.go
+++ b/cmd/cloud-controller-manager/app/controllermanager.go
@@ -321,12 +321,12 @@ func Run(ctx context.Context, c *cloudcontrollerconfig.CompletedConfig, h *contr
 	)
 
 	if c.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile != "" {
-		cloud, err = provider.NewCloudFromConfigFile(c.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile, true)
+		cloud, err = provider.NewCloudFromConfigFile(ctx, c.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile, true)
 		if err != nil {
 			klog.Fatalf("Cloud provider azure could not be initialized: %v", err)
 		}
 	} else if c.DynamicReloadingConfig.EnableDynamicReloading && c.DynamicReloadingConfig.CloudConfigSecretName != "" {
-		cloud, err = provider.NewCloudFromSecret(c.ClientBuilder, c.DynamicReloadingConfig.CloudConfigSecretName, c.DynamicReloadingConfig.CloudConfigSecretNamespace, c.DynamicReloadingConfig.CloudConfigKey)
+		cloud, err = provider.NewCloudFromSecret(ctx, c.ClientBuilder, c.DynamicReloadingConfig.CloudConfigSecretName, c.DynamicReloadingConfig.CloudConfigSecretNamespace, c.DynamicReloadingConfig.CloudConfigKey)
 		if err != nil {
 			klog.Fatalf("Run: Cloud provider azure could not be initialized dynamically from secret %s/%s: %v", c.DynamicReloadingConfig.CloudConfigSecretNamespace, c.DynamicReloadingConfig.CloudConfigSecretName, err)
 		}
diff --git a/cmd/cloud-node-manager/app/nodemanager.go b/cmd/cloud-node-manager/app/nodemanager.go
index 390b49d07..f0acb7ab9 100644
--- a/cmd/cloud-node-manager/app/nodemanager.go
+++ b/cmd/cloud-node-manager/app/nodemanager.go
@@ -125,7 +125,7 @@ func Run(c *cloudnodeconfig.Config, stopCh <-chan struct{}) error {
 	}
 
 	run := func(ctx context.Context) {
-		if err := startControllers(c, ctx.Done(), healthzHandler); err != nil {
+		if err := startControllers(ctx, c, ctx.Done(), healthzHandler); err != nil {
 			klog.Fatalf("error running controllers: %v", err)
 		}
 	}
@@ -135,7 +135,7 @@ func Run(c *cloudnodeconfig.Config, stopCh <-chan struct{}) error {
 }
 
 // startControllers starts the cloud specific controller loops.
-func startControllers(c *cloudnodeconfig.Config, stopCh <-chan struct{}, healthzHandler *controllerhealthz.MutableHealthzHandler) error {
+func startControllers(ctx context.Context, c *cloudnodeconfig.Config, stopCh <-chan struct{}, healthzHandler *controllerhealthz.MutableHealthzHandler) error {
 	klog.V(1).Infof("Starting cloud-node-manager...")
 
 	// Start the CloudNodeController
@@ -144,7 +144,7 @@ func startControllers(c *cloudnodeconfig.Config, stopCh <-chan struct{}, healthz
 		c.SharedInformers.Core().V1().Nodes(),
 		// cloud node controller uses existing cluster role from node-controller
 		c.ClientBuilder.ClientOrDie("node-controller"),
-		nodeprovider.NewNodeProvider(c.UseInstanceMetadata, c.CloudConfigFilePath),
+		nodeprovider.NewNodeProvider(ctx, c.UseInstanceMetadata, c.CloudConfigFilePath),
 		c.NodeStatusUpdateFrequency.Duration,
 		c.WaitForRoutes)
 
diff --git a/hack/verify-golint.sh b/hack/verify-golint.sh
new file mode 100755
index 000000000..1cf2c3a6e
--- /dev/null
+++ b/hack/verify-golint.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# Copyright 2020 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.
+
+set -euo pipefail
+
+if [[ -z "$(command -v golangci-lint)" ]]; then
+  echo "Cannot find golangci-lint. Installing golangci-lint..."
+  go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.0
+  export PATH=$PATH:$(go env GOPATH)/bin
+fi
+
+echo "Verifying golint"
+readonly PKG_ROOT="$(git rev-parse --show-toplevel)"
+
+LINTERS=("deadcode" "errcheck" "goconst" "gofmt" "goimports" "revive" "gosec" "gosimple" "govet" "ineffassign" "misspell" "nakedret" "staticcheck" "structcheck" "typecheck" "unconvert" "unused" "varcheck" )
+GOLANGCI_YML="${PKG_ROOT}/.golangci.yml"
+GOLANGCI_YML_TEST="${PKG_ROOT}/.golangci-test.yml"
+for LINTER in "${LINTERS[@]}"; do
+  cp -rf "${GOLANGCI_YML}" "${GOLANGCI_YML_TEST}"
+  sed -i "s|LINTER_TO_RUN|${LINTER}|g" "${GOLANGCI_YML_TEST}"
+  golangci-lint run -v --config "${GOLANGCI_YML_TEST}"
+  echo ""
+done
+
+echo "Congratulations! Lint check completed for all Go source files."
diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go
index 04838b5d1..d832b28d4 100644
--- a/pkg/consts/consts.go
+++ b/pkg/consts/consts.go
@@ -300,7 +300,7 @@ const (
 
 	// ServiceAnnotationLoadBalancerHealthProbeRequestPath determines the request path of the load balancer health probe.
 	// This is only useful for the HTTP and HTTPS, and would be ignored when using TCP. If not set,
-	// `/` would be configured by default.
+	// `/healthz` would be configured by default.
 	ServiceAnnotationLoadBalancerHealthProbeRequestPath = "service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path"
 
 	// ServiceAnnotationAzurePIPTags determines what tags should be applied to the public IP of the service. The cluster name
@@ -428,19 +428,9 @@ const RateLimited = "rate limited"
 // CreatedByTag tag key for CSI drivers
 const CreatedByTag = "k8s-azure-created-by"
 
-// port specific
-const (
-	PortAnnotationPrefixPattern            = "service.beta.kubernetes.io/port_%d_%s"
-	PortAnnotationNoLBRule      PortParams = "no_lb_rule"
-	// NoHealthProbeRule determines whether the port is only used for health probe. no lb probe rule will be created.
-	PortAnnotationNoHealthProbeRule PortParams = "no_probe_rule"
-)
-
-type PortParams string
-
 // health probe
 const (
-	HealthProbeAnnotationPrefixPattern = "health-probe_%s"
+	HealthProbeAnnotationPrefixPattern = "service.beta.kubernetes.io/port_%d_health-probe_"
 
 	// HealthProbeParamsProtocol determines the protocol for the health probe params.
 	// It always takes priority over spec.appProtocol or any other specified protocol
diff --git a/pkg/consts/helpers.go b/pkg/consts/helpers.go
index b800e9c64..141aff688 100644
--- a/pkg/consts/helpers.go
+++ b/pkg/consts/helpers.go
@@ -50,16 +50,6 @@ func GetHealthProbeConfigOfPortFromK8sSvcAnnotation(annotations map[string]strin
 	return GetAttributeValueInSvcAnnotation(annotations, BuildHealthProbeAnnotationKeyForPort(port, key), validators...)
 }
 
-// IsHealthProbeRuleOnK8sServicePortDisabled return if port is for health probe only
-func IsHealthProbeRuleOnK8sServicePortDisabled(annotations map[string]string, port int32) (bool, error) {
-	return expectAttributeInSvcAnnotationBeEqualTo(annotations, BuildAnnotationKeyForPort(port, PortAnnotationNoHealthProbeRule), TrueAnnotationValue), nil
-}
-
-// IsHealthProbeRuleOnK8sServicePortDisabled return if port is for health probe only
-func IsLBRuleOnK8sServicePortDisabled(annotations map[string]string, port int32) (bool, error) {
-	return expectAttributeInSvcAnnotationBeEqualTo(annotations, BuildAnnotationKeyForPort(port, PortAnnotationNoLBRule), TrueAnnotationValue), nil
-}
-
 // Getint32ValueFromK8sSvcAnnotation get health probe configuration for port
 func Getint32ValueFromK8sSvcAnnotation(annotations map[string]string, key string, validators ...Int32BusinessValidator) (*int32, error) {
 	val, err := GetAttributeValueInSvcAnnotation(annotations, key)
@@ -69,14 +59,9 @@ func Getint32ValueFromK8sSvcAnnotation(annotations map[string]string, key string
 	return nil, err
 }
 
-// BuildHealthProbeAnnotationKeyForPort get health probe configuration key for port
-func BuildAnnotationKeyForPort(port int32, key PortParams) string {
-	return fmt.Sprintf(PortAnnotationPrefixPattern, port, string(key))
-}
-
 // BuildHealthProbeAnnotationKeyForPort get health probe configuration key for port
 func BuildHealthProbeAnnotationKeyForPort(port int32, key HealthProbeParams) string {
-	return BuildAnnotationKeyForPort(port, PortParams(fmt.Sprintf(HealthProbeAnnotationPrefixPattern, key)))
+	return fmt.Sprintf(HealthProbeAnnotationPrefixPattern, port) + string(key)
 }
 
 // GetInt32HealthProbeConfigOfPortFromK8sSvcAnnotation get health probe configuration for port
diff --git a/pkg/node/node.go b/pkg/node/node.go
index f2f9eee1c..11256e3dc 100644
--- a/pkg/node/node.go
+++ b/pkg/node/node.go
@@ -34,8 +34,8 @@ type IMDSNodeProvider struct {
 }
 
 // NewIMDSNodeProvider creates a new IMDSNodeProvider.
-func NewIMDSNodeProvider() *IMDSNodeProvider {
-	az, err := azureprovider.NewCloud(bytes.NewBuffer([]byte(`{
+func NewIMDSNodeProvider(ctx context.Context) *IMDSNodeProvider {
+	az, err := azureprovider.NewCloud(ctx, bytes.NewBuffer([]byte(`{
 			"useInstanceMetadata": true,
 			"vmType": "vmss"
 		}`)), false)
diff --git a/pkg/node/nodearm.go b/pkg/node/nodearm.go
index 5294c00ce..58dbc5f78 100644
--- a/pkg/node/nodearm.go
+++ b/pkg/node/nodearm.go
@@ -35,7 +35,7 @@ type ARMNodeProvider struct {
 }
 
 // NewARMNodeProvider creates a new ARMNodeProvider.
-func NewARMNodeProvider(cloudConfigFilePath string) *ARMNodeProvider {
+func NewARMNodeProvider(ctx context.Context, cloudConfigFilePath string) *ARMNodeProvider {
 	var err error
 	var configFile *os.File
 	var az cloudprovider.Interface
@@ -47,7 +47,7 @@ func NewARMNodeProvider(cloudConfigFilePath string) *ARMNodeProvider {
 		}
 		defer configFile.Close()
 
-		az, err = azureprovider.NewCloud(configFile, false)
+		az, err = azureprovider.NewCloud(ctx, configFile, false)
 
 		if err != nil {
 			klog.Fatalf("Failed to initialize Azure cloud provider: %v", err)
diff --git a/pkg/node/nodeproviderfactory.go b/pkg/node/nodeproviderfactory.go
index a11c360db..dfaa593e7 100644
--- a/pkg/node/nodeproviderfactory.go
+++ b/pkg/node/nodeproviderfactory.go
@@ -17,17 +17,19 @@ limitations under the License.
 package node
 
 import (
+	"context"
+
 	nodemanager "sigs.k8s.io/cloud-provider-azure/pkg/nodemanager"
 )
 
 // NewNodeProvider returns a node provider depending on the use case
-func NewNodeProvider(useMetadata bool, cloudConfigFilePath string) nodemanager.NodeProvider {
+func NewNodeProvider(ctx context.Context, useMetadata bool, cloudConfigFilePath string) nodemanager.NodeProvider {
 	var nodeProvider nodemanager.NodeProvider
 
 	if useMetadata {
-		nodeProvider = NewIMDSNodeProvider()
+		nodeProvider = NewIMDSNodeProvider(ctx)
 	} else {
-		nodeProvider = NewARMNodeProvider(cloudConfigFilePath)
+		nodeProvider = NewARMNodeProvider(ctx, cloudConfigFilePath)
 	}
 
 	return nodeProvider
diff --git a/pkg/provider/azure.go b/pkg/provider/azure.go
index adc623eeb..55e2517c5 100644
--- a/pkg/provider/azure.go
+++ b/pkg/provider/azure.go
@@ -17,6 +17,7 @@ limitations under the License.
 package provider
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"io"
@@ -375,8 +376,8 @@ type Cloud struct {
 }
 
 // NewCloud returns a Cloud with initialized clients
-func NewCloud(configReader io.Reader, callFromCCM bool) (cloudprovider.Interface, error) {
-	az, err := NewCloudWithoutFeatureGates(configReader, callFromCCM)
+func NewCloud(ctx context.Context, configReader io.Reader, callFromCCM bool) (cloudprovider.Interface, error) {
+	az, err := NewCloudWithoutFeatureGates(ctx, configReader, callFromCCM)
 	if err != nil {
 		return nil, err
 	}
@@ -385,7 +386,7 @@ func NewCloud(configReader io.Reader, callFromCCM bool) (cloudprovider.Interface
 	return az, nil
 }
 
-func NewCloudFromConfigFile(configFilePath string, calFromCCM bool) (cloudprovider.Interface, error) {
+func NewCloudFromConfigFile(ctx context.Context, configFilePath string, calFromCCM bool) (cloudprovider.Interface, error) {
 	var (
 		cloud cloudprovider.Interface
 		err   error
@@ -400,11 +401,11 @@ func NewCloudFromConfigFile(configFilePath string, calFromCCM bool) (cloudprovid
 		}
 
 		defer config.Close()
-		cloud, err = NewCloud(config, calFromCCM)
+		cloud, err = NewCloud(ctx, config, calFromCCM)
 	} else {
 		// Pass explicit nil so plugins can actually check for nil. See
 		// "Why is my nil error value not equal to nil?" in golang.org/doc/faq.
-		cloud, err = NewCloud(nil, false)
+		cloud, err = NewCloud(ctx, nil, false)
 	}
 
 	if err != nil {
@@ -435,7 +436,7 @@ func (az *Cloud) configSecretMetadata(secretName, secretNamespace, cloudConfigKe
 	}
 }
 
-func NewCloudFromSecret(clientBuilder cloudprovider.ControllerClientBuilder, secretName, secretNamespace, cloudConfigKey string) (cloudprovider.Interface, error) {
+func NewCloudFromSecret(ctx context.Context, clientBuilder cloudprovider.ControllerClientBuilder, secretName, secretNamespace, cloudConfigKey string) (cloudprovider.Interface, error) {
 	az := &Cloud{
 		nodeNames:                sets.NewString(),
 		nodeZones:                map[string]sets.String{},
@@ -450,7 +451,7 @@ func NewCloudFromSecret(clientBuilder cloudprovider.ControllerClientBuilder, sec
 
 	az.Initialize(clientBuilder, wait.NeverStop)
 
-	err := az.InitializeCloudFromSecret()
+	err := az.InitializeCloudFromSecret(ctx)
 	if err != nil {
 		return nil, fmt.Errorf("NewCloudFromSecret: failed to initialize cloud from secret %s/%s: %v", az.SecretNamespace, az.SecretName, err)
 	}
@@ -462,7 +463,7 @@ func NewCloudFromSecret(clientBuilder cloudprovider.ControllerClientBuilder, sec
 
 // NewCloudWithoutFeatureGates returns a Cloud without trying to wire the feature gates.  This is used by the unit tests
 // that don't load the actual features being used in the cluster.
-func NewCloudWithoutFeatureGates(configReader io.Reader, callFromCCM bool) (*Cloud, error) {
+func NewCloudWithoutFeatureGates(ctx context.Context, configReader io.Reader, callFromCCM bool) (*Cloud, error) {
 	config, err := ParseConfig(configReader)
 	if err != nil {
 		return nil, err
@@ -478,7 +479,7 @@ func NewCloudWithoutFeatureGates(configReader io.Reader, callFromCCM bool) (*Clo
 		nodePrivateIPs:           map[string]sets.String{},
 	}
 
-	err = az.InitializeCloudFromConfig(config, false, callFromCCM)
+	err = az.InitializeCloudFromConfig(ctx, config, false, callFromCCM)
 	if err != nil {
 		return nil, err
 	}
@@ -487,7 +488,7 @@ func NewCloudWithoutFeatureGates(configReader io.Reader, callFromCCM bool) (*Clo
 }
 
 // InitializeCloudFromConfig initializes the Cloud from config.
-func (az *Cloud) InitializeCloudFromConfig(config *Config, fromSecret, callFromCCM bool) error {
+func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config, fromSecret, callFromCCM bool) error {
 	if config == nil {
 		// should not reach here
 		return fmt.Errorf("InitializeCloudFromConfig: cannot initialize from nil config")
@@ -606,12 +607,12 @@ func (az *Cloud) InitializeCloudFromConfig(config *Config, fromSecret, callFromC
 	}
 
 	if strings.EqualFold(consts.VMTypeVMSS, az.Config.VMType) {
-		az.VMSet, err = newScaleSet(az)
+		az.VMSet, err = newScaleSet(ctx, az)
 		if err != nil {
 			return err
 		}
 	} else if strings.EqualFold(consts.VMTypeVmssFlex, az.Config.VMType) {
-		az.VMSet, err = newFlexScaleSet(az)
+		az.VMSet, err = newFlexScaleSet(ctx, az)
 		if err != nil {
 			return err
 		}
diff --git a/pkg/provider/azure_config.go b/pkg/provider/azure_config.go
index 4b0af9e7e..6711c5f65 100644
--- a/pkg/provider/azure_config.go
+++ b/pkg/provider/azure_config.go
@@ -39,7 +39,7 @@ const (
 )
 
 // InitializeCloudFromSecret initializes Azure cloud provider from Kubernetes secret.
-func (az *Cloud) InitializeCloudFromSecret() error {
+func (az *Cloud) InitializeCloudFromSecret(ctx context.Context) error {
 	config, err := az.GetConfigFromSecret()
 	if err != nil {
 		klog.Errorf("Failed to get cloud-config from secret: %v", err)
@@ -51,7 +51,7 @@ func (az *Cloud) InitializeCloudFromSecret() error {
 		return nil
 	}
 
-	if err := az.InitializeCloudFromConfig(config, true, true); err != nil {
+	if err := az.InitializeCloudFromConfig(ctx, config, true, true); err != nil {
 		klog.Errorf("Failed to initialize Azure cloud provider: %v", err)
 		return fmt.Errorf("InitializeCloudFromSecret: failed to initialize Azure cloud provider: %w", err)
 	}
diff --git a/pkg/provider/azure_fakes.go b/pkg/provider/azure_fakes.go
index a78281ba0..77919a094 100644
--- a/pkg/provider/azure_fakes.go
+++ b/pkg/provider/azure_fakes.go
@@ -17,6 +17,7 @@ limitations under the License.
 package provider
 
 import (
+	"context"
 	"fmt"
 
 	"github.com/golang/mock/gomock"
@@ -52,7 +53,7 @@ func NewTestScaleSet(ctrl *gomock.Controller) (*ScaleSet, error) {
 
 func newTestScaleSetWithState(ctrl *gomock.Controller) (*ScaleSet, error) {
 	cloud := GetTestCloud(ctrl)
-	ss, err := newScaleSet(cloud)
+	ss, err := newScaleSet(context.Background(), cloud)
 	if err != nil {
 		return nil, err
 	}
@@ -62,7 +63,7 @@ func newTestScaleSetWithState(ctrl *gomock.Controller) (*ScaleSet, error) {
 
 func NewTestFlexScaleSet(ctrl *gomock.Controller) (*FlexScaleSet, error) {
 	cloud := GetTestCloud(ctrl)
-	fs, err := newFlexScaleSet(cloud)
+	fs, err := newFlexScaleSet(context.Background(), cloud)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/provider/azure_loadbalancer.go b/pkg/provider/azure_loadbalancer.go
index f4a32f30b..6ac852af0 100644
--- a/pkg/provider/azure_loadbalancer.go
+++ b/pkg/provider/azure_loadbalancer.go
@@ -2062,7 +2062,7 @@ func lbRuleConflictsWithPort(rule network.LoadBalancingRule, frontendIPConfigID
 // buildHealthProbeRulesForPort
 // for following sku: basic loadbalancer vs standard load balancer
 // for following protocols: TCP HTTP HTTPS(SLB only)
-func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port v1.ServicePort, lbrule string) (*network.Probe, error) {
+func (az *Cloud) buildHealthProbeRulesForPort(annotations map[string]string, port v1.ServicePort, lbrule string) (*network.Probe, error) {
 	if port.Protocol == v1.ProtocolUDP || port.Protocol == v1.ProtocolSCTP {
 		return nil, nil
 	}
@@ -2080,7 +2080,7 @@ func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port
 	var protocol *string
 
 	// 1. Look up port-specific override
-	protocol, err = consts.GetHealthProbeConfigOfPortFromK8sSvcAnnotation(serviceManifest.Annotations, port.Port, consts.HealthProbeParamsProtocol)
+	protocol, err = consts.GetHealthProbeConfigOfPortFromK8sSvcAnnotation(annotations, port.Port, consts.HealthProbeParamsProtocol)
 	if err != nil {
 		return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.BuildHealthProbeAnnotationKeyForPort(port.Port, consts.HealthProbeParamsProtocol), err)
 	}
@@ -2093,7 +2093,7 @@ func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port
 
 	// 3. If protocol is still nil, check the global annotation
 	if protocol == nil {
-		protocol, err = consts.GetAttributeValueInSvcAnnotation(serviceManifest.Annotations, consts.ServiceAnnotationLoadBalancerHealthProbeProtocol)
+		protocol, err = consts.GetAttributeValueInSvcAnnotation(annotations, consts.ServiceAnnotationLoadBalancerHealthProbeProtocol)
 		if err != nil {
 			return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.ServiceAnnotationLoadBalancerHealthProbeProtocol, err)
 		}
@@ -2126,71 +2126,37 @@ func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port
 	// Lookup or Override Health Probe Port
 	properties.Port = &port.NodePort
 
-	probePort, err := consts.GetHealthProbeConfigOfPortFromK8sSvcAnnotation(serviceManifest.Annotations, port.Port, consts.HealthProbeParamsPort, func(s *string) error {
-		if s == nil {
-			return nil
-		}
-		//nolint:gosec
-		port, err := strconv.Atoi(*s)
-		if err != nil {
-			//not a integer
-			for _, item := range serviceManifest.Spec.Ports {
-				if strings.EqualFold(item.Name, *s) {
-					//found the port
-					return nil
-				}
-			}
-			return fmt.Errorf("port %s not found in service", *s)
-		}
-		if port < 0 || port > 65535 {
-			return fmt.Errorf("port %d is out of range", port)
-		}
-		for _, item := range serviceManifest.Spec.Ports {
-			//nolint:gosec
-			if item.Port == int32(port) {
-				//found the port
-				return nil
-			}
+	// Look up port-specific override
+	var probePortValidator = func(val *int32) error {
+		//minimum number of unhealthy responses is 2. ref: https://docs.microsoft.com/en-us/rest/api/load-balancer/load-balancers/create-or-update#probe
+		const (
+			MinProbePort = 1
+			MaxProbePort = 65535
+		)
+		if *val < MinProbePort || *val > MaxProbePort {
+			return fmt.Errorf("the value of %s must be between %d and %d inclusive", consts.HealthProbeParamsPort, MinProbePort, MaxProbePort)
 		}
-		return fmt.Errorf("port %s not found in service", *s)
-	})
+		return nil
+	}
+
+	probePort, err := consts.GetInt32HealthProbeConfigOfPortFromK8sSvcAnnotation(annotations, port.Port, consts.HealthProbeParamsPort, probePortValidator)
 	if err != nil {
 		return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.BuildHealthProbeAnnotationKeyForPort(port.Port, consts.HealthProbeParamsPort), err)
 	}
 
 	if probePort != nil {
-		//nolint:gosec
-		port, err := strconv.Atoi(*probePort)
-		if err != nil {
-			//not a integer
-			for _, item := range serviceManifest.Spec.Ports {
-				if strings.EqualFold(item.Name, *probePort) {
-					//found the port
-					properties.Port = to.Int32Ptr(item.NodePort)
-				}
-			}
-		} else {
-			if port >= 0 || port <= 65535 {
-				for _, item := range serviceManifest.Spec.Ports {
-					//nolint:gosec
-					if item.Port == int32(port) {
-						//found the port
-						properties.Port = to.Int32Ptr(item.NodePort)
-					}
-				}
-			}
-		}
+		properties.Port = probePort
 	}
 
 	// Select request path
 	if strings.EqualFold(string(properties.Protocol), string(network.ProtocolHTTPS)) || strings.EqualFold(string(properties.Protocol), string(network.ProtocolHTTP)) {
 		// get request path ,only used with http/https probe
-		path, err := consts.GetHealthProbeConfigOfPortFromK8sSvcAnnotation(serviceManifest.Annotations, port.Port, consts.HealthProbeParamsRequestPath)
+		path, err := consts.GetHealthProbeConfigOfPortFromK8sSvcAnnotation(annotations, port.Port, consts.HealthProbeParamsRequestPath)
 		if err != nil {
 			return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.BuildHealthProbeAnnotationKeyForPort(port.Port, consts.HealthProbeParamsRequestPath), err)
 		}
 		if path == nil {
-			if path, err = consts.GetAttributeValueInSvcAnnotation(serviceManifest.Annotations, consts.ServiceAnnotationLoadBalancerHealthProbeRequestPath); err != nil {
+			if path, err = consts.GetAttributeValueInSvcAnnotation(annotations, consts.ServiceAnnotationLoadBalancerHealthProbeRequestPath); err != nil {
 				return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.ServiceAnnotationLoadBalancerHealthProbeRequestPath, err)
 			}
 		}
@@ -2210,12 +2176,12 @@ func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port
 		}
 		return nil
 	}
-	numberOfProbes, err := consts.GetInt32HealthProbeConfigOfPortFromK8sSvcAnnotation(serviceManifest.Annotations, port.Port, consts.HealthProbeParamsNumOfProbe, numOfProbeValidator)
+	numberOfProbes, err := consts.GetInt32HealthProbeConfigOfPortFromK8sSvcAnnotation(annotations, port.Port, consts.HealthProbeParamsNumOfProbe, numOfProbeValidator)
 	if err != nil {
 		return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.BuildHealthProbeAnnotationKeyForPort(port.Port, consts.HealthProbeParamsNumOfProbe), err)
 	}
 	if numberOfProbes == nil {
-		if numberOfProbes, err = consts.Getint32ValueFromK8sSvcAnnotation(serviceManifest.Annotations, consts.ServiceAnnotationLoadBalancerHealthProbeNumOfProbe, numOfProbeValidator); err != nil {
+		if numberOfProbes, err = consts.Getint32ValueFromK8sSvcAnnotation(annotations, consts.ServiceAnnotationLoadBalancerHealthProbeNumOfProbe, numOfProbeValidator); err != nil {
 			return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.ServiceAnnotationLoadBalancerHealthProbeNumOfProbe, err)
 		}
 	}
@@ -2236,12 +2202,12 @@ func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port
 		}
 		return nil
 	}
-	probeInterval, err := consts.GetInt32HealthProbeConfigOfPortFromK8sSvcAnnotation(serviceManifest.Annotations, port.Port, consts.HealthProbeParamsProbeInterval, probeIntervalValidator)
+	probeInterval, err := consts.GetInt32HealthProbeConfigOfPortFromK8sSvcAnnotation(annotations, port.Port, consts.HealthProbeParamsProbeInterval, probeIntervalValidator)
 	if err != nil {
 		return nil, fmt.Errorf("failed to parse annotation %s:%w", consts.BuildHealthProbeAnnotationKeyForPort(port.Port, consts.HealthProbeParamsProbeInterval), err)
 	}
 	if probeInterval == nil {
-		if probeInterval, err = consts.Getint32ValueFromK8sSvcAnnotation(serviceManifest.Annotations, consts.ServiceAnnotationLoadBalancerHealthProbeInterval, probeIntervalValidator); err != nil {
+		if probeInterval, err = consts.Getint32ValueFromK8sSvcAnnotation(annotations, consts.ServiceAnnotationLoadBalancerHealthProbeInterval, probeIntervalValidator); err != nil {
 			return nil, fmt.Errorf("failed to parse annotation %s: %w", consts.ServiceAnnotationLoadBalancerHealthProbeInterval, err)
 		}
 	}
@@ -2263,6 +2229,25 @@ func (az *Cloud) buildHealthProbeRulesForPort(serviceManifest *v1.Service, port
 	return probe, nil
 }
 
+// probeKey generates a string key containing all functional probe configuration, to allow de-duplication of like probes.
+func probeKey(probe network.Probe) string {
+	var port, interval, number int32
+	var path string
+	if probe.Port != nil {
+		port = *probe.Port
+	}
+	if probe.IntervalInSeconds != nil {
+		interval = *probe.IntervalInSeconds
+	}
+	if probe.NumberOfProbes != nil {
+		number = *probe.NumberOfProbes
+	}
+	if probe.RequestPath != nil {
+		path = *probe.RequestPath
+	}
+	return fmt.Sprintf("%s-%d-%d-%d-%s", probe.Protocol, port, interval, number, path)
+}
+
 // buildLBRules
 // for following sku: basic loadbalancer vs standard load balancer
 // for following scenario: internal vs external
@@ -2274,6 +2259,7 @@ func (az *Cloud) getExpectedLBRules(
 
 	var expectedRules []network.LoadBalancingRule
 	var expectedProbes []network.Probe
+	uniqueProbes := make(map[string]network.Probe)
 
 	// support podPresence health check when External Traffic Policy is local
 	// take precedence over user defined probe configuration
@@ -2294,7 +2280,7 @@ func (az *Cloud) getExpectedLBRules(
 				NumberOfProbes:    to.Int32Ptr(consts.HealthProbeDefaultNumOfProbe),
 			},
 		}
-		expectedProbes = append(expectedProbes, *nodeEndpointHealthprobe)
+		uniqueProbes[probeKey(*nodeEndpointHealthprobe)] = *nodeEndpointHealthprobe
 	}
 
 	// In HA mode, lb forward traffic of all port to backend
@@ -2314,17 +2300,17 @@ func (az *Cloud) getExpectedLBRules(
 		if nodeEndpointHealthprobe == nil {
 			// use user customized health probe rule if any
 			for _, port := range service.Spec.Ports {
-				portprobe, err := az.buildHealthProbeRulesForPort(service, port, lbRuleName)
+				portprobe, err := az.buildHealthProbeRulesForPort(service.Annotations, port, lbRuleName)
 				if err != nil {
 					klog.V(2).ErrorS(err, "error occurred when buildHealthProbeRulesForPort", "service", service.Name, "namespace", service.Namespace,
 						"rule-name", lbRuleName, "port", port.Port)
 					//ignore error because we only need one correct rule
 				}
 				if portprobe != nil {
+					uniqueProbes[probeKey(*portprobe)] = *portprobe
 					props.Probe = &network.SubResource{
 						ID: to.StringPtr(az.getLoadBalancerProbeID(lbName, az.getLoadBalancerResourceGroup(), *portprobe.Name)),
 					}
-					expectedProbes = append(expectedProbes, *portprobe)
 					break
 				}
 			}
@@ -2345,16 +2331,7 @@ func (az *Cloud) getExpectedLBRules(
 		for _, port := range service.Spec.Ports {
 			lbRuleName := az.getLoadBalancerRuleName(service, port.Protocol, port.Port)
 			klog.V(2).Infof("getExpectedLBRules lb name (%s) rule name (%s)", lbName, lbRuleName)
-			isNoLBRuleRequired, err := consts.IsLBRuleOnK8sServicePortDisabled(service.Annotations, port.Port)
-			if err != nil {
-				err := fmt.Errorf("failed to parse annotation %s: %w", consts.BuildAnnotationKeyForPort(port.Port, consts.PortAnnotationNoLBRule), err)
-				klog.V(2).ErrorS(err, "error occurred when getExpectedLoadBalancingRulePropertiesForPort", "service", service.Name, "namespace", service.Namespace,
-					"rule-name", lbRuleName, "port", port.Port)
-			}
-			if isNoLBRuleRequired {
-				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)) {
 				return expectedProbes, expectedRules, fmt.Errorf("SCTP is only supported on standard loadbalancer in internal mode")
 			}
@@ -2368,31 +2345,23 @@ func (az *Cloud) getExpectedLBRules(
 				return expectedProbes, expectedRules, fmt.Errorf("error generate lb rule for ha mod loadbalancer. err: %w", err)
 			}
 
-			isNoHealthProbeRule, err := consts.IsHealthProbeRuleOnK8sServicePortDisabled(service.Annotations, port.Port)
-			if err != nil {
-				err := fmt.Errorf("failed to parse annotation %s: %w", consts.BuildAnnotationKeyForPort(port.Port, consts.PortAnnotationNoHealthProbeRule), err)
-				klog.V(2).ErrorS(err, "error occurred when buildHealthProbeRulesForPort", "service", service.Name, "namespace", service.Namespace,
-					"rule-name", lbRuleName, "port", port.Port)
-			}
-			if !isNoHealthProbeRule {
-				if nodeEndpointHealthprobe == nil {
-					portprobe, err := az.buildHealthProbeRulesForPort(service, port, lbRuleName)
-					if err != nil {
-						klog.V(2).ErrorS(err, "error occurred when buildHealthProbeRulesForPort", "service", service.Name, "namespace", service.Namespace,
-							"rule-name", lbRuleName, "port", port.Port)
-						return expectedProbes, expectedRules, err
-					}
-					if portprobe != nil {
-						props.Probe = &network.SubResource{
-							ID: to.StringPtr(az.getLoadBalancerProbeID(lbName, az.getLoadBalancerResourceGroup(), *portprobe.Name)),
-						}
-						expectedProbes = append(expectedProbes, *portprobe)
-					}
-				} else {
+			if nodeEndpointHealthprobe == nil {
+				portprobe, err := az.buildHealthProbeRulesForPort(service.Annotations, port, lbRuleName)
+				if err != nil {
+					klog.V(2).ErrorS(err, "error occurred when buildHealthProbeRulesForPort", "service", service.Name, "namespace", service.Namespace,
+						"rule-name", lbRuleName, "port", port.Port)
+					return expectedProbes, expectedRules, err
+				}
+				if portprobe != nil {
+					uniqueProbes[probeKey(*portprobe)] = *portprobe
 					props.Probe = &network.SubResource{
-						ID: to.StringPtr(az.getLoadBalancerProbeID(lbName, az.getLoadBalancerResourceGroup(), *nodeEndpointHealthprobe.Name)),
+						ID: to.StringPtr(az.getLoadBalancerProbeID(lbName, az.getLoadBalancerResourceGroup(), *portprobe.Name)),
 					}
 				}
+			} else {
+				props.Probe = &network.SubResource{
+					ID: to.StringPtr(az.getLoadBalancerProbeID(lbName, az.getLoadBalancerResourceGroup(), *nodeEndpointHealthprobe.Name)),
+				}
 			}
 			if consts.IsK8sServiceDisableLoadBalancerFloatingIP(service) {
 				props.BackendPort = to.Int32Ptr(port.NodePort)
@@ -2402,9 +2371,14 @@ func (az *Cloud) getExpectedLBRules(
 				Name:                              &lbRuleName,
 				LoadBalancingRulePropertiesFormat: props,
 			})
+
 		}
 	}
 
+	for _, probe := range uniqueProbes {
+		expectedProbes = append(expectedProbes, probe)
+	}
+
 	return expectedProbes, expectedRules, nil
 }
 
diff --git a/pkg/provider/azure_standard.go b/pkg/provider/azure_standard.go
index b515d7bb1..328758e63 100644
--- a/pkg/provider/azure_standard.go
+++ b/pkg/provider/azure_standard.go
@@ -56,6 +56,15 @@ var (
 	vmasIDRE           = regexp.MustCompile(`/subscriptions/(?:.*)/resourceGroups/(?:.*)/providers/Microsoft.Compute/availabilitySets/(.+)`)
 )
 
+// getStandardMachineID returns the full identifier of a virtual machine.
+func (az *Cloud) getStandardMachineID(subscriptionID, resourceGroup, machineName string) string {
+	return fmt.Sprintf(
+		consts.MachineIDTemplate,
+		subscriptionID,
+		strings.ToLower(resourceGroup),
+		machineName)
+}
+
 // returns the full identifier of an availabilitySet
 func (az *Cloud) getAvailabilitySetID(resourceGroup, availabilitySetName string) string {
 	return fmt.Sprintf(
diff --git a/pkg/provider/azure_vmss.go b/pkg/provider/azure_vmss.go
index 3bff4627c..6c8668cb1 100644
--- a/pkg/provider/azure_vmss.go
+++ b/pkg/provider/azure_vmss.go
@@ -17,6 +17,7 @@ limitations under the License.
 package provider
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"regexp"
@@ -98,7 +99,7 @@ type ScaleSet struct {
 }
 
 // newScaleSet creates a new ScaleSet.
-func newScaleSet(az *Cloud) (VMSet, error) {
+func newScaleSet(ctx context.Context, az *Cloud) (VMSet, error) {
 	if az.Config.VmssVirtualMachinesCacheTTLInSeconds == 0 {
 		az.Config.VmssVirtualMachinesCacheTTLInSeconds = consts.VMSSVirtualMachinesCacheTTLDefaultInSeconds
 	}
@@ -108,7 +109,7 @@ func newScaleSet(az *Cloud) (VMSet, error) {
 	if err != nil {
 		return nil, err
 	}
-	fs, err := newFlexScaleSet(az)
+	fs, err := newFlexScaleSet(ctx, az)
 	if err != nil {
 		return nil, err
 	}
@@ -127,7 +128,7 @@ func newScaleSet(az *Cloud) (VMSet, error) {
 		}
 	}
 
-	ss.vmssCache, err = ss.newVMSSCache()
+	ss.vmssCache, err = ss.newVMSSCache(ctx)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/provider/azure_vmss_cache.go b/pkg/provider/azure_vmss_cache.go
index 6d031be38..644a15718 100644
--- a/pkg/provider/azure_vmss_cache.go
+++ b/pkg/provider/azure_vmss_cache.go
@@ -64,7 +64,7 @@ const (
 	ManagedByUnknownVMSet VMManagementType = "ManagedByUnknownVMSet"
 )
 
-func (ss *ScaleSet) newVMSSCache() (*azcache.TimedCache, error) {
+func (ss *ScaleSet) newVMSSCache(ctx context.Context) (*azcache.TimedCache, error) {
 	getter := func(key string) (interface{}, error) {
 		localCache := &sync.Map{} // [vmssName]*vmssEntry
 
@@ -75,7 +75,7 @@ func (ss *ScaleSet) newVMSSCache() (*azcache.TimedCache, error) {
 
 		resourceGroupNotFound := false
 		for _, resourceGroup := range allResourceGroups.List() {
-			allScaleSets, rerr := ss.VirtualMachineScaleSetsClient.List(context.Background(), resourceGroup)
+			allScaleSets, rerr := ss.VirtualMachineScaleSetsClient.List(ctx, resourceGroup)
 			if rerr != nil {
 				if rerr.IsNotFound() {
 					klog.Warningf("Skip caching vmss for resource group %s due to error: %v", resourceGroup, rerr.Error())
diff --git a/pkg/provider/azure_vmssflex.go b/pkg/provider/azure_vmssflex.go
index 060532429..b2eaea870 100644
--- a/pkg/provider/azure_vmssflex.go
+++ b/pkg/provider/azure_vmssflex.go
@@ -17,6 +17,7 @@ limitations under the License.
 package provider
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"strconv"
@@ -56,7 +57,7 @@ type FlexScaleSet struct {
 	lockMap *lockMap
 }
 
-func newFlexScaleSet(az *Cloud) (VMSet, error) {
+func newFlexScaleSet(ctx context.Context, az *Cloud) (VMSet, error) {
 	fs := &FlexScaleSet{
 		Cloud:                    az,
 		vmssFlexVMNameToVmssID:   &sync.Map{},
@@ -65,11 +66,11 @@ func newFlexScaleSet(az *Cloud) (VMSet, error) {
 	}
 
 	var err error
-	fs.vmssFlexCache, err = fs.newVmssFlexCache()
+	fs.vmssFlexCache, err = fs.newVmssFlexCache(ctx)
 	if err != nil {
 		return nil, err
 	}
-	fs.vmssFlexVMCache, err = fs.newVmssFlexVMCache()
+	fs.vmssFlexVMCache, err = fs.newVmssFlexVMCache(ctx)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/provider/azure_vmssflex_cache.go b/pkg/provider/azure_vmssflex_cache.go
index 488b84b60..6b6a8d131 100644
--- a/pkg/provider/azure_vmssflex_cache.go
+++ b/pkg/provider/azure_vmssflex_cache.go
@@ -32,7 +32,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 )
 
-func (fs *FlexScaleSet) newVmssFlexCache() (*azcache.TimedCache, error) {
+func (fs *FlexScaleSet) newVmssFlexCache(ctx context.Context) (*azcache.TimedCache, error) {
 	getter := func(key string) (interface{}, error) {
 		localCache := &sync.Map{}
 
@@ -42,7 +42,7 @@ func (fs *FlexScaleSet) newVmssFlexCache() (*azcache.TimedCache, error) {
 		}
 
 		for _, resourceGroup := range allResourceGroups.List() {
-			allScaleSets, rerr := fs.VirtualMachineScaleSetsClient.List(context.Background(), resourceGroup)
+			allScaleSets, rerr := fs.VirtualMachineScaleSetsClient.List(ctx, resourceGroup)
 			if rerr != nil {
 				if rerr.IsNotFound() {
 					klog.Warningf("Skip caching vmss for resource group %s due to error: %v", resourceGroup, rerr.Error())
@@ -74,13 +74,10 @@ func (fs *FlexScaleSet) newVmssFlexCache() (*azcache.TimedCache, error) {
 	return azcache.NewTimedcache(time.Duration(fs.Config.VmssFlexCacheTTLInSeconds)*time.Second, getter)
 }
 
-func (fs *FlexScaleSet) newVmssFlexVMCache() (*azcache.TimedCache, error) {
+func (fs *FlexScaleSet) newVmssFlexVMCache(ctx context.Context) (*azcache.TimedCache, error) {
 	getter := func(key string) (interface{}, error) {
 		localCache := &sync.Map{}
 
-		ctx, cancel := getContextWithCancel()
-		defer cancel()
-
 		vms, rerr := fs.VirtualMachinesClient.ListVmssFlexVMsWithoutInstanceView(ctx, key)
 		if rerr != nil {
 			klog.Errorf("ListVmssFlexVMsWithoutInstanceView failed: %v", rerr)


Test patch:
diff --git a/.golangci-test.yml b/.golangci-test.yml
deleted file mode 100644
index 05efbaf64..000000000
--- a/.golangci-test.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-run:
-  deadline: 30m
-  concurrency: 2
-  go: '1.18'
-  allow-serial-runners: true
-skip-dirs:
-    - vendor
-linters:
-  disable-all: true
-  enable:
-    - gosec
-  # Run with --fast=false for more extensive checks
-  fast: false
-  govet:
-    # Report about shadowed variables.
-    # Default: false
-    check-shadowing: true
-issues:
-  exclude-rules:
-    - path: tests/e2e
-      linters:
-        - revive
-  #include:
-  #  - EXC0002 # include "missing comments" issues from golint
-  max-issues-per-linter: 0
-  max-same-issues: 0
diff --git a/pkg/consts/helpers_test.go b/pkg/consts/helpers_test.go
index c38f5074a..0763de2fd 100644
--- a/pkg/consts/helpers_test.go
+++ b/pkg/consts/helpers_test.go
@@ -376,39 +376,3 @@ func TestGetInt32HealthProbeConfigOfPortFromK8sSvcAnnotation(t *testing.T) {
 		})
 	}
 }
-
-func TestBuildAnnotationKeyForPort(t *testing.T) {
-	type args struct {
-		port int32
-		key  PortParams
-	}
-	tests := []struct {
-		name string
-		args args
-		want string
-	}{
-		{
-			name: "no lb rule",
-			args: args{
-				port: 80,
-				key:  PortAnnotationNoLBRule,
-			},
-			want: "service.beta.kubernetes.io/port_80_no_lb_rule",
-		},
-		{
-			name: "no lb rule",
-			args: args{
-				port: 80,
-				key:  PortAnnotationNoHealthProbeRule,
-			},
-			want: "service.beta.kubernetes.io/port_80_no_probe_rule",
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := BuildAnnotationKeyForPort(tt.args.port, tt.args.key); got != tt.want {
-				t.Errorf("BuildAnnotationKeyForPort() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
diff --git a/pkg/provider/azure_config_test.go b/pkg/provider/azure_config_test.go
index 3da00c653..49d6e4f44 100644
--- a/pkg/provider/azure_config_test.go
+++ b/pkg/provider/azure_config_test.go
@@ -283,7 +283,7 @@ func TestInitializeCloudFromSecret(t *testing.T) {
 			mockZoneClient.EXPECT().GetZones(gomock.Any(), gomock.Any()).Return(map[string][]string{"eastus": {"1", "2", "3"}}, nil).MaxTimes(1)
 			az.ZoneClient = mockZoneClient
 
-			err := az.InitializeCloudFromSecret()
+			err := az.InitializeCloudFromSecret(context.Background())
 			assert.Equal(t, test.expectErr, err != nil)
 		})
 	}
diff --git a/pkg/provider/azure_controller_common_test.go b/pkg/provider/azure_controller_common_test.go
index c5819913b..6ce2110c3 100644
--- a/pkg/provider/azure_controller_common_test.go
+++ b/pkg/provider/azure_controller_common_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package provider
 
 import (
+	"context"
 	"fmt"
 	"net/http"
 	"reflect"
@@ -246,7 +247,7 @@ func TestCommonAttachDiskWithVMSS(t *testing.T) {
 			} else {
 				testCloud.DisableAvailabilitySetNodes = true
 			}
-			ss, err := newScaleSet(testCloud)
+			ss, err := newScaleSet(context.Background(), testCloud)
 			assert.NoError(t, err)
 			testCloud.VMSet = ss
 		}
diff --git a/pkg/provider/azure_loadbalancer_test.go b/pkg/provider/azure_loadbalancer_test.go
index 924dddc31..b28fda12d 100644
--- a/pkg/provider/azure_loadbalancer_test.go
+++ b/pkg/provider/azure_loadbalancer_test.go
@@ -2486,61 +2486,21 @@ func TestReconcileLoadBalancerRule(t *testing.T) {
 			expectedProbes: getDefaultTestProbes("Tcp", ""),
 		},
 		{
-			desc: "getExpectedLBRules should support customize health probe port in multi-port service",
+			desc: "getExpectedLBRules should allow setting port specific health probe port",
 			service: getTestService("test1", v1.ProtocolTCP, map[string]string{
-				"service.beta.kubernetes.io/port_8000_health-probe_port": "port-tcp-80",
-			}, false, 80, 8000),
-			expectedRules: []network.LoadBalancingRule{
-				getTestRule(false, 80),
-				getTestRule(false, 8000),
-			},
-			expectedProbes: []network.Probe{
-				getTestProbe("Tcp", "/", to.Int32Ptr(5), to.Int32Ptr(80), to.Int32Ptr(10080), to.Int32Ptr(2)),
-				getTestProbe("Tcp", "/", to.Int32Ptr(5), to.Int32Ptr(8000), to.Int32Ptr(10080), to.Int32Ptr(2)),
-			},
-		},
-		{
-			desc: "getExpectedLBRules should support customize health probe port in multi-port service",
-			service: getTestService("test1", v1.ProtocolTCP, map[string]string{
-				"service.beta.kubernetes.io/port_8000_health-probe_port": "80",
-			}, false, 80, 8000),
-			expectedRules: []network.LoadBalancingRule{
-				getTestRule(false, 80),
-				getTestRule(false, 8000),
-			},
-			expectedProbes: []network.Probe{
-				getTestProbe("Tcp", "/", to.Int32Ptr(5), to.Int32Ptr(80), to.Int32Ptr(10080), to.Int32Ptr(2)),
-				getTestProbe("Tcp", "/", to.Int32Ptr(5), to.Int32Ptr(8000), to.Int32Ptr(10080), to.Int32Ptr(2)),
-			},
-		},
-		{
-			desc: "getExpectedLBRules should not generate probe rule when no health probe rule is specified.",
-			service: getTestService("test1", v1.ProtocolTCP, map[string]string{
-				"service.beta.kubernetes.io/port_8000_no_probe_rule": "true",
-			}, false, 80, 8000),
-			expectedRules: []network.LoadBalancingRule{
-				getTestRule(false, 80),
-				func() network.LoadBalancingRule {
-					rule := getTestRule(false, 8000)
-					rule.Probe = nil
-					return rule
-				}(),
-			},
-			expectedProbes: []network.Probe{
-				getTestProbe("Tcp", "/", to.Int32Ptr(5), to.Int32Ptr(80), to.Int32Ptr(10080), to.Int32Ptr(2)),
-			},
+				"service.beta.kubernetes.io/port_80_health-probe_protocol": "Http",
+				"service.beta.kubernetes.io/port_80_health-probe_port":     "15012",
+			}, false, 80),
+			expectedRules:  getDefaultTestRules(false),
+			expectedProbes: getTestProbes("Http", "/", to.Int32Ptr(5), to.Int32Ptr(80), to.Int32Ptr(15012), to.Int32Ptr(2)),
 		},
 		{
-			desc: "getExpectedLBRules should not generate lb rule and health probe rule when no lb rule is specified.",
+			desc: "getExpectedLBRules should not include duplicate probes when overrides would create them",
 			service: getTestService("test1", v1.ProtocolTCP, map[string]string{
-				"service.beta.kubernetes.io/port_8000_no_lb_rule": "true",
+				"service.beta.kubernetes.io/port_8000_health-probe_port": "10080",
 			}, false, 80, 8000),
-			expectedRules: []network.LoadBalancingRule{
-				getTestRule(false, 80),
-			},
-			expectedProbes: []network.Probe{
-				getTestProbe("Tcp", "/", to.Int32Ptr(5), to.Int32Ptr(80), to.Int32Ptr(10080), to.Int32Ptr(2)),
-			},
+			expectedRules:  []network.LoadBalancingRule{getTestRule(false, 80), getTestRule(false, 8000)},
+			expectedProbes: getTestProbes("Tcp", "/", to.Int32Ptr(5), to.Int32Ptr(8000), to.Int32Ptr(10080), to.Int32Ptr(2)),
 		},
 	}
 	rules := getDefaultTestRules(true)
@@ -5386,7 +5346,7 @@ func TestCleanOrphanedLoadBalancerLBInUseByVMSS(t *testing.T) {
 
 	t.Run("cleanOrphanedLoadBalancer should retry deleting lb when meeting LoadBalancerInUseByVirtualMachineScaleSet", func(t *testing.T) {
 		cloud := GetTestCloud(ctrl)
-		vmss, err := newScaleSet(cloud)
+		vmss, err := newScaleSet(context.Background(), cloud)
 		assert.NoError(t, err)
 		cloud.VMSet = vmss
 		cloud.LoadBalancerSku = consts.LoadBalancerSkuStandard
@@ -5411,7 +5371,7 @@ func TestCleanOrphanedLoadBalancerLBInUseByVMSS(t *testing.T) {
 
 	t.Run("cleanupOrphanedLoadBalancer should not call delete api if the lb does not exist", func(t *testing.T) {
 		cloud := GetTestCloud(ctrl)
-		vmss, err := newScaleSet(cloud)
+		vmss, err := newScaleSet(context.Background(), cloud)
 		assert.NoError(t, err)
 		cloud.VMSet = vmss
 		cloud.LoadBalancerSku = consts.LoadBalancerSkuStandard
diff --git a/pkg/provider/azure_test.go b/pkg/provider/azure_test.go
index a52f91ee6..443e6dca6 100644
--- a/pkg/provider/azure_test.go
+++ b/pkg/provider/azure_test.go
@@ -2335,7 +2335,7 @@ func getCloudFromConfig(t *testing.T, config string) *Cloud {
 	mockZoneClient := az.ZoneClient.(*mockzoneclient.MockInterface)
 	mockZoneClient.EXPECT().GetZones(gomock.Any(), gomock.Any()).Return(map[string][]string{"eastus": {"1", "2", "3"}}, nil)
 
-	err = az.InitializeCloudFromConfig(c, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), c, false, true)
 	assert.NoError(t, err)
 
 	return az
@@ -3607,14 +3607,14 @@ func TestInitializeCloudFromConfig(t *testing.T) {
 	mockZoneClient.EXPECT().GetZones(gomock.Any(), gomock.Any()).Return(map[string][]string{"eastus": {"1", "2", "3"}}, nil).AnyTimes()
 	az.ZoneClient = mockZoneClient
 
-	err := az.InitializeCloudFromConfig(nil, false, true)
+	err := az.InitializeCloudFromConfig(context.Background(), nil, false, true)
 	assert.Equal(t, fmt.Errorf("InitializeCloudFromConfig: cannot initialize from nil config"), err)
 
 	config := Config{
 		DisableAvailabilitySetNodes: true,
 		VMType:                      consts.VMTypeStandard,
 	}
-	err = az.InitializeCloudFromConfig(&config, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), &config, false, true)
 	expectedErr := fmt.Errorf("disableAvailabilitySetNodes true is only supported when vmType is 'vmss'")
 	assert.Equal(t, expectedErr, err)
 
@@ -3624,19 +3624,19 @@ func TestInitializeCloudFromConfig(t *testing.T) {
 		},
 		CloudConfigType: cloudConfigTypeFile,
 	}
-	err = az.InitializeCloudFromConfig(&config, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), &config, false, true)
 	expectedErr = fmt.Errorf("useInstanceMetadata must be enabled without Azure credentials")
 	assert.Equal(t, expectedErr, err)
 
 	config = Config{
 		LoadBalancerBackendPoolConfigurationType: "invalid",
 	}
-	err = az.InitializeCloudFromConfig(&config, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), &config, 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(&config, false, true)
+	err = az.InitializeCloudFromConfig(context.Background(), &config, false, true)
 	assert.NoError(t, err)
 	assert.Equal(t, az.Config.LoadBalancerBackendPoolConfigurationType, consts.LoadBalancerBackendPoolConfigurationTypeNodeIPConfiguration)
 }
diff --git a/pkg/provider/azure_vmss_cache_test.go b/pkg/provider/azure_vmss_cache_test.go
index 2404415b1..aa721c291 100644
--- a/pkg/provider/azure_vmss_cache_test.go
+++ b/pkg/provider/azure_vmss_cache_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package provider
 
 import (
+	"context"
 	"fmt"
 	"net/http"
 	"testing"
@@ -86,7 +87,7 @@ func TestVMSSVMCache(t *testing.T) {
 	vmList := []string{"vmssee6c2000000", "vmssee6c2000001", "vmssee6c2000002"}
 	c := GetTestCloud(ctrl)
 	c.DisableAvailabilitySetNodes = true
-	vmSet, err := newScaleSet(c)
+	vmSet, err := newScaleSet(context.Background(), c)
 	assert.NoError(t, err)
 	ss := vmSet.(*ScaleSet)
 
diff --git a/tests/e2e/network/service_annotations.go b/tests/e2e/network/service_annotations.go
index 138a277b5..b020b0be2 100644
--- a/tests/e2e/network/service_annotations.go
+++ b/tests/e2e/network/service_annotations.go
@@ -23,7 +23,6 @@ import (
 	"os"
 	"reflect"
 	"regexp"
-	"strconv"
 	"strings"
 	"time"
 
@@ -54,9 +53,8 @@ var (
 )
 
 const (
-	serverPort             = 80
-	alterNativeServicePort = 8080
-	testingPort            = 81
+	serverPort  = 80
+	testingPort = 81
 )
 
 var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnnotation), func() {
@@ -73,7 +71,10 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 	labels := map[string]string{
 		"app": serviceName,
 	}
-	var ports []v1.ServicePort
+	ports := []v1.ServicePort{{
+		Port:       serverPort,
+		TargetPort: intstr.FromInt(serverPort),
+	}}
 
 	BeforeEach(func() {
 		var err error
@@ -95,12 +96,6 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 		utils.Logf("Waiting for backend pods to be ready")
 		err = utils.WaitPodsToBeReady(cs, ns.Name)
 		Expect(err).NotTo(HaveOccurred())
-
-		ports = []v1.ServicePort{{
-			Name:       "http",
-			Port:       serverPort,
-			TargetPort: intstr.FromInt(serverPort),
-		}}
 	})
 
 	AfterEach(func() {
@@ -658,79 +653,16 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 		Expect(targetProbes[0].Protocol).To(Equal(network.ProbeProtocolHTTP))
 	})
 
-	It("should generate health probe configs in multi-port scenario", func() {
-		By("Creating a service with health probe annotations")
-		annotation := map[string]string{
-			consts.ServiceAnnotationLoadBalancerHealthProbeNumOfProbe:                                      "5",
-			consts.BuildHealthProbeAnnotationKeyForPort(serverPort, consts.HealthProbeParamsNumOfProbe):    "3",
-			consts.ServiceAnnotationLoadBalancerHealthProbeInterval:                                        "15",
-			consts.BuildHealthProbeAnnotationKeyForPort(serverPort, consts.HealthProbeParamsProbeInterval): "10",
-			consts.BuildHealthProbeAnnotationKeyForPort(serverPort, consts.HealthProbeParamsPort):          strconv.Itoa(alterNativeServicePort),
-			consts.ServiceAnnotationLoadBalancerHealthProbeProtocol:                                        "Http",
-			consts.ServiceAnnotationLoadBalancerHealthProbeRequestPath:                                     "/",
-			consts.BuildAnnotationKeyForPort(alterNativeServicePort, consts.PortAnnotationNoLBRule):        "true",
-		}
-		ports = append(ports, v1.ServicePort{
-			Name:       "port2",
-			Port:       alterNativeServicePort,
-			TargetPort: intstr.FromInt(serverPort),
-		})
-
-		// create service with given annotation and wait it to expose
-		publicIP := createAndExposeDefaultServiceWithAnnotation(cs, serviceName, ns.Name, labels, annotation, ports)
-		defer func() {
-			By("Cleaning up service")
-			err := utils.DeleteService(cs, ns.Name, serviceName)
-			Expect(err).NotTo(HaveOccurred())
-		}()
-		pipFrontendConfigID := getPIPFrontendConfigurationID(tc, publicIP, tc.GetResourceGroup(), "")
-		pipFrontendConfigIDSplit := strings.Split(pipFrontendConfigID, "/")
-		Expect(len(pipFrontendConfigIDSplit)).NotTo(Equal(0))
-
-		var lb *network.LoadBalancer
-		var targetProbes []*network.Probe
-		//wait for backend update
-		err := wait.PollImmediate(5*time.Second, 60*time.Second, func() (bool, error) {
-			lb = getAzureLoadBalancerFromPIP(tc, publicIP, tc.GetResourceGroup(), "")
-			targetProbes = []*network.Probe{}
-			for i := range *lb.LoadBalancerPropertiesFormat.Probes {
-				probe := (*lb.LoadBalancerPropertiesFormat.Probes)[i]
-				utils.Logf("One probe of LB is %q", *probe.Name)
-				targetProbes = append(targetProbes, &probe)
-			}
-			return len(targetProbes) == 1, nil
-		})
-		Expect(err).NotTo(HaveOccurred())
-
-		By("Validating health probe configs")
-		var numberOfProbes *int32
-		var intervalInSeconds *int32
-		for _, probe := range targetProbes {
-			if probe.NumberOfProbes != nil {
-				numberOfProbes = probe.NumberOfProbes
-			}
-			if probe.IntervalInSeconds != nil {
-				intervalInSeconds = probe.IntervalInSeconds
-			}
-		}
-		utils.Logf("Validating health probe config numberOfProbes")
-		Expect(*numberOfProbes).To(Equal(int32(3)))
-		utils.Logf("Validating health probe config intervalInSeconds")
-		Expect(*intervalInSeconds).To(Equal(int32(10)))
-		utils.Logf("Validating health probe config protocol")
-		Expect((len(targetProbes))).To(Equal(1))
-		Expect(targetProbes[0].Protocol).To(Equal(network.ProbeProtocolHTTP))
-	})
-
 	// Check if the following annotations are correctly set with Service LB IP
 	// service.beta.kubernetes.io/azure-load-balancer-ipv4 or service.beta.kubernetes.io/azure-load-balancer-ipv6
 	It("should support service annotation 'service.beta.kubernetes.io/azure-load-balancer-ip'", func() {
 		pipName := fmt.Sprintf("%s-public-IP%s", basename, string(uuid.NewUUID())[0:4])
 		By(fmt.Sprintf("Creating a public IP %q", pipName))
 		var pip network.PublicIPAddress
-		// TODO: dual-stack support
 		if tc.IPFamily != utils.DualStack {
 			pip = defaultPublicIPAddress(pipName, tc.IPFamily == utils.IPv6)
+		} else {
+			// TODO: dual-stack support
 		}
 		rg := tc.GetResourceGroup()
 		pip, err := utils.WaitCreatePIP(tc, pipName, rg, pip)
@@ -744,11 +676,12 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 		utils.Logf("Created pip with address %s", pipAddr)
 
 		annotation := map[string]string{}
-		// TODO: dual-stack support
 		if tc.IPFamily == utils.IPv4 {
 			annotation[consts.ServiceAnnotationLoadBalancerIPDualStack[false]] = pipAddr
 		} else if tc.IPFamily == utils.IPv6 {
 			annotation[consts.ServiceAnnotationLoadBalancerIPDualStack[true]] = pipAddr
+		} else {
+			// TODO: dual-stack support
 		}
 
 		By("Creating a Service")