De Docker a containerd: una breve historia de los runtimes de Kubernetes
Por qué Kubernetes dejó de hablar directamente con Docker y qué es realmente containerd en relación con él.
Los tutoriales antiguos de Kubernetes asumen que Docker es el runtime de contenedores. Los actuales asumen containerd. Ninguno se equivoca: describen momentos distintos de la historia de Kubernetes, y entender qué cambió aclara la mayor parte de la confusión en torno a ctr, crictl y por qué docker ps dejó de mostrarte algo útil en un nodo del clúster.
Docker fue primero, y Kubernetes se construyó en torno a él
Docker hizo que los contenedores fueran utilizables: una CLI, un formato de imagen, un daemon que lo ejecutaba todo. El Kubernetes inicial se construyó específicamente para orquestar contenedores Docker, y ambos estaban estrechamente acoplados. A medida que Kubernetes crecía, otros runtimes (rkt, entre otros) quisieron integrarse también, lo que significaba que Kubernetes necesitaba una forma de trabajar con más de un runtime en lugar de estar atado a la API de Docker.
CRI y OCI: estandarizar la interfaz
La respuesta de Kubernetes fue la Container Runtime Interface (CRI), una API gRPC que el kubelet usa para hablar con el runtime instalado, sin necesitar código específico para cada uno. Cualquier runtime que implemente CRI puede conectarse a Kubernetes.
La propia CRI se apoya en estándares de la Open Container Initiative (OCI), una especificación que Docker ayudó a establecer precisamente para que el ecosistema no dependiera de la implementación de un solo proveedor:
- La image spec define cómo se estructura y direcciona una imagen de contenedor, de modo que una imagen construida con una herramienta pueda ejecutarse con otra.
- La runtime spec define cómo debe crearse y ejecutarse realmente un contenedor en un host, hasta los namespaces, montajes y configuración del proceso.
- La distribution spec (añadida después) define cómo se suben y descargan las imágenes de un registro.
Entre ellas, CRI y OCI significan que un runtime y un orquestador ya no tienen que ser el mismo producto, ni siquiera del mismo proveedor.
Docker es anterior a CRI, así que Kubernetes tuvo que tender un puente
Docker no se construyó para hablar CRI, ya que CRI no existía cuando se creó Docker, y Docker siguió siendo el runtime dominante de todos modos. La solución de Kubernetes fue dockershim: una capa de compatibilidad que traducía las llamadas CRI a la propia API de Docker, permitiendo que el kubelet siguiera funcionando con Docker sin que Docker cambiara.
containerd ya estaba dentro de Docker
Docker nunca fue solo un runtime. Incluía una CLI, un sistema de construcción, gestión de volúmenes y redes, autenticación y, por debajo de todo eso, la pieza que realmente ejecutaba los contenedores: un daemon llamado containerd, asentado sobre el runtime de bajo nivel runc. containerd se separó como proyecto propio y se donó a la CNCF, donde se graduó en 2019 y, a diferencia de las herramientas de cara al usuario de Docker, habla CRI de forma nativa. Esa es toda la relación en una frase: containerd es el componente de runtime que siempre estuvo dentro de Docker, ahora disponible, y compatible con CRI, por sí solo.
La eliminación de dockershim
Mantener una capa de traducción para un solo runtime, cuando todos los demás hablaban CRI directamente, era una carga continua con beneficios decrecientes. Kubernetes eliminó dockershim en la versión 1.24 (2022) y, con ello, el soporte directo para ejecutar Docker como runtime de contenedores de un clúster.
Esto no rompió las imágenes existentes. Docker construía las imágenes según la especificación de imagen OCI, así que todo lo que ya estaba en un registro se ejecuta en containerd exactamente igual que antes. Lo que dejó de funcionar fue usar el propio Docker Engine como lo que realmente ejecuta los contenedores en un nodo; los clústeres tuvieron que pasar a un runtime nativo de CRI como containerd o CRI-O.
Qué significa esto cuando estás en un nodo hoy
docker ps en un nodo moderno o bien no existe o no muestra nada relevante, porque Docker ya no es lo que ejecuta tus contenedores. Las herramientas para eso son crictl, ctr y nerdctl, y la siguiente guía de esta serie cubre cuándo usar cada una. Las imágenes de contenedor en sí, las capas reales de la aplicación, no se ven afectadas por nada de esta historia; lo que cambió está enteramente en la maquinaria que hay por debajo.
Guías populares
-
Internos del runtime: cgroups, runc y dónde encaja containerd Qué aísla y limita realmente a un contenedor, desde la función del kernel hasta el daemon con el que habla Kubernetes. -
Las herramientas CLI de containerd: ctr, nerdctl y crictl Tres herramientas de línea de comandos, tres trabajos distintos: cuál usar y cuándo.