Installing Container Runtime Interface

Getting Started

You can select one of the supported container runtime interfaces for your Kubernetes cluster infrastructure. Since Kubernetes is deprecating Docker as a container runtime after v1.20, I choose containerd as my runtime interface and writing an Ansible role to install it. Let's do deep dive on how to install containerd. You can find my Ansible role here.

All installation steps for different container runtimes can be found here.

Installing Prerequisites

containerd expects some kernel parameters and kernel modules to be set persistently. I am handling that step in a separate playbook as below:

---
- name: Enable kernel module
  lineinfile:
    path: /etc/modules-load.d/containerd.conf
    line: "{{ item }}"
    state: present
    create: true
    mode: '0644'
  loop:
    - overlay
    - br_netfilter

- name: Reload kernel modules
  modprobe:
    name: "{{ item }}"
    state: present
  loop:
    - overlay
    - br_netfilter

- name: Setup required sysctl params
  sysctl:
    name: "{{ item.name }}"
    value: "{{ item.value }}"
    sysctl_file: /etc/sysctl.d/99-kubernetes-cri.conf
    reload: true
  loop:
    - { name: net.bridge.bridge-nf-call-iptables, value: 1 }
    - { name: net.ipv4.ip_forward, value: 1}
    - { name: net.bridge.bridge-nf-call-ip6tables, value: 1}

Installing containerd runtime interface

I am covering containerd installation on Centos 7, Ubuntu 18.04, and Ubuntu 20.04. Each operating system has its own installation requirements. I prefer to split them into different plays and include them in my tasks/main.yml as below:

- name: Install containerd
  include_tasks: "install_{{ ansible_distribution | lower }}.yaml"

So each supported operating system calls its own yaml file as below:

tasks/install_centos.yaml
---
- name: Install on CentOS 7
  block:
    - name: Install required packages
      package:
        name:
          - yum-utils
          - device-mapper-persistent-data
          - lvm2
        state: present

    - name: Create docker-ce package repository
      get_url:
        url: "https://download.docker.com/linux/centos/docker-ce.repo"
        dest: /etc/yum.repos.d/docker-ce.repo
        owner: root
        group: root
        mode: '0644'

    - name: Install containerd.io
      package:
        name: containerd.io
        state: present
  when: ansible_distribution_major_version | int == 7

containerd version is not defined in the current version of the Ansible role. In the near future, I can add it to provide more stability but for now, I will go with the latest version always.

Configuration

Once the binary is installed, we need to create the configuration file under /etc/containerd/config.toml. Then we will need to enable and restart the service so the new configuration can be read by the daemon. Since the configuration step is common on all operating systems, I created a single play and include it in the main play. Let's take a look at the configuration code:

tasks/configure.yaml
---
- name: Create /etc/containerd
  file:
    path: /etc/containerd
    state: directory
    mode: '0755'

- name: Check if /etc/containerd/config.toml exists
  stat:
    path: /etc/containerd/config.toml
  register: containerd_config

- name: Copy containerd configuration
  shell: "containerd config default > /etc/containerd/config.toml"
  args:
    warn: no
  tags: ['skip_ansible_lint']
  when: not containerd_config.stat.exists
  notify: restart containerd

- name: Enable containerd
  service:
    name: containerd
    enabled: true

Putting things together

All the above steps are included in the main playbook of the role as below:

tasks/main.yml
- name: Handle prereqs
  include_tasks: prereq.yaml

- name: Install containerd
  include_tasks: "install_{{ ansible_distribution | lower }}.yaml"

- name: Configure containerd
  include_tasks: configure.yaml

Calling this role will enable us to install containerd on supported operating systems. Now we can continue with installing kubeadm, kubelet, and kubectl.

Last updated