← Назад к вопросам

Почему Kubernetes отказался от использования Docker?

2.0 Middle🔥 142 комментариев
#Kubernetes

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Короткий ответ: Kubernetes (k8s) никогда напрямую не зависел и не "отказывался" от Docker как такового. Он отказывается от компонента Docker Engine (dockershim), который ранее использовался как один из возможных Container Runtimes (сред выполнения контейнеров). Это решение было вызвано фундаментальным различием в архитектуре и стремлением k8s к стандартизации на низкоуровневом интерфейсе выполнения контейнеров — CRI (Container Runtime Interface).

Давайте разберем это подробно.

1. Анатомия заблуждения: Docker ≠ "Докер"

Первое и главное — необходимо разделять понятия:

  • Docker как высокоуровневая платформа и UX-инструмент: Это то, что знают разработчики — docker build, docker run, Docker CLI, Docker Compose, Docker Desktop. Этот уровень никогда не был нужен Kubernetes.
  • Docker Engine (демон dockerd) : Это сервис, который принимает команды от CLI, управляет образами, сетью, томами и, что критически важно, запускает контейнеры через свой собственный компонент — containerd.
  • containerd: Это специализированный, низкоуровневый runtime, который напрямую управляет жизненным циклом контейнеров (создание, запуск, остановка). Именно его использует Docker Engine "под капотом".

Изначально, для простоты интеграции, k8s включал в свой код компонент под названием dockershim. Его задача была проста: "переводить" запросы k8s (через CRI) на "родной" для Docker Engine API.

graph TD
    subgraph "Архитектура до удаления dockershim (упрощенно)"
        Kubelet -->|CRI запрос| Dockershim
        Dockershim -->|Docker API| Docker_Engine
        Docker_Engine -->|использует| Containerd
        Containerd -->|использует| runc
        runc -->|запускает| Container
    end

2. Почему dockershim стал проблемой? Основные причины удаления

  • Избыточность и сложность (Docker Engine как ненужная прослойка): Kubelet'у для работы нужен только низкоуровневый runtime (containerd, CRI-O). Docker Engine добавлял лишний уровень абстракции, усложнял стек, потреблял ресурсы и был источником потенциальных точек отказа. K8s по сути использовал лишь малую часть его функционала.
  • Следование стандарту CRI: CRI — это четко определенный плагино-ориентированный интерфейс. Специализированные CRI-совместимые runtime (такие как containerd и CRI-O) созданы именно для k8s и реализуют только необходимый функционал. Docker Engine не реализует CRI нативно.
  • Развитие экосистемы: Появились альтернативные, более легкие и безопасные container runtime (особенно CRI-O, тесно связанный с Red Hat/OpenShift). Поддерживать уникальный код dockershim для одного runtime стало обузой для сообщества k8s.
  • Вопросы безопасности и инноваций: Docker Engine имеет свою собственную сложную систему управления сетью, логированием и т.д. Прямая интеграция через dockershim ограничивала возможности k8s внедрять новые фичи на уровне runtime (например, поддержку новых типов sandbox) и могла создавать security-риски.

3. Что изменилось на практике? Требуемые действия

Для администраторов кластеров переход означал смену Container Runtime с Docker Engine на непосредственно поддерживаемый CRI-совместимый runtime, чаще всего — на тот же containerd, который уже был внутри Docker.

# Пример: Как мог выглядеть процесс переключения runtime в kubelet (на узле)
# Старая конфигурация (использует dockershim):
KUBELET_KUBEADM_ARGS="--container-runtime=docker --network-plugin=cni ..."

# Новая конфигурация (использует containerd):
KUBELET_KUBEADM_ARGS="--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock ..."

Важно: Ваши Dockerfile, образы (docker.io/nginx), контейнеры — ничего не изменилось. Они продолжают работать. Вы по-прежнему можете использовать Docker для сборки образов и локальной разработки. Изменения коснулись только того, как kubelet на рабочих узлах кластера запускает эти контейнеры.

4. Ключевые выводы

  • Не "отказ", а эволюция архитектуры. K8s убрал кастомную интеграцию (dockershim) в пользу стандартного интерфейса CRI.
  • Docker как инструмент разработчика остался. Сборка, тестирование, публикация образов — все работает по-прежнему.
  • Основное изменение — на уровне production-кластера. Container Runtime на узлах теперь должен быть нативным CRI-совместимым (containerd, CRI-O).
  • Выигрыш в стабильности и эффективности. Упрощенный стек (kubelet -> CRI -> containerd -> runc) более надежен, потребляет меньше ресурсов и лучше поддерживается.

Таким образом, Kubernetes не "перестал работать с Docker", а совершил закономерный переход от использования монолитного Docker Engine в качестве "костыля" к прямой и эффективной работе со стандартизированными, легковесными компонентами (containerd), которые всегда были ядром Docker. Это шаг к более зрелой, модульной и производительной экосистеме контейнеров.

Почему Kubernetes отказался от использования Docker? | PrepBro