Table of Contents

https://kruyt.org/migrate-docker-containerd-kubernetes/

Проверяем, что у нас всё хорошо с containerd. Смотрим его неймспейсы. Там должен быть неймспейс moby - неймспейс, в котором запускает контейнеры docker:

sudo ctr namespace list
sudo ctr --namespace moby container list

Если неймспейс и контейнеры видны - значит все хорошо. Кордоним и дрейним ноду:

kubectl cordon kub
kubectl drain kub --delete-emptydir-data --ignore-daemonsets

Останавливаем сервисы:

systemctl stop kubelet
systemctl stop docker

Удаляем докер:

sudo apt-get purge docker.io

Генерим дефолтный конфиг и убеждаемся, что плагин cri не входит в список отключенных в конфиге containerd:

sudo mkdir -p /etc/containerd/
sudo containerd config default | sudo tee -a /etc/containerd/config.toml
containerd config dump | grep disabled_plugins

А если он там есть, то включаем cri (удаляем его из списка отключенных). Для этого комментируем строку в файле /etc/containerd/config.toml:

#disabled_plugins = ["cri"]

Включаем containerd в конфиг kubelet. То есть добавляем параметры

--container-runtime=remote --container-runtimeendpoint=unix:///run/containerd/containerd.sock

к строке с параметрами запуска kubelet в файле /var/lib/kubelet/kubeadm-flags.env. В итоге содержимое файла в моем случае стало таким:

KUBELET_KUBEADM_ARGS="--cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 --resolv-conf=/run/systemd/resolve/resolv.conf --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"

Всё. теперь можно перезагрузить ноду.
После перезагрузки у меня kubelet не завелся с ошибкой:

Flag --cgroup-driver has been deprecated, This parameter should be set via the config file specified by the Kubelet's --config flag.
Flag --resolv-conf has been deprecated, This parameter should be set via the config file specified by the Kubelet's --config flag. 

В итоге:

После удаления docker многие пакеты, в том числе и containerd, будут считаться ненужными и могут быть автоматически удалены! Поэтому - их нужно переустановить вручную:

apt-get install bridge-utils cgroupfs-mount containerd git patch pigz runc

Также - нужно прописать в свойствах ноды путь до сокета нового CRI. Проверить что там прописано сейчас можно так:

kubetl get no -o yaml | grep cri

И там должен быть путь до сокета containerd:

kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock

В моем случае - некорректное значение этого параметра (он указывал на docker-shim) приводило к тому что в логах kubelet service было много такого:

Apr 23 16:57:45 kub kubelet[771273]: E0423 16:57:45.583662  771273 cri_stats_provider.go:669] "Unable to fetch container log stats" err="failed to get fsstats for \"/var/log/pods/elk_elk-es-data-0_67a13965-df24-4d48-9abb-e6670f35acab/elasticsearch/4.log\": no such file or directory" containerName="elasticsearch"

Кажется, что по пути до сокета CRI определяется его тип и путь до логов. В моем случае - файл который пытался обнаружить kubelet был символической ссылкой на файл в /var/lib/docker, а после зуказания корректного пути до сокета в свойствах ноды - всё встало на свои места!
Ну и анкордоним ноду:

kubectl uncordon kub

Проблемы

не запускается pod eck

После перехода на containerd перестал запускаться под ElasticSearch Operator for kubernetes - eck с такой ошибкой:

{"log.level":"error","@timestamp":"2021-06-01T20:31:34.184Z","log.logger":"manager","message":"Error setting GOMAXPROCS","service.version":"1.1.1-f13b6d26","service.type":"eck","ecs.version":"1.4.0","error":"invalid format for CGroupSubsys: \"12:freezer:/kubepods-burstable-podf1fe3a11_2795_4c46_8eb6_a1929f4a53b5.slice:cri-containerd:96c7b19a81ff398e19131d816fb6de264e53499e5ad9b5a563f879cf1b37390c\"","error.stack_trace":"github.com/go-logr/zapr.(*zapLogger).Error\n\t/go/pkg/mod/github.com/go-logr/zapr@v0.1.0/zapr.go:128\ngithub.com/elastic/cloud-on-k8s/cmd/manager.execute\n\t/go/src/github.com/elastic/cloud-on-k8s/cmd/manager/main.go:188\ngithub.com/elastic/cloud-on-k8s/cmd/manager.glob..func1\n\t/go/src/github.com/elastic/cloud-on-k8s/cmd/manager/main.go:74\ngithub.com/spf13/cobra.(*Command).execute\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.5/command.go:830\ngithub.com/spf13/cobra.(*Command).ExecuteC\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.5/command.go:914\ngithub.com/spf13/cobra.(*Command).Execute\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.5/command.go:864\nmain.main\n\t/go/src/github.com/elastic/cloud-on-k8s/cmd/main.go:27\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:203"}

Гугление вывело сюда: https://discuss.elastic.co/t/elastic-operator-0-crashloopbackoff/267736/3
Нужно подредактировать конфиг containerd. В файлике /etc/containerd/config.toml для пары плагинов нужно выставить параметры:

version = 2
[plugins]
  [plugins."io.containerd.grpc.v1.cri"]
   [plugins."io.containerd.grpc.v1.cri".containerd]
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
          runtime_type = "io.containerd.runc.v1"
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
            SystemdCgroup = true

В кластере не работает DNS

kubernetes_dns_reply_from_unexpected_source

Диагностика с помощью crictl

Создаем файлик /etc/crictl.yaml:

runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: true

И дальше можем делать то что написано тут: https://kubernetes.io/docs/tasks/debug-application-cluster/crictl/
смотреть поды:

crictl pods

Смотреть контейнеры:

crictl ps -a

И логи контейнеров (это полезно, когда не работает инфрастурктура кубера kube-api или etcd):

crictl logs {Container_ID}