--- - name: Deploy Calico to cluster when: ansible_hostname == hostvars[groups[group_name_master | default('master')][0]]['ansible_hostname'] run_once: true block: - name: Create manifests directory on first master ansible.builtin.file: path: /tmp/k3s state: directory owner: root group: root mode: "0755" - name: "Download to first master: Calico CRD bundle for {{ calico_tag }}" ansible.builtin.get_url: url: https://raw.githubusercontent.com/projectcalico/calico/{{ calico_tag }}/manifests/v1_crd_projectcalico_org.yaml # noqa yaml[line-length] dest: /tmp/k3s/v1_crd_projectcalico_org.yaml owner: root group: root mode: "0755" register: calico_crd_download retries: "{{ download_retries }}" delay: "{{ download_delay }}" until: calico_crd_download is succeeded - name: "Download to first master: manifest for Tigera Operator and Calico CRDs" ansible.builtin.get_url: url: https://raw.githubusercontent.com/projectcalico/calico/{{ calico_tag }}/manifests/tigera-operator.yaml dest: /tmp/k3s/tigera-operator.yaml owner: root group: root mode: "0755" register: tigera_operator_download retries: "{{ download_retries }}" delay: "{{ download_delay }}" until: tigera_operator_download is succeeded - name: Apply Calico CRD bundle with server-side apply ansible.builtin.command: >- {{ k3s_kubectl_binary | default('k3s kubectl') }} apply --server-side --force-conflicts -f /tmp/k3s/v1_crd_projectcalico_org.yaml register: apply_crds changed_when: >- 'created' in apply_crds.stdout or 'configured' in apply_crds.stdout or 'applied' in apply_crds.stdout failed_when: apply_crds.rc != 0 - name: Apply Tigera Operator manifest idempotently with server-side apply ansible.builtin.command: >- {{ k3s_kubectl_binary | default('k3s kubectl') }} apply --server-side --force-conflicts -f /tmp/k3s/tigera-operator.yaml register: apply_operator changed_when: >- 'created' in apply_operator.stdout or 'configured' in apply_operator.stdout or 'applied' in apply_operator.stdout failed_when: apply_operator.rc != 0 - name: Wait for Tigera Operator and managed CRDs to become available ansible.builtin.command: >- {{ k3s_kubectl_binary | default('k3s kubectl') }} wait {{ item.type }}/{{ item.name }} {% if item.namespace is defined %}--namespace='{{ item.namespace }}'{% endif %} --for=condition={{ item.condition }} --timeout=30s register: tigera_result changed_when: false until: tigera_result is succeeded retries: 7 delay: 7 with_items: - { name: tigera-operator, type: deployment, namespace: tigera-operator, condition: Available=True } - { name: installations.operator.tigera.io, type: crd, condition: Established } - { name: apiservers.operator.tigera.io, type: crd, condition: Established } loop_control: label: "{{ item.type }}/{{ item.name }}" - name: Copy Calico custom resources manifest to first master ansible.builtin.template: src: calico.crs.j2 dest: /tmp/k3s/custom-resources.yaml owner: root group: root mode: "0755" - name: Apply Calico custom resources ansible.builtin.command: >- {{ k3s_kubectl_binary | default('k3s kubectl') }} apply -f /tmp/k3s/custom-resources.yaml register: apply_cr changed_when: >- 'configured' in apply_cr.stdout or 'created' in apply_cr.stdout or 'unchanged' in apply_cr.stdout failed_when: apply_cr.rc != 0 - name: Wait for Calico system resources to be available ansible.builtin.command: >- {% if item.type == 'daemonset' %} {{ k3s_kubectl_binary | default('k3s kubectl') }} wait pods --namespace='{{ item.namespace }}' --selector={{ item.selector }} --for=condition=Ready {% else %} {{ k3s_kubectl_binary | default('k3s kubectl') }} wait {{ item.type }}/{{ item.name }} --namespace='{{ item.namespace }}' --for=condition=Available {% endif %} --timeout=30s register: cr_result changed_when: false until: cr_result is succeeded retries: 60 delay: 10 with_items: - { name: calico-typha, type: deployment, namespace: calico-system } - { name: calico-kube-controllers, type: deployment, namespace: calico-system } - name: csi-node-driver type: daemonset selector: k8s-app=csi-node-driver namespace: calico-system - name: calico-node type: daemonset selector: k8s-app=calico-node namespace: calico-system loop_control: label: "{{ item.type }}/{{ item.name }}" # The Calico API server is an optional add-on for managing Calico policy via # kubectl (the projectcalico.org/v3 Kubernetes API). It is not required for # Calico CNI data plane operation and does not reconcile on K3s with recent # Calico releases, so it is treated as best-effort here. - name: Wait for the optional Calico API server (best effort) ansible.builtin.command: >- {{ k3s_kubectl_binary | default('k3s kubectl') }} wait deployment/calico-apiserver --namespace=calico-apiserver --for=condition=Available --timeout=30s register: cr_apiserver changed_when: false until: cr_apiserver is succeeded retries: 30 delay: 10 ignore_errors: true - name: Verify Calico TigeraStatus reports Available ansible.builtin.command: >- {{ k3s_kubectl_binary | default('k3s kubectl') }} get tigerastatus {{ item }} -o jsonpath='{.status.conditions[?(@.type=="Available")].status}' register: tigera_status changed_when: false until: tigera_status.stdout | trim == 'True' retries: 30 delay: 7 failed_when: tigera_status.rc != 0 or (tigera_status.stdout | trim) != 'True' with_items: - calico loop_control: label: "tigerastatus/{{ item }}" - name: Patch Felix configuration for eBPF mode ansible.builtin.command: cmd: > {{ k3s_kubectl_binary | default('k3s kubectl') }} patch felixconfiguration default --type='merge' --patch='{"spec": {"bpfKubeProxyIptablesCleanupEnabled": false}}' register: patch_result changed_when: "'felixconfiguration.projectcalico.org/default patched' in patch_result.stdout" failed_when: "'Error' in patch_result.stderr" when: calico_ebpf