Skip to main content
Navigation
HomeTechnical ReferenceJournalGitHubGitHub
Sidebar — toggle document categories via the logo
Categories

RKE2 (Rancher Kubernetes Engine 2)

Overview​

RKE2 is Rancher's Kubernetes distribution, originally created to satisfy the security requirements of US federal customers under RKE Government. It ships a fully conformant upstream Kubernetes and runs every component as a systemd-managed process rather than as Docker containers. There is no Docker dependency: RKE2 bundles containerd and drives the kubelet directly.

The defining properties:

  • Systemd-native. The control plane is a set of static pods managed by the rke2-server service, while node services run under rke2-agent. There is no containerized control plane and no Docker socket.
  • Hardened by default. The default configuration already restricts anonymous API access, enables RBAC and NodeRestriction, and is close to the CIS benchmark. A profile: cis switch applies the full hardening set.
  • CIS and FIPS. FIPS 140-2/140-3 validated builds are published as separate binaries for regulated environments.
  • Edge and air-gapped ready. A single binary plus an image tarball can install a cluster with no internet access.
  • Packaged components. The CNI, CoreDNS, metrics-server, ingress, Traefik, and the Helm controller are all deployed automatically from the server's manifest directory.

Choose RKE2 when you need a conformance-verified, CIS-oriented distribution that is simple to operate and update. Choose kubeadm when you want to assemble the control plane yourself and control every component; choose a managed offering (EKS, GKE, AKS) when you do not want to operate the control plane or etcd at all.

Architecture​

RKE2 has two unit types, both installed from the same binary.

  • Server nodes run the control plane (kube-apiserver, kube-controller-manager, kube-scheduler) as static pods, plus etcd, the supervisor API, and the packaged components. A server also runs a full agent (kubelet and containerd) unless the agent is explicitly disabled.
  • Agent nodes run only kubelet, containerd, and kube-proxy. They register with a server through the supervisor and are not part of the control plane.

The supervisor API listens on port 9345 on every server. Agents and joining servers talk to it instead of the main API server (6443) so that a new node can authenticate with the shared token before it has a client certificate. Static control-plane pod manifests live under /var/lib/rancher/rke2/agent/pod-manifests/; the kubelet watches that directory and applies changes, which is why editing a file there restarts a control-plane component.

The directory /var/lib/rancher/rke2/server/manifests/ is an auto-deploy directory. Every YAML manifest placed there is applied by RKE2 at startup. This is how the packaged components are installed, and the same mechanism accepts a HelmChart custom resource (from the bundled Helm controller) and a HelmChartConfig to override its values.

Datastore options:

  • Embedded etcd (default). RKE2 manages an etcd cluster across server nodes and takes snapshots.
  • External datastore. MySQL, PostgreSQL, or an external etcd configured with datastore-endpoint.
  • SQLite. Available but not recommended for production. RKE2's default for a server is embedded etcd, not SQLite.

Packaged components deployed by default include the Canal CNI (flannel plus Calico policy), CoreDNS, metrics-server, the local-path provisioner, the Helm controller, and an ingress controller. The historical default ingress controller was ingress-nginx, which is being retired upstream; recent RKE2 releases are moving new clusters to Traefik. Do not assume the default for your version: check the release notes and select the ingress explicitly with the disable list plus your own manifests.

# Inspect the server's packaged manifests
ls /var/lib/rancher/rke2/server/manifests/

# Show the running static control-plane pods and their manifests
ls /var/lib/rancher/rke2/agent/pod-manifests/

Installation​

The installation script configures RKE2 as a systemd service. It detects the package manager (RPM versus tar) and downloads the release.

# Install as a server (default type)
curl -sfL https://get.rke2.io | sh -

# Install as an agent
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" sh -

The script is driven by environment variables:

VariablePurpose
INSTALL_RKE2_TYPEserver (default) or agent
INSTALL_RKE2_CHANNELRelease channel: stable (default), latest, testing
INSTALL_RKE2_VERSIONPin an exact version, e.g. v1.31.4+rke2r1
INSTALL_RKE2_METHODrpm on RPM systems, otherwise tar
INSTALL_RKE2_CHANNEL_URLAlternate channel endpoint, defaults to https://update.rke2.io/v1-release/channels
# Pin a specific version and channel
curl -sfL https://get.rke2.io | \
INSTALL_RKE2_CHANNEL="stable" \
INSTALL_RKE2_VERSION="v1.31.4+rke2r1" \
sh -

