Container runtimes

You need to install a container runtime into each node in the cluster so that Pods can run there. This page outlines what is involved and describes related tasks for setting up nodes.

This page lists details for using several common container runtimes with Kubernetes, on Linux:

Note: For other operating systems, look for documentation specific to your platform.

Cgroup drivers

Control groups are used to constrain resources that are allocated to processes.

When systemd is chosen as the init system for a Linux distribution, the init process generates and consumes a root control group (cgroup) and acts as a cgroup manager. Systemd has a tight integration with cgroups and allocates a cgroup per systemd unit. It’s possible to configure your container runtime and the kubelet to use cgroupfs. Using cgroupfs alongside systemd means that there will be two different cgroup managers.

A single cgroup manager simplifies the view of what resources are being allocated and will by default have a more consistent view of the available and in-use resources. When there are two cgroup managers on a system, you end up with two views of those resources. In the field, people have reported cases where nodes that are configured to use cgroupfs for the kubelet and Docker, but systemd for the rest of the processes, become unstable under resource pressure.

Changing the settings such that your container runtime and kubelet use systemd as the cgroup driver stabilized the system. To configure this for Docker, set native.cgroupdriver=systemd.

Caution:

Changing the cgroup driver of a Node that has joined a cluster is a sensitive operation. If the kubelet has created Pods using the semantics of one cgroup driver, changing the container runtime to another cgroup driver can cause errors when trying to re-create the Pod sandbox for such existing Pods. Restarting the kubelet may not solve such errors.

If you have automation that makes it feasible, replace the node with another using the updated configuration, or reinstall it using automation.

Cgroup v2

Cgroup v2 is the next version of the cgroup Linux API. Differently than cgroup v1, there is a single hierarchy instead of a different one for each controller.

The new version offers several improvements over cgroup v1, some of these improvements are:

  • cleaner and easier to use API
  • safe sub-tree delegation to containers
  • newer features like Pressure Stall Information

Even if the kernel supports a hybrid configuration where some controllers are managed by cgroup v1 and some others by cgroup v2, Kubernetes supports only the same cgroup version to manage all the controllers.

If systemd doesn’t use cgroup v2 by default, you can configure the system to use it by adding systemd.unified_cgroup_hierarchy=1 to the kernel command line.

  1. # dnf install -y grubby && \
  2. sudo grubby \
  3. --update-kernel=ALL \
  4. --args=”systemd.unified_cgroup_hierarchy=1"

To apply the configuration, it is necessary to reboot the node.

There should not be any noticeable difference in the user experience when switching to cgroup v2, unless users are accessing the cgroup file system directly, either on the node or from within the containers.

In order to use it, cgroup v2 must be supported by the CRI runtime as well.

Migrating to the systemd driver in kubeadm managed clusters

Follow this Migration guide if you wish to migrate to the systemd cgroup driver in existing kubeadm managed clusters.

Container runtimes

Caution: This section links to third party projects that provide functionality required by Kubernetes. The Kubernetes project authors aren’t responsible for these projects. This page follows CNCF website guidelines by listing projects alphabetically. To add a project to this list, read the content guide before submitting a change.

containerd

This section contains the necessary steps to use containerd as CRI runtime.

Use the following commands to install Containerd on your system:

Install and configure prerequisites:

  1. cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
  2. overlay
  3. br_netfilter
  4. EOF
  5. sudo modprobe overlay
  6. sudo modprobe br_netfilter
  7. # Setup required sysctl params, these persist across reboots.
  8. cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
  9. net.bridge.bridge-nf-call-iptables = 1
  10. net.ipv4.ip_forward = 1
  11. net.bridge.bridge-nf-call-ip6tables = 1
  12. EOF
  13. # Apply sysctl params without reboot
  14. sudo sysctl --system

Install containerd:

  1. Install the containerd.io package from the official Docker repositories. Instructions for setting up the Docker repository for your respective Linux distribution and installing the containerd.io package can be found at Install Docker Engine.

  2. Configure containerd:

    1. sudo mkdir -p /etc/containerd
    2. containerd config default | sudo tee /etc/containerd/config.toml
  3. Restart containerd:

    1. sudo systemctl restart containerd

Start a Powershell session, set $Version to the desired version (ex: $Version=1.4.3), and then run the following commands:

  1. Download containerd:

    1. curl.exe -L https://github.com/containerd/containerd/releases/download/v$Version/containerd-$Version-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz
    2. tar.exe xvf .\containerd-windows-amd64.tar.gz
  2. Extract and configure:

    1. Copy-Item -Path ".\bin\" -Destination "$Env:ProgramFiles\containerd" -Recurse -Force
    2. cd $Env:ProgramFiles\containerd\
    3. .\containerd.exe config default | Out-File config.toml -Encoding ascii
    4. # Review the configuration. Depending on setup you may want to adjust:
    5. # - the sandbox_image (Kubernetes pause image)
    6. # - cni bin_dir and conf_dir locations
    7. Get-Content config.toml
    8. # (Optional - but highly recommended) Exclude containerd from Windows Defender Scans
    9. Add-MpPreference -ExclusionProcess "$Env:ProgramFiles\containerd\containerd.exe"
  3. Start containerd:

    1. .\containerd.exe --register-service
    2. Start-Service containerd

Using the systemd cgroup driver

