diff --git a/inventory/sample/group_vars/k8s-cluster/k8s-cluster.yml b/inventory/sample/group_vars/k8s-cluster/k8s-cluster.yml
index a52834af8c4acec658fdd690fd5553e63c55569f..eadae61b561c4ee0bb0f47b9718b54c7e0e4c6db 100644
--- a/inventory/sample/group_vars/k8s-cluster/k8s-cluster.yml
+++ b/inventory/sample/group_vars/k8s-cluster/k8s-cluster.yml
@@ -211,8 +211,6 @@ kata_containers_enabled: false
 kubelet_deployment_type: host
 helm_deployment_type: host
 
-# Enable kubeadm experimental control plane
-kubeadm_control_plane: false
 kubeadm_certificate_key: "{{ lookup('password', credentials_dir + '/kubeadm_certificate_key.creds length=64 chars=hexdigits') | lower }}"
 
 # K8s image pull policy (imagePullPolicy)
diff --git a/roles/kubernetes/kubeadm/tasks/main.yml b/roles/kubernetes/kubeadm/tasks/main.yml
index ae2c0484ecc961f202b09795af2edccbc92e88ac..71b3933beaefb15301bc5f43e507d101a3c9d954 100644
--- a/roles/kubernetes/kubeadm/tasks/main.yml
+++ b/roles/kubernetes/kubeadm/tasks/main.yml
@@ -163,7 +163,6 @@
   include_tasks: kubeadm_etcd_node.yml
   when:
     - etcd_kubeadm_enabled
-    - kubeadm_control_plane
     - inventory_hostname not in groups['kube-master']
     - kube_network_plugin in ["calico", "flannel", "canal", "cilium"] or cilium_deploy_additionally | default(false) | bool
     - kube_network_plugin != "calico" or calico_datastore == "etcd"
diff --git a/roles/kubernetes/master/defaults/main/main.yml b/roles/kubernetes/master/defaults/main/main.yml
index 01fdd2946bdbfc7d61ae271fb25aac359a39f4d1..0ca43ef36f0fc75fea3b5e8abe671114b98a9c8e 100644
--- a/roles/kubernetes/master/defaults/main/main.yml
+++ b/roles/kubernetes/master/defaults/main/main.yml
@@ -2,9 +2,6 @@
 # disable upgrade cluster
 upgrade_cluster_setup: false
 
-# Enable kubeadm experimental control plane
-kubeadm_control_plane: false
-
 # Experimental kubeadm etcd deployment mode. Available only for new deployment
 etcd_kubeadm_enabled: false
 
diff --git a/roles/kubernetes/master/tasks/kubeadm-secondary-legacy.yml b/roles/kubernetes/master/tasks/kubeadm-secondary-legacy.yml
deleted file mode 100644
index 07e0c1a88b1533f65f1260678542bc76b2988560..0000000000000000000000000000000000000000
--- a/roles/kubernetes/master/tasks/kubeadm-secondary-legacy.yml
+++ /dev/null
@@ -1,44 +0,0 @@
----
-- name: slurp kubeadm certs
-  slurp:
-    src: "{{ item }}"
-  with_items:
-    - "{{ kube_cert_dir }}/apiserver.crt"
-    - "{{ kube_cert_dir }}/apiserver.key"
-    - "{{ kube_cert_dir }}/apiserver-kubelet-client.crt"
-    - "{{ kube_cert_dir }}/apiserver-kubelet-client.key"
-    - "{{ kube_cert_dir }}/ca.crt"
-    - "{{ kube_cert_dir }}/ca.key"
-    - "{{ kube_cert_dir }}/front-proxy-ca.crt"
-    - "{{ kube_cert_dir }}/front-proxy-ca.key"
-    - "{{ kube_cert_dir }}/front-proxy-client.crt"
-    - "{{ kube_cert_dir }}/front-proxy-client.key"
-    - "{{ kube_cert_dir }}/sa.key"
-    - "{{ kube_cert_dir }}/sa.pub"
-  register: kubeadm_certs
-  delegate_to: "{{ groups['kube-master']|first }}"
-
-- name: kubeadm | write out kubeadm certs
-  copy:
-    dest: "{{ item.item }}"
-    content: "{{ item.content | b64decode }}"
-    owner: root
-    group: root
-    mode: 0640
-  no_log: true
-  register: copy_kubeadm_certs
-  with_items: "{{ kubeadm_certs.results }}"
-  when: inventory_hostname != groups['kube-master']|first
-
-- name: kubeadm | Init other uninitialized masters
-  command: timeout -k 600s 600s {{ bin_dir }}/kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --ignore-preflight-errors=all --skip-phases=addon/coredns
-  register: kubeadm_init
-  retries: 10
-  until: kubeadm_init is succeeded or "field is immutable" in kubeadm_init.stderr
-  when:
-    - inventory_hostname != groups['kube-master']|first
-    - not kubeadm_already_run.stat.exists
-  failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
-  environment:
-    PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}"
-  notify: Master | restart kubelet
diff --git a/roles/kubernetes/master/tasks/kubeadm-secondary-experimental.yml b/roles/kubernetes/master/tasks/kubeadm-secondary.yml
similarity index 100%
rename from roles/kubernetes/master/tasks/kubeadm-secondary-experimental.yml
rename to roles/kubernetes/master/tasks/kubeadm-secondary.yml
diff --git a/roles/kubernetes/master/tasks/kubeadm-setup.yml b/roles/kubernetes/master/tasks/kubeadm-setup.yml
index fc442b3bebd17d71c67978b51601701d2c943f5d..cecdad27d9518ef0fbbe3e8f609f3c07b694e770 100644
--- a/roles/kubernetes/master/tasks/kubeadm-setup.yml
+++ b/roles/kubernetes/master/tasks/kubeadm-setup.yml
@@ -199,13 +199,8 @@
   tags:
     - kubeadm_token
 