# Force the tar installation method
curl -sfL https://get.rke2.io | INSTALL_RKE2_METHOD="tar" sh -

Configuration lives in /etc/rancher/rke2/config.yaml and must be created manually. Additional fragments are read from /etc/rancher/rke2/config.yaml.d/*.yaml in alphabetical order.

# Create the config file before enabling the service
mkdir -p /etc/rancher/rke2
touch /etc/rancher/rke2/config.yaml

Air-gapped installation uses the same script with a local artifact path. Download the RKE2 tarball and the matching image bundle from the release page, then point INSTALL_RKE2_ARTIFACT_PATH at the directory containing them.

# airgap-install: place rke2.linux-amd64.tar.gz and
# rke2-images.linux-amd64.tar.zst in /tmp/rke2-artifacts first
INSTALL_RKE2_ARTIFACT_PATH=/tmp/rke2-artifacts \
INSTALL_RKE2_TYPE="server" sh install.sh

# Pre-load the image bundle so kubelet does not pull from the internet
mkdir -p /var/lib/rancher/rke2/agent/images/
cp /tmp/rke2-artifacts/rke2-images.linux-amd64.tar.zst \
/var/lib/rancher/rke2/agent/images/

Enable and start the service. A server must be started before agents can join it.

# Server node
systemctl enable --now rke2-server

# Agent node
systemctl enable --now rke2-agent

# Confirm the unit state
systemctl status rke2-server

Configuration reference​

Every configuration file key maps directly to a CLI flag: write-kubeconfig-mode in YAML becomes --write-kubeconfig-mode on the command line, repeatable flags become YAML lists, and booleans become true/false. CLI arguments override the config file, but for repeatable arguments the CLI value replaces the entire list.

# /etc/rancher/rke2/config.yaml (server)
token: "SUPER_SECRET_TOKEN"
write-kubeconfig-mode: "0644"
node-name: "rke2-server-1"
tls-san:
- "api.example.com"
- "10.0.0.10"
node-label:
- "role=control-plane"
- "topology.kubernetes.io/zone=eu-west-1a"
node-taint:
- "CriticalAddonsOnly=true:NoExecute"
cluster-cidr: "10.42.0.0/16"
service-cidr: "10.43.0.0/16"
cluster-dns: "10.43.0.10"
cni: "canal"
profile: "cis"
secrets-encryption: true
selinux: true
disable:
- "rke2-ingress-nginx"
kubelet-arg:
- "max-pods=250"
kube-apiserver-arg:
- "audit-log-path=/var/log/kubernetes/audit.log"

Key options:

  • token — shared secret used for node bootstrap, supervisor authentication, and encrypting snapshot secrets. Sensitive.
  • server — supervisor URL of an existing server, e.g. https://rke2-server-1:9345. Required on joining nodes.
  • node-name, node-label, node-taint — node identity, labels, and taints applied at registration.
  • tls-san — additional SANs added to the API server certificate, needed for load balancers and external DNS names.
  • cluster-cidr, service-cidr, cluster-dns — pod network, service network, and CoreDNS service IP. Must not overlap.
  • disable — list of packaged components to skip, e.g. rke2-ingress-nginx, rke2-traefik, rke2-metrics-server, rke2-coredns, rke2-canal.
  • cni — selects the CNI: canal (default), cilium, none, or a multus list such as multus,canal.
  • datastore-endpoint — external datastore URL. Supports mysql://, postgres://, etcd://, and sqlite://. Set alongside datastore-cafile, datastore-certfile, and datastore-keyfile for TLS.
  • write-kubeconfig-mode — permissions of the generated kubeconfig, commonly "0644" when non-root users must read it.
  • profile — hardening profile, cis or a versioned value such as cis-1.23. Enables the CIS-recommended component arguments.
  • secrets-encryption — enables encryption at rest for Secrets using the generated AES key.
  • selinux — enables SELinux labeling for pod containers, required on enforcing SELinux hosts.
  • kubelet-arg and kube-apiserver-arg — pass-through arguments to the kubelet and API server.
# Validate an on-disk config by printing the effective server arguments
rke2 server --help | grep -E "token|datastore|cni|profile"

# Run a one-off check with an override without editing the config
rke2 server --debug --config /etc/rancher/rke2/config.yaml

Node roles & cluster membership​

A single-server cluster is the simplest deployment: one rke2-server runs the control plane, etcd, and the agent. It is not highly available. For production, use three or five servers with embedded etcd and keep the server count odd so quorum is maintained.

RKE2 primarily defines two units, but a server's control-plane components can be split across nodes with disable-* flags, producing dedicated roles:

  • Dedicated etcd node: disable all control-plane components (disable-apiserver, disable-controller-manager, disable-scheduler).
  • Dedicated control-plane node: disable etcd (disable-etcd: true) and join an existing etcd node via server:.

A dedicated control-plane node cannot be the first server in a cluster; an etcd node must exist first. Roles can be added later by removing the disable-* keys and restarting.

# /etc/rancher/rke2/config.yaml — dedicated etcd node
disable-apiserver: true
disable-controller-manager: true
disable-scheduler: true
# Join an additional server to an existing etcd cluster
systemctl enable --now rke2-server
# config.yaml on the joining server:
# server: https://rke2-server-1:9345
# token: SUPER_SECRET_TOKEN

Agents are added by installing the agent type and pointing them at a server.

# /etc/rancher/rke2/config.yaml (agent)
server: https://rke2-server-1:9345
token: SUPER_SECRET_TOKEN
node-label:
- "workload=batch"
# Maintenance: stop new pods from scheduling, then evict
kubectl cordon rke2-agent-1
kubectl drain rke2-agent-1 --ignore-daemonsets --delete-emptydir-data

# Return the node to service
kubectl uncordon rke2-agent-1

# Remove a node from the cluster
kubectl delete node rke2-agent-1
# Then on the removed node, uninstall to clear local state
/usr/local/bin/rke2-uninstall.sh

kubectl access​

RKE2 writes a kubeconfig to /etc/rancher/rke2/rke2.yaml. Use it directly, copy it to a user's home directory, or export it for the session. The bundled kubectl is available as rke2 kubectl and as a binary under /var/lib/rancher/rke2/bin/.

# Use the server-generated kubeconfig
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
kubectl get nodes

# Copy for a non-root user
mkdir -p ~/.kube
sudo cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
sudo chown "$(id -u):$(id -g)" ~/.kube/config

# Use the bundled kubectl even if none is on PATH
/var/lib/rancher/rke2/bin/kubectl get pods -A
rke2 kubectl get nodes

# Make the kubeconfig world-readable at generation time (config.yaml)
# write-kubeconfig-mode: "0644"

The server address inside rke2.yaml is 127.0.0.1 by default. When accessing the cluster from a remote host, replace it with a reachable control-plane endpoint or the tls-san address.

# Rewrite the API server endpoint for remote access
sed -i 's/127.0.0.1:6443/rke2-server-1:6443/' ~/.kube/config

High availability & datastores​

An HA control plane with embedded etcd requires an odd number of servers: 3 tolerates one failure, 5 tolerates two. A server added to an existing cluster must be configured with server: and token: so it joins the etcd cluster.

# Confirm etcd cluster health and membership
kubectl -n kube-system exec -it etcd-rke2-server-1 -- \
etcdctl member list -w table

# Endpoint health from inside the etcd static pod
kubectl -n kube-system exec -it etcd-rke2-server-1 -- \
etcdctl endpoint health --cluster

External datastores are configured with datastore-endpoint and the TLS file options. With an external datastore, RKE2 does not manage etcd and snapshots are the database administrator's responsibility.

# /etc/rancher/rke2/config.yaml (external PostgreSQL)
datastore-endpoint: "postgres://rke2:password@db.example.com:5432/rke2?sslmode=require"
datastore-cafile: "/etc/rancher/rke2/db-ca.pem"

A broken etcd cluster can be collapsed back to a single-member cluster with a cluster reset. This discards cluster membership and is destructive if the remaining members are still healthy.

# Reset etcd membership without restoring data
rke2 server --cluster-reset

# RKE2 writes a guard flag to prevent accidental repeated resets
ls /var/lib/rancher/rke2/server/db/reset-flag

etcd snapshots & restore​

Snapshots apply to embedded etcd only. Scheduled snapshots run by default at 00:00 and 12:00 system time, retaining five, and are named etcd-snapshot-<node>-<timestamp>. On-demand snapshots have no retention policy and are named on-demand-<node>-<timestamp> unless --name is supplied.

# Take an on-demand snapshot
rke2 etcd-snapshot save

# Take a named on-demand snapshot
rke2 etcd-snapshot save --name before-upgrade

# Compress the snapshot on disk
rke2 etcd-snapshot save --etcd-snapshot-compress

# List snapshots on this node
rke2 etcd-snapshot list

# Delete specific snapshots
rke2 etcd-snapshot delete on-demand-rke2-server-1-1730308816

# Prune on-demand snapshots to the two most recent
rke2 etcd-snapshot prune --snapshot-retention 2

# Prune scheduled snapshots by name prefix using the retention flag
rke2 etcd-snapshot prune --name etcd-snapshot --etcd-snapshot-retention 3

Snapshot schedule and retention are configured on the server, either in config.yaml or as flags.

# /etc/rancher/rke2/config.yaml
etcd-snapshot-schedule-cron: "0 */6 * * *" # every six hours
etcd-snapshot-retention: 10 # keep ten snapshots
etcd-snapshot-dir: "/var/lib/rancher/rke2/server/db/snapshots"
etcd-snapshot-compress: true

