Repository: kubermatic/machine-controller
Pull request #1430 (2022-09-13 12:44:05)

Fix dualstack IPv6 addr assignment issue in rockylinux and RHEL
Signed-off-by: Sachin Tiptur <sachin@kubermatic.com>

**What this PR does / why we need it**:
IPv6 interface configuration was not proper and config files were flooded in failure scenarios. This PR fixes this bug
and Configures/enables IPv6 address for the interface in case of RHEL and RockyLinux which uses NetworkManager.
**Which issue(s) this PR fixes**:
<!--optional, in `fixes #<issue number>` format, will close the issue(s) when PR gets merged-->
Fixes #[10871](https://github.com/kubermatic/kubermatic/issues/10871)

**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
-->

**Special notes for your reviewer**:
Manual tests and KKP CI dual stack e2e tests are done.
**Does this PR introduce a user-facing change? Then add your Release Note here**:
<!--
Write your release note:
1. Enter your extended release note in the below block. If the PR requires additional action from users switching to the new release, include the string "action required".
2. If no release note is required, just write "NONE".
-->
```release-note
NONE
```

**Documentation**:
<!--
Please do one of the following options:
- Add a link to the existing documentation
- Add a link to the kubermatic/docs pull request
- If no documentation change is applicable then add:
  - TBD (documentation will be added later)
  - NONE (no documentation needed for this PR)
-->
```documentation
NONE
```


kubermatic-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubermatic/machine-controller/pull/1430#" title="Author self-approved">sachintiptur</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **moadqassem** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @moadqassem` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubermatic%2Fmachine-controller).

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

- **[pkg/userdata/OWNERS](https://github.com/kubermatic/machine-controller/blob/master/pkg/userdata/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":["moadqassem"]} -->
kubermatic-bot: @sachintiptur: 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-machine-controller-e2e-vsphere | 2b41b3fb7cde2e296b3e8c3cc0d6e6647a3c58fb | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/1430/pull-machine-controller-e2e-vsphere/1569679526273748992) | true | `/test pull-machine-controller-e2e-vsphere`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=1430)

<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 -->
kubermatic-bot: @sachintiptur: 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-machine-controller-e2e-vsphere | a57e6065ee07acac0580aca8275ee213c6ee62aa | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/1430/pull-machine-controller-e2e-vsphere/1569752590059573248) | true | `/test pull-machine-controller-e2e-vsphere`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=1430)

<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 -->
rastislavs: /lgtm
kubermatic-bot: LGTM label has been added.  <details>Git tree hash: 0c23e99f5d91d9002a08616f99688fee971d5b84</details>
kubermatic-bot: @sachintiptur: 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-machine-controller-e2e-vsphere | a57e6065ee07acac0580aca8275ee213c6ee62aa | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/1430/pull-machine-controller-e2e-vsphere/1569948331843522560) | true | `/test pull-machine-controller-e2e-vsphere`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=1430)

<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 -->
kubermatic-bot: New changes are detected. LGTM label has been removed.
kubermatic-bot: @sachintiptur: 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-machine-controller-e2e-vsphere | f830ffcf6e65dca97b136bf87b10fd534eb6b0e1 | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/1430/pull-machine-controller-e2e-vsphere/1569962615826812928) | true | `/test pull-machine-controller-e2e-vsphere`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=1430)

<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 -->
kubermatic-bot: LGTM label has been added.  <details>Git tree hash: 790de2240a7bc02f3a59c4870e325f2f2517188f</details>
kubermatic-bot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubermatic/machine-controller/pull/1430#pullrequestreview-1107040034" title="Approved">ahmedwaleedmalik</a>*, *<a href="https://github.com/kubermatic/machine-controller/pull/1430#" title="Author self-approved">sachintiptur</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubermatic%2Fmachine-controller).

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:

- ~~[pkg/userdata/OWNERS](https://github.com/kubermatic/machine-controller/blob/master/pkg/userdata/OWNERS)~~ [ahmedwaleedmalik]

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":[]} -->
ahmedwaleedmalik: /hold

Our vSphere setup is inaccessible directly over the internet at the moment. `pull-machine-controller-e2e-vsphere` will fail till it's back up.
kubermatic-bot: @sachintiptur: 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-machine-controller-e2e-vsphere | f830ffcf6e65dca97b136bf87b10fd534eb6b0e1 | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/1430/pull-machine-controller-e2e-vsphere/1570426213246177280) | true | `/test pull-machine-controller-e2e-vsphere`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=1430)

