diff --git a/docs/hardening.md b/docs/hardening.md
index 7dd42e0ef065c6400ac72ea7767b7b79b86d77de..180979ed630c211ac96e05a663fd45657ce34fe1 100644
--- a/docs/hardening.md
+++ b/docs/hardening.md
@@ -84,6 +84,10 @@ kubelet_rotate_certificates: true
 kubelet_streaming_connection_idle_timeout: "5m"
 kubelet_make_iptables_util_chains: true
 kubelet_feature_gates: ["RotateKubeletServerCertificate=true"]
+
+# additional configurations
+kube_owner: root
+kube_cert_group: root
 ```
 
 Let's take a deep look to the resultant **kubernetes** configuration:
diff --git a/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml b/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
index d311394791d2f890b07db991a65361e73134aedd..fe41e916adba584ab6d1e3b2a40fecbcc857db15 100644
--- a/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
+++ b/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml
@@ -25,6 +25,9 @@ local_release_dir: "/tmp/releases"
 # Random shifts for retrying failed ops like pushing/downloading
 retry_stagger: 5
 
+# This is the user that owns tha cluster installation.
+kube_owner: kube
+
 # This is the group that the cert creation scripts chgrp the
 # cert files to. Not really changeable...
 kube_cert_group: kube-cert
diff --git a/roles/adduser/defaults/main.yml b/roles/adduser/defaults/main.yml
index c7f683710454a51fdfab4198ffea7faf908d8b65..3c692343ab88a3a1b043c0cdd7444fdca47f5521 100644
--- a/roles/adduser/defaults/main.yml
+++ b/roles/adduser/defaults/main.yml
@@ -1,4 +1,5 @@
 ---
+kube_owner: kube
 kube_cert_group: kube-cert
 etcd_data_dir: "/var/lib/etcd"
 
diff --git a/roles/adduser/tasks/main.yml b/roles/adduser/tasks/main.yml
index 774eb412b6b1b401f7a9c4f4c13ac0ef454a52b1..a364679772bc492215b80103a94a46703bd10207 100644
--- a/roles/adduser/tasks/main.yml
+++ b/roles/adduser/tasks/main.yml
@@ -13,3 +13,4 @@
     shell: "{{ user.shell|default(omit) }}"
     name: "{{ user.name }}"
     system: "{{ user.system|default(omit) }}"
+  when: kube_owner != "root"
diff --git a/roles/container-engine/cri-dockerd/molecule/default/prepare.yml b/roles/container-engine/cri-dockerd/molecule/default/prepare.yml
index 77e48b0833a85611b77bb0fdca43f8476d01064b..c54feaca255ebeb6a47542c7ea32a978c92cdc28 100644
--- a/roles/container-engine/cri-dockerd/molecule/default/prepare.yml
+++ b/roles/container-engine/cri-dockerd/molecule/default/prepare.yml
@@ -35,7 +35,7 @@
       file:
         path: /etc/cni/net.d
         state: directory
-        owner: kube
+        owner: "{{ kube_owner }}"
         mode: 0755
     - name: Setup CNI
       copy:
diff --git a/roles/container-engine/kata-containers/molecule/default/prepare.yml b/roles/container-engine/kata-containers/molecule/default/prepare.yml
index 9299a7e2d7d23638683fcbdbf47d29e1cb570934..8a0978f56be37fb79392b6cc8939bf6f5cfbe0c6 100644
--- a/roles/container-engine/kata-containers/molecule/default/prepare.yml
+++ b/roles/container-engine/kata-containers/molecule/default/prepare.yml
@@ -36,7 +36,7 @@
       file:
         path: /etc/cni/net.d
         state: directory
-        owner: kube
+        owner: "{{ kube_owner }}"
         mode: 0755
     - name: Setup CNI
       copy:
diff --git a/roles/download/defaults/main.yml b/roles/download/defaults/main.yml
index 039fccea166c7cd59bb2bd4d501fe9f67d876a46..cac0d36973c2c156ba3edb2d604e3b8326ca42b8 100644
--- a/roles/download/defaults/main.yml
+++ b/roles/download/defaults/main.yml
@@ -1614,5 +1614,5 @@ download_defaults:
   version: None
   url: None
   unarchive: false
-  owner: kube
+  owner: "{{ kube_owner }}"
   mode: None
diff --git a/roles/etcd/defaults/main.yml b/roles/etcd/defaults/main.yml
index 32971bc71598c088e478000aff60b3dea8e8f472..79ed16493aeff21087e52db7a828cdd52028d154 100644
--- a/roles/etcd/defaults/main.yml
+++ b/roles/etcd/defaults/main.yml
@@ -1,4 +1,7 @@
 ---
+# Set etcd user
+etcd_owner: etcd
+
 # Set to false to only do certificate management
 etcd_cluster_setup: true
 etcd_events_cluster_setup: false
diff --git a/roles/etcd/tasks/gen_certs_script.yml b/roles/etcd/tasks/gen_certs_script.yml
index 680df69db0a2338bead8af507ffd2b1e916d9a7e..cf5580bb81cec954a4ecf78cbea5d5f227a5679a 100644
--- a/roles/etcd/tasks/gen_certs_script.yml
+++ b/roles/etcd/tasks/gen_certs_script.yml
@@ -4,7 +4,7 @@
     path: "{{ etcd_cert_dir }}"
     group: "{{ etcd_cert_group }}"
     state: directory
-    owner: kube
+    owner: "{{ etcd_owner }}"
     mode: "{{ etcd_cert_dir_mode }}"
     recurse: yes
 
@@ -81,7 +81,7 @@
     dest: "{{ item.item }}"
     content: "{{ item.content | b64decode }}"
     group: "{{ etcd_cert_group }}"
-    owner: kube
+    owner: "{{ etcd_owner }}"
     mode: 0640
   with_items: "{{ etcd_master_certs.results }}"
   when:
@@ -111,7 +111,7 @@
     dest: "{{ item.item }}"
     content: "{{ item.content | b64decode }}"
     group: "{{ etcd_cert_group }}"
-    owner: kube
+    owner: "{{ etcd_owner }}"
     mode: 0640
   with_items: "{{ etcd_master_node_certs.results }}"
   when:
@@ -165,6 +165,6 @@
     path: "{{ etcd_cert_dir }}"
     group: "{{ etcd_cert_group }}"
     state: directory
-    owner: kube
+    owner: "{{ etcd_owner }}"
     mode: "{{ etcd_cert_dir_mode }}"
     recurse: yes
diff --git a/roles/kubernetes/control-plane/defaults/main/etcd.yml b/roles/kubernetes/control-plane/defaults/main/etcd.yml
index 60e934bc2dda347b251626031503a2b49fa6dae0..344ce9b35360006979cd8303afd2fd56c29fb73b 100644
--- a/roles/kubernetes/control-plane/defaults/main/etcd.yml
+++ b/roles/kubernetes/control-plane/defaults/main/etcd.yml
@@ -1,4 +1,7 @@
 ---
+# Set etcd user/group
+etcd_owner: etcd
+
 # Note: This does not set up DNS entries. It simply adds the following DNS
 # entries to the certificate
 etcd_cert_alt_names:
diff --git a/roles/kubernetes/control-plane/tasks/kubeadm-etcd.yml b/roles/kubernetes/control-plane/tasks/kubeadm-etcd.yml
index 8c0c47bb75d76a6e3493801df34371d7ce211ecd..1e97ac24064e077c8a5bb25fc322c4e6b1057949 100644
--- a/roles/kubernetes/control-plane/tasks/kubeadm-etcd.yml
+++ b/roles/kubernetes/control-plane/tasks/kubeadm-etcd.yml
@@ -16,3 +16,10 @@
   import_role:
     name: etcdctl
   when: etcd_deployment_type == "kubeadm"
+
+- name: Set ownership for etcd data directory
+  file:
+    path: "{{ etcd_data_dir }}"
+    owner: "{{ etcd_owner }}"
+    group: "{{ etcd_owner }}"
+    mode: 0700
diff --git a/roles/kubernetes/preinstall/defaults/main.yml b/roles/kubernetes/preinstall/defaults/main.yml
index fc17b79d491394ce8361e89e8084be12fb38f644..9624ea6fa1f921478aa5839216c734d38b37c0cb 100644
--- a/roles/kubernetes/preinstall/defaults/main.yml
+++ b/roles/kubernetes/preinstall/defaults/main.yml
@@ -22,6 +22,7 @@ common_required_pkgs:
 # GCE docker repository
 disable_ipv6_dns: false
 
+kube_owner: kube
 kube_cert_group: kube-cert
 kube_config_dir: /etc/kubernetes
 kube_cert_dir: "{{ kube_config_dir }}/ssl"
diff --git a/roles/kubernetes/preinstall/tasks/0050-create_directories.yml b/roles/kubernetes/preinstall/tasks/0050-create_directories.yml
index 0c6ded0f9084be8628ed8cacb2c1b7d30734fe45..35d7e04dfcfd4a291e558cd0a3b47db3e7e2a1cd 100644
--- a/roles/kubernetes/preinstall/tasks/0050-create_directories.yml
+++ b/roles/kubernetes/preinstall/tasks/0050-create_directories.yml
@@ -3,7 +3,7 @@
   file:
     path: "{{ item }}"
     state: directory
-    owner: kube
+    owner: "{{ kube_owner }}"
     mode: 0755
   when: inventory_hostname in groups['k8s_cluster']
   become: true
@@ -71,7 +71,7 @@
   file:
     path: "{{ item }}"
     state: directory
-    owner: kube
+    owner: "{{ kube_owner }}"
     mode: 0755
   with_items:
     - "/etc/cni/net.d"
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index 756c6f7c38c881b868fd01f1fdb759148e39901b..9a6c58c0c7731dc547d23027b7d90bcc7a66e676 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -153,6 +153,9 @@ kube_cert_compat_dir: "/etc/kubernetes/pki"
 # This is where all of the bearer tokens will be stored
 kube_token_dir: "{{ kube_config_dir }}/tokens"
 
+# This is the user that owns tha cluster installation.
+kube_owner: kube
+
 # This is the group that the cert creation scripts chgrp the
 # cert files to. Not really changeable...
 kube_cert_group: kube-cert
diff --git a/roles/network_plugin/canal/tasks/main.yml b/roles/network_plugin/canal/tasks/main.yml
index 5d7637289fa9330f9350b91b07cc1b3a386e5acc..0d62b16eecce43532de7f023fe854b5e1269b69c 100644
--- a/roles/network_plugin/canal/tasks/main.yml
+++ b/roles/network_plugin/canal/tasks/main.yml
@@ -4,7 +4,7 @@
     src: "cni-canal.conflist.j2"
     dest: "/etc/cni/net.d/canal.conflist.template"
     mode: 0644
-    owner: kube
+    owner: "{{ kube_owner }}"
   register: canal_conflist
   notify: reset_canal_cni
 
diff --git a/roles/network_plugin/cni/tasks/main.yml b/roles/network_plugin/cni/tasks/main.yml
index d9f46939c6cacf786c4925dad2a36bcd2da86cb5..b8bcec322a300ccc0c6e0e756a974c5b02608609 100644
--- a/roles/network_plugin/cni/tasks/main.yml
+++ b/roles/network_plugin/cni/tasks/main.yml
@@ -4,7 +4,7 @@
     path: /opt/cni/bin
     state: directory
     mode: 0755
-    owner: kube
+    owner: "{{ kube_owner }}"
     recurse: true
 
 - name: CNI | Copy cni plugins
diff --git a/roles/network_plugin/kube-router/tasks/main.yml b/roles/network_plugin/kube-router/tasks/main.yml
index 6cda7fe35dd1e36afaf6e946ed55c2275a869818..4cc078ae7af128b98a2a03964fd3f6d605c7b3d4 100644
--- a/roles/network_plugin/kube-router/tasks/main.yml
+++ b/roles/network_plugin/kube-router/tasks/main.yml
@@ -7,7 +7,7 @@
   file:
     path: /var/lib/kube-router
     state: directory
-    owner: kube
+    owner: "{{ kube_owner }}"
     recurse: true
     mode: 0755
 
@@ -16,7 +16,7 @@
     src: kubeconfig.yml.j2
     dest: /var/lib/kube-router/kubeconfig
     mode: 0644
-    owner: kube
+    owner: "{{ kube_owner }}"
   notify:
     - reset_kube_router
 
@@ -44,7 +44,7 @@
     src: cni-conf.json.j2
     dest: /etc/cni/net.d/10-kuberouter.conflist
     mode: 0644
-    owner: kube
+    owner: "{{ kube_owner }}"
   notify:
     - reset_kube_router