To use the systemd cgroup driver in /etc/containerd/config.toml with runc, set

  1. [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  2. ...
  3. [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  4. SystemdCgroup = true

If you apply this change make sure to restart containerd again:

  1. sudo systemctl restart containerd

When using kubeadm, manually configure the cgroup driver for kubelet.

CRI-O

This section contains the necessary steps to install CRI-O as a container runtime.

Use the following commands to install CRI-O on your system:

Note: The CRI-O major and minor versions must match the Kubernetes major and minor versions. For more information, see the CRI-O compatibility matrix.

Install and configure prerequisites:

  1. # Create the .conf file to load the modules at bootup
  2. cat <<EOF | sudo tee /etc/modules-load.d/crio.conf
  3. overlay
  4. br_netfilter
  5. EOF
  6. sudo modprobe overlay
  7. sudo modprobe br_netfilter
  8. # Set up required sysctl params, these persist across reboots.
  9. cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
  10. net.bridge.bridge-nf-call-iptables = 1
  11. net.ipv4.ip_forward = 1
  12. net.bridge.bridge-nf-call-ip6tables = 1
  13. EOF
  14. sudo sysctl --system

To install CRI-O on the following operating systems, set the environment variable OS to the appropriate value from the following table:

Operating system$OS
Debian UnstableDebian_Unstable
Debian TestingDebian_Testing

Then, set $VERSION to the CRI-O version that matches your Kubernetes version. For instance, if you want to install CRI-O 1.20, set VERSION=1.20. You can pin your installation to a specific release. To install version 1.20.0, set VERSION=1.20:1.20.0.

Then run

  1. cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
  2. deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /
  3. EOF
  4. cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
  5. deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /
  6. EOF
  7. curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers.gpg add -
  8. curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers.gpg add -
  9. sudo apt-get update
  10. sudo apt-get install cri-o cri-o-runc

To install on the following operating systems, set the environment variable OS to the appropriate field in the following table:

Operating system$OS
Ubuntu 20.04xUbuntu_20.04
Ubuntu 19.10xUbuntu_19.10
Ubuntu 19.04xUbuntu_19.04
Ubuntu 18.04xUbuntu_18.04

Then, set $VERSION to the CRI-O version that matches your Kubernetes version. For instance, if you want to install CRI-O 1.20, set VERSION=1.20. You can pin your installation to a specific release. To install version 1.20.0, set VERSION=1.20:1.20.0.

Then run

  1. cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
  2. deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /
  3. EOF
  4. cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
  5. deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /
  6. EOF
  7. curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers.gpg add -
  8. curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers-cri-o.gpg add -
  9. sudo apt-get update
  10. sudo apt-get install cri-o cri-o-runc

To install on the following operating systems, set the environment variable OS to the appropriate field in the following table:

Operating system$OS
Centos 8CentOS_8
Centos 8 StreamCentOS_8_Stream
Centos 7CentOS_7

Then, set $VERSION to the CRI-O version that matches your Kubernetes version. For instance, if you want to install CRI-O 1.20, set VERSION=1.20. You can pin your installation to a specific release. To install version 1.20.0, set VERSION=1.20:1.20.0.

Then run

  1. sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/devel:kubic:libcontainers:stable.repo
  2. sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
  3. sudo yum install cri-o
  1. sudo zypper install cri-o

Set $VERSION to the CRI-O version that matches your Kubernetes version. For instance, if you want to install CRI-O 1.20, VERSION=1.20.

You can find available versions with:

  1. sudo dnf module list cri-o

CRI-O does not support pinning to specific releases on Fedora.

Then run

  1. sudo dnf module enable cri-o:$VERSION
  2. sudo dnf install cri-o

Start CRI-O:

  1. sudo systemctl daemon-reload
  2. sudo systemctl enable crio --now

Refer to the CRI-O installation guide for more information.

cgroup driver

CRI-O uses the systemd cgroup driver per default. To switch to the cgroupfs cgroup driver, either edit /etc/crio/crio.conf or place a drop-in configuration in /etc/crio/crio.conf.d/02-cgroup-manager.conf, for example:

  1. [crio.runtime]
  2. conmon_cgroup = "pod"
  3. cgroup_manager = "cgroupfs"

Please also note the changed conmon_cgroup, which has to be set to the value pod when using CRI-O with cgroupfs. It is generally necessary to keep the cgroup driver configuration of the kubelet (usually done via kubeadm) and CRI-O in sync.

Docker

  1. On each of your nodes, install the Docker for your Linux distribution as per Install Docker Engine. You can find the latest validated version of Docker in this dependencies file.

  2. Configure the Docker daemon, in particular to use systemd for the management of the container’s cgroups.

    1. sudo mkdir /etc/docker
    2. cat <<EOF | sudo tee /etc/docker/daemon.json
    3. {
    4. "exec-opts": ["native.cgroupdriver=systemd"],
    5. "log-driver": "json-file",
    6. "log-opts": {
    7. "max-size": "100m"
    8. },
    9. "storage-driver": "overlay2"
    10. }
    11. EOF

    Note: overlay2 is the preferred storage driver for systems running Linux kernel version 4.0 or higher, or RHEL or CentOS using version 3.10.0-514 and above.

  3. Restart Docker and enable on boot:

    1. sudo systemctl enable docker
    2. sudo systemctl daemon-reload
    3. sudo systemctl restart docker

Note:

For more information refer to