S3 replication is enabled with the etcd-s3* configuration options. The server config flags are --etcd-s3, --etcd-s3-bucket, --etcd-s3-endpoint, --etcd-s3-region, --etcd-s3-access-key, --etcd-s3-secret-key, --etcd-s3-folder, and --etcd-s3-retention. The rke2 etcd-snapshot subcommand accepts the shorter --s3, --s3-bucket, and related aliases.

# /etc/rancher/rke2/config.yaml
etcd-s3: true
etcd-s3-bucket: "my-rke2-snapshots"
etcd-s3-endpoint: "s3.eu-west-1.amazonaws.com"
etcd-s3-region: "eu-west-1"
etcd-s3-folder: "prod"
etcd-s3-retention: 10

Snapshot secrets can be read from a Kubernetes Secret instead of being stored in the config file. Only etcd-s3 and etcd-s3-config-secret may be set when using this mode; any other S3 flag causes the Secret to be ignored.

# On-demand snapshot to S3
rke2 etcd-snapshot save \
--s3 --s3-bucket=my-rke2-snapshots \
--s3-access-key=ACCESS --s3-secret-key=SECRET

# View snapshots cluster-wide, not just on the local node
kubectl get etcdsnapshotfile
kubectl describe etcdsnapshotfile <name>

Restore stops the service, runs a cluster reset that also loads the snapshot, then restarts. On a multi-server cluster, the other servers must have their database directories removed before rejoining.

