diff --git a/extra_playbooks/upgrade-only-k8s.yml b/extra_playbooks/upgrade-only-k8s.yml
index b9263cb0277295051b7c4a36af9f730cff84cdd4..9cae3e85b48c4ed19db59e0293ce746c54516850 100644
--- a/extra_playbooks/upgrade-only-k8s.yml
+++ b/extra_playbooks/upgrade-only-k8s.yml
@@ -46,7 +46,7 @@
     - { role: kubespray-defaults}
     - { role: upgrade/pre-upgrade, tags: pre-upgrade }
     - { role: kubernetes/node, tags: node }
-    - { role: kubernetes/master, tags: master }
+    - { role: kubernetes/master, tags: master, upgrade_cluster_setup: true }
     - { role: kubernetes/client, tags: client }
     - { role: kubernetes-apps/cluster_roles, tags: cluster-roles }
     - { role: upgrade/post-upgrade, tags: post-upgrade }
diff --git a/roles/kubernetes/master/defaults/main.yml b/roles/kubernetes/master/defaults/main.yml
index c0fabcd4273414fe4dc79db3657ce2faf4ed03d8..e40a9d1aa47aa68b0c08e45813a893b95d57fc0f 100644
--- a/roles/kubernetes/master/defaults/main.yml
+++ b/roles/kubernetes/master/defaults/main.yml
@@ -1,4 +1,7 @@
 ---
+# disable upgrade cluster
+upgrade_cluster_setup: false
+
 # An experimental dev/test only dynamic volumes provisioner,
 # for PetSets. Works for kube>=v1.3 only.
 kube_hostpath_dynamic_provisioner: "false"
diff --git a/roles/kubernetes/master/tasks/kubeadm-setup.yml b/roles/kubernetes/master/tasks/kubeadm-setup.yml
index 6792a6e1e266afe8a61b50350e9e519bd034367e..32f1703256d0b502d47b1ad2e4ee548de67b2fd2 100644
--- a/roles/kubernetes/master/tasks/kubeadm-setup.yml
+++ b/roles/kubernetes/master/tasks/kubeadm-setup.yml
@@ -86,45 +86,14 @@
     dest: "{{ audit_policy_file }}"
   when: kubernetes_audit|default(false)
 
-- name: gets the kubeadm version
-  command: "{{ bin_dir }}/kubeadm version -o short"
-  register: kubeadm_output
-
-- name: sets kubeadm api version to v1alpha1
-  set_fact:
-    kubeadmConfig_api_version: v1alpha1
-  when: kubeadm_output.stdout is version('v1.11.0', '<')
-
-- name: sets kubeadm api version to v1alpha2
-  set_fact:
-    kubeadmConfig_api_version: v1alpha2
-  when:
-    - kubeadm_output.stdout is version('v1.11.0', '>=')
-    - kubeadm_output.stdout is version('v1.12.0', '<')
-
-- name: sets kubeadm api version to v1alpha3
-  set_fact:
-    kubeadmConfig_api_version: v1alpha3
-  when:
-    - kubeadm_output.stdout is version('v1.12.0', '>=')
-    - kubeadm_output.stdout is version('v1.13.0', '<')
-
-- name: sets kubeadm api version to v1beta1
-  set_fact:
-    kubeadmConfig_api_version: v1beta1
-  when: kubeadm_output.stdout is version('v1.13.0', '>=')
-
 # Nginx LB(default), If kubeadm_config_api_fqdn is defined, use other LB by kubeadm controlPlaneEndpoint.
 - name: set kubeadm_config_api_fqdn define
   set_fact:
     kubeadm_config_api_fqdn: "{{ apiserver_loadbalancer_domain_name|default('lb-apiserver.kubernetes.local') }}"
   when: loadbalancer_apiserver is defined
 
-- name: kubeadm | Create kubeadm config
-  template:
-    src: "kubeadm-config.{{ kubeadmConfig_api_version }}.yaml.j2"
-    dest: "{{ kube_config_dir }}/kubeadm-config.yaml"
-  register: kubeadm_config
+- name: kubeadm | set kubeadm version
+  import_tasks: kubeadm-version.yml
 
 - name: kubeadm | Initialize first master
   command: timeout -k 600s 600s {{ bin_dir }}/kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --ignore-preflight-errors=all
@@ -135,24 +104,6 @@
   failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
   notify: Master | restart kubelet
 
-- name: kubeadm | Upgrade first master
-  command: >-
-    timeout -k 600s 600s
-    {{ bin_dir }}/kubeadm
-    upgrade apply -y {{ kube_version }}
-    --config={{ kube_config_dir }}/kubeadm-config.yaml
-    --ignore-preflight-errors=all
-    --allow-experimental-upgrades
-    --allow-release-candidate-upgrades
-    --etcd-upgrade=false
-    --force
-  register: kubeadm_upgrade
-  # Retry is because upload config sometimes fails
-  retries: 3
-  when: inventory_hostname == groups['kube-master']|first and (kubeadm_config.changed and kubeadm_already_run.stat.exists)
-  failed_when: kubeadm_upgrade.rc != 0 and "field is immutable" not in kubeadm_upgrade.stderr
-  notify: Master | restart kubelet
-
 - name: slurp kubeadm certs
   slurp:
     src: "{{ item }}"
@@ -194,20 +145,9 @@
   failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
   notify: Master | restart kubelet
 
