Назад | Перейти на главную страницу

Узел Kubernetes ломается при перезапуске containerd

После обновления до последней версии docker (18.09.0) и kubernetes (1.12.2) мой узел Kubernetes ломается при развертывании обновлений безопасности, которые перезапускаются. containerd.

У меня есть: /etc/docker/daemon.json:

{
  "storage-driver": "overlay2",
  "live-restore": true
}

В прошлом этого было достаточно для перезапуска докера без перезапуска модулей.

Кубелет запускается как:

/usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --cgroup-driver=cgroupfs --cni-bin-dir=/opt/cni/bin --cni-conf-dir=/etc/cni/net.d --network-plugin=cni --fail-swap-on=false --feature-gates=PodPriority=true

Теперь перезапускаем containerd сохранит старые стручки, но также воссоздает их под свежими containerd обработать.

Исходная ситуация до перезапуска:

/usr/bin/containerd
/usr/bin/dockerd -H unix://
 \_ containerd --config /var/run/docker/containerd/containerd.toml --log-level info
     \_ containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/1a36f40f3c3531d13b8bc493049a1900662822e01e2c911f8
     |   \_ /usr/bin/dumb-init /bin/bash /entrypoint.sh /nginx-ingress-controller --default-backend-service=infra/old-nginx-php --election-id=ingress-controller-leader 
     |       \_ /bin/bash /entrypoint.sh /nginx-ingress-controller --default-backend-service=infra/old-nginx-php --election-id=ingress-controller-leader --ingress-class
     |           \_ /nginx-ingress-controller --default-backend-service=infra/old-nginx-php --election-id=ingress-controller-leader --ingress-class=nginx-php --configma
     |               \_ nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
     |                   \_ nginx: worker process
     |                   \_ nginx: worker process
     \_ containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/c9a82204115c50788d132aa6c11735d90412dacb48a219d31
     |   \_ /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf
     \_ containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/3004e3fa5f7e2b45865c6cc33abb884d9140af16f2594a11d
     |   \_ /sbin/runsvdir -P /etc/service/enabled
     |       \_ runsv bird
     |       |   \_ bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg
     |       \_ runsv bird6
     |       |   \_ bird6 -R -s /var/run/calico/bird6.ctl -d -c /etc/calico/confd/config/bird6.cfg
     |       \_ runsv confd
     |       |   \_ calico-node -confd
     |       \_ runsv felix
     |           \_ calico-node -felix
     \_ containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/1f3c48e28c7fde2f67c40d5641abfa9a29e3dfcbc436321f6
     |   \_ /bin/sh /install-cni.sh
     |       \_ sleep 10
     \_ containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/8371571ce29be4959951cf8ad70e57aa1f4a146f5ca43435b
         \_ /coredns -conf /etc/coredns/Corefile

После перезапуска containerd / docker эти старые контейнеры не обнаруживаются, и все они воссоздаются в новом containerd обработать. Это дает дублирование процессов для всех модулей!

Похоже, containerd полностью забыл о старых контейнерах, потому что killall containerd-shim, не просто убьет эти старые поды, а просто переродит потомков в init:

/usr/bin/dumb-init /bin/bash /entrypoint.sh /nginx-ingress-controller --default-backend-service=infra/old-nginx-php --election-id=ingress-controller-leader --ingress-cl
 \_ /bin/bash /entrypoint.sh /nginx-ingress-controller --default-backend-service=infra/old-nginx-php --election-id=ingress-controller-leader --ingress-class=nginx-php -
     \_ /nginx-ingress-controller --default-backend-service=infra/old-nginx-php --election-id=ingress-controller-leader --ingress-class=nginx-php --configmap=infra/phpi
         \_ nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
             \_ nginx: worker process
             \_ nginx: worker process
/usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf
/sbin/runsvdir -P /etc/service/enabled
 \_ bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg
 \_ bird6 -R -s /var/run/calico/bird6.ctl -d -c /etc/calico/confd/config/bird6.cfg
/bin/sh /install-cni.sh
 \_ sleep 10

Очевидно, что наличие старого calico и nginx позволяет использовать хост-порты, поэтому новые поды не запускаются, и узел становится полностью непригодным для использования. Единственный вариант - убить все старые процессы вручную или перезагрузить компьютер.

Требуются ли какие-то новые настройки, чтобы убедиться, что kubelet находит эти старые containerd экземпляры? Или это происходит из-за глобального containerd а версия, запущенная докером?

Вчера я столкнулся с той же проблемой, и после перезапуска контейнера я также не смог выполнить запуск в своих работающих модулях. Проблема в самом докере.

После перезапуска containerd демон docker все еще пытается обрабатывать потоки событий со старыми дескрипторами сокетов. После этого обработка ошибок, когда клиент не может подключиться к containerd, приводит к скачку загрузки ЦП на машине.

Единственный способ выйти из этой ситуации - перезапустить докер (докер systemctl restart).

Проблема устранена с помощью следующего тикета:

https://github.com/moby/moby/pull/36173

Надеюсь это поможет.