# 1. Stop RKE2 on the server
systemctl stop rke2-server

# 2. Restore the snapshot and collapse etcd to this member
rke2 server \
--cluster-reset \
--cluster-reset-restore-path=/var/lib/rancher/rke2/server/db/snapshots/on-demand-rke2-server-1-1730308816

# Wait for: "Managed etcd cluster membership has been reset,
# restart without --cluster-reset flag now."

# 3. Start normally
systemctl start rke2-server

# On other server nodes, discard stale etcd data before rejoining
rm -rf /var/lib/rancher/rke2/server/db/
systemctl restart rke2-server

When restoring to a different host, pass the original server token, because the snapshot is encrypted with a key derived from it.

rke2 server \
--cluster-reset \
--cluster-reset-restore-path=/path/to/snapshot \
--token=<ORIGINAL-TOKEN-FROM-/var/lib/rancher/rke2/server/token>

Snapshots contain the full datastore, cluster CA certificates, and private keys, and are only as protected as the filesystem and bucket holding them. Treat them as cluster credentials.

Upgrades​

RKE2 tracks Kubernetes release channels. The install script's INSTALL_RKE2_CHANNEL accepts stable, latest, and testing; the v1.xx versioned channels resolve to the latest patch of a minor line.

# Re-run the installer to fetch a new version, then restart the service
curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL="stable" sh -
systemctl restart rke2-server

