Container Runtime¶
Part of: Install a Kubernetes Cluster with kubeadm
Phases 3 & 4 of 9 — Installs containerd, runc, crictl, and CNI plugin binaries on every node.
Prerequisite: Node Preparation must be complete. Next: Kubernetes Packages — install kubelet, kubeadm, and kubectl.
The container runtime layer installs and configures everything Kubernetes needs to run containers: containerd, runc (OCI runtime), crictl (CRI debugger), and the CNI plugin binaries (the low-level networking primitives that CNI plugins like Calico and Flannel depend on).
This layer runs in Phases 3 and 4 of both entrypoint scripts.
Scripts¶
| Script | Phase | Path |
|---|---|---|
| Install CNI binaries | 3 | runtime/install-cni-binaries.sh |
| Install crictl | 3 | runtime/install-crictl.sh |
| Install containerd (dispatcher) | 4 | runtime/install-containerd.sh |
| Install containerd — package method | 4 | runtime/install-containerd-package.sh |
| Configure containerd — package method | 4 | runtime/config-containerd-package.sh |
| Install runc (binary method only) | 4 | runtime/install-runc.sh |
| Install containerd — binary method | 4 | runtime/install-containerd-binary.sh |
| Configure containerd — binary method | 4 | runtime/config-containerd-binary.sh |
| Configure crictl | 4 (post) | runtime/config-crictl.sh |
Phase 3 — Runtime Prerequisites¶
Phase 3 installs two components that are needed before containerd itself: CNI plugin binaries and crictl.
CNI Plugin Binaries (install-cni-binaries.sh)¶
CNI binaries ≠ CNI plugin
The binaries installed here (/opt/cni/bin/bridge, host-local, loopback, etc.) are the low-level primitives that CNI plugins like Calico and Flannel call internally. They are not the CNI plugin itself. The CNI plugin (Calico or Flannel) is installed separately after kubeadm init — see kubeconfig-and-cni.md.
What the script does:
- Resolves architecture (
x86_64→amd64,aarch64→arm64) - Downloads
cni-plugins-linux-<arch>-<version>.tgzfromcontainernetworking/pluginsGitHub releases (default:v1.9.0) - Verifies SHA256 checksum
- Extracts all binaries to
/opt/cni/bin/ - Skips if
/opt/cni/bin/bridgealready exists (idempotent)
Verify:
crictl (install-crictl.sh)¶
crictl is the low-level CRI debugging tool (kubectl equivalent for the container runtime layer). It is installed before containerd because Phase 4 uses it to validate containerd configuration.
What the script does:
- Downloads
crictl-<version>-linux-<arch>.tar.gzfromkubernetes-sigs/cri-tools(default:v1.30.0) - Verifies SHA256 checksum
- Extracts
crictlbinary to/usr/local/bin/ - Skips if already installed (idempotent)
Phase 4 — Containerd Installation¶
install-containerd.sh is a dispatcher: it reads the CONTAINERD_INSTALL_METHOD environment variable (set during Phase 1 by the cluster parameters wizard) and routes to one of two installation paths.
CONTAINERD_INSTALL_METHOD=package → install-containerd-package.sh
config-containerd-package.sh
CONTAINERD_INSTALL_METHOD=binary → install-runc.sh
install-containerd-binary.sh
config-containerd-binary.sh
After either path completes, the dispatcher enables containerd via systemd and validates that the service is active.
Package Method (Recommended)¶
Uses the Docker official APT repository to install containerd.io. This package bundles runc and is maintained by Docker, making it the industry-standard approach for Ubuntu-based nodes.
install-containerd-package.sh:
- Installs
ca-certificates,curl,gnupg,lsb-release - Adds the Docker GPG key to
/etc/apt/keyrings/docker.asc - Writes a Deb822-format source to
/etc/apt/sources.list.d/docker.sources - Installs
containerd.ioviaapt-get
config-containerd-package.sh:
- Runs
containerd config default > /etc/containerd/config.tomlto generate a clean baseline - Sets
SystemdCgroup = true— this is the critical change; without it, kubelet and containerd use different cgroup drivers and the node becomes unstable - Restarts containerd
Binary Method (Advanced)¶
Downloads containerd directly from the upstream GitHub releases at containerd/containerd. runc must be installed first because the binary method does not bundle it.
install-runc.sh:
- Downloads
runc.<arch>fromopencontainers/runcreleases (default:v1.4.0) - Verifies SHA256 from the official checksum file (parses the correct line for the architecture)
- Installs to
/usr/local/sbin/runcwithinstall -m 0755
install-containerd-binary.sh:
- Requires
runcto be present (exits if not found) - Downloads
containerd-<version>-linux-<arch>.tar.gz(default:v2.2.0) - Verifies SHA256 checksum
- Extracts to
/usr/local - Creates a complete systemd unit at
/etc/systemd/system/containerd.service - Enables and starts the service
config-containerd-binary.sh (extended):
Applies more configuration than the package variant:
- Generates default config
- Sets
SystemdCgroup = true - Sets
sandbox_imagetoregistry.k8s.io/pause:3.9 - Sets
bin_dirto/opt/cni/binandconf_dirto/etc/cni/net.d - Waits up to 10 seconds for the containerd socket
- Runs
crictl infoto validate CRI plugin is functional
Phase 4 (Post) — Configure crictl¶
After containerd is running, config-crictl.sh configures crictl to communicate with it.
What the script does:
- Confirms
crictlis installed and the containerd socket exists at/run/containerd/containerd.sock - Writes
/etc/crictl.yaml:
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
pull-image-on-create: false
- Validates the configuration with
crictl info
Verify:
Key Design Notes¶
| Topic | Detail |
|---|---|
SystemdCgroup = true | Must be set in both package and binary config scripts. kubelet uses systemd cgroup driver by default since Kubernetes 1.22; containerd must match. |
| CNI binaries vs CNI plugin | Binaries in /opt/cni/bin/ are always installed. The CNI plugin (Calico/Flannel) is not installed until after kubeadm init. |
| Package method preference | The package method is preferred because Docker maintains containerd.io with stable release cadence and bundled runc. The binary method gives explicit version control at the cost of manual runc management. |
| Idempotency | install-runc.sh, install-containerd-binary.sh, install-crictl.sh, and install-cni-binaries.sh all check if the binary already exists and skip if it does. |