diff --git a/roles/kubernetes-apps/network_plugin/calico/tasks/main.yml b/roles/kubernetes-apps/network_plugin/calico/tasks/main.yml
index 013d3b056749a62fc00296a69e24adb987e06f1b..e4215ed62011052352759ab28b83a67486064a30 100644
--- a/roles/kubernetes-apps/network_plugin/calico/tasks/main.yml
+++ b/roles/kubernetes-apps/network_plugin/calico/tasks/main.yml
@@ -16,4 +16,5 @@
   shell: "{{ bin_dir }}/calico-upgrade complete --no-prompts --apiconfigv1 /etc/calico/etcdv2.yml --apiconfigv3 /etc/calico/etcdv3.yml"
   when:
     - inventory_hostname == groups['kube-master'][0]
+    - calico_upgrade_enabled|default(True)
     - calico_upgrade_needed|default(False)
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index e5a287d2c80483a878d9447fe462f0f36b5b667f..970d7eecfdc5970e5dc748442450dfe75e2b7fbf 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -100,6 +100,9 @@ kube_network_plugin: calico
 # Determines if calico-rr group exists
 peer_with_calico_rr: "{{ 'calico-rr' in groups and groups['calico-rr']|length > 0 }}"
 
+# Set to false to disable calico-upgrade
+calico_upgrade_enabled: true
+
 # Kubernetes internal network for services, unused block of space.
 kube_service_addresses: 10.233.0.0/18
 
diff --git a/roles/network_plugin/calico/defaults/main.yml b/roles/network_plugin/calico/defaults/main.yml
index e65d569ed3ff0f9fe21417590062e65da923794b..e9f3c70a72e5e18e266b0606fe4325dab54e9793 100644
--- a/roles/network_plugin/calico/defaults/main.yml
+++ b/roles/network_plugin/calico/defaults/main.yml
@@ -41,6 +41,7 @@ calico_felix_prometheusgometricsenabled: "true"
 calico_felix_prometheusprocessmetricsenabled: "true"
 
 ### check latest version https://github.com/projectcalico/calico-upgrade/releases
+calico_upgrade_enabled: true
 calico_upgrade_version: v1.0.5
 
 # Should calico ignore kernel's RPF check setting,
@@ -56,4 +57,4 @@ calico_node_ignorelooserpf: false
 calico_baremetal_nodename: "{{ inventory_hostname }}"
 
 ### do not enable this, this is detected in scope of tasks, this is just a default value
-calico_upgrade_needed: false
\ No newline at end of file
+calico_upgrade_needed: false
diff --git a/roles/network_plugin/calico/tasks/install.yml b/roles/network_plugin/calico/tasks/install.yml
index 67eaec0fd113f8c8e7cdd0122a77f0dad47844f7..94cbbde5f4bf861733dded4aacd1a15103acfd0e 100644
--- a/roles/network_plugin/calico/tasks/install.yml
+++ b/roles/network_plugin/calico/tasks/install.yml
@@ -147,9 +147,28 @@
   with_items:
     - "{{ peers|default([]) }}"
   when:
+    - calico_version_on_server.stdout|version_compare('v3.0.0', '>') or calico_upgrade_enabled
     - peer_with_router|default(false)
     - inventory_hostname in groups['k8s-cluster']
 
+- name: Calico | Configure peering with router(s) (legacy)
+  shell: >
+   echo '{
+   "kind": "bgpPeer",
+   "spec": {"asNumber": "{{ item.as }}"},
+   "apiVersion": "v1",
+   "metadata": {"node": "{{ inventory_hostname }}", "scope": "node", "peerIP": "{{ item.router_id }}"}
+   }'
+   | {{ bin_dir }}/calicoctl create --skip-exists -f -
+  retries: 4
+  delay: "{{ retry_stagger | random + 3 }}"
+  with_items: "{{ peers|default([]) }}"
+  when:
+   - calico_version_on_server.stdout|version_compare('v3.0.0', '<')
+   - not calico_upgrade_enabled
+   - peer_with_router|default(false)
+   - inventory_hostname in groups['k8s-cluster']
+
 - name: Calico | Configure peering with route reflectors
   shell: >
    echo '{
@@ -169,9 +188,31 @@
   with_items:
     - "{{ groups['calico-rr'] | default([]) }}"
   when:
-    - (peer_with_calico_rr|default(false)
+    - calico_version_on_server.stdout|version_compare('v3.0.0', '>') or calico_upgrade_enabled
+    - peer_with_calico_rr|default(false)
     - inventory_hostname in groups['k8s-cluster']
-    - hostvars[item]['cluster_id'] == cluster_id)
+    - hostvars[item]['cluster_id'] == cluster_id
+
+- name: Calico | Configure peering with route reflectors (legacy)
+  shell: >
+   echo '{
+   "kind": "bgpPeer",
+   "spec": {"asNumber": "{{ local_as | default(global_as_num)}}"},
+   "apiVersion": "v1",
+   "metadata": {"node": "{{ inventory_hostname }}",
+     "scope": "node",
+     "peerIP": "{{ hostvars[item]["calico_rr_ip"]|default(hostvars[item]["ip"])|default(hostvars[item]["ansible_default_ipv4"]["address"]) }}"}
+   }'
+   | {{ bin_dir }}/calicoctl create --skip-exists -f -
+  retries: 4
+  delay: "{{ retry_stagger | random + 3 }}"
+  with_items: "{{ groups['calico-rr'] | default([]) }}"
+  when:
+   - calico_version_on_server.stdout|version_compare('v3.0.0', '<')
+   - not calico_upgrade_enabled
+   - peer_with_calico_rr|default(false)
+   - hostvars[item]['cluster_id'] == cluster_id
+
 
 - name: Calico | Create calico manifests
   template:
diff --git a/roles/network_plugin/calico/tasks/main.yml b/roles/network_plugin/calico/tasks/main.yml
index 72d8e3e11875f63c026373b06df985d9810de009..fefd8a7ff4c987ce253bb244ecac330258e0ad88 100644
--- a/roles/network_plugin/calico/tasks/main.yml
+++ b/roles/network_plugin/calico/tasks/main.yml
@@ -5,6 +5,7 @@
 
 - include_tasks: upgrade.yml
   when:
+    - calico_upgrade_enabled
     - calico_upgrade_needed
   run_once: yes
   delegate_to: "{{ groups['kube-master'][0] }}"