# Pin an exact target version
curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION="v1.31.4+rke2r1" sh -
systemctl restart rke2-server

Upgrade servers one at a time and verify the API server and etcd health between nodes, then upgrade agents. With embedded etcd, never restart all servers simultaneously.

The supported large-scale pattern uses Rancher's system-upgrade-controller with a Plan custom resource. RKE2 publishes rke2-upgrade (also invoked by the upgrade job) which wraps the version switch.

# Plan to roll a server node to a target RKE2 version
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: rke2-server
namespace: system-upgrade
spec:
concurrency: 1
serviceAccountName: system-upgrade
channel: https://update.rke2.io/v1-release/channels/stable
nodeSelector:
matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: Exists
upgrade:
image: rancher/rke2-upgrade

Caveats: Kubernetes supports only one minor-version jump at a time, so upgrade one minor at a time. Downgrades are not supported — the datastore schema is migrated forward. Restore from an etcd snapshot is the rollback path, and the snapshot must have been taken before the upgrade.

# Confirm versions across the cluster after an upgrade
kubectl get nodes -o wide
kubectl version

Networking & CNI​

RKE2 deploys a CNI automatically. The default is Canal, which combines flannel for the pod overlay with Calico's policy engine for NetworkPolicy enforcement. Cilium is selectable when eBPF-based networking is required and is installed as a packaged manifest. Multus can be layered in front of another CNI to provide multiple network interfaces.

# /etc/rancher/rke2/config.yaml
cni: "canal" # default; flannel overlay + Calico policy
# cni: "cilium" # eBPF-based networking
# cni: "multus,canal" # multus with canal as the primary network
# cni: "none" # no CNI; install your own

Pod and service CIDRs must not overlap with the host network or with each other. Changing them after installation requires re-deploying the CNI and is effectively a rebuild.

cluster-cidr: "10.42.0.0/16"
service-cidr: "10.43.0.0/16"
cluster-dns: "10.43.0.10"

Ingress and other add-ons are packaged components installed from the server manifest directory. They can be disabled with the disable list and replaced with your own manifests in /var/lib/rancher/rke2/server/manifests/.

# Check the CNI and kube-proxy pods
kubectl get pods -n kube-system | grep -E "canal|cilium|kube-proxy"

# List services and NodePorts in use
kubectl get svc -A
kubectl get svc -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.type}{"\t"}{.spec.ports[*].nodePort}{"\n"}{end}'

# Verify CoreDNS resolution from a pod
kubectl run -it --rm dns-test --image=busybox:1.36 -- nslookup kubernetes.default

Security & hardening​

RKE2 is hardened by default. Setting profile: cis applies the CIS-recommended arguments and file permissions; versioned profiles such as cis-1.23 track a specific benchmark revision. The RKE2 hardening guidance and scripts are published under the rke2-hardening name and are version-sensitive — verify the guide matches your RKE2 minor before applying, because the cis profile changes component arguments.

# /etc/rancher/rke2/config.yaml
profile: "cis"

Secrets encryption at rest is enabled with secrets-encryption: true. The encryption key is generated and stored on the server. The rke2 secrets-encrypt subcommands report status and rotate the key; rotating requires re-encrypting existing Secrets.

# Show encryption status and the current key
rke2 secrets-encrypt status

# Rotate the encryption key (prepare, then reencrypt)
rke2 secrets-encrypt prepare
rke2 secrets-encrypt rotate
rke2 secrets-encrypt reencrypt

FIPS builds are published as separate binaries for regulated environments. They are installed by selecting the FIPS artifact during installation rather than by a configuration key; the FIPS build uses FIPS-validated crypto modules for the control plane and etcd.

