> ## Documentation Index
> Fetch the complete documentation index at: https://docs.siderolabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Calico CNI

> In this guide you will learn how to set up Calico CNI on Talos in two modes: eBPF and NFTables.

export const k8s_release = '1.36.0';

This documentation is designed to get you up and running with Talos and Calico CNI. Since both Calico and Talos support multiple networking technologies, you will learn how to run your environment with both the [Calico eBPF dataplane](https://docs.tigera.io/calico/latest/operations/ebpf/enabling-ebpf) and [NFTables](https://docs.tigera.io/calico/latest/getting-started/kubernetes/nftables). Optionally, you can also enable Calico's network [observability stack](https://docs.tigera.io/calico/latest/observability/) to gain insights into your cluster networking and policy behavior.

## Configuring Talos

To install Calico, you first need to disable the default CNI. This can be done by applying a patch file during cluster creation.

```bash theme={null}
cat <<EOF > patch.yaml
cluster:
  network:
    cni:
      name: none
EOF
```

After generating the patch file add the `--config-patch` argument to your `talosctl gen config`.

```bash theme={null}
talosctl gen config \
    my-cluster https://calico-talos.local:6443 \
    --config-patch @patch.yaml
```

### Installation using Omni

If you are using [Omni](https://www.siderolabs.com/platform/saas-for-kubernetes/), you can deploy Calico using the [manifest sync](../../omni/cluster-management/sync-kubernetes-manifests) feature in a cluster template.

**Step 1.** Download the Tigera operator manifest:

```bash theme={null}
curl -Lo tigera-operator.yaml https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/tigera-operator.yaml
```

**Step 2.** Create an `installation.yaml` file with your desired Calico configuration. Choose the dataplane that fits your use case:

<Tabs>
  <Tab title="NFTables">
    ```bash theme={null}
    cat <<EOF > installation.yaml
    apiVersion: operator.tigera.io/v1
    kind: Installation
    metadata:
      name: default
    spec:
      calicoNetwork:
        bgp: Disabled
        linuxDataplane: Nftables
        ipPools:
        - name: default-ipv4-ippool
          blockSize: 26
          cidr: 10.244.0.0/16
          encapsulation: VXLAN
          natOutgoing: Enabled
          nodeSelector: all()
      kubeletVolumePluginPath: None
    ---
    apiVersion: operator.tigera.io/v1
    kind: APIServer
    metadata:
      name: default
    EOF
    ```
  </Tab>

  <Tab title="eBPF">
    ```bash theme={null}
    cat <<EOF > installation.yaml
    apiVersion: crd.projectcalico.org/v1
    kind: FelixConfiguration
    metadata:
      name: default
    spec:
      cgroupV2Path: "/sys/fs/cgroup"
    ---
    apiVersion: operator.tigera.io/v1
    kind: Installation
    metadata:
      name: default
    spec:
      calicoNetwork:
        bgp: Disabled
        linuxDataplane: BPF
        bpfNetworkBootstrap: Enabled
        kubeProxyManagement: Enabled
        ipPools:
        - name: default-ipv4-ippool
          blockSize: 26
          cidr: 10.244.0.0/16
          encapsulation: VXLAN
          natOutgoing: Enabled
          nodeSelector: all()
      kubeletVolumePluginPath: None
    ---
    apiVersion: operator.tigera.io/v1
    kind: APIServer
    metadata:
      name: default
    EOF
    ```
  </Tab>
</Tabs>

**Step 3.** Reference both manifests in your Omni cluster template:

<CodeBlock lang="yaml">
  {`kind: Cluster\nname: my-cluster\nkubernetes:\n  version: ${k8s_release}\n  manifests:\n    - name: tigera-operator\n      file: tigera-operator.yaml\n      mode: one-time\n    - name: calico-installation\n      file: installation.yaml\n      mode: one-time\npatches:\n  - name: disable-default-cni\n    inline:\n      cluster:\n        network:\n          cni:\n            name: none\n...\n# Include machines for template`}
</CodeBlock>

**Step 4.** Apply the cluster template:

```bash theme={null}
omnictl cluster template sync --file cluster-template.yaml
```

Omni will wait until the Kubernetes API is available and the cluster is healthy before applying the manifests. See [Sync Kubernetes Manifests](../../omni/cluster-management/sync-kubernetes-manifests) for more details on manifest sync modes and status monitoring.

## Installing Tigera operator

Recommended way to install Calico is via `Tigera-operator` manifest. The operator will make sure that all Calico components are always up and running.

> **Note:** If you’d like to install Calico using Helm, check out the [Install using Helm documentation](https://docs.tigera.io/calico/latest/getting-started/kubernetes/helm).

**Step 1.** Install the latest Tigera operator.

```bash theme={null}
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/tigera-operator.yaml
```

### Step 2. Configure Calico networking

Calico has a pluggable dataplane architecture that lets you choose the networking technology based on your use case. You can configure the dataplane by setting the `linuxDataplane` key in the installation manifest.

> **Note**: To learn more about the available Calico configurations, check out the [Installation reference documentation](https://docs.tigera.io/calico/latest/reference/installation/api).

<Tabs>
  <Tab title="NFTables">
    Use the following command to run Calico with NFTables backend.

    ```bash theme={null}
    kubectl create -f -<<EOF
    # This section includes base Calico installation configuration.
    apiVersion: operator.tigera.io/v1
    kind: Installation
    metadata:
      name: default
    spec:
      calicoNetwork:
        bgp: Disabled
        linuxDataplane: Nftables
        ipPools:
        - name: default-ipv4-ippool
          blockSize: 26
          cidr: 10.244.0.0/16
          encapsulation: VXLAN
          natOutgoing: Enabled
          nodeSelector: all()
      kubeletVolumePluginPath: None
    ---
    apiVersion: operator.tigera.io/v1
    kind: APIServer
    metadata:
      name: default
    EOF
    ```
  </Tab>

  <Tab title="eBPF">
    By default, Calico uses the `/var` directory to mount cgroups. However, since this path is not writable in Talos Linux, you need to change it to `/sys/fs/cgroup`.

    Use the following command to update the cgroup mount path:

    ```bash theme={null}
    kubectl create -f -<<EOF
    apiVersion: crd.projectcalico.org/v1
    kind: FelixConfiguration
    metadata:
      name: default
    spec:
      cgroupV2Path: "/sys/fs/cgroup"
    EOF
    ```

    There are three values that we need to set for eBPF in the installation manifest

    1. `linuxDataplane` needs to be set to `BPF`.
    2. `bpfNetworkBootstrap` needs to be set to `Enabled`.
    3. kubeProxyManagement to `Enabled` so that the Tigera operator automatically disables the kube-proxy.

    Next, you have to configure Calico:

    ```bash theme={null}
    kubectl create -f -<<EOF
    apiVersion: operator.tigera.io/v1
    kind: Installation
    metadata:
      name: default
    spec:
      calicoNetwork:
        bgp: Disabled
        linuxDataplane: BPF
        bpfNetworkBootstrap: Enabled
        kubeProxyManagement: Enabled
        ipPools:
        - name: default-ipv4-ippool
          blockSize: 26
          cidr: 10.244.0.0/16
          encapsulation: VXLAN
          natOutgoing: Enabled
          nodeSelector: all()
      kubeletVolumePluginPath: None
    EOF
    ```
  </Tab>
</Tabs>

## Deploy Calico Whisker network observability stack

Use the following command to enable Calico observability stack:

```bash theme={null}
kubectl create -f -<<EOF
# Configures the Calico Goldmane flow aggregator.
apiVersion: operator.tigera.io/v1
kind: Goldmane
metadata:
  name: default
---
# Configures the Calico Whisker observability UI.
apiVersion: operator.tigera.io/v1
kind: Whisker
metadata:
  name: default
EOF
```

Use the following command to access Calico Whisker:

```bash theme={null}
kubectl port-forward -n calico-system service/whisker 8081:8081
```

Fire up a browser and point it to `localhost:8081` to observe your policies and network flows.

## Next steps

* Enable Calico Prometheus and Grafana integrations, click here to [learn more](https://docs.tigera.io/calico/latest/operations/monitor/).

## Considerations

**In eBPF mode**, if you cannot disable kube-proxy for any reason please make sure to adjust `BPFKubeProxyIptablesCleanupEnabled` to `false`.
This can be done with kubectl as follows:

```bash theme={null}
kubectl patch felixconfiguration default --patch='{"spec": {"bpfKubeProxyIptablesCleanupEnabled": false}}'
```
