Почему Kubernetes отказался от Docker в качестве runtime?

«Почему Kubernetes отказался от Docker в качестве runtime?» — вопрос из категории Kubernetes, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Kubernetes не "отказался от Docker", а перестал использовать Docker в качестве контейнерного runtime по умолчанию, начиная с версии 1.20. Это было эволюционным шагом к более простой и стандартизированной архитектуре.

Причины и контекст:

  1. Стандартизация через CRI (Container Runtime Interface): Kubernetes абстрагировал работу с контейнерами через CRI. Docker не реализовывал этот интерфейс напрямую. Для его поддержки использовался дополнительный компонент dockershim, который создавал лишнюю сложность и точку отказа.
    # Kubelet теперь напрямую общается с CRI-совместимым runtime
    containerRuntimeEndpoint: "unix:///run/containerd/containerd.sock"
  2. Упрощение стека: Docker Engine — это монолит, включающий множество сервисов (демон, CLI, build, networking). Kubernetes для запуска контейнеров нужен был только низкоуровневый компонент — containerd, который уже был частью Docker. Отказ от dockershim позволил Kubernetes общаться с containerd напрямую.
  3. Снижение накладных расходов: Прямое взаимодействие с containerd (или CRI-O) более эффективно и безопасно, чем через промежуточный слой dockershim.

Важное уточнение:

  • Docker-образы продолжают работать. И containerd, и CRI-O используют стандартный формат образов OCI (Open Container Initiative), который и создаёт Docker. Вы по-прежнему можете собирать образы с помощью Docker и запускать их в Kubernetes.
  • Изменение коснулось только runtime на узлах. Разработчики на своих машинах продолжают использовать Docker без изменений.