Files
kubespray/roles/network_plugin/calico/tasks/install.yml
Max Gautier e4be213cf7 Disable podCIDR allocation from control-plane when using calico (#10639) (#10715)
* Disable control plane allocating podCIDR for nodes when using calico

Calico does not use the .spec.podCIDR field for its IP address
management.
Furthermore, it can false positives from the kube controller manager if
kube_network_node_prefix and calico_pool_blocksize are unaligned, which
is the case with the default shipped by kubespray.

If the subnets obtained from using kube_network_node_prefix are bigger,
this would result at some point in the control plane thinking it does
not have subnets left for a new node, while calico will work without
problems.

Explicitely set a default value of false for calico_ipam_host_local to
facilitate its use in templates.

* Don't default to kube_network_node_prefix for calico_pool_blocksize

They have different semantics: kube_network_node_prefix is intended to
be the size of the subnet for all pods on a node, while there can be
more than on calico block of the specified size (they are allocated on
demand).

Besides, this commit does not actually change anything, because the
current code is buggy: we don't ever default to
kube_network_node_prefix, since the variable is defined in the role
defaults.
2023-12-13 11:30:18 +01:00

480 lines
17 KiB
YAML

---
- name: Calico | Install Wireguard packages
package:
name: "{{ item }}"
state: present
with_items: "{{ calico_wireguard_packages }}"
register: calico_package_install
until: calico_package_install is succeeded
retries: 4
when: calico_wireguard_enabled
- name: Calico | Copy calicoctl binary from download dir
copy:
src: "{{ downloads.calicoctl.dest }}"
dest: "{{ bin_dir }}/calicoctl"
mode: 0755
remote_src: yes
- name: Calico | Create calico certs directory
file:
dest: "{{ calico_cert_dir }}"
state: directory
mode: 0750
owner: root
group: root
when: calico_datastore == "etcd"
- name: Calico | Link etcd certificates for calico-node
file:
src: "{{ etcd_cert_dir }}/{{ item.s }}"
dest: "{{ calico_cert_dir }}/{{ item.d }}"
state: hard
mode: 0640
force: yes
with_items:
- {s: "{{ kube_etcd_cacert_file }}", d: "ca_cert.crt"}
- {s: "{{ kube_etcd_cert_file }}", d: "cert.crt"}
- {s: "{{ kube_etcd_key_file }}", d: "key.pem"}
when: calico_datastore == "etcd"
- name: Calico | Generate typha certs
include_tasks: typha_certs.yml
when:
- typha_secure
- inventory_hostname == groups['kube_control_plane'][0]
- name: Calico | Generate apiserver certs
include_tasks: calico_apiserver_certs.yml
when:
- calico_apiserver_enabled
- inventory_hostname == groups['kube_control_plane'][0]
- name: Calico | Install calicoctl wrapper script
template:
src: "calicoctl.{{ calico_datastore }}.sh.j2"
dest: "{{ bin_dir }}/calicoctl.sh"
mode: 0755
owner: root
group: root
- name: Calico | wait for etcd
uri:
url: "{{ etcd_access_addresses.split(',') | first }}/health"
validate_certs: no
client_cert: "{{ calico_cert_dir }}/cert.crt"
client_key: "{{ calico_cert_dir }}/key.pem"
register: result
until: result.status == 200 or result.status == 401
retries: 10
delay: 5
run_once: true
when: calico_datastore == "etcd"
- name: Calico | Check if calico network pool has already been configured
# noqa risky-shell-pipe - grep will exit 1 if no match found
shell: >
{{ bin_dir }}/calicoctl.sh get ippool | grep -w "{{ calico_pool_cidr | default(kube_pods_subnet) }}" | wc -l
args:
executable: /bin/bash
register: calico_conf
retries: 4
until: calico_conf.rc == 0
delay: "{{ retry_stagger | random + 3 }}"
changed_when: false
when:
- inventory_hostname == groups['kube_control_plane'][0]
- name: Calico | Ensure that calico_pool_cidr is within kube_pods_subnet when defined
assert:
that: "[calico_pool_cidr] | ipaddr(kube_pods_subnet) | length == 1"
msg: "{{ calico_pool_cidr }} is not within or equal to {{ kube_pods_subnet }}"
when:
- inventory_hostname == groups['kube_control_plane'][0]
- 'calico_conf.stdout == "0"'
- calico_pool_cidr is defined
- name: Calico | Check if calico IPv6 network pool has already been configured
# noqa risky-shell-pipe - grep will exit 1 if no match found
shell: >
{{ bin_dir }}/calicoctl.sh get ippool | grep -w "{{ calico_pool_cidr_ipv6 | default(kube_pods_subnet_ipv6) }}" | wc -l
args:
executable: /bin/bash
register: calico_conf_ipv6
retries: 4
until: calico_conf_ipv6.rc == 0
delay: "{{ retry_stagger | random + 3 }}"
changed_when: false
when:
- inventory_hostname == groups['kube_control_plane'][0]
- enable_dual_stack_networks
- name: Calico | Ensure that calico_pool_cidr_ipv6 is within kube_pods_subnet_ipv6 when defined
assert:
that: "[calico_pool_cidr_ipv6] | ipaddr(kube_pods_subnet_ipv6) | length == 1"
msg: "{{ calico_pool_cidr_ipv6 }} is not within or equal to {{ kube_pods_subnet_ipv6 }}"
when:
- inventory_hostname == groups['kube_control_plane'][0]
- calico_conf_ipv6.stdout is defined and calico_conf_ipv6.stdout == "0"
- calico_pool_cidr_ipv6 is defined
- enable_dual_stack_networks
- name: Calico | kdd specific configuration
when:
- inventory_hostname in groups['kube_control_plane']
- calico_datastore == "kdd"
block:
- name: Calico | Check if extra directory is needed
stat:
path: "{{ local_release_dir }}/calico-{{ calico_version }}-kdd-crds/{{ 'kdd' if (calico_version is version('v3.22.3', '<')) else 'crd' }}"
register: kdd_path
- name: Calico | Set kdd path when calico < v3.22.3
set_fact:
calico_kdd_path: "{{ local_release_dir }}/calico-{{ calico_version }}-kdd-crds{{ '/kdd' if kdd_path.stat.exists is defined and kdd_path.stat.exists }}"
when:
- calico_version is version('v3.22.3', '<')
- name: Calico | Set kdd path when calico > v3.22.2
set_fact:
calico_kdd_path: "{{ local_release_dir }}/calico-{{ calico_version }}-kdd-crds{{ '/crd' if kdd_path.stat.exists is defined and kdd_path.stat.exists }}"
when:
- calico_version is version('v3.22.2', '>')
- name: Calico | Create calico manifests for kdd
assemble:
src: "{{ calico_kdd_path }}"
dest: "{{ kube_config_dir }}/kdd-crds.yml"
mode: 0644
delimiter: "---\n"
regexp: ".*\\.yaml"
remote_src: true
- name: Calico | Create Calico Kubernetes datastore resources
kube:
kubectl: "{{ bin_dir }}/kubectl"
filename: "{{ kube_config_dir }}/kdd-crds.yml"
state: "latest"
register: kubectl_result
until: kubectl_result is succeeded
retries: 5
when:
- inventory_hostname == groups['kube_control_plane'][0]
- name: Calico | Configure Felix
when:
- inventory_hostname == groups['kube_control_plane'][0]
block:
- name: Calico | Get existing FelixConfiguration
command: "{{ bin_dir }}/calicoctl.sh get felixconfig default -o json"
register: _felix_cmd
ignore_errors: True
changed_when: False
- name: Calico | Set kubespray FelixConfiguration
set_fact:
_felix_config: >
{
"kind": "FelixConfiguration",
"apiVersion": "projectcalico.org/v3",
"metadata": {
"name": "default",
},
"spec": {
"ipipEnabled": {{ calico_ipip_mode != 'Never' }},
"reportingInterval": "{{ calico_felix_reporting_interval }}",
"bpfLogLevel": "{{ calico_bpf_log_level }}",
"bpfEnabled": {{ calico_bpf_enabled | bool }},
"bpfExternalServiceMode": "{{ calico_bpf_service_mode }}",
"wireguardEnabled": {{ calico_wireguard_enabled | bool }},
"logSeverityScreen": "{{ calico_felix_log_severity_screen }}",
"vxlanEnabled": {{ calico_vxlan_mode != 'Never' }},
"featureDetectOverride": "{{ calico_feature_detect_override }}",
"floatingIPs": "{{ calico_felix_floating_ips }}"
}
}
- name: Calico | Process FelixConfiguration
set_fact:
_felix_config: "{{ _felix_cmd.stdout | from_json | combine(_felix_config, recursive=True) }}"
when:
- _felix_cmd is success
- name: Calico | Configure calico FelixConfiguration
command:
cmd: "{{ bin_dir }}/calicoctl.sh apply -f -"
stdin: "{{ _felix_config is string | ternary(_felix_config, _felix_config | to_json) }}"
changed_when: False
- name: Calico | Configure Calico IP Pool
when:
- inventory_hostname == groups['kube_control_plane'][0]
block:
- name: Calico | Get existing calico network pool
command: "{{ bin_dir }}/calicoctl.sh get ippool {{ calico_pool_name }} -o json"
register: _calico_pool_cmd
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
set_fact:
_calico_pool: "{{ _calico_pool_cmd.stdout | from_json | combine(_calico_pool, recursive=True) }}"
when:
- _calico_pool_cmd is success
- name: Calico | Configure calico network pool
command:
cmd: "{{ bin_dir }}/calicoctl.sh apply -f -"
stdin: "{{ _calico_pool is string | ternary(_calico_pool, _calico_pool | to_json) }}"
changed_when: False
- name: Calico | Configure Calico IPv6 Pool
when:
- inventory_hostname == groups['kube_control_plane'][0]
- enable_dual_stack_networks | bool
block:
- name: Calico | Get existing calico ipv6 network pool
command: "{{ bin_dir }}/calicoctl.sh get ippool {{ calico_pool_name }}-ipv6 -o json"
register: _calico_pool_ipv6_cmd
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
set_fact:
_calico_pool_ipv6: "{{ _calico_pool_ipv6_cmd.stdout | from_json | combine(_calico_pool_ipv6, recursive=True) }}"
when:
- _calico_pool_ipv6_cmd is success
- name: Calico | Configure calico ipv6 network pool
command:
cmd: "{{ bin_dir }}/calicoctl.sh apply -f -"
stdin: "{{ _calico_pool_ipv6 is string | ternary(_calico_pool_ipv6, _calico_pool_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: yes
- 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: yes
- name: "Determine nodeToNodeMesh needed state"
set_fact:
nodeToNodeMeshEnabled: "false"
when:
- peer_with_router | default(false) or peer_with_calico_rr | default(false)
- inventory_hostname in groups['k8s_cluster']
run_once: yes
- name: Calico | Configure Calico BGP
when:
- inventory_hostname == groups['kube_control_plane'][0]
block:
- name: Calico | Get existing BGP Configuration
command: "{{ bin_dir }}/calicoctl.sh get bgpconfig default -o json"
register: _bgp_config_cmd
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": [{"cidr": "{{ kube_service_addresses }}" } {{ ',{"cidr":"' + kube_service_addresses_ipv6 + '"}' if enable_dual_stack_networks else '' }}],{% 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
command:
cmd: "{{ bin_dir }}/calicoctl.sh apply -f -"
stdin: "{{ _bgp_config is string | ternary(_bgp_config, _bgp_config | to_json) }}"
changed_when: False
- name: Calico | Create calico manifests
template:
src: "{{ item.file }}.j2"
dest: "{{ kube_config_dir }}/{{ item.file }}"
mode: 0644
with_items:
- {name: calico-config, file: calico-config.yml, type: cm}
- {name: calico-node, file: calico-node.yml, type: ds}
- {name: calico, file: calico-node-sa.yml, type: sa}
- {name: calico, file: calico-cr.yml, type: clusterrole}
- {name: calico, file: calico-crb.yml, type: clusterrolebinding}
- {name: kubernetes-services-endpoint, file: kubernetes-services-endpoint.yml, type: cm }
register: calico_node_manifests
when:
- inventory_hostname in groups['kube_control_plane']
- rbac_enabled or item.type not in rbac_resources
- name: Calico | Create calico manifests for typha
template:
src: "{{ item.file }}.j2"
dest: "{{ kube_config_dir }}/{{ item.file }}"
mode: 0644
with_items:
- {name: calico, file: calico-typha.yml, type: typha}
register: calico_node_typha_manifest
when:
- inventory_hostname in groups['kube_control_plane']
- typha_enabled
- name: Calico | get calico apiserver caBundle
command: "{{ bin_dir }}/kubectl get secret -n calico-apiserver calico-apiserver-certs -o jsonpath='{.data.apiserver\\.crt}'"
changed_when: false
register: calico_apiserver_cabundle
when:
- inventory_hostname == groups['kube_control_plane'][0]
- calico_apiserver_enabled
- name: Calico | set calico apiserver caBundle fact
set_fact:
calico_apiserver_cabundle: "{{ calico_apiserver_cabundle.stdout }}"
when:
- inventory_hostname == groups['kube_control_plane'][0]
- calico_apiserver_enabled
- name: Calico | Create calico manifests for apiserver
template:
src: "{{ item.file }}.j2"
dest: "{{ kube_config_dir }}/{{ item.file }}"
mode: 0644
with_items:
- {name: calico, file: calico-apiserver.yml, type: calico-apiserver}
register: calico_apiserver_manifest
when:
- inventory_hostname in groups['kube_control_plane']
- calico_apiserver_enabled
- name: Start Calico resources
kube:
name: "{{ item.item.name }}"
namespace: "kube-system"
kubectl: "{{ bin_dir }}/kubectl"
resource: "{{ item.item.type }}"
filename: "{{ kube_config_dir }}/{{ item.item.file }}"
state: "latest"
with_items:
- "{{ calico_node_manifests.results }}"
- "{{ calico_node_typha_manifest.results }}"
when:
- inventory_hostname == groups['kube_control_plane'][0]
- not item is skipped
loop_control:
label: "{{ item.item.file }}"
- name: Start Calico apiserver resources
kube:
name: "{{ item.item.name }}"
namespace: "calico-apiserver"
kubectl: "{{ bin_dir }}/kubectl"
resource: "{{ item.item.type }}"
filename: "{{ kube_config_dir }}/{{ item.item.file }}"
state: "latest"
with_items:
- "{{ calico_apiserver_manifest.results }}"
when:
- inventory_hostname == groups['kube_control_plane'][0]
- not item is skipped
loop_control:
label: "{{ item.item.file }}"
- name: Wait for calico kubeconfig to be created
wait_for:
path: /etc/cni/net.d/calico-kubeconfig
timeout: "{{ calico_kubeconfig_wait_timeout }}"
when:
- inventory_hostname not in groups['kube_control_plane']
- calico_datastore == "kdd"
- name: Calico | Create Calico ipam manifests
template:
src: "{{ item.file }}.j2"
dest: "{{ kube_config_dir }}/{{ item.file }}"
mode: 0644
with_items:
- {name: calico, file: calico-ipamconfig.yml, type: ipam}
when:
- inventory_hostname in groups['kube_control_plane']
- calico_datastore == "kdd"
- name: Calico | Create ipamconfig resources
kube:
kubectl: "{{ bin_dir }}/kubectl"
filename: "{{ kube_config_dir }}/calico-ipamconfig.yml"
state: "latest"
register: resource_result
until: resource_result is succeeded
retries: 4
when:
- inventory_hostname == groups['kube_control_plane'][0]
- calico_datastore == "kdd"
- name: Calico | Peer with Calico Route Reflector
include_tasks: peer_with_calico_rr.yml
when:
- peer_with_calico_rr | default(false)
- name: Calico | Peer with the router
include_tasks: peer_with_router.yml
when:
- peer_with_router | default(false)