Repository: kubernetes-sigs/cloud-provider-azure
Pull request #4289 (2023-07-14 05:29:19)

fix: fix bugs regarding multiple slbs
<!--  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 bug

#### What this PR does / why we need it:

1. `getServiceLoadBalancer` should return the existing lb object instead of creating a new one when a service is being moved from another lb to this one.
2. `existingLBs` should be updated when the lb is updated to prevent potential etag mismatches in `EnsureHostsInPool`.
3. Should skip non-existent lb when arranging nodes.

#### 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 #
Related: [4013](https://github.com/kubernetes-sigs/cloud-provider-azure/issues/4013)


#### 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
fix: update the lb list after changing lb to prevent etag mismatches
fix: return the existing lb  it if the lb exists without creating a new lb when the service was moved to the lb
fix: should skip non-existent lb when arranging nodes
```

#### 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

```


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

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/cloud-provider-azure/pull/4289#" title="Author self-approved">nilo19</a>*

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

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

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

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

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":[]} -->
k8s-ci-robot: @nilo19: 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 | 9ede84786a9019ea7f51cd5e26267389d9ad0236 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmssflex-capz/1679724741335715840) | 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=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
nilo19: /test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz
k8s-ci-robot: @nilo19: 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-vmss-multi-slb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz/1681492604107100160) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cloud-provider-azure&pr=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
nilo19: /test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz
k8s-ci-robot: @nilo19: 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-vmss-multi-slb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz/1681536648682147840) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cloud-provider-azure&pr=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
nilo19: /test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz
k8s-ci-robot: @nilo19: 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-vmss-multi-slb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz/1681562251531653120) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cloud-provider-azure&pr=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
nilo19: /retest
k8s-ci-robot: @nilo19: The following tests **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-vmss-multi-slb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz/1681562251531653120) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz`
pull-cloud-provider-azure-e2e-ccm-vmss-ip-lb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-ip-lb-capz/1681660690923786240) | false | `/test pull-cloud-provider-azure-e2e-ccm-vmss-ip-lb-capz`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cloud-provider-azure&pr=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
k8s-ci-robot: @nilo19: The following tests **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-vmss-ip-lb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-ip-lb-capz/1681660690923786240) | false | `/test pull-cloud-provider-azure-e2e-ccm-vmss-ip-lb-capz`
pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz/1681660073778089984) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cloud-provider-azure&pr=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
nilo19: /retest
k8s-ci-robot: @nilo19: 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-vmss-multi-slb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz/1681842102205419520) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cloud-provider-azure&pr=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
nilo19: /test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz
nilo19: /test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz
k8s-ci-robot: @nilo19: The following tests **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-vmss-multi-slb-capz | 0b26912fa3e1a588f85f3b4bb1b29952b45dd3b4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz/1681842102205419520) | true | `/test pull-cloud-provider-azure-e2e-ccm-vmss-multi-slb-capz`
pull-cloud-provider-azure-e2e-ccm-vmssflex-capz | 8283c190b4fea4e470bbbbecf18fad622a64a8f8 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cloud-provider-azure/4289/pull-cloud-provider-azure-e2e-ccm-vmssflex-capz/1681971384651091968) | 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=4289). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Anilo19). 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 -->
nilo19: /test pull-cloud-provider-azure-e2e-ccm-vmssflex-capz 

Patch:
diff --git a/go.mod b/go.mod
index 0a547c538..d26879c5f 100644
--- a/go.mod
+++ b/go.mod
@@ -23,16 +23,16 @@ require (
 	golang.org/x/sync v0.3.0
 	golang.org/x/sys v0.10.0
 	golang.org/x/text v0.11.0
-	k8s.io/api v0.27.4
-	k8s.io/apimachinery v0.27.4
-	k8s.io/apiserver v0.27.4
-	k8s.io/client-go v0.27.4
-	k8s.io/cloud-provider v0.27.4
-	k8s.io/component-base v0.27.4
-	k8s.io/component-helpers v0.27.4
-	k8s.io/controller-manager v0.27.4
+	k8s.io/api v0.27.3
+	k8s.io/apimachinery v0.27.3
+	k8s.io/apiserver v0.27.3
+	k8s.io/client-go v0.27.3
+	k8s.io/cloud-provider v0.27.3
+	k8s.io/component-base v0.27.3
+	k8s.io/component-helpers v0.27.3
+	k8s.io/controller-manager v0.27.3
 	k8s.io/klog/v2 v2.100.1
-	k8s.io/kubelet v0.27.4
+	k8s.io/kubelet v0.27.3
 	k8s.io/utils v0.0.0-20230209194617-a36077c30491
 	sigs.k8s.io/yaml v1.3.0
 )
@@ -129,7 +129,7 @@ require (
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/kms v0.27.4 // indirect
+	k8s.io/kms v0.27.3 // indirect
 	k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
 	sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
diff --git a/go.sum b/go.sum
index 5868383ca..0cd9b4fed 100644
--- a/go.sum
+++ b/go.sum
@@ -503,8 +503,8 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5
 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -954,31 +954,31 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.27.4 h1:0pCo/AN9hONazBKlNUdhQymmnfLRbSZjd5H5H3f0bSs=
-k8s.io/api v0.27.4/go.mod h1:O3smaaX15NfxjzILfiln1D8Z3+gEYpjEpiNA/1EVK1Y=
-k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
-k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
-k8s.io/apiserver v0.27.4 h1:ncZ0MBR9yQ/Gf34rtu1EK+HqT8In1YpfAUINu/Akvho=
-k8s.io/apiserver v0.27.4/go.mod h1:GDEFRfFZ4/l+pAvwYRnoSfz0K4j3TWiN4WsG2KnRteE=
-k8s.io/client-go v0.27.4 h1:vj2YTtSJ6J4KxaC88P4pMPEQECWMY8gqPqsTgUKzvjk=
-k8s.io/client-go v0.27.4/go.mod h1:ragcly7lUlN0SRPk5/ZkGnDjPknzb37TICq07WhI6Xc=
-k8s.io/cloud-provider v0.27.4 h1:FkZ1z40+YPm+nEqkojgPbjNQ3QLvU98gsFW3ZbZnrwo=
-k8s.io/cloud-provider v0.27.4/go.mod h1:LpqG1hrNPQQySPWrMrNNNGl79dK0fk/yTkYUlRMoaWU=
-k8s.io/component-base v0.27.4 h1:Wqc0jMKEDGjKXdae8hBXeskRP//vu1m6ypC+gwErj4c=
-k8s.io/component-base v0.27.4/go.mod h1:hoiEETnLc0ioLv6WPeDt8vD34DDeB35MfQnxCARq3kY=
-k8s.io/component-helpers v0.27.4 h1:l1hn/Zx9mWXflo5xz1mo5RRW2g8b6rptWCG7My6rYoE=
-k8s.io/component-helpers v0.27.4/go.mod h1:ayW5btpTdJkVv+CcxhzNRfWT+oPrV6T6qZ1Ay6NEJNI=
-k8s.io/controller-manager v0.27.4 h1:iisi3D1AKknVAGgU1dk/HG/UusmBqeS2fCFiRAS0DnE=
-k8s.io/controller-manager v0.27.4/go.mod h1:5+Fo0k+t3MDyuNLjmXzU/dJcD2c34ii8Wef+OmqhkVg=
+k8s.io/api v0.27.3 h1:yR6oQXXnUEBWEWcvPWS0jQL575KoAboQPfJAuKNrw5Y=
+k8s.io/api v0.27.3/go.mod h1:C4BNvZnQOF7JA/0Xed2S+aUyJSfTGkGFxLXz9MnpIpg=
+k8s.io/apimachinery v0.27.3 h1:Ubye8oBufD04l9QnNtW05idcOe9Z3GQN8+7PqmuVcUM=
+k8s.io/apimachinery v0.27.3/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
+k8s.io/apiserver v0.27.3 h1:AxLvq9JYtveYWK+D/Dz/uoPCfz8JC9asR5z7+I/bbQ4=
+k8s.io/apiserver v0.27.3/go.mod h1:Y61+EaBMVWUBJtxD5//cZ48cHZbQD+yIyV/4iEBhhNA=
+k8s.io/client-go v0.27.3 h1:7dnEGHZEJld3lYwxvLl7WoehK6lAq7GvgjxpA3nv1E8=
+k8s.io/client-go v0.27.3/go.mod h1:2MBEKuTo6V1lbKy3z1euEGnhPfGZLKTS9tiJ2xodM48=
+k8s.io/cloud-provider v0.27.3 h1:YylqJpKCB3O2MRnNXshxSVOQTOZE4I0G+cnyOfLwkGA=
+k8s.io/cloud-provider v0.27.3/go.mod h1:+C4rgsL3O0pxXdjoxRDOjCzNTj4C6jYUmK2OyogK1Jw=
+k8s.io/component-base v0.27.3 h1:g078YmdcdTfrCE4fFobt7qmVXwS8J/3cI1XxRi/2+6k=
+k8s.io/component-base v0.27.3/go.mod h1:JNiKYcGImpQ44iwSYs6dysxzR9SxIIgQalk4HaCNVUY=
+k8s.io/component-helpers v0.27.3 h1:oK7+AlwBKsSUIIRC5Vv8/4HEtmgzXNQD+zLbsOUwVso=
+k8s.io/component-helpers v0.27.3/go.mod h1:uxhXqoWHh4eBVcPj+LKWjtQq0V/vP5ihn4xmf5xNZso=
+k8s.io/controller-manager v0.27.3 h1:tw1zoCi8ylYXoyImThlPkmdo9wQDtyhAojrjWdfBv/E=
+k8s.io/controller-manager v0.27.3/go.mod h1:dH5WQMqZOTHZdY8sTQRv1RkZRibaaDx7sncvejUUICc=
 k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
 k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/kms v0.27.4 h1:FeT17HfqxZMP7dTq3Gpa9dG05iP3J3wgGtqGh1SUoN0=
-k8s.io/kms v0.27.4/go.mod h1:0BY6tkfa+zOP85u8yE7iNNf1Yx7rEZnRQSWLEbsSk+w=
+k8s.io/kms v0.27.3 h1:O6mZqi647ZLmxxkEv5Q9jMlmcXOh42CBD+A3MxI6zaQ=
+k8s.io/kms v0.27.3/go.mod h1:VDfnSIK0dk5J+jasbe+kKpb3CQVwlcDeBLyq59P2KyY=
 k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
 k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
-k8s.io/kubelet v0.27.4 h1:P8+MoRx4ikcAc5eEa3k2A6kd8AXtoDRaoC8KX2HFZe4=
-k8s.io/kubelet v0.27.4/go.mod h1:2y4peCA57vKEhBcDL6Q5EkPuGP7FFxj9U41NV9hk1ac=
+k8s.io/kubelet v0.27.3 h1:5WhTV1iiBu9q/rr+gvy65LQ+K/e7dmgcaYjys5ipLqY=
+k8s.io/kubelet v0.27.3/go.mod h1:Mz42qgZZgWgPmOJEYaR5evmh+EoSwFzEvPBozA2y9mg=
 k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY=
 k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/pkg/azclient/go.mod b/pkg/azclient/go.mod
index 9c6661a20..f317eacb9 100644
--- a/pkg/azclient/go.mod
+++ b/pkg/azclient/go.mod
@@ -14,7 +14,7 @@ require (
 	github.com/golang/mock v1.6.0
 	github.com/google/uuid v1.3.0
 	github.com/onsi/ginkgo/v2 v2.11.0
-	github.com/onsi/gomega v1.27.10
+	github.com/onsi/gomega v1.27.8
 	go.opentelemetry.io/otel v1.16.0
 	go.opentelemetry.io/otel/trace v1.16.0
 	golang.org/x/crypto v0.11.0
@@ -37,7 +37,7 @@ require (
 	github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
 	github.com/rogpeppe/go-internal v1.10.0 // indirect
 	go.opentelemetry.io/otel/metric v1.16.0 // indirect
-	golang.org/x/net v0.12.0 // indirect
+	golang.org/x/net v0.10.0 // indirect
 	golang.org/x/sys v0.10.0 // indirect
 	golang.org/x/text v0.11.0 // indirect
 	golang.org/x/tools v0.9.3 // indirect
diff --git a/pkg/azclient/go.sum b/pkg/azclient/go.sum
index b8420f2e1..c7d6dc62c 100644
--- a/pkg/azclient/go.sum
+++ b/pkg/azclient/go.sum
@@ -56,8 +56,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
 github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
 github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
-github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
+github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -85,8 +85,8 @@ golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
-golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go
index cbed3f4d0..0cbbbb819 100644
--- a/pkg/consts/consts.go
+++ b/pkg/consts/consts.go
@@ -427,9 +427,6 @@ const (
 const (
 	RouteNameFmt       = "%s____%s"
 	RouteNameSeparator = "____"
-
-	// routeUpdateInterval defines the route reconciling interval.
-	RouteUpdateInterval = 30 * time.Second
 )
 
 // cloud provider config secret
diff --git a/pkg/provider/azure.go b/pkg/provider/azure.go
index 1e4482fe0..e608da04d 100644
--- a/pkg/provider/azure.go
+++ b/pkg/provider/azure.go
@@ -710,7 +710,7 @@ func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *Config,
 	// updating routes and syncing zones only in CCM
 	if callFromCCM {
 		// start delayed route updater.
-		az.routeUpdater = newDelayedRouteUpdater(az, consts.RouteUpdateInterval)
+		az.routeUpdater = newDelayedRouteUpdater(az, routeUpdateInterval)
 		go az.routeUpdater.run()
 
 		// Azure Stack does not support zone at the moment
diff --git a/pkg/provider/azure_loadbalancer.go b/pkg/provider/azure_loadbalancer.go
index bca5c3d2e..542f9ff3e 100644
--- a/pkg/provider/azure_loadbalancer.go
+++ b/pkg/provider/azure_loadbalancer.go
@@ -585,6 +585,7 @@ func (az *Cloud) getServiceLoadBalancer(service *v1.Service, clusterName string,
 	}
 
 	// check if the service already has a load balancer
+	var shouldChangeLB bool
 	for i := range existingLBs {
 		existingLB := existingLBs[i]
 
@@ -610,6 +611,7 @@ func (az *Cloud) getServiceLoadBalancer(service *v1.Service, clusterName string,
 		// the current one if the change is needed
 		var err error
 		if wantLb && az.shouldChangeLoadBalancer(service, pointer.StringDeref(existingLB.Name, ""), clusterName, defaultLBName) {
+			shouldChangeLB = true
 			fipConfigNames := []string{}
 			for _, fipConfig := range fipConfigs {
 				fipConfigNames = append(fipConfigNames, pointer.StringDeref(fipConfig.Name, ""))
@@ -643,6 +645,16 @@ func (az *Cloud) getServiceLoadBalancer(service *v1.Service, clusterName string,
 		return selectedLB, status, lbIPsPrimaryPIPs, exists, "", err
 	}
 
+	// If the service moves to a different load balancer, return the one
+	// instead of creating a new load balancer if it exists.
+	if shouldChangeLB {
+		for _, existingLB := range existingLBs {
+			if strings.EqualFold(pointer.StringDeref(existingLB.Name, ""), defaultLBName) {
+				return &existingLB, status, lbIPsPrimaryPIPs, true, deletedLBName, nil
+			}
+		}
+	}
+
 	// create a default LB with meta data if not present
 	if defaultLB == nil {
 		defaultLB = &network.LoadBalancer{
@@ -1582,6 +1594,7 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
 			if err != nil {
 				return lb, fmt.Errorf("reconcileLoadBalancer for service (%s): failed to get load balancer %s: %w", serviceName, lbName, err)
 			}
+			addOrUpdateLBInList(&existingLBs, lb)
 		}
 	}
 
@@ -1702,17 +1715,7 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
 			}
 			lb = newLB
 
-			var found bool
-			for i, existingLB := range existingLBs {
-				if strings.EqualFold(pointer.StringDeref(existingLB.Name, ""), pointer.StringDeref(newLB.Name, "")) {
-					existingLBs[i] = *newLB
-					found = true
-					break
-				}
-			}
-			if !found {
-				existingLBs = append(existingLBs, *newLB)
-			}
+			addOrUpdateLBInList(&existingLBs, newLB)
 		}
 	}
 
@@ -1763,6 +1766,17 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
 	return lb, nil
 }
 
+// addOrUpdateLBInList adds or updates the given lb in the list
+func addOrUpdateLBInList(lbs *[]network.LoadBalancer, targetLB *network.LoadBalancer) {
+	for i, lb := range *lbs {
+		if strings.EqualFold(pointer.StringDeref(lb.Name, ""), pointer.StringDeref(targetLB.Name, "")) {
+			(*lbs)[i] = *targetLB
+			return
+		}
+	}
+	*lbs = append(*lbs, *targetLB)
+}
+
 // removeLBFromList removes the given lb from the list
 func removeLBFromList(lbs *[]network.LoadBalancer, lbName string) {
 	if lbs != nil {
@@ -1836,15 +1850,7 @@ func (az *Cloud) accommodateNodesByPrimaryVMSet(
 		for i := range az.MultipleStandardLoadBalancerConfigurations {
 			multiSLBConfig := az.MultipleStandardLoadBalancerConfigurations[i]
 			if strings.EqualFold(multiSLBConfig.PrimaryVMSet, vmSetName) {
-				var foundPrimaryLB bool
-				if lbs != nil {
-					for _, lb := range *lbs {
-						if strings.EqualFold(strings.TrimSuffix(pointer.StringDeref(lb.Name, ""), consts.InternalLoadBalancerNameSuffix), multiSLBConfig.Name) {
-							foundPrimaryLB = true
-							break
-						}
-					}
-				}
+				foundPrimaryLB := isLBInList(lbs, multiSLBConfig.Name)
 				if !foundPrimaryLB && !strings.EqualFold(strings.TrimSuffix(lbName, consts.InternalLoadBalancerNameSuffix), multiSLBConfig.Name) {
 					klog.V(4).Infof("accommodateNodesByPrimaryVMSet: node(%s) should be on lb(%s) because of primary vmSet (%s), but the lb is not found and will not be created this time, will ignore the primaryVMSet", node.Name, multiSLBConfig.Name, vmSetName)
 					continue
@@ -1895,17 +1901,9 @@ func (az *Cloud) accommodateNodesByNodeSelector(
 					return err
 				}
 				if nodeSelector.Matches(labels.Set(node.Labels)) {
-					var foundLB bool
-					if lbs != nil {
-						for _, lb := range *lbs {
-							if strings.EqualFold(strings.TrimSuffix(pointer.StringDeref(lb.Name, ""), consts.InternalLoadBalancerNameSuffix), multiSLBConfig.Name) {
-								foundLB = true
-								break
-							}
-						}
-					}
 					klog.V(4).Infof("accommodateNodesByNodeSelector: lb(%s) matches node(%s) labels", multiSLBConfig.Name, node.Name)
-					if !foundLB && !strings.EqualFold(strings.TrimSuffix(lbName, consts.InternalLoadBalancerNameSuffix), multiSLBConfig.Name) {
+					found := isLBInList(lbs, multiSLBConfig.Name)
+					if !found && !strings.EqualFold(strings.TrimSuffix(lbName, consts.InternalLoadBalancerNameSuffix), multiSLBConfig.Name) {
 						klog.V(4).Infof("accommodateNodesByNodeSelector: but the lb is not found and will not be created this time, will ignore this load balancer")
 						continue
 					}
@@ -1921,6 +1919,16 @@ func (az *Cloud) accommodateNodesByNodeSelector(
 				}
 			}
 		}
+		// Check if the valid load balancer exists or will exist
+		// after the reconciliation.
+		for i := len(eligibleLBsIDX) - 1; i >= 0; i-- {
+			multiSLBConfig := az.MultipleStandardLoadBalancerConfigurations[eligibleLBsIDX[i]]
+			found := isLBInList(lbs, multiSLBConfig.Name)
+			if !found && !strings.EqualFold(strings.TrimSuffix(lbName, consts.InternalLoadBalancerNameSuffix), multiSLBConfig.Name) {
+				klog.V(4).Infof("accommodateNodesByNodeSelector: the load balancer %s is a valid placement target for node %s, but the lb is not found and will not be created this time, ignore this load balancer", multiSLBConfig.Name, node.Name)
+				eligibleLBsIDX = append(eligibleLBsIDX[:i], eligibleLBsIDX[i+1:]...)
+			}
+		}
 		if idx, ok := nodeNameToLBConfigIDXMap[node.Name]; ok {
 			if IntInSlice(idx, eligibleLBsIDX) {
 				klog.V(4).Infof("accommodateNodesByNodeSelector: node(%s) is already on the eligible lb(%s)", node.Name, az.MultipleStandardLoadBalancerConfigurations[idx].Name)
@@ -1961,6 +1969,18 @@ func (az *Cloud) accommodateNodesByNodeSelector(
 	return nil
 }
 
+// isLBInList checks if the lb is in the list by multipleStandardLoadBalancerConfig name
+func isLBInList(lbs *[]network.LoadBalancer, lbConfigName string) bool {
+	if lbs != nil {
+		for _, lb := range *lbs {
+			if strings.EqualFold(strings.TrimSuffix(pointer.StringDeref(lb.Name, ""), consts.InternalLoadBalancerNameSuffix), lbConfigName) {
+				return true
+			}
+		}
+	}
+	return false
+}
+
 // reconcileMultipleStandardLoadBalancerBackendNodes makes sure the arrangement of nodes
 // across load balancer configurations is expected. This is used in two places:
 // 1. Every time the cloud provide restarts.
diff --git a/pkg/provider/azure_routes.go b/pkg/provider/azure_routes.go
index ecb6ca642..966bbceff 100644
--- a/pkg/provider/azure_routes.go
+++ b/pkg/provider/azure_routes.go
@@ -37,6 +37,11 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/metrics"
 )
 
+var (
+	// routeUpdateInterval defines the route reconciling interval.
+	routeUpdateInterval = 30 * time.Second
+)
+
 // routeOperation defines the allowed operations for route updating.
 type routeOperation string
 
diff --git a/pkg/provider/azure_standard.go b/pkg/provider/azure_standard.go
index 1040317be..2b4a7a362 100644
--- a/pkg/provider/azure_standard.go
+++ b/pkg/provider/azure_standard.go
@@ -1079,19 +1079,15 @@ func (as *availabilitySet) EnsureBackendPoolDeleted(service *v1.Service, backend
 			ipconfigPrefixToNicMap[ipConfigIDPrefix] = nic
 		}
 	}
-	v4Enabled, v6Enabled := getIPFamiliesEnabled(service)
-	isServiceIPv4 := v4Enabled && !v6Enabled
 	var nicUpdated atomic.Bool
 	for k := range ipconfigPrefixToNicMap {
 		nic := ipconfigPrefixToNicMap[k]
 		newIPConfigs := *nic.IPConfigurations
 		for j, ipConf := range newIPConfigs {
-			if isServiceIPv4 && !pointer.BoolDeref(ipConf.Primary, false) {
+			if !pointer.BoolDeref(ipConf.Primary, false) {
 				continue
 			}
-			// To support IPv6 only and dual-stack clusters, all IP configurations
-			// should be checked regardless of primary or not because IPv6 IP configurations
-			// are not marked as primary.
+			// found primary ip configuration
 			if ipConf.LoadBalancerBackendAddressPools != nil {
 				newLBAddressPools := *ipConf.LoadBalancerBackendAddressPools
 				for k := len(newLBAddressPools) - 1; k >= 0; k-- {
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/converter.go b/vendor/k8s.io/apimachinery/pkg/runtime/converter.go
index 62eb27afc..90bf487e3 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/converter.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/converter.go
@@ -231,7 +231,7 @@ func (c *fromUnstructuredContext) pushKey(key string) {
 
 }
 
-// FromUnstructuredWithValidation converts an object from map[string]interface{} representation into a concrete type.
+// FromUnstructuredWIthValidation converts an object from map[string]interface{} representation into a concrete type.
 // It uses encoding/json/Unmarshaler if object implements it or reflection if not.
 // It takes a validationDirective that indicates how to behave when it encounters unknown fields.
 func (c *unstructuredConverter) FromUnstructuredWithValidation(u map[string]interface{}, obj interface{}, returnUnknownFields bool) error {
@@ -465,7 +465,7 @@ func sliceFromUnstructured(sv, dv reflect.Value, ctx *fromUnstructuredContext) e
 			}
 			dv.SetBytes(data)
 		} else {
-			dv.Set(reflect.MakeSlice(dt, 0, 0))
+			dv.Set(reflect.Zero(dt))
 		}
 		return nil
 	}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/wait/loop.go b/vendor/k8s.io/apimachinery/pkg/util/wait/loop.go
index 0dd13c626..51864d70f 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/wait/loop.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/wait/loop.go
@@ -27,11 +27,9 @@ import (
 // the provided timer until the provided context is cancelled, the condition returns
 // true, or the condition returns an error. If sliding is true, the period is computed
 // after condition runs. If it is false then period includes the runtime for condition.
-// If immediate is false the first delay happens before any call to condition, if
-// immediate is true the condition will be invoked before waiting and guarantees that
-// the condition is invoked at least once, regardless of whether the context has been
-// cancelled. The returned error is the error returned by the last condition or the
-// context error if the context was terminated.
+// If immediate is false the first delay happens before any call to condition. The
+// returned error is the error returned by the last condition or the context error if
+// the context was terminated.
 //
 // This is the common loop construct for all polling in the wait package.
 func loopConditionUntilContext(ctx context.Context, t Timer, immediate, sliding bool, condition ConditionWithContextFunc) error {
@@ -40,17 +38,8 @@ func loopConditionUntilContext(ctx context.Context, t Timer, immediate, sliding
 	var timeCh <-chan time.Time
 	doneCh := ctx.Done()
 
-	// if immediate is true the condition is
-	// guaranteed to be executed at least once,
 	// if we haven't requested immediate execution, delay once
-	if immediate {
-		if ok, err := func() (bool, error) {
-			defer runtime.HandleCrash()
-			return condition(ctx)
-		}(); err != nil || ok {
-			return err
-		}
-	} else {
+	if !immediate {
 		timeCh = t.C()
 		select {
 		case <-doneCh:
diff --git a/vendor/k8s.io/apiserver/pkg/server/options/etcd.go b/vendor/k8s.io/apiserver/pkg/server/options/etcd.go
index a3b20a4a3..6aabbf255 100644
--- a/vendor/k8s.io/apiserver/pkg/server/options/etcd.go
+++ b/vendor/k8s.io/apiserver/pkg/server/options/etcd.go
@@ -444,10 +444,6 @@ func (s *SimpleStorageFactory) ResourcePrefix(resource schema.GroupResource) str
 	return resource.Group + "/" + resource.Resource
 }
 
-func (s *SimpleStorageFactory) Configs() []storagebackend.Config {
-	return serverstorage.Configs(s.StorageConfig)
-}
-
 func (s *SimpleStorageFactory) Backends() []serverstorage.Backend {
 	// nothing should ever call this method but we still provide a functional implementation
 	return serverstorage.Backends(s.StorageConfig)
@@ -478,10 +474,6 @@ func (t *transformerStorageFactory) ResourcePrefix(resource schema.GroupResource
 	return t.delegate.ResourcePrefix(resource)
 }
 
-func (t *transformerStorageFactory) Configs() []storagebackend.Config {
-	return t.delegate.Configs()
-}
-
 func (t *transformerStorageFactory) Backends() []serverstorage.Backend {
 	return t.delegate.Backends()
 }
diff --git a/vendor/k8s.io/apiserver/pkg/server/storage/storage_factory.go b/vendor/k8s.io/apiserver/pkg/server/storage/storage_factory.go
index 1c32b9772..5b1c24446 100644
--- a/vendor/k8s.io/apiserver/pkg/server/storage/storage_factory.go
+++ b/vendor/k8s.io/apiserver/pkg/server/storage/storage_factory.go
@@ -22,13 +22,14 @@ import (
 	"io/ioutil"
 	"strings"
 
+	"k8s.io/klog/v2"
+
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/util/sets"
 	"k8s.io/apiserver/pkg/features"
 	"k8s.io/apiserver/pkg/storage/storagebackend"
 	utilfeature "k8s.io/apiserver/pkg/util/feature"
-	"k8s.io/klog/v2"
 )
 
 // Backend describes the storage servers, the information here should be enough
@@ -51,12 +52,8 @@ type StorageFactory interface {
 	// centralized control over the shape of etcd directories
 	ResourcePrefix(groupResource schema.GroupResource) string
 
-	// Configs gets configurations for all of registered storage destinations.
-	Configs() []storagebackend.Config
-
 	// Backends gets all backends for all registered storage destinations.
 	// Used for getting all instances for health validations.
-	// Deprecated: Use Configs instead
 	Backends() []Backend
 }
 
@@ -279,52 +276,14 @@ func (s *DefaultStorageFactory) NewConfig(groupResource schema.GroupResource) (*
 	return storageConfig.ForResource(groupResource), nil
 }
 
-// Configs implements StorageFactory.
-func (s *DefaultStorageFactory) Configs() []storagebackend.Config {
-	return configs(s.StorageConfig, s.Overrides)
-}
-
-// Configs gets configurations for all of registered storage destinations.
-func Configs(storageConfig storagebackend.Config) []storagebackend.Config {
-	return configs(storageConfig, nil)
-}
-
-// Returns all storage configurations including those for group resource overrides
-func configs(storageConfig storagebackend.Config, grOverrides map[schema.GroupResource]groupResourceOverrides) []storagebackend.Config {
-	locations := sets.NewString()
-	configs := []storagebackend.Config{}
-	for _, loc := range storageConfig.Transport.ServerList {
-		// copy
-		newConfig := storageConfig
-		newConfig.Transport.ServerList = []string{loc}
-		configs = append(configs, newConfig)
-		locations.Insert(loc)
-	}
-
-	for _, override := range grOverrides {
-		for _, loc := range override.etcdLocation {
-			if locations.Has(loc) {
-				continue
-			}
-			// copy
-			newConfig := storageConfig
-			override.Apply(&newConfig, &StorageCodecConfig{})
-			newConfig.Transport.ServerList = []string{loc}
-			configs = append(configs, newConfig)
-			locations.Insert(loc)
-		}
-	}
-	return configs
-}
-
-// Backends implements StorageFactory.
+// Backends returns all backends for all registered storage destinations.
+// Used for getting all instances for health validations.
 func (s *DefaultStorageFactory) Backends() []Backend {
 	return backends(s.StorageConfig, s.Overrides)
 }
 
 // Backends returns all backends for all registered storage destinations.
 // Used for getting all instances for health validations.
-// Deprecated: Validate health by passing storagebackend.Config directly to storagefactory.CreateProber.
 func Backends(storageConfig storagebackend.Config) []Backend {
 	return backends(storageConfig, nil)
 }
diff --git a/vendor/k8s.io/apiserver/pkg/storage/etcd3/healthcheck.go b/vendor/k8s.io/apiserver/pkg/storage/etcd3/healthcheck.go
index 3d4898103..ad051d2d6 100644
--- a/vendor/k8s.io/apiserver/pkg/storage/etcd3/healthcheck.go
+++ b/vendor/k8s.io/apiserver/pkg/storage/etcd3/healthcheck.go
@@ -28,7 +28,6 @@ type etcdHealth struct {
 }
 
 // EtcdHealthCheck decodes data returned from etcd /healthz handler.
-// Deprecated: Validate health by passing storagebackend.Config directly to storagefactory.CreateProber.
 func EtcdHealthCheck(data []byte) error {
 	obj := etcdHealth{}
 	if err := json.Unmarshal(data, &obj); err != nil {
diff --git a/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go b/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go
index 64bcabadb..c17859649 100644
--- a/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go
+++ b/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go
@@ -153,18 +153,18 @@ func newETCD3Check(c storagebackend.Config, timeout time.Duration, stopCh <-chan
 	// retry in a loop in the background until we successfully create the client, storing the client or error encountered
 
 	lock := sync.RWMutex{}
-	var prober *etcd3Prober
+	var client *clientv3.Client
 	clientErr := fmt.Errorf("etcd client connection not yet established")
 
 	go wait.PollUntil(time.Second, func() (bool, error) {
-		newProber, err := newETCD3Prober(c)
+		newClient, err := newETCD3Client(c.Transport)
 		lock.Lock()
 		defer lock.Unlock()
 		// Ensure that server is already not shutting down.
 		select {
 		case <-stopCh:
 			if err == nil {
-				newProber.Close()
+				newClient.Close()
 			}
 			return true, nil
 		default:
@@ -173,7 +173,7 @@ func newETCD3Check(c storagebackend.Config, timeout time.Duration, stopCh <-chan
 			clientErr = err
 			return false, nil
 		}
-		prober = newProber
+		client = newClient
 		clientErr = nil
 		return true, nil
 	}, stopCh)
@@ -185,8 +185,8 @@ func newETCD3Check(c storagebackend.Config, timeout time.Duration, stopCh <-chan
 
 		lock.Lock()
 		defer lock.Unlock()
-		if prober != nil {
-			prober.Close()
+		if client != nil {
+			client.Close()
 			clientErr = fmt.Errorf("server is shutting down")
 		}
 	}()
@@ -214,56 +214,17 @@ func newETCD3Check(c storagebackend.Config, timeout time.Duration, stopCh <-chan
 		}
 		ctx, cancel := context.WithTimeout(context.Background(), timeout)
 		defer cancel()
+		// See https://github.com/etcd-io/etcd/blob/c57f8b3af865d1b531b979889c602ba14377420e/etcdctl/ctlv3/command/ep_command.go#L118
 		now := time.Now()
-		err := prober.Probe(ctx)
+		_, err := client.Get(ctx, path.Join("/", c.Prefix, "health"))
+		if err != nil {
+			err = fmt.Errorf("error getting data from etcd: %w", err)
+		}
 		lastError.Store(err, now)
 		return err
 	}, nil
 }
 
-func newETCD3Prober(c storagebackend.Config) (*etcd3Prober, error) {
-	client, err := newETCD3Client(c.Transport)
-	if err != nil {
-		return nil, err
-	}
-	return &etcd3Prober{
-		client: client,
-		prefix: c.Prefix,
-	}, nil
-}
-
-type etcd3Prober struct {
-	prefix string
-
-	mux    sync.RWMutex
-	client *clientv3.Client
-	closed bool
-}
-
-func (p *etcd3Prober) Close() error {
-	p.mux.Lock()
-	defer p.mux.Unlock()
-	if !p.closed {
-		p.closed = true
-		return p.client.Close()
-	}
-	return fmt.Errorf("prober was closed")
-}
-
-func (p *etcd3Prober) Probe(ctx context.Context) error {
-	p.mux.RLock()
-	defer p.mux.RUnlock()
-	if p.closed {
-		return fmt.Errorf("prober was closed")
-	}
-	// See https://github.com/etcd-io/etcd/blob/c57f8b3af865d1b531b979889c602ba14377420e/etcdctl/ctlv3/command/ep_command.go#L118
-	_, err := p.client.Get(ctx, path.Join("/", p.prefix, "health"))
-	if err != nil {
-		return fmt.Errorf("error getting data from etcd: %w", err)
-	}
-	return nil
-}
-
 var newETCD3Client = func(c storagebackend.TransportConfig) (*clientv3.Client, error) {
 	tlsInfo := transport.TLSInfo{
 		CertFile:      c.CertFile,
diff --git a/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/factory.go b/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/factory.go
index c8cdd19b9..4c8a409d6 100644
--- a/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/factory.go
+++ b/vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/factory.go
@@ -17,7 +17,6 @@ limitations under the License.
 package factory
 
 import (
-	"context"
 	"fmt"
 
 	"k8s.io/apimachinery/pkg/runtime"
@@ -62,20 +61,3 @@ func CreateReadyCheck(c storagebackend.Config, stopCh <-chan struct{}) (func() e
 		return nil, fmt.Errorf("unknown storage type: %s", c.Type)
 	}
 }
-
-func CreateProber(c storagebackend.Config) (Prober, error) {
-	switch c.Type {
-	case storagebackend.StorageTypeETCD2:
-		return nil, fmt.Errorf("%s is no longer a supported storage backend", c.Type)
-	case storagebackend.StorageTypeUnset, storagebackend.StorageTypeETCD3:
-		return newETCD3Prober(c)
-	default:
-		return nil, fmt.Errorf("unknown storage type: %s", c.Type)
-	}
-}
-
-// Prober is an interface that defines the Probe function for doing etcd readiness/liveness checks.
-type Prober interface {
-	Probe(ctx context.Context) error
-	Close() error
-}
diff --git a/vendor/k8s.io/client-go/util/cert/cert.go b/vendor/k8s.io/client-go/util/cert/cert.go
index 37b023ef2..4be1dfe49 100644
--- a/vendor/k8s.io/client-go/util/cert/cert.go
+++ b/vendor/k8s.io/client-go/util/cert/cert.go
@@ -25,7 +25,6 @@ import (
 	"crypto/x509/pkix"
 	"encoding/pem"
 	"fmt"
-	"math"
 	"math/big"
 	"net"
 	"os"
@@ -58,14 +57,8 @@ type AltNames struct {
 // NewSelfSignedCACert creates a CA certificate
 func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) {
 	now := time.Now()
-	// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
-	serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
-	if err != nil {
-		return nil, err
-	}
-	serial = new(big.Int).Add(serial, big.NewInt(1))
 	tmpl := x509.Certificate{
-		SerialNumber: serial,
+		SerialNumber: new(big.Int).SetInt64(0),
 		Subject: pkix.Name{
 			CommonName:   cfg.CommonName,
 			Organization: cfg.Organization,
@@ -123,14 +116,9 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
 	if err != nil {
 		return nil, nil, err
 	}
-	// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
-	serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
-	if err != nil {
-		return nil, nil, err
-	}
-	serial = new(big.Int).Add(serial, big.NewInt(1))
+
 	caTemplate := x509.Certificate{
-		SerialNumber: serial,
+		SerialNumber: big.NewInt(1),
 		Subject: pkix.Name{
 			CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()),
 		},
@@ -156,14 +144,9 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
 	if err != nil {
 		return nil, nil, err
 	}
-	// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
-	serial, err = cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
-	if err != nil {
-		return nil, nil, err
-	}
-	serial = new(big.Int).Add(serial, big.NewInt(1))
+
 	template := x509.Certificate{
-		SerialNumber: serial,
+		SerialNumber: big.NewInt(2),
 		Subject: pkix.Name{
 			CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
 		},
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 283c8a698..eedca48b9 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -687,7 +687,7 @@ gopkg.in/yaml.v2
 # gopkg.in/yaml.v3 v3.0.1
 ## explicit
 gopkg.in/yaml.v3
-# k8s.io/api v0.27.4
+# k8s.io/api v0.27.3
 ## explicit; go 1.20
 k8s.io/api/admission/v1
 k8s.io/api/admission/v1beta1
@@ -743,7 +743,7 @@ k8s.io/api/scheduling/v1beta1
 k8s.io/api/storage/v1
 k8s.io/api/storage/v1alpha1
 k8s.io/api/storage/v1beta1
-# k8s.io/apimachinery v0.27.4
+# k8s.io/apimachinery v0.27.3
 ## explicit; go 1.20
 k8s.io/apimachinery/pkg/api/equality
 k8s.io/apimachinery/pkg/api/errors
@@ -798,7 +798,7 @@ k8s.io/apimachinery/pkg/version
 k8s.io/apimachinery/pkg/watch
 k8s.io/apimachinery/third_party/forked/golang/json
 k8s.io/apimachinery/third_party/forked/golang/reflect
-# k8s.io/apiserver v0.27.4
+# k8s.io/apiserver v0.27.3
 ## explicit; go 1.20
 k8s.io/apiserver/pkg/admission
 k8s.io/apiserver/pkg/admission/cel
@@ -940,7 +940,7 @@ k8s.io/apiserver/plugin/pkg/audit/truncate
 k8s.io/apiserver/plugin/pkg/audit/webhook
 k8s.io/apiserver/plugin/pkg/authenticator/token/webhook
 k8s.io/apiserver/plugin/pkg/authorizer/webhook
-# k8s.io/client-go v0.27.4
+# k8s.io/client-go v0.27.3
 ## explicit; go 1.20
 k8s.io/client-go/applyconfigurations/admissionregistration/v1
 k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1
@@ -1254,7 +1254,7 @@ k8s.io/client-go/util/homedir
 k8s.io/client-go/util/keyutil
 k8s.io/client-go/util/retry
 k8s.io/client-go/util/workqueue
-# k8s.io/cloud-provider v0.27.4
+# k8s.io/cloud-provider v0.27.3
 ## explicit; go 1.20
 k8s.io/cloud-provider
 k8s.io/cloud-provider/api
@@ -1276,7 +1276,7 @@ k8s.io/cloud-provider/service/helpers
 k8s.io/cloud-provider/volume
 k8s.io/cloud-provider/volume/errors
 k8s.io/cloud-provider/volume/helpers
-# k8s.io/component-base v0.27.4
+# k8s.io/component-base v0.27.3
 ## explicit; go 1.20
 k8s.io/component-base/cli/flag
 k8s.io/component-base/cli/globalflag
@@ -1305,10 +1305,10 @@ k8s.io/component-base/term
 k8s.io/component-base/tracing
 k8s.io/component-base/tracing/api/v1
 k8s.io/component-base/version
-# k8s.io/component-helpers v0.27.4
+# k8s.io/component-helpers v0.27.3
 ## explicit; go 1.20
 k8s.io/component-helpers/node/util
-# k8s.io/controller-manager v0.27.4
+# k8s.io/controller-manager v0.27.3
 ## explicit; go 1.20
 k8s.io/controller-manager/app
 k8s.io/controller-manager/config
@@ -1332,7 +1332,7 @@ k8s.io/klog/v2/internal/clock
 k8s.io/klog/v2/internal/dbg
 k8s.io/klog/v2/internal/serialize
 k8s.io/klog/v2/internal/severity
-# k8s.io/kms v0.27.4
+# k8s.io/kms v0.27.3
 ## explicit; go 1.20
 k8s.io/kms/apis/v1beta1
 k8s.io/kms/apis/v2
@@ -1360,7 +1360,7 @@ k8s.io/kube-openapi/pkg/validation/errors
 k8s.io/kube-openapi/pkg/validation/spec
 k8s.io/kube-openapi/pkg/validation/strfmt
 k8s.io/kube-openapi/pkg/validation/strfmt/bson
-# k8s.io/kubelet v0.27.4
+# k8s.io/kubelet v0.27.3
 ## explicit; go 1.20
 k8s.io/kubelet/pkg/apis/credentialprovider
 k8s.io/kubelet/pkg/apis/credentialprovider/install


Test patch:
diff --git a/kubetest2-aks/go.mod b/kubetest2-aks/go.mod
index 00bc3a180..f75d4e2f8 100644
--- a/kubetest2-aks/go.mod
+++ b/kubetest2-aks/go.mod
@@ -7,10 +7,10 @@ require (
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v2 v2.4.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1
-	github.com/go-git/go-git/v5 v5.8.0
+	github.com/go-git/go-git/v5 v5.7.0
 	github.com/octago/sflags v0.2.0
 	github.com/spf13/pflag v1.0.5
-	k8s.io/apimachinery v0.27.4
+	k8s.io/apimachinery v0.27.3
 	k8s.io/klog v1.0.0
 	k8s.io/utils v0.0.0-20230209194617-a36077c30491
 	sigs.k8s.io/kubetest2 v0.0.0-20220728001911-c76fb417aa01
diff --git a/kubetest2-aks/go.sum b/kubetest2-aks/go.sum
index 06d17fe49..44b20f313 100644
--- a/kubetest2-aks/go.sum
+++ b/kubetest2-aks/go.sum
@@ -39,8 +39,8 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmS
 github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
 github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
-github.com/go-git/go-git/v5 v5.8.0 h1:Rc543s6Tyq+YcyPwZRvU4jzZGM8rB/wWu94TnTIYALQ=
-github.com/go-git/go-git/v5 v5.8.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8=
+github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE=
+github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8=
 github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
@@ -168,8 +168,8 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
-k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
+k8s.io/apimachinery v0.27.3 h1:Ubye8oBufD04l9QnNtW05idcOe9Z3GQN8+7PqmuVcUM=
+k8s.io/apimachinery v0.27.3/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
 k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
 k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
diff --git a/pkg/provider/azure_loadbalancer_test.go b/pkg/provider/azure_loadbalancer_test.go
index db6238f1c..3c0789a3e 100644
--- a/pkg/provider/azure_loadbalancer_test.go
+++ b/pkg/provider/azure_loadbalancer_test.go
@@ -1656,6 +1656,80 @@ func TestGetServiceTags(t *testing.T) {
 	}
 }
 
+func TestGetServiceLoadBalancerMultiSLB(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	for _, tc := range []struct {
+		description           string
+		existingLBs           []network.LoadBalancer
+		service               v1.Service
+		multiSLBConfigs       []MultipleStandardLoadBalancerConfiguration
+		expectedLB            *network.LoadBalancer
+		expectedDeletedLBName string
+		expectedError         error
+	}{
+		{
+			description: "should return the existing lb if the service is moved to the lb",
+			existingLBs: []network.LoadBalancer{
+				{
+					Name: pointer.String("lb1-internal"),
+					LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+						FrontendIPConfigurations: &[]network.FrontendIPConfiguration{
+							{
+								Name: pointer.String("atest1"),
+								ID:   pointer.String("atest1"),
+								FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{
+									PrivateIPAddress: pointer.String("1.2.3.4"),
+								},
+							},
+						},
+					},
+				},
+				{
+					Name: pointer.String("lb2-internal"),
+				},
+			},
+			service: getInternalTestService("test1"),
+			multiSLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+				{
+					Name: "lb1",
+				},
+				{
+					Name: "lb2",
+					MultipleStandardLoadBalancerConfigurationStatus: MultipleStandardLoadBalancerConfigurationStatus{
+						ActiveServices: sets.Set[string]{"default/test1": sets.Empty{}},
+					},
+				},
+			},
+			expectedDeletedLBName: "lb1-internal",
+			expectedLB: &network.LoadBalancer{
+				Name: pointer.String("lb2-internal"),
+			},
+		},
+	} {
+		t.Run(tc.description, func(t *testing.T) {
+			cloud := GetTestCloud(ctrl)
+			cloud.LoadBalancerSku = "Standard"
+			cloud.MultipleStandardLoadBalancerConfigurations = tc.multiSLBConfigs
+			cloud.plsCache, _ = cloud.newPLSCache()
+			lbClient := mockloadbalancerclient.NewMockInterface(ctrl)
+			lbClient.EXPECT().Delete(gomock.Any(), gomock.Any(), "lb1-internal")
+			cloud.LoadBalancerClient = lbClient
+
+			expectedPLS := make([]network.PrivateLinkService, 0)
+			mockPLSClient := cloud.PrivateLinkServiceClient.(*mockprivatelinkserviceclient.MockInterface)
+			mockPLSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return(expectedPLS, nil)
+
+			lb, _, _, _, deletedLBName, err := cloud.getServiceLoadBalancer(&tc.service, testClusterName,
+				[]*v1.Node{}, true, tc.existingLBs)
+			assert.Equal(t, tc.expectedError, err)
+			assert.Equal(t, tc.expectedLB, lb)
+			assert.Equal(t, tc.expectedDeletedLBName, deletedLBName)
+		})
+	}
+}
+
 func TestGetServiceLoadBalancerCommon(t *testing.T) {
 	testCases := []struct {
 		desc           string
@@ -7251,7 +7325,7 @@ func TestGetEligibleLoadBalancers(t *testing.T) {
 		{
 			description: "should respect label selector",
 			svc:         getTestService("test", v1.ProtocolTCP, nil, false),
-			labels:      map[string]string{"k2": "v2"},
+			labels:      map[string]string{"k2": "v2", "k3": "v3"},
 			lbConfigs: []MultipleStandardLoadBalancerConfiguration{
 				{
 					Name: "a",
@@ -8477,6 +8551,16 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 						},
 					},
 				},
+				{
+					Name: pointer.String("lb4"),
+					LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+						BackendAddressPools: &[]network.BackendAddressPool{
+							{
+								Name: pointer.String("kubernetes"),
+							},
+						},
+					},
+				},
 			},
 			expectedLBToNodesMap: map[string]sets.Set[string]{
 				"lb1": {"node1": sets.Empty{}},
@@ -8551,6 +8635,16 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 						},
 					},
 				},
+				{
+					Name: pointer.String("lb4"),
+					LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+						BackendAddressPools: &[]network.BackendAddressPool{
+							{
+								Name: pointer.String("kubernetes"),
+							},
+						},
+					},
+				},
 			},
 			existingNodes: []*v1.Node{
 				getTestNodeWithMetadata("node1", "vmss-1", map[string]string{"k1": "v1"}, "10.1.0.1"),
@@ -8566,6 +8660,64 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 				"lb4": {"node1": sets.Empty{}, "node2": sets.Empty{}, "node6": sets.Empty{}},
 			},
 		},
+		{
+			description: "should skip lbs that do not exist or will not be created when no lb is selected by node selector",
+			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
+				{
+					Name: "lb1",
+					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+						PrimaryVMSet: "vmss-1",
+						NodeSelector: &metav1.LabelSelector{
+							MatchLabels: map[string]string{"k1": "v1"},
+						},
+					},
+				},
+				{
+					Name: "lb2",
+					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+						PrimaryVMSet: "vmss-2",
+						NodeSelector: &metav1.LabelSelector{
+							MatchLabels: map[string]string{"k2": "v2"},
+						},
+					},
+				},
+				{
+					Name: "lb3",
+					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
+						PrimaryVMSet: "vmss-2",
+						NodeSelector: &metav1.LabelSelector{
+							MatchLabels: map[string]string{"k3": "v3"},
+						},
+					},
+				},
+				{
+					Name: "lb4",
+				},
+			},
+			existingLBs: []network.LoadBalancer{
+				{
+					Name: pointer.String("lb2-internal"),
+					LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+						BackendAddressPools: &[]network.BackendAddressPool{
+							{Name: pointer.String("kubernetes")},
+						},
+					},
+				},
+			},
+			existingNodes: []*v1.Node{
+				getTestNodeWithMetadata("node1", "vmss-1", map[string]string{"k1": "v1"}, "10.1.0.1"),
+				getTestNodeWithMetadata("node2", "vmss-3", map[string]string{"k3": "v3"}, "10.1.0.2"),
+				getTestNodeWithMetadata("node3", "vmss-3", map[string]string{"k2": "v2"}, "10.1.0.3"),
+				getTestNodeWithMetadata("node5", "vmss-3", map[string]string{"k2": "v2"}, "10.1.0.5"),
+				getTestNodeWithMetadata("node6", "vmss-3", map[string]string{"k3": "v3"}, "10.1.0.6"),
+			},
+			expectedLBToNodesMap: map[string]sets.Set[string]{
+				"lb1": nil,
+				"lb2": {"node3": sets.Empty{}, "node5": sets.Empty{}},
+				"lb3": nil,
+				"lb4": nil,
+			},
+		},
 	} {
 		t.Run(tc.description, func(t *testing.T) {
 			az := GetTestCloud(ctrl)
@@ -8604,3 +8756,79 @@ func getTestNodeWithMetadata(nodeName, vmssName string, labels map[string]string
 		},
 	}
 }
+
+func TestAddOrUpdateLBInList(t *testing.T) {
+	existingLBs := []network.LoadBalancer{
+		{
+			Name: pointer.String("lb1"),
+			LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+				BackendAddressPools: &[]network.BackendAddressPool{
+					{Name: pointer.String("kubernetes")},
+				},
+			},
+		},
+		{
+			Name: pointer.String("lb2"),
+			LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+				BackendAddressPools: &[]network.BackendAddressPool{
+					{Name: pointer.String("kubernetes")},
+				},
+			},
+		},
+	}
+	targetLB := network.LoadBalancer{
+		Name: pointer.String("lb1"),
+		LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+			BackendAddressPools: &[]network.BackendAddressPool{
+				{Name: pointer.String("lb1")},
+			},
+		},
+	}
+	expectedLBs := []network.LoadBalancer{
+		{
+			Name: pointer.String("lb1"),
+			LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+				BackendAddressPools: &[]network.BackendAddressPool{
+					{Name: pointer.String("lb1")},
+				},
+			},
+		},
+		{
+			Name: pointer.String("lb2"),
+			LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+				BackendAddressPools: &[]network.BackendAddressPool{
+					{Name: pointer.String("kubernetes")},
+				},
+			},
+		},
+	}
+
+	addOrUpdateLBInList(&existingLBs, &targetLB)
+	assert.Equal(t, expectedLBs, existingLBs)
+
+	targetLB = network.LoadBalancer{
+		Name: pointer.String("lb3"),
+	}
+	expectedLBs = []network.LoadBalancer{
+		{
+			Name: pointer.String("lb1"),
+			LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+				BackendAddressPools: &[]network.BackendAddressPool{
+					{Name: pointer.String("lb1")},
+				},
+			},
+		},
+		{
+			Name: pointer.String("lb2"),
+			LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
+				BackendAddressPools: &[]network.BackendAddressPool{
+					{Name: pointer.String("kubernetes")},
+				},
+			},
+		},
+		{Name: pointer.String("lb3")},
+	}
+
+	addOrUpdateLBInList(&existingLBs, &targetLB)
+	assert.Equal(t, expectedLBs, existingLBs)
+}
diff --git a/tests/e2e/network/ensureloadbalancer.go b/tests/e2e/network/ensureloadbalancer.go
index 16b95f586..48345c83f 100644
--- a/tests/e2e/network/ensureloadbalancer.go
+++ b/tests/e2e/network/ensureloadbalancer.go
@@ -18,7 +18,6 @@ package network
 
 import (
 	"context"
-	"errors"
 	"fmt"
 	"net"
 	"os"
@@ -673,7 +672,7 @@ var _ = Describe("Ensure LoadBalancer", Label(utils.TestSuiteLabelLB), func() {
 		}
 	})
 
-	It("should support node label `node.kubernetes.io/exclude-from-external-load-balancers`", func() {
+	It("should support node label `node.kubernetes.io/exclude-from-external-load-balancers`", Label(utils.TestSuiteLabelNonMultiSLB), func() {
 		label := "node.kubernetes.io/exclude-from-external-load-balancers"
 		By("Checking the number of the node pools")
 		nodes, err := utils.GetAgentNodes(cs)
@@ -703,9 +702,7 @@ var _ = Describe("Ensure LoadBalancer", Label(utils.TestSuiteLabelLB), func() {
 		lb := getAzureLoadBalancerFromPIP(tc, publicIP, tc.GetResourceGroup(), "")
 		if lb.Sku != nil && lb.Sku.Name == aznetwork.LoadBalancerSkuNameBasic {
 			// For a basic lb, not autoscaling pipeline
-			idxes := getLBBackendPoolIndex(lb)
-			Expect(idxes).NotTo(BeZero())
-			ipConfigs := (*lb.BackendAddressPools)[idxes[0]].BackendIPConfigurations
+			ipConfigs := (*lb.BackendAddressPools)[getLBBackendPoolIndex(lb)].BackendIPConfigurations
 			Expect(ipConfigs).NotTo(BeNil())
 			lbBackendPoolIPConfigCount := len(*ipConfigs)
 			Expect(lbBackendPoolIPConfigCount).To(Equal(len(nodes)))
@@ -713,9 +710,7 @@ var _ = Describe("Ensure LoadBalancer", Label(utils.TestSuiteLabelLB), func() {
 		} else {
 			// SLB: Here we use BackendPool IP instead of IP config because this works for both NIC based LB and IP based LB.
 			lbBackendPoolIPCount := 0
-			idxes := getLBBackendPoolIndex(lb)
-			Expect(idxes).NotTo(BeZero())
-			lbBackendPoolIPs := (*lb.BackendAddressPools)[idxes[0]].LoadBalancerBackendAddresses
+			lbBackendPoolIPs := (*lb.BackendAddressPools)[getLBBackendPoolIndex(lb)].LoadBalancerBackendAddresses
 			Expect(lbBackendPoolIPs).NotTo(BeNil())
 			if utils.IsAutoscalingAKSCluster() {
 				for _, ip := range *lbBackendPoolIPs {
@@ -817,7 +812,7 @@ var _ = Describe("Ensure LoadBalancer", Label(utils.TestSuiteLabelLB), func() {
 			utils.Logf("Checking LB rule %q", *lbRule.Name)
 			lbRuleSplit := strings.Split(*lbRule.Name, "-")
 			Expect(len(lbRuleSplit)).NotTo(Equal(0))
-			// id is like xxx or xxx-IPv6 and lbRuleSplit[0] is like xxx.
+			// id is like xxx-IPv4 or xxx-IPv6 and lbRuleSplit[0] is like xxx.
 			if !strings.Contains(configID, lbRuleSplit[0]) {
 				continue
 			}
@@ -1210,62 +1205,44 @@ func waitForNodesInLBBackendPool(tc *utils.AzureTestClient, ip string, expectedN
 		lb := getAzureLoadBalancerFromPIP(tc, ip, tc.GetResourceGroup(), "")
 		if lb.Sku != nil && lb.Sku.Name == aznetwork.LoadBalancerSkuNameBasic {
 			// basic lb
-			idxes := getLBBackendPoolIndex(lb)
-			if len(idxes) == 0 {
-				return false, errors.New("no backend pool found")
+			lbBackendPoolIPConfigs := (*lb.BackendAddressPools)[getLBBackendPoolIndex(lb)].BackendIPConfigurations
+			ipConfigNum := 0
+			if lbBackendPoolIPConfigs != nil {
+				ipConfigNum = len(*lbBackendPoolIPConfigs)
 			}
-			failed := false
-			for _, idx := range idxes {
-				bp := (*lb.BackendAddressPools)[idx]
-				lbBackendPoolIPConfigs := bp.BackendIPConfigurations
-				ipConfigNum := 0
-				if lbBackendPoolIPConfigs != nil {
-					ipConfigNum = len(*lbBackendPoolIPConfigs)
-				}
-				if expectedNum == ipConfigNum {
-					utils.Logf("Number of IP configs in the LB backend pool %q matches expected number %d. Success", *bp.Name, expectedNum)
-				} else {
-					utils.Logf("Number of IP configs: %d in the LB backend pool %q, expected %d, will retry soon", ipConfigNum, *bp.Name, expectedNum)
-					failed = true
-				}
+			if expectedNum == ipConfigNum {
+				utils.Logf("Number of IP configs matches expected number %d. Success", expectedNum)
+				return true, nil
 			}
-			return !failed, nil
+			utils.Logf("Number of IP configs: %d in the LB backend pool, expected %d, will retry soon", ipConfigNum, expectedNum)
+			return false, nil
 		}
 		// SLB
-		idxes := getLBBackendPoolIndex(lb)
-		if len(idxes) == 0 {
-			return false, errors.New("no backend pool found")
-		}
-		failed := false
-		for _, idx := range idxes {
-			bp := (*lb.BackendAddressPools)[idx]
-			lbBackendPoolIPs := bp.LoadBalancerBackendAddresses
-			ipNum := 0
-			if lbBackendPoolIPs != nil {
-				if utils.IsAutoscalingAKSCluster() {
-					// Autoscaling tests don't include IP based LB.
-					for _, ip := range *lbBackendPoolIPs {
-						if ip.LoadBalancerBackendAddressPropertiesFormat == nil ||
-							ip.LoadBalancerBackendAddressPropertiesFormat.NetworkInterfaceIPConfiguration == nil {
-							return false, fmt.Errorf("LB backendPool address's NIC IP config ID is nil")
-						}
-						ipConfigID := pointer.StringDeref(ip.LoadBalancerBackendAddressPropertiesFormat.NetworkInterfaceIPConfiguration.ID, "")
-						if !strings.Contains(ipConfigID, utils.SystemPool) {
-							ipNum++
-						}
+		lbBackendPoolIPs := (*lb.BackendAddressPools)[getLBBackendPoolIndex(lb)].LoadBalancerBackendAddresses
+		ipNum := 0
+		if lbBackendPoolIPs != nil {
+			if utils.IsAutoscalingAKSCluster() {
+				// Autoscaling tests don't include IP based LB.
+				for _, ip := range *lbBackendPoolIPs {
+					if ip.LoadBalancerBackendAddressPropertiesFormat == nil ||
+						ip.LoadBalancerBackendAddressPropertiesFormat.NetworkInterfaceIPConfiguration == nil {
+						return false, fmt.Errorf("LB backendPool address's NIC IP config ID is nil")
+					}
+					ipConfigID := pointer.StringDeref(ip.LoadBalancerBackendAddressPropertiesFormat.NetworkInterfaceIPConfiguration.ID, "")
+					if !strings.Contains(ipConfigID, utils.SystemPool) {
+						ipNum++
 					}
-				} else {
-					ipNum = len(*lbBackendPoolIPs)
 				}
-			}
-			if ipNum == expectedNum {
-				utils.Logf("Number of IPs in the LB backend pool %q matches expected number %d. Success", *bp.Name, expectedNum)
 			} else {
-				utils.Logf("Number of IPs: %d in the LB backend pool %q, expected %d, will retry soon", ipNum, *bp.Name, expectedNum)
-				failed = true
+				ipNum = len(*lbBackendPoolIPs)
 			}
 		}
-		return !failed, nil
+		if ipNum == expectedNum {
+			utils.Logf("Number of IPs matches expected number %d. Success", expectedNum)
+			return true, nil
+		}
+		utils.Logf("Number of IPs: %d in the LB backend pool, expected %d, will retry soon", ipNum, expectedNum)
+		return false, nil
 	})
 }
 
@@ -1273,14 +1250,15 @@ func judgeInternal(service v1.Service) bool {
 	return service.Annotations[consts.ServiceAnnotationLoadBalancerInternal] == utils.TrueValue
 }
 
-func getLBBackendPoolIndex(lb *aznetwork.LoadBalancer) []int {
-	idxes := []int{}
-	for index, backendPool := range *lb.BackendAddressPools {
-		if !strings.Contains(strings.ToLower(*backendPool.Name), "outboundbackendpool") {
-			idxes = append(idxes, index)
+func getLBBackendPoolIndex(lb *aznetwork.LoadBalancer) int {
+	if os.Getenv(utils.AKSTestCCM) != "" {
+		for index, backendPool := range *lb.BackendAddressPools {
+			if *backendPool.Name != "aksOutboundBackendPool" {
+				return index
+			}
 		}
 	}
-	return idxes
+	return 0
 }
 
 func updateServiceLBIPs(service *v1.Service, isInternal bool, ips []string) (result *v1.Service) {
diff --git a/tests/e2e/network/multiple_standard_lb.go b/tests/e2e/network/multiple_standard_lb.go
index 89f2a4218..37047a3a0 100644
--- a/tests/e2e/network/multiple_standard_lb.go
+++ b/tests/e2e/network/multiple_standard_lb.go
@@ -105,9 +105,9 @@ var _ = Describe("Ensure LoadBalancer", Label(utils.TestSuiteLabelMultiSLB), fun
 
 		clusterName := os.Getenv("CLUSTER_NAME")
 		lbNameToExpectedVMSetNameMap := map[string]string{
-			clusterName: fmt.Sprintf("%s-vmss-0", clusterName),
-			"lb1":       fmt.Sprintf("%s-vmss-1", clusterName),
-			"lb2":       fmt.Sprintf("%s-vmss-2", clusterName),
+			clusterName: fmt.Sprintf("%s-mp-0", clusterName),
+			"lb1":       fmt.Sprintf("%s-mp-1", clusterName),
+			"lb2":       fmt.Sprintf("%s-mp-2", clusterName),
 		}
 
 		for _, svcIP := range svcIPs {
@@ -166,16 +166,17 @@ var _ = Describe("Ensure LoadBalancer", Label(utils.TestSuiteLabelMultiSLB), fun
 		_, err = waitLBCountEqualTo(tc, interval, timeout, 3, svcIPs)
 		Expect(err).NotTo(HaveOccurred())
 
-		By(fmt.Sprintf("Updating service %s to move to another load balancer", svc.Name))
-		updateServiceAnnotation(svc, map[string]string{"service.beta.kubernetes.io/azure-load-balancer-configurations": "lb-2"})
+		clusterName := os.Getenv("CLUSTER_NAME")
+		By(fmt.Sprintf("Updating service %s to move to another load balancer %s", svc.Name, clusterName))
+		updateServiceAnnotation(svc, map[string]string{"service.beta.kubernetes.io/azure-load-balancer-configurations": clusterName})
 		_, err = cs.CoreV1().Services(ns.Name).Update(context.TODO(), svc, metav1.UpdateOptions{})
 		Expect(err).NotTo(HaveOccurred())
 
 		By("Checking the load balancer count to equal 2")
 		lbNames, err = waitLBCountEqualTo(tc, interval, timeout, 2, svcIPs)
 		Expect(err).NotTo(HaveOccurred())
-		Expect(lbNames.Has("lb-2")).To(BeTrue())
 		Expect(lbNames.Has("lb-1")).To(BeFalse())
+		Expect(lbNames.Has(clusterName)).To(BeTrue())
 	})
 })
 
diff --git a/tests/e2e/network/node.go b/tests/e2e/network/node.go
index bc3ff6027..19d8e2a8e 100644
--- a/tests/e2e/network/node.go
+++ b/tests/e2e/network/node.go
@@ -23,7 +23,6 @@ import (
 	"reflect"
 	"regexp"
 	"strings"
-	"time"
 
 	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-08-01/compute"
 	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-07-01/network"
@@ -32,11 +31,9 @@ import (
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
-	"k8s.io/apimachinery/pkg/util/wait"
 	clientset "k8s.io/client-go/kubernetes"
 	"k8s.io/utils/pointer"
 
-	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 	"sigs.k8s.io/cloud-provider-azure/tests/e2e/utils"
 )
 
@@ -253,23 +250,21 @@ var _ = Describe("Azure node resources", Label(utils.TestSuiteLabelNode), func()
 		}
 		utils.Logf("nodeSet: %v", nodeSet)
 
-		// Considering the route reconciling interval, the timeout is set to interval + 10s.
-		err = wait.PollImmediate(5*time.Second, consts.RouteUpdateInterval+10*time.Second, func() (bool, error) {
-			for _, routeTable := range *routeTables {
-				routeSet, err := utils.GetNodesInRouteTable(routeTable)
-				if err != nil {
-					return false, err
-				}
+		var succeeded bool
+		for _, routeTable := range *routeTables {
+			utils.Logf("getting all routes in route table %s", *routeTable.Name)
+			routeSet, err := utils.GetNodesInRouteTable(routeTable)
+			Expect(err).NotTo(HaveOccurred())
 
-				utils.Logf("all routes in route table: %v", routeSet)
-				if reflect.DeepEqual(nodeSet, routeSet) {
-					return true, nil
-				}
+			utils.Logf("routeSet: %v", routeSet)
+
+			if reflect.DeepEqual(nodeSet, routeSet) {
+				succeeded = true
+				break
 			}
-			return false, nil
-		})
+		}
 
-		Expect(err).NotTo(HaveOccurred())
+		Expect(succeeded).To(BeTrue())
 	})
 })
 
diff --git a/tests/e2e/network/service_annotations.go b/tests/e2e/network/service_annotations.go
index b54902939..e9df7fb47 100644
--- a/tests/e2e/network/service_annotations.go
+++ b/tests/e2e/network/service_annotations.go
@@ -795,7 +795,6 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 			Expect(len(pipFrontendConfigIDSplit)).NotTo(Equal(0))
 			ids = append(ids, pipFrontendConfigIDSplit[len(pipFrontendConfigIDSplit)-1])
 		}
-		utils.Logf("PIP frontend config IDs %q", ids)
 
 		var lb *network.LoadBalancer
 		var targetProbes []*network.Probe
@@ -813,7 +812,8 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 				probeSplit := strings.Split(*probe.Name, "-")
 				Expect(len(probeSplit)).NotTo(Equal(0))
 				probeSplitID := probeSplit[0]
-				if probeSplit[len(probeSplit)-1] == "IPv6" {
+				if len(probeSplit) > 1 &&
+					(probeSplit[len(probeSplit)-1] == "IPv4" || probeSplit[len(probeSplit)-1] == "IPv6") {
 					probeSplitID += "-" + probeSplit[len(probeSplit)-1]
 				}
 				for _, id := range ids {
@@ -823,7 +823,6 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 				}
 			}
 
-			utils.Logf("targetProbes count %d, expectedTargetProbes count %d", len(targetProbes), expectedTargetProbesCount)
 			return len(targetProbes) == expectedTargetProbesCount, nil
 		})
 		Expect(err).NotTo(HaveOccurred())
@@ -838,15 +837,11 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 				utils.Logf("Validating health probe config intervalInSeconds")
 				Expect(*probe.IntervalInSeconds).To(Equal(int32(10)))
 			}
-			utils.Logf("Validating health probe config ProbeProtocolHTTP")
 			Expect(probe.Protocol).To(Equal(network.ProbeProtocolHTTP))
 		}
 
 		By("Changing ExternalTrafficPolicy of the service to Local")
-		expectedTargetProbesLocalCount := 1
-		if tc.IPFamily == utils.DualStack {
-			expectedTargetProbesLocalCount = 2
-		}
+		expectedTargetProbesCount = 1
 		var service *v1.Service
 		utils.Logf("Updating service " + serviceName + " in namespace " + ns.Name)
 		retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
@@ -874,7 +869,7 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 		})
 		Expect(retryErr).NotTo(HaveOccurred())
 
-		err = wait.PollImmediate(5*time.Second, 300*time.Second, func() (bool, error) {
+		err = wait.PollImmediate(5*time.Second, 60*time.Second, func() (bool, error) {
 			lb = getAzureLoadBalancerFromPIP(tc, publicIPs[0], tc.GetResourceGroup(), "")
 			targetProbes = []*network.Probe{}
 			for i := range *lb.LoadBalancerPropertiesFormat.Probes {
@@ -883,7 +878,8 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 				probeSplit := strings.Split(*probe.Name, "-")
 				Expect(len(probeSplit)).NotTo(Equal(0))
 				probeSplitID := probeSplit[0]
-				if probeSplit[len(probeSplit)-1] == "IPv6" {
+				if len(probeSplit) > 1 &&
+					(probeSplit[len(probeSplit)-1] == "IPv4" || probeSplit[len(probeSplit)-1] == "IPv6") {
 					probeSplitID += "-" + probeSplit[len(probeSplit)-1]
 				}
 				for _, id := range ids {
@@ -893,28 +889,22 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 				}
 			}
 
-			utils.Logf("targetProbes count %d, expectedTargetProbesLocal count %d", len(targetProbes), expectedTargetProbesLocalCount)
-			if len(targetProbes) != expectedTargetProbesLocalCount {
-				return false, nil
-			}
-			By("Validating health probe configs")
-			for _, probe := range targetProbes {
+			return len(targetProbes) == expectedTargetProbesCount, nil
+		})
+		Expect(err).NotTo(HaveOccurred())
+
+		By("Validating health probe configs")
+		for _, probe := range targetProbes {
+			if probe.ProbeThreshold != nil {
 				utils.Logf("Validating health probe config numberOfProbes")
-				if probe.ProbeThreshold == nil || *probe.ProbeThreshold != int32(5) {
-					return false, nil
-				}
+				Expect(*probe.ProbeThreshold).To(Equal(int32(5)))
+			}
+			if probe.IntervalInSeconds != nil {
 				utils.Logf("Validating health probe config intervalInSeconds")
-				if probe.IntervalInSeconds == nil || *probe.IntervalInSeconds != int32(15) {
-					return false, nil
-				}
-				utils.Logf("Validating health probe config ProbeProtocolHTTP")
-				if !strings.EqualFold(string(probe.Protocol), string(network.ProbeProtocolHTTP)) {
-					return false, nil
-				}
+				Expect(*probe.IntervalInSeconds).To(Equal(int32(15)))
 			}
-			return true, nil
-		})
-		Expect(err).NotTo(HaveOccurred())
+			Expect(probe.Protocol).To(Equal(network.ProbeProtocolHTTP))
+		}
 	})
 
 	It("should generate health probe configs in multi-port scenario", func() {
diff --git a/tests/e2e/utils/network_utils.go b/tests/e2e/utils/network_utils.go
index 7af398a0d..27f26794b 100644
--- a/tests/e2e/utils/network_utils.go
+++ b/tests/e2e/utils/network_utils.go
@@ -255,6 +255,7 @@ func CreateLoadBalancerServiceManifest(name string, annotation map[string]string
 			Name:        name,
 			Namespace:   namespace,
 			Annotations: DeepCopyServiceAnnotation(annotation),
+			Labels:      labels,
 		},
 		Spec: v1.ServiceSpec{
 			Selector:       labels,
diff --git a/tests/k8s-azure/manifest/cluster-api/cloud-config-vmss-multi-slb.json b/tests/k8s-azure/manifest/cluster-api/cloud-config-vmss-multi-slb.json
index 5f9dbcdea..7e807161b 100644
--- a/tests/k8s-azure/manifest/cluster-api/cloud-config-vmss-multi-slb.json
+++ b/tests/k8s-azure/manifest/cluster-api/cloud-config-vmss-multi-slb.json
@@ -26,7 +26,7 @@
     },
     {
       "name": "lb-1",
-      "primaryVMSet": "${CLUSTER_NAME}-mp-1"
+      "primaryVMSet": "${CLUSTER_NAME}-mp-win"
     },
     {
       "name": "lb-2",
diff --git a/tests/k8s-azure/manifest/cluster-api/linux-vmss-multiple-zones-ci-version.yaml b/tests/k8s-azure/manifest/cluster-api/linux-vmss-multiple-zones-ci-version.yaml
index 96a22ddca..26634daec 100644
--- a/tests/k8s-azure/manifest/cluster-api/linux-vmss-multiple-zones-ci-version.yaml
+++ b/tests/k8s-azure/manifest/cluster-api/linux-vmss-multiple-zones-ci-version.yaml
@@ -222,7 +222,7 @@ spec:
         marketplace:
           offer: capi
           publisher: cncf-upstream
-          sku: ubuntu-2204-gen1
+          sku: ubuntu-1804-gen1
           version: latest
       osDisk:
         diskSizeGB: 128
@@ -273,7 +273,7 @@ spec:
       marketplace:
         offer: capi
         publisher: cncf-upstream
-        sku: ubuntu-2204-gen1
+        sku: ubuntu-1804-gen1
         version: latest
     osDisk:
       diskSizeGB: 30