Cómo depurar imágenes OCI que fallan en runtime con containerd

Última actualización: julio 2, 2026
Autor: Isaac
  • Diferencias fundamentales entre los runtimes de alto nivel como containerd y los de bajo nivel basados en la especificación OCI.
  • Evolución de la arquitectura de contenedores desde el monolito de Docker hacia la interfaz estándar CRI de Kubernetes.
  • Metodologías de diagnóstico para solucionar errores de ejecución relacionados con cgroups, kernels y fallos de OCI runtime.

Depuración de contenedores

Si te dedicas al mundo de la tecnología, habrás notado que la gestión de contenedores ha pegado un salto increíble. Desde que Docker se hizo famoso hasta la llegada de la orquestación masiva con Kubernetes, la forma en que damos vida a las aplicaciones ha cambiado la jugada por completo. Para no perderse, es vital entender qué ocurre realmente en el corazón de los contenedores y cómo funcionan los mecanismos que permiten que un proceso esté aislado del resto del sistema.

En este sentido, profundizar en los runtimes OCI y los entornos específicos para Kubernetes, como containerd o CRI-O, no es solo un ejercicio teórico, sino una necesidad práctica. A menudo nos topamos con errores crípticos al lanzar una imagen que, sobre el papel, debería funcionar, pero que en el runtime de ejecución nos lanza un fallo inesperado. Vamos a desgranar todo esto para que sepas exactamente dónde mirar cuando las cosas se tuercen.

Un repaso necesario: de las jaulas chroot a la modernidad

Para entender por qué fallan las imágenes hoy, hay que mirar atrás. Todo empezó en los años 70 con las chroot jails en Unix. Básicamente, se trataba de engañar a un proceso haciéndole creer que un subdirectorio cualquiera era la raíz del sistema, limitando así su capacidad de hacer destrozos en el resto del equipo. Fue el primer paso hacia el aislamiento que hoy damos por hecho.

Scripts de Bash en Windows: Cómo crearlos con WSL
Related article:
Scripts de Bash en Windows: cómo crearlos con WSL

Mucho más tarde, hacia 2008, aparecieron los contenedores de LXC. Aquí es donde la cosa se pone interesante porque empezaron a usar funciones del kernel de Linux como los cgroups y los namespaces. Los cgroups se encargan de que un contenedor no se coma toda la CPU o la RAM del servidor, mientras que los namespaces crean esa burbuja de aislamiento para la red, los procesos y el sistema de archivos. Básicamente, LXC creó mini sistemas operativos que comparten el mismo kernel pero viven en mundos separados.

  ¿Cuál es la versión de Linux más parecida a Windows?

La era de Docker y el motor que lo cambió todo

Docker no inventó el contenedor, pero sí lo hizo extremadamente fácil de usar. Introdujo el concepto de imágenes en capas y el famoso Dockerfile, permitiendo que cualquier desarrollador pudiera empaquetar sus dependencias y asegurarse de que el código funcionara igual en su portátil que en la nube. Esta consistencia eliminó el clásico problema de «en mi máquina funciona» que tanto dolor de cabeza daba antiguamente.

Si analizamos el Docker Engine, vemos que se divide en varias piezas. El daemon dockerd es el cerebro que gestiona imágenes y redes, pero para la ejecución real, Docker se apoya en containerd. Es importante no confundirlos: dockerd es la capa de gestión amigable y containerd es el runtime de bajo nivel que se encarga de las tareas pesadas como iniciar o detener el contenedor interactuando con el kernel.

Kubernetes y el divorcio con Docker

Hubo un momento clave cuando Kubernetes decidió dejar de soportar Docker directamente. No es que Docker fuera malo, sino que era demasiado grande. Kubernetes solo necesitaba una pequeña parte de sus funciones y mantener todo el motor de Docker era un riesgo innecesario para la seguridad, ya que aumentaba la superficie de ataque.

empaquetar aplicaciones con msix
Related article:
Guía completa para empaquetar aplicaciones con MSIX

Para solucionar esto, se creó la Container Runtime Interface (CRI). Esta interfaz permite que Kubernetes sea agnóstico al runtime que se use. Así es como hoy en día podemos elegir entre containerd y CRI-O. Mientras que containerd es robusto y versátil, CRI-O es la apuesta minimalista de Red Hat, diseñada específicamente para cumplir con la norma CRI sin añadir ni un gramo de código extra que no sea estrictamente necesario.

  ¿Cómo ver los grupos de usuarios en Linux?

Runtimes OCI: El estándar de la industria

La Open Container Initiative (OCI) nació para evitar que el destino de los contenedores dependiera de una sola empresa. Un runtime OCI es el encargado de hacer las llamadas al sistema del kernel para crear el contenedor. El más conocido es runc, que es la implementación de referencia y la que utilizan tanto Docker como containerd.

Sin embargo, existen alternativas más aisladas como gVisor de Google. A diferencia de runc, gVisor actúa como un kernel en el espacio de usuario, proporcionando una capa de seguridad extra. También tenemos firecracker-containerd de AWS, que básicamente convierte la especificación OCI en micro-máquinas virtuales extremadamente ligeras, la tecnología que hace que AWS Lambda sea tan rápido.

El camino hacia la creación de imágenes con Paketo

Hoy en día, escribir Dockerfiles a mano puede ser tedioso. Herramientas como Paketo permiten generar imágenes compatibles con OCI directamente desde el código, sin necesidad de definir cada paso manualmente. Paketo utiliza buildpacks para detectar el tipo de aplicación (como una app de Spring Boot en Java) y empaquetarla siguiendo las mejores prácticas.

configuraciones workstation más usadas para IA
Related article:
Configuraciones de workstation más usadas para IA y deep learning

Una de las grandes ventajas de este enfoque es la reproducibilidad de la construcción. Paketo fija las fechas de creación de las capas para que, si el código no ha cambiado, la imagen generada sea idéntica. Además, optimiza la disposición de las capas, colocando aquello que cambia con menos frecuencia al principio para acelerar la caché de construcción.

Depurando fallos de runtime y errores de OCI

Cuando una imagen falla al arrancar con containerd, solemos ver errores como «OCI runtime create failed». Estos fallos pueden ser frustrantes porque a veces el log de Docker no muestra suficiente información. En casos donde se usan runtimes alternativos como youki, es posible que el runtime devuelva un error pero el wrapper de Docker no logre capturar el output, dejando el log vacío o con mensajes genéricos de «closed fifo».

  ¿Cómo instalar el servidor de MySQL?

Para solucionar estos problemas, es fundamental seguir una estrategia de diagnóstico estructurada. Primero, hay que verificar la compatibilidad del kernel del nodo (usando uname -r) ya que un desajuste entre la versión del kernel y la imagen puede romper la configuración de los cgroups. Luego, debemos analizar los logs del runtime mediante journalctl o los archivos de log específicos de containerd para encontrar el motivo real del colapso del proceso hijo.

Si el problema persiste, herramientas como docker inspect ayudan a revisar si hay configuraciones de cgroups conflictivas en la imagen. En entornos de EKS, por ejemplo, actualizar el cluster a una versión más reciente puede solucionar limitaciones conocidas del kernel que impiden que el runtime OCI gestione correctamente los ganchos de procesos o la jerarquía de recursos del sistema.