<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/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index f035f371..126374da 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -19,6 +19,7 @@ Optionally add one or more of the following kinds if applicable:
 /kind failing-test
 /kind flake
 /kind regression
+/kind chore
 -->
 
 **Special notes for your reviewer**:
diff --git a/.prow/provider-nutanix.yaml b/.prow/provider-nutanix.yaml
index 4775ec78..c0b95522 100644
--- a/.prow/provider-nutanix.yaml
+++ b/.prow/provider-nutanix.yaml
@@ -14,10 +14,7 @@
 
 presubmits:
   - name: pull-machine-controller-e2e-nutanix
-    optional: true
-    always_run: false
-    # TODO uncomment this when Nutanix is in a working condition
-    #run_if_changed: "(pkg/cloudprovider/provider/nutanix/)"
+    run_if_changed: "(pkg/cloudprovider/provider/nutanix/)"
     decorate: true
     clone_uri: "ssh://git@github.com/kubermatic/machine-controller.git"
     labels:
diff --git a/cmd/machine-controller/main.go b/cmd/machine-controller/main.go
index 1f4f8f9c..320e4705 100644
--- a/cmd/machine-controller/main.go
+++ b/cmd/machine-controller/main.go
@@ -69,6 +69,8 @@ var (
 	bootstrapTokenServiceAccountName string
 	skipEvictionAfter                time.Duration
 	caBundleFile                     string
+	enableLeaderElection             bool
+	leaderElectionNamespace          string
 
 	useOSM bool
 
@@ -88,6 +90,7 @@ var (
 
 const (
 	defaultLeaderElectionNamespace = "kube-system"
+	defaultLeaderElectionID        = "machine-controller"
 )
 
 // controllerRunOptions holds data that are required to create and run machine controller.
@@ -152,6 +155,9 @@ func main() {
 	flag.StringVar(&healthProbeAddress, "health-probe-address", "127.0.0.1:8085", "The address on which the liveness check on /healthz and readiness check on /readyz will be available")
 	flag.StringVar(&metricsAddress, "metrics-address", "127.0.0.1:8080", "The address on which Prometheus metrics will be available under /metrics")
 	flag.StringVar(&name, "name", "", "When set, the controller will only process machines with the label \"machine.k8s.io/controller\": name")
+	flag.BoolVar(&enableLeaderElection, "enable-leader-election", true, "Enable leader election for machine-controller. Enabling this will ensure there is only one active instance.")
+	flag.StringVar(&leaderElectionNamespace, "leader-election-namespace", "kube-system", "Namespace to use for leader election.")
+
 	flag.StringVar(&joinClusterTimeout, "join-cluster-timeout", "", "when set, machines that have an owner and do not join the cluster within the configured duration will be deleted, so the owner re-creates them")
 	flag.StringVar(&bootstrapTokenServiceAccountName, "bootstrap-token-service-account-name", "", "When set use the service account token from this SA as bootstrap token instead of creating a temporary one. Passed in namespace/name format")
 	flag.BoolVar(&profiling, "enable-profiling", false, "when set, enables the endpoints on the http server under /debug/pprof/")
@@ -303,11 +309,16 @@ func main() {
 }
 
 func createManager(syncPeriod time.Duration, options controllerRunOptions) (manager.Manager, error) {
+	namespace := leaderElectionNamespace
+	if namespace == "" {
+		namespace = defaultLeaderElectionNamespace
+	}
+
 	mgr, err := manager.New(options.cfg, manager.Options{
 		SyncPeriod:              &syncPeriod,
-		LeaderElection:          true,
-		LeaderElectionID:        "machine-controller",
-		LeaderElectionNamespace: defaultLeaderElectionNamespace,
+		LeaderElection:          enableLeaderElection,
+		LeaderElectionID:        defaultLeaderElectionID,
+		LeaderElectionNamespace: namespace,
 		HealthProbeBindAddress:  healthProbeAddress,
 		MetricsBindAddress:      metricsAddress,
 	})
diff --git a/pkg/userdata/rhel/provider.go b/pkg/userdata/rhel/provider.go
index 46f3b304..41016bc2 100644
--- a/pkg/userdata/rhel/provider.go
+++ b/pkg/userdata/rhel/provider.go
@@ -232,10 +232,16 @@ write_files:
 {{ .ContainerRuntimeScript | indent 4 }}
 {{ safeDownloadBinariesScript .KubeletVersion | indent 4 }}
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+              
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/provider.go b/pkg/userdata/rockylinux/provider.go
index eebe3734..7efb0533 100644
--- a/pkg/userdata/rockylinux/provider.go
+++ b/pkg/userdata/rockylinux/provider.go
@@ -234,10 +234,16 @@ write_files:
 {{ .ContainerRuntimeScript | indent 4 }}
 {{ safeDownloadBinariesScript .KubeletVersion | indent 4 }}
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/


Test patch:
diff --git a/hack/ci/run-e2e-tests.sh b/hack/ci/run-e2e-tests.sh
index 95b4687a..cf848be6 100755
--- a/hack/ci/run-e2e-tests.sh
+++ b/hack/ci/run-e2e-tests.sh
@@ -68,11 +68,6 @@ beforeMCSetup=$(nowms)
 source hack/ci/setup-machine-controller-in-kind.sh
 pushElapsed kind_mc_setup_duration_milliseconds $beforeMCSetup
 
-if [[ ! -z "${NUTANIX_E2E_PROXY_HOST:-}" ]]; then
-  vm_priv_addr=$(cat ./priv_addr)
-  export NUTANIX_E2E_PROXY_URL="http://${NUTANIX_E2E_PROXY_USERNAME}:${NUTANIX_E2E_PROXY_PASSWORD}@${vm_priv_addr}:${NUTANIX_E2E_PROXY_PORT}/"
-fi
-
 echo "Running e2e tests..."
 EXTRA_ARGS=""
 if [[ $# -gt 0 ]]; then
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.22-aws.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.22-aws.yaml
index dbdb97a1..46499581 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.22-aws.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.22-aws.yaml
@@ -168,10 +168,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.22-nutanix.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.22-nutanix.yaml
index 82ee1029..940fff79 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.22-nutanix.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.22-nutanix.yaml
@@ -176,10 +176,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.23-aws-external.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.23-aws-external.yaml
index 98a5f9b6..abf428dd 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.23-aws-external.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.23-aws-external.yaml
@@ -168,10 +168,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.23-aws.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.23-aws.yaml
index deeef0ad..db517280 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.23-aws.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.23-aws.yaml
@@ -168,10 +168,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-mirrors.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-mirrors.yaml
index 749268ce..24a0d557 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-mirrors.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-mirrors.yaml
@@ -182,10 +182,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-proxy.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-proxy.yaml
index 1ec73c6a..4cad3586 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-proxy.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere-proxy.yaml
@@ -182,10 +182,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere.yaml
index 49a601c3..67eec404 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.23-vsphere.yaml
@@ -174,10 +174,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.24-aws-external.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.24-aws-external.yaml
index 88dfc838..3c100fa6 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.24-aws-external.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.24-aws-external.yaml
@@ -167,10 +167,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.24-aws.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.24-aws.yaml
index f1905c82..49e9b76b 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.24-aws.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.24-aws.yaml
@@ -167,10 +167,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rhel/testdata/pod-cidr-azure-rhel.yaml b/pkg/userdata/rhel/testdata/pod-cidr-azure-rhel.yaml
index 0a661c05..61430455 100644
--- a/pkg/userdata/rhel/testdata/pod-cidr-azure-rhel.yaml
+++ b/pkg/userdata/rhel/testdata/pod-cidr-azure-rhel.yaml
@@ -173,10 +173,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.22-aws.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.22-aws.yaml
index 2b58e6cc..56d87093 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.22-aws.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.22-aws.yaml
@@ -169,10 +169,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws-external.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws-external.yaml
index fb1eafba..0f11df4f 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws-external.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws-external.yaml
@@ -169,10 +169,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws.yaml
index e3082bbf..377cb87b 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-aws.yaml
@@ -169,10 +169,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-nutanix.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-nutanix.yaml
index 721b1194..a201b939 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-nutanix.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-nutanix.yaml
@@ -176,10 +176,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-mirrors.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-mirrors.yaml
index 14cb1eab..beb60d9a 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-mirrors.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-mirrors.yaml
@@ -182,10 +182,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-proxy.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-proxy.yaml
index 9273d0b8..7ef8f1de 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-proxy.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere-proxy.yaml
@@ -182,10 +182,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere.yaml
index 75d43c26..ed4b93aa 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.23-vsphere.yaml
@@ -174,10 +174,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/pkg/userdata/rockylinux/testdata/kubelet-v1.24-aws.yaml b/pkg/userdata/rockylinux/testdata/kubelet-v1.24-aws.yaml
index 16f21929..3f6a48f7 100644
--- a/pkg/userdata/rockylinux/testdata/kubelet-v1.24-aws.yaml
+++ b/pkg/userdata/rockylinux/testdata/kubelet-v1.24-aws.yaml
@@ -168,10 +168,16 @@ write_files:
     fi
 
     DEFAULT_IFC_NAME=$(ip -o route get 1  | grep -oP "dev \K\S+")
-    echo NETWORKING_IPV6=yes >> /etc/sysconfig/network
-    echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    echo DHCPV6C=yes >> /etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
-    ifdown $DEFAULT_IFC_NAME && ifup $DEFAULT_IFC_NAME
+    IFC_CFG_FILE=/etc/sysconfig/network-scripts/ifcfg-$DEFAULT_IFC_NAME
+    # Enable IPv6 and DHCPv6 on the default interface
+    grep IPV6INIT $IFC_CFG_FILE && sed -i '/IPV6INIT*/c IPV6INIT=yes' $IFC_CFG_FILE || echo "IPV6INIT=yes" >> $IFC_CFG_FILE
+    grep DHCPV6C $IFC_CFG_FILE && sed -i '/DHCPV6C*/c DHCPV6C=yes' $IFC_CFG_FILE || echo "DHCPV6C=yes" >> $IFC_CFG_FILE
+    grep IPV6_AUTOCONF $IFC_CFG_FILE && sed -i '/IPV6_AUTOCONF*/c IPV6_AUTOCONF=yes' $IFC_CFG_FILE || echo "IPV6_AUTOCONF=yes" >> $IFC_CFG_FILE
+
+    # Restart NetworkManager to apply for IPv6 configs
+    systemctl restart NetworkManager
+    # Let NetworkManager apply the DHCPv6 configs
+    sleep 3
 
     # set kubelet nodeip environment variable
     mkdir -p /etc/systemd/system/kubelet.service.d/
diff --git a/test/e2e/provisioning/all_e2e_test.go b/test/e2e/provisioning/all_e2e_test.go
index 25244065..9cec18e1d 100644
--- a/test/e2e/provisioning/all_e2e_test.go
+++ b/test/e2e/provisioning/all_e2e_test.go
@@ -80,7 +80,7 @@ const (
 	nutanixManifest                   = "./testdata/machinedeployment-nutanix.yaml"
 )
 
-const defaultKubernetesVersion = "1.23.5"
+const defaultKubernetesVersion = "1.23.11"
 
 var testRunIdentifier = flag.String("identifier", "local", "The unique identifier for this test run")
 
@@ -956,11 +956,6 @@ func getNutanixTestParams(t *testing.T) []string {
 			"NUTANIX_E2E_ENDPOINT, NUTANIX_E2E_PROJECT_NAME or NUTANIX_E2E_SUBNET_NAME environment variables cannot be empty")
 	}
 
-	// a proxy URL will be passed in our e2e test environment so
-	// a HTTP proxy can be used to access the Nutanix API in a different
-	// network segment.
-	proxyURL := os.Getenv("NUTANIX_E2E_PROXY_URL")
-
 	// set up parameters
 	params := []string{fmt.Sprintf("<< NUTANIX_PASSWORD >>=%s", password),
 		fmt.Sprintf("<< NUTANIX_USERNAME >>=%s", username),
@@ -968,7 +963,6 @@ func getNutanixTestParams(t *testing.T) []string {
 		fmt.Sprintf("<< NUTANIX_CLUSTER >>=%s", cluster),
 		fmt.Sprintf("<< NUTANIX_PROJECT >>=%s", project),
 		fmt.Sprintf("<< NUTANIX_SUBNET >>=%s", subnet),
-		fmt.Sprintf("<< NUTANIX_PROXY_URL >>=%s", proxyURL),
 	}
 	return params
 }
diff --git a/test/e2e/provisioning/helper.go b/test/e2e/provisioning/helper.go
index 39812773..6f992772 100644
--- a/test/e2e/provisioning/helper.go
+++ b/test/e2e/provisioning/helper.go
@@ -33,9 +33,9 @@ var (
 	scenarios = buildScenarios()
 
 	versions = []*semver.Version{
-		semver.MustParse("v1.22.7"),
-		semver.MustParse("v1.23.5"),
-		semver.MustParse("v1.24.0"),
+		semver.MustParse("v1.22.14"),
+		semver.MustParse("v1.23.11"),
+		semver.MustParse("v1.24.5"),
 	}
 
 	operatingSystems = []providerconfigtypes.OperatingSystem{
diff --git a/test/e2e/provisioning/testdata/machinedeployment-nutanix.yaml b/test/e2e/provisioning/testdata/machinedeployment-nutanix.yaml
index ddc75358..5a2bea06 100644
--- a/test/e2e/provisioning/testdata/machinedeployment-nutanix.yaml
+++ b/test/e2e/provisioning/testdata/machinedeployment-nutanix.yaml
@@ -27,7 +27,6 @@ spec:
             username: '<< NUTANIX_USERNAME >>'
             password: '<< NUTANIX_PASSWORD >>'
             endpoint: '<< NUTANIX_ENDPOINT >>'
-            proxyURL: '<< NUTANIX_PROXY_URL >>'
             allowInsecure: true
             clusterName: '<< NUTANIX_CLUSTER >>'
             projectName: '<< NUTANIX_PROJECT >>'
diff --git a/test/e2e/provisioning/testdata/machinedeployment-vsphere-datastore-cluster.yaml b/test/e2e/provisioning/testdata/machinedeployment-vsphere-datastore-cluster.yaml
index c07b9c0f..b42016a6 100644
--- a/test/e2e/provisioning/testdata/machinedeployment-vsphere-datastore-cluster.yaml
+++ b/test/e2e/provisioning/testdata/machinedeployment-vsphere-datastore-cluster.yaml
@@ -35,6 +35,7 @@ spec:
             cpus: 2
             MemoryMB: 2048
             diskSizeGB: << DISK_SIZE >>
+            allowInsecure: true
           operatingSystem: "<< OS_NAME >>"
           operatingSystemSpec:
             distUpgradeOnBoot: false
diff --git a/test/e2e/provisioning/testdata/machinedeployment-vsphere-resource-pool.yaml b/test/e2e/provisioning/testdata/machinedeployment-vsphere-resource-pool.yaml
index 4ead4d9e..0e505c1f 100644
--- a/test/e2e/provisioning/testdata/machinedeployment-vsphere-resource-pool.yaml
+++ b/test/e2e/provisioning/testdata/machinedeployment-vsphere-resource-pool.yaml
@@ -35,6 +35,7 @@ spec:
             cpus: 2
             MemoryMB: 2048
             diskSizeGB: << DISK_SIZE >>
+            allowInsecure: true
           operatingSystem: "<< OS_NAME >>"
           operatingSystemSpec:
             distUpgradeOnBoot: false
diff --git a/test/e2e/provisioning/testdata/machinedeployment-vsphere-static-ip.yaml b/test/e2e/provisioning/testdata/machinedeployment-vsphere-static-ip.yaml
index 36920702..131e6f91 100644
--- a/test/e2e/provisioning/testdata/machinedeployment-vsphere-static-ip.yaml
+++ b/test/e2e/provisioning/testdata/machinedeployment-vsphere-static-ip.yaml
@@ -32,9 +32,9 @@ spec:
             password: << VSPHERE_PASSWORD >>
             # example: 'https://your-vcenter:8443'. '/sdk' gets appended automatically
             datastore: alpha1
-            allowInsecure: true
             cpus: 2
             MemoryMB: 2048
+            allowInsecure: true
           operatingSystem: "<< OS_NAME >>"
           operatingSystemSpec:
             distUpgradeOnBoot: false
diff --git a/test/e2e/provisioning/testdata/machinedeployment-vsphere.yaml b/test/e2e/provisioning/testdata/machinedeployment-vsphere.yaml
index 223ffc5b..7ddc15a6 100644
--- a/test/e2e/provisioning/testdata/machinedeployment-vsphere.yaml
+++ b/test/e2e/provisioning/testdata/machinedeployment-vsphere.yaml
@@ -35,6 +35,7 @@ spec:
             cpus: 2
             MemoryMB: 4096
             diskSizeGB: << DISK_SIZE >>
+            allowInsecure: true
           operatingSystem: "<< OS_NAME >>"
           operatingSystemSpec:
             distUpgradeOnBoot: false