Pod Security Admission is built into modern Kubernetes and is controlled at the namespace level. RKE2 does not change the upstream defaults; label namespaces to enforce a level.

# Enforce the restricted policy on a namespace
kubectl label namespace my-app \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted

# Inspect what a workload would violate
kubectl -n my-app get pods -o yaml | \
grep -i "pod-security.kubernetes.io"

Disable unused packaged components to shrink the attack surface. The disable list accepts packaged chart names and removes them from the auto-deploy manifests.

disable:
- "rke2-ingress-nginx"
- "rke2-metrics-server"
- "rke2-snapshot-controller"
# Confirm the API server runs with RBAC and NodeRestriction
kubectl get pod -n kube-system -l component=kube-apiserver -o yaml | \
grep -E "anonymous-auth|authorization-mode|enable-admission"

# Check file permissions on the kubeconfig and token
stat -c '%a %n' /etc/rancher/rke2/rke2.yaml
stat -c '%a %n' /var/lib/rancher/rke2/server/token

Operations & troubleshooting​

Start with the systemd unit and journal. The server logs include etcd, control-plane, and packaged-component output.

# Service state and recent logs
systemctl status rke2-server
systemctl restart rke2-server
systemctl stop rke2-server
journalctl -u rke2-server -f
journalctl -u rke2-server --since "30 min ago"

# Agent logs
journalctl -u rke2-agent -f

# Run the server in debug mode for verbose logging
rke2 server --debug

Key paths:

  • Server logs (when not using journald): /var/lib/rancher/rke2/agent/logs/
  • Container logs: /var/log/pods/ and /var/log/containers/
  • Data directory: /var/lib/rancher/rke2/, etcd data under server/db/
  • Static pod manifests: /var/lib/rancher/rke2/agent/pod-manifests/
  • Config and kubeconfig: /etc/rancher/rke2/

The containerd socket used by RKE2 is /run/k3s/containerd/containerd.sock. Point crictl at it explicitly, since the default socket path may not match.

# List containers on the node
crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock ps

# Inspect a container and its logs
crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock \
inspect <container-id>
crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock \
logs <container-id>

# Show pod-level sandboxes on the node
crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock pods

Common failure modes and first checks:

  • Node NotReady. Check journalctl -u rke2-agent -f, confirm the CNI pod is running, and resolve any disk or memory pressure the kubelet reports.
  • etcd quorum loss. With embedded etcd, a majority of servers must be reachable. If quorum cannot be restored, recover from a snapshot with --cluster-reset.
  • Certificate or TLS errors on join. The joining node must reach the supervisor on 9345 and present the correct token. Verify with openssl s_client -connect <server>:9345.
  • Kubeconfig permission errors. write-kubeconfig-mode: "0644" sets the file mode; the containing directory must also be traversable by the user.
# Check node conditions and taints
kubectl describe node <node> | grep -A5 "Conditions"
kubectl get nodes -o custom-columns='NAME:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status'

# Inspect supervisor reachability from the joining node
curl -sk https://<server>:9345/ping

# Watch kubelet logs on a node
journalctl -u rke2-agent -f --no-pager

# Verify component pod health across the cluster
kubectl get pods -n kube-system -o wide

Uninstall​

Uninstall stops the services and removes RKE2-managed data and configuration. Both scripts are installed under /usr/local/bin/.

# Stop all RKE2 containers and processes without removing data
/usr/local/bin/rke2-killall.sh

# Remove services, manifests, and data (destructive)
/usr/local/bin/rke2-uninstall.sh

rke2-uninstall.sh deletes the etcd database, packaged manifests, CNI configuration, and systemd units on the local node. On an HA cluster, remove nodes from the cluster first and never uninstall the last quorum members while the cluster is still needed. The script is destructive and local-only; it does not clean up resources on remote nodes.

# Manual stop/disable if the scripts are unavailable
systemctl disable --now rke2-server
systemctl disable --now rke2-agent

# Orphaned CNI configuration that may need manual cleanup
rm -rf /etc/cni/net.d/10-*

See also​