-- name: kubeadm | Initialize other masters (experimental control plane)
-  include_tasks: kubeadm-secondary-experimental.yml
-  when: kubeadm_control_plane
-
-- name: kubeadm | Initialize other masters (legacy not control plane)
-  include_tasks: kubeadm-secondary-legacy.yml
-  when: not kubeadm_control_plane
+- name: kubeadm | Join other masters
+  include_tasks: kubeadm-secondary.yml
 
 - name: kubeadm | upgrade kubernetes cluster
   include_tasks: kubeadm-upgrade.yml
diff --git a/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml b/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml
index 07c53965d7fb4109909d093809a9653933863211..98e80e15c9940ecf53f74415135289753d38422b 100644
--- a/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml
+++ b/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml
@@ -258,12 +258,6 @@
   when: resolvconf_mode is defined
   run_once: true
 
-- name: Stop if kubeadm etcd mode is enabled but experimental control plane is not
-  assert:
-    that: kubeadm_control_plane
-    msg: "kubeadm etcd mode requires experimental control plane"
-  when: etcd_kubeadm_enabled
-
 - name: Stop if etcd deployment type is not host or docker
   assert:
     that: etcd_deployment_type in ['host', 'docker']
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index fcfa6d53c3362af4fd10b294582f0094499d8201..6aa3b99c50e3735a885265a282c7041120e81732 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -402,9 +402,6 @@ kubelet_protect_kernel_defaults: true
 ## the k8s cluster.
 kube_feature_gates: []
 
-# Enable kubeadm experimental control plane
-kubeadm_control_plane: false
-
 # Local volume provisioner storage classes
 # Levarages Ansibles string to Python datatype casting. Otherwise the dict_key isn't substituted
 # see https://github.com/ansible/ansible/issues/17324
diff --git a/tests/files/packet_centos7-flannel-containerd-addons-ha.yml b/tests/files/packet_centos7-flannel-containerd-addons-ha.yml
index 59a4dcaef40eb7d19f0f3297bfbe75c2b29d11cf..9dfcf6b0d59b540eb98ea4ba7776f72371572ff2 100644
--- a/tests/files/packet_centos7-flannel-containerd-addons-ha.yml
+++ b/tests/files/packet_centos7-flannel-containerd-addons-ha.yml
@@ -4,7 +4,6 @@ cloud_image: centos-7
 mode: ha
 
 # Kubespray settings
-kubeadm_control_plane: true
 kubeadm_certificate_key: 3998c58db6497dd17d909394e62d515368c06ec617710d02edea31c06d741085
 kube_proxy_mode: iptables
 kube_network_plugin: flannel
diff --git a/tests/files/packet_ubuntu16-flannel-ha.yml b/tests/files/packet_ubuntu16-flannel-ha.yml
index 47d643af22288c63844f2f4c345e4bf4ebb1b412..8253ca8fae09ea9b0f3612a7f5525b0652b0ac3a 100644
--- a/tests/files/packet_ubuntu16-flannel-ha.yml
+++ b/tests/files/packet_ubuntu16-flannel-ha.yml
@@ -6,7 +6,6 @@ mode: ha
 # Kubespray settings
 kube_network_plugin: flannel
 etcd_kubeadm_enabled: true
-kubeadm_control_plane: true
 kubeadm_certificate_key: 3998c58db6497dd17d909394e62d515368c06ec617710d02edea31c06d741085
 skip_non_kubeadm_warning: true
 deploy_netchecker: true
diff --git a/tests/files/packet_ubuntu18-flannel-containerd-ha-once.yml b/tests/files/packet_ubuntu18-flannel-containerd-ha-once.yml
index 3b26f429081ba0f8d6819c827fe2bf7f76294a65..67b0ff963125254c83a7db5a1e015063af8f7ef8 100644
--- a/tests/files/packet_ubuntu18-flannel-containerd-ha-once.yml
+++ b/tests/files/packet_ubuntu18-flannel-containerd-ha-once.yml
@@ -5,7 +5,6 @@ mode: ha
 vm_memory: 1600Mi
 
 # Kubespray settings
-kubeadm_control_plane: true
 kubeadm_certificate_key: 3998c58db6497dd17d909394e62d515368c06ec617710d02edea31c06d741085
 kube_proxy_mode: iptables
 kube_network_plugin: flannel
diff --git a/tests/files/packet_ubuntu18-flannel-containerd-ha.yml b/tests/files/packet_ubuntu18-flannel-containerd-ha.yml
index 3b26f429081ba0f8d6819c827fe2bf7f76294a65..67b0ff963125254c83a7db5a1e015063af8f7ef8 100644
--- a/tests/files/packet_ubuntu18-flannel-containerd-ha.yml
+++ b/tests/files/packet_ubuntu18-flannel-containerd-ha.yml
@@ -5,7 +5,6 @@ mode: ha
 vm_memory: 1600Mi
 
 # Kubespray settings
-kubeadm_control_plane: true
 kubeadm_certificate_key: 3998c58db6497dd17d909394e62d515368c06ec617710d02edea31c06d741085
 kube_proxy_mode: iptables
 kube_network_plugin: flannel