diff --git a/roles/kubespray_defaults/defaults/main/main.yml b/roles/kubespray_defaults/defaults/main/main.yml index 0bd09c279..eb9171119 100644 --- a/roles/kubespray_defaults/defaults/main/main.yml +++ b/roles/kubespray_defaults/defaults/main/main.yml @@ -241,9 +241,6 @@ cilium_identity_allocation_mode: crd # https://docs.cilium.io/en/stable/concepts/networking/ipam/ cilium_ipam_mode: cluster-pool -# Determines if calico_rr group exists -peer_with_calico_rr: "{{ 'calico_rr' in groups and groups['calico_rr'] | length > 0 }}" - # Choose data store type for calico: "etcd" or "kdd" (kubernetes datastore) calico_datastore: "kdd" diff --git a/roles/network_plugin/calico/tasks/install.yml b/roles/network_plugin/calico/tasks/install.yml index 8946aba2b..d2992f35e 100644 --- a/roles/network_plugin/calico/tasks/install.yml +++ b/roles/network_plugin/calico/tasks/install.yml @@ -191,44 +191,36 @@ ignore_errors: true changed_when: false - - name: Calico | Set kubespray calico network pool - set_fact: - _calico_pool: > - { - "kind": "IPPool", - "apiVersion": "projectcalico.org/v3", - "metadata": { - "name": "{{ calico_pool_name }}", - }, - "spec": { - "blockSize": {{ calico_pool_blocksize }}, - "cidr": "{{ calico_pool_cidr | default(kube_pods_subnet) }}", - "ipipMode": "{{ calico_ipip_mode }}", - "vxlanMode": "{{ calico_vxlan_mode }}", - "natOutgoing": {{ nat_outgoing | default(false) }} - } - } - - - name: Calico | Process calico network pool - when: - - _calico_pool_cmd is success - block: - - name: Calico | Get current calico network pool blocksize - set_fact: - _calico_blocksize: > - { - "spec": { - "blockSize": {{ (_calico_pool_cmd.stdout | from_json).spec.blockSize }} - } - } - - name: Calico | Merge calico network pool - set_fact: - _calico_pool: "{{ _calico_pool_cmd.stdout | from_json | combine(_calico_pool, _calico_blocksize, recursive=True) }}" - - name: Calico | Configure calico network pool + vars: + _calico_blocksize: "{{ {'spec': {'blockSize': (_calico_pool_cmd.stdout | from_json).spec.blockSize } } }}" + # We need to specify the dict inside jinja because otherwhise the blockSize can become a string + # instead of a int and no amount of | int makes it back into and integer + # TODO: use a normal yaml dict after upgrading to ansible-core 2.19, where the issue does not exist + _calico_pool: + kind: "IPPool" + apiVersion: "projectcalico.org/v3" + metadata: + name: "{{ calico_pool_name }}" + spec: + blockSize: "{{ calico_pool_blocksize }}" + cidr: "{{ calico_pool_cidr | default(kube_pods_subnet) }}" + ipipMode: "{{ calico_ipip_mode }}" + vxlanMode: "{{ calico_vxlan_mode }}" + natOutgoing: "{{ nat_outgoing | default(false) }}" + _calico_pool_merged: "{{ ( + (_calico_pool_cmd.stdout | from_json) + if _calico_pool_cmd is success else {} + ) + | combine( + _calico_pool, + _calico_blocksize if _calico_pool_cmd is success else {}, + recursive=True) }}" + # override order is current state < config < blocksize + # because blocksize is immutable, so we always reuse it command: cmd: "{{ bin_dir }}/calicoctl.sh apply -f -" - stdin: "{{ _calico_pool is string | ternary(_calico_pool, _calico_pool | to_json) }}" + stdin: "{{ _calico_pool_merged | to_json }}" changed_when: false - name: Calico | Configure Calico IPv6 Pool @@ -242,66 +234,38 @@ ignore_errors: true changed_when: false - - name: Calico | Set kubespray calico network pool - set_fact: - _calico_pool_ipv6: > - { - "kind": "IPPool", - "apiVersion": "projectcalico.org/v3", - "metadata": { - "name": "{{ calico_pool_name }}-ipv6", - }, - "spec": { - "blockSize": {{ calico_pool_blocksize_ipv6 }}, - "cidr": "{{ calico_pool_cidr_ipv6 | default(kube_pods_subnet_ipv6) }}", - "ipipMode": "{{ calico_ipip_mode_ipv6 }}", - "vxlanMode": "{{ calico_vxlan_mode_ipv6 }}", - "natOutgoing": {{ nat_outgoing_ipv6 | default(false) }} - } - } - - - name: Calico | Process calico ipv6 network pool - when: - - _calico_pool_ipv6_cmd is success - block: - - name: Calico | Get current calico ipv6 network pool blocksize - set_fact: - _calico_blocksize_ipv6: > - { - "spec": { - "blockSize": {{ (_calico_pool_ipv6_cmd.stdout | from_json).spec.blockSize }} - } - } - - name: Calico | Merge calico ipv6 network pool - set_fact: - _calico_pool_ipv6: "{{ _calico_pool_ipv6_cmd.stdout | from_json | combine(_calico_pool_ipv6, _calico_blocksize_ipv6, recursive=True) }}" - - - name: Calico | Configure calico ipv6 network pool + - name: Calico | Configure calico IPv6 network pool + vars: + _calico_blocksize_ipv6: "{{ {'spec': {'blockSize': (_calico_pool_ipv6_cmd.stdout | from_json).spec.blockSize } } }}" + # We need to specify the dict inside jinja because otherwhise the blockSize can become a string + # instead of a int and no amount of | int makes it back into and integer + # TODO: use a normal yaml dict after upgrading to ansible-core 2.19, where the issue does not exist + _calico_pool_ipv6: + kind: "IPPool" + apiVersion: "projectcalico.org/v3" + metadata: + name: "{{ calico_pool_name }}-ipv6" + spec: + blockSize: "{{ calico_pool_blocksize_ipv6 }}" + cidr: "{{ calico_pool_cidr_ipv6 | default(kube_pods_subnet_ipv6) }}" + ipipMode: "{{ calico_ipip_mode_ipv6 }}" + vxlanMode: "{{ calico_vxlan_mode_ipv6 }}" + natOutgoing: "{{ nat_outgoing_ipv6 | default(false) }}" + _calico_pool_merged_ipv6: "{{ ( + (_calico_pool_ipv6_cmd.stdout | from_json) + if _calico_pool_ipv6_cmd is success else {} + ) + | combine( + _calico_pool_ipv6, + _calico_blocksize_ipv6 if _calico_pool_ipv6_cmd is success else {}, + recursive=True) }}" + # override order is current state < config < blocksize + # because blocksize is immutable, so we always reuse it command: cmd: "{{ bin_dir }}/calicoctl.sh apply -f -" - stdin: "{{ _calico_pool_ipv6 is string | ternary(_calico_pool_ipv6, _calico_pool_ipv6 | to_json) }}" + stdin: "{{ _calico_pool_merged_ipv6 | to_json }}" changed_when: false -- name: Populate Service External IPs - set_fact: - _service_external_ips: "{{ _service_external_ips | default([]) + [{'cidr': item}] }}" - with_items: "{{ calico_advertise_service_external_ips }}" - run_once: true - -- name: Populate Service LoadBalancer IPs - set_fact: - _service_loadbalancer_ips: "{{ _service_loadbalancer_ips | default([]) + [{'cidr': item}] }}" - with_items: "{{ calico_advertise_service_loadbalancer_ips }}" - run_once: true - -- name: "Determine nodeToNodeMesh needed state" - set_fact: - nodeToNodeMeshEnabled: "false" - when: - - peer_with_router | default(false) or peer_with_calico_rr | default(false) - - ('k8s_cluster' in group_names) - run_once: true - - name: Calico | Configure Calico BGP when: - inventory_hostname == groups['kube_control_plane'][0] @@ -312,46 +276,40 @@ ignore_errors: true changed_when: false - - name: Calico | Set kubespray BGP Configuration - set_fact: - # noqa: jinja[spacing] - _bgp_config: > - { - "kind": "BGPConfiguration", - "apiVersion": "projectcalico.org/v3", - "metadata": { - "name": "default", - }, - "spec": { - "listenPort": {{ calico_bgp_listen_port }}, - "logSeverityScreen": "Info", - {% if not calico_no_global_as_num | default(false) %}"asNumber": {{ global_as_num }},{% endif %} - "nodeToNodeMeshEnabled": {{ nodeToNodeMeshEnabled | default('true') }} , - {% if calico_advertise_cluster_ips | default(false) %} - "serviceClusterIPs": - {%- if ipv4_stack and ipv6_stack-%} - [{"cidr": "{{ kube_service_addresses }}", "cidr": "{{ kube_service_addresses_ipv6 }}"}], - {%- elif ipv6_stack-%} - [{"cidr": "{{ kube_service_addresses_ipv6 }}"}], - {%- else -%} - [{"cidr": "{{ kube_service_addresses }}"}], - {%- endif -%} - {% endif %} - {% if calico_advertise_service_loadbalancer_ips | length > 0 %}"serviceLoadBalancerIPs": {{ _service_loadbalancer_ips }},{% endif %} - "serviceExternalIPs": {{ _service_external_ips | default([]) }} - } - } - - - name: Calico | Process BGP Configuration - set_fact: - _bgp_config: "{{ _bgp_config_cmd.stdout | from_json | combine(_bgp_config, recursive=True) }}" - when: - - _bgp_config_cmd is success - - name: Calico | Set up BGP Configuration + vars: + _service_ips: + - "{{ kube_service_addresses if ipv4_stack else '' }}" + - "{{ kube_service_addresses_ipv6 if ipv6_stack else '' }}" + _cluster_ips: + spec: + serviceClusterIPs: "{{ _service_ips | select | map('community.general.dict_kv', 'cidr') }}" + _lb_ips: + spec: + serviceLoadBalancerIPs: "{{ calico_advertise_service_loadbalancer_ips | map('community.general.dict_kv', 'cidr') }}" + _as_num: + spec: + asNumber: "{{ global_as_num }}" + _bgp_config_base: + kind: "BGPConfiguration" + apiVersion: "projectcalico.org/v3" + metadata: + name: "default" + spec: + listenPort: "{{ calico_bgp_listen_port }}" + logSeverityScreen: "Info" + nodeToNodeMeshEnabled: "{{ not (peer_with_router or peer_with_calico_rr) }}" + serviceExternalIPs: "{{ calico_advertise_service_external_ips | map('community.general.dict_kv', 'cidr') }}" + _bgp_config_merged: "{{ ((_bgp_config_cmd.stdout | from_json) if _bgp_config_cmd is success else {}) + | combine(_bgp_config_base, + _cluster_ips if calico_advertise_cluster_ips else {}, + _lb_ips if calico_advertise_service_loadbalancer_ips != [] else {}, + _as_num if not calico_no_global_as_num else {}, + recursive=True) + }}" command: cmd: "{{ bin_dir }}/calicoctl.sh apply -f -" - stdin: "{{ _bgp_config is string | ternary(_bgp_config, _bgp_config | to_json) }}" + stdin: "{{ _bgp_config_merged | to_json }}" changed_when: false - name: Calico | Create calico manifests @@ -477,9 +435,9 @@ - name: Calico | Peer with Calico Route Reflector include_tasks: peer_with_calico_rr.yml when: - - peer_with_calico_rr | default(false) + - peer_with_calico_rr - name: Calico | Peer with the router include_tasks: peer_with_router.yml when: - - peer_with_router | default(false) + - peer_with_router diff --git a/roles/network_plugin/calico_defaults/defaults/main.yml b/roles/network_plugin/calico_defaults/defaults/main.yml index bade3978a..3ab5cf933 100644 --- a/roles/network_plugin/calico_defaults/defaults/main.yml +++ b/roles/network_plugin/calico_defaults/defaults/main.yml @@ -32,11 +32,18 @@ calico_cert_dir: /etc/calico/certs # Global as_num (/calico/bgp/v1/global/as_num) global_as_num: "64512" +calico_no_global_as_num: false +# TODO : deprecate and use undef() or another invalid value in global_as_num for the same meaning +peer_with_router: false +peer_with_calico_rr: "{{ groups.get('calico_rr', []) != [] }}" + # You can set MTU value here. If left undefined or empty, it will # not be specified in calico CNI config, so Calico will use built-in # defaults. The value should be a number, not a string. # calico_mtu: 1500 +calico_advertise_cluster_ips: false + # Advertise Service External IPs calico_advertise_service_external_ips: []