-- name: kubeadm | Upgrade other masters
-  command: >-
-    timeout -k 600s 600s
-    {{ bin_dir }}/kubeadm
-    upgrade apply -y {{ kube_version }}
-    --config={{ kube_config_dir }}/kubeadm-config.yaml
-    --ignore-preflight-errors=all
-    --allow-experimental-upgrades
-    --allow-release-candidate-upgrades
-    --etcd-upgrade=false
-  register: kubeadm_upgrade
-  when: inventory_hostname != groups['kube-master']|first and (kubeadm_config.changed and kubeadm_already_run.stat.exists)
-  failed_when: kubeadm_upgrade.rc != 0 and "field is immutable" not in kubeadm_upgrade.stderr
-  notify: Master | restart kubelet
+- name: kubeadm | upgrage kubernetes cluster
+  import_tasks: kubeadm-upgrade.yml
+  when: upgrade_cluster_setup
 
 - name: kubeadm | Check service account key again
   stat:
diff --git a/roles/kubernetes/master/tasks/kubeadm-upgrade.yml b/roles/kubernetes/master/tasks/kubeadm-upgrade.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7b74c85c39940bcf8f2842867f9f731c010846fd
--- /dev/null
+++ b/roles/kubernetes/master/tasks/kubeadm-upgrade.yml
@@ -0,0 +1,33 @@
+---
+- name: kubeadm | Upgrade first master
+  command: >-
+    timeout -k 600s 600s
+    {{ bin_dir }}/kubeadm
+    upgrade apply -y {{ kube_version }}
+    --config={{ kube_config_dir }}/kubeadm-config.yaml
+    --ignore-preflight-errors=all
+    --allow-experimental-upgrades
+    --allow-release-candidate-upgrades
+    --etcd-upgrade=false
+    --force
+  register: kubeadm_upgrade
+  # Retry is because upload config sometimes fails
+  retries: 3
+  when: inventory_hostname == groups['kube-master']|first
+  failed_when: kubeadm_upgrade.rc != 0 and "field is immutable" not in kubeadm_upgrade.stderr
+  notify: Master | restart kubelet
+
+- name: kubeadm | Upgrade other masters
+  command: >-
+    timeout -k 600s 600s
+    {{ bin_dir }}/kubeadm
+    upgrade apply -y {{ kube_version }}
+    --config={{ kube_config_dir }}/kubeadm-config.yaml
+    --ignore-preflight-errors=all
+    --allow-experimental-upgrades
+    --allow-release-candidate-upgrades
+    --etcd-upgrade=false
+  register: kubeadm_upgrade
+  when: inventory_hostname != groups['kube-master']|first
+  failed_when: kubeadm_upgrade.rc != 0 and "field is immutable" not in kubeadm_upgrade.stderr
+  notify: Master | restart kubelet
diff --git a/roles/kubernetes/master/tasks/kubeadm-version.yml b/roles/kubernetes/master/tasks/kubeadm-version.yml
new file mode 100644
index 0000000000000000000000000000000000000000..971e7930f178ec46d54ec600e20a0a0014a88782
--- /dev/null
+++ b/roles/kubernetes/master/tasks/kubeadm-version.yml
@@ -0,0 +1,33 @@
+---
+- name: gets the kubeadm version
+  command: "{{ bin_dir }}/kubeadm version -o short"
+  register: kubeadm_output
+
+- name: sets kubeadm api version to v1alpha1
+  set_fact:
+    kubeadmConfig_api_version: v1alpha1
+  when: kubeadm_output.stdout is version('v1.11.0', '<')
+
+- name: sets kubeadm api version to v1alpha2
+  set_fact:
+    kubeadmConfig_api_version: v1alpha2
+  when:
+    - kubeadm_output.stdout is version('v1.11.0', '>=')
+    - kubeadm_output.stdout is version('v1.12.0', '<')
+
+- name: sets kubeadm api version to v1alpha3
+  set_fact:
+    kubeadmConfig_api_version: v1alpha3
+  when:
+    - kubeadm_output.stdout is version('v1.12.0', '>=')
+    - kubeadm_output.stdout is version('v1.13.0', '<')
+
+- name: sets kubeadm api version to v1beta1
+  set_fact:
+    kubeadmConfig_api_version: v1beta1
+  when: kubeadm_output.stdout is version('v1.13.0', '>=')
+
+- name: kubeadm | Create kubeadm config
+  template:
+    src: "kubeadm-config.{{ kubeadmConfig_api_version }}.yaml.j2"
+    dest: "{{ kube_config_dir }}/kubeadm-config.yaml"
diff --git a/roles/kubernetes/master/tasks/pre-upgrade.yml b/roles/kubernetes/master/tasks/pre-upgrade.yml
index 56e57b015d98eb1270d536c20d430889bf21f15d..7a36ebc8953cc3f6bd3b9cbcb2cb988667164d39 100644
--- a/roles/kubernetes/master/tasks/pre-upgrade.yml
+++ b/roles/kubernetes/master/tasks/pre-upgrade.yml
@@ -33,4 +33,4 @@
   register: remove_master_container
   retries: 4
   until: remove_master_container.rc == 0
-  delay: 5
\ No newline at end of file
+  delay: 5
diff --git a/upgrade-cluster.yml b/upgrade-cluster.yml
index 2823f050d7c4597cbdb5a598e7ca6cb3ff3fa298..e542cc80090c3c03ef83092fa9a815b7c2857c0d 100644
--- a/upgrade-cluster.yml
+++ b/upgrade-cluster.yml
@@ -72,7 +72,7 @@
     - { role: kubespray-defaults}
     - { role: upgrade/pre-upgrade, tags: pre-upgrade }
     - { role: kubernetes/node, tags: node }
-    - { role: kubernetes/master, tags: master }
+    - { role: kubernetes/master, tags: master, upgrade_cluster_setup: true }
     - { role: kubernetes/client, tags: client }
     - { role: kubernetes-apps/cluster_roles, tags: cluster-roles }
     - { role: upgrade/post-upgrade, tags: post-upgrade }