containerd 2.0 en produccion: migraciones reales

Banner horizontal oficial del proyecto containerd mantenido por la CNCF, runtime de contenedores de nivel industrial graduado en la fundacion

containerd 2.0 se publico en noviembre de 2024 y hemos tenido seis meses para ver como se comporta en despliegues reales. La 1.7 sigue recibiendo soporte, pero la rama 1.6 entro en fin de soporte en marzo de 2025 y forzo a muchos equipos a plantear el salto. En este tiempo han aparecido suficientes informes para hacer una lectura honesta: que se rompe, que mejora y cuando compensa planificar la migración.

Este post es el resumen de lo que he visto al migrar varios clusters pequeños y un entorno de Docker Swarm con 70 contenedores. No pretende ser exhaustivo sobre todos los breaking changes, solo los que importan en despliegues tipicos.

Que trae 2.0 que justifique la migración

Dejando a un lado la limpieza interna, hay cuatro cosas que el cambio aporta y que tienen valor operativo concreto.

Soporte nativo de sandboxes. Kata Containers y Firecracker pueden integrarse como runtimes via la API de sandbox sin necesidad de shims externos. Para equipos que evalulan aislamiento reforzado esto reduce el número de piezas moviles en el stack.

CRI v1 estable y v1alpha2 retirado. Kubernetes 1.26 en adelante usa CRI v1 por defecto. containerd 2.0 elimina la implementación de v1alpha2, lo cual simplifica el código pero rompe compatibilidad con kubelet anteriores a 1.26. Si el cluster esta en 1.26 o superior no importa; si hay nodos con kubelet mas viejo, hay que actualizarlos antes.

Mejoras en el runtime shim. El shim de runc se refactorizo y consume menos memoria por contenedor. En un host con cientos de contenedores el ahorro es perceptible: del orden de decenas de megabytes menos de overhead total. No es dramatico pero suma en cargas densas.

NRI como API de plugins estable. El Node Resource Interface, que antes era experimental, es ahora la interfaz oficial para integrar CNI custom, device plugins y agentes de seguridad. Si el cluster tiene alguno de estos, el cambio a NRI es la via sostenible.

Lo que se rompe al migrar

No es una actualizacion drop-in en la mayoria de casos. Hay al menos cinco sitios donde tuve que tocar configuración o scripts.

El primero es el formato del archivo de configuración. La clausula versión = 2 deja de reconocerse, hay que declarar versión = 3 en /etc/containerd/config.toml. Scripts de Ansible o Puppet que inyectan configuración deben ajustar la plantilla. El propio containerd 2.0 convierte automaticamente la versión 2 pero emite aviso, y en la 2.1 planean retirar la conversion automática.

El segundo son los plugins desregistrados. Varios plugins del tipo io.containerd.grpc.v1.introspection cambiaron de namespace o nombre. Si hay integraciones externas que hacen introspeccion de plugins (raro pero ocurre), hay que revisar. En mi caso afecto a un exporter de métricas que se estaba consumiendo valores de la API vieja.

El tercero es el soporte de Schema 1 de imagenes OCI retirado. Imagenes viejas construidas antes de 2017 pueden ser Schema 1 y containerd 2.0 no las ejecuta. La mayoria de registros modernas convierten al pullar, pero si hay imagenes en registros privados antiguos hay que reempaquetarlas. Afecto a dos imagenes legacy en un entorno que migre.

El cuarto es el comportamiento de ctr en contenedores compartidos entre namespaces. Algunos comandos que antes trabajaban silenciosamente across namespaces ahora piden el namespace explicito. Los scripts que usaban ctr sin --namespace fallan con errores claros, pero si esos scripts corren en cron o CI hay que adaptarlos.

El quinto es la deprecacion de CNI 0.x. containerd 2.0 requiere plugins CNI 1.0 o superior. Si el cluster tiene un deployment antiguo con Calico 3.17 o Flannel pre-0.20 hay que actualizarlos antes o después (idealmente antes).

El caso de Docker Swarm

Para quien aun opera Swarm (como en nuestro caso con vps1), la migración es mas suave que en Kubernetes porque Swarm no depende de CRI. Lo que matters es que Docker Engine acepte containerd 2.0 como runtime subyacente.

Docker Engine 27.x, publicado a lo largo de 2024, ya soporta containerd 2.0 como backend. Para instalaciones que usan el containerd embebido en Docker la migración llega al actualizar Docker. Para instalaciones con containerd standalone (el containerd del sistema usado por Docker Engine via socket, que es como funciona en servidores Debian bien configurados) hay que actualizar primero containerd, verificar que Docker arranca y luego Docker Engine.

En el entorno que migre, el orden fue: actualizar containerd de 1.7 a 2.0, reiniciar containerd.service, verificar ctr versión y que los contenedores existentes seguian corriendo, luego subir Docker Engine a 27.x y reiniciar docker.service. No hubo caidas de contenedores, pero si un par de imagenes que tuve que reconstruir porque eran Schema 1.

Observabilidad durante la migración

Algo que aprendi a la fuerza en una migración anterior es que el containerd por defecto no emite métricas prometheus sin configurarlo. Antes de migrar hay que asegurarse de que metrics.address = "0.0.0.0:1338" esta en la config y de que el exporter esta scrapeado. Sin eso, la unica señal de que algo va mal es que los contenedores mueren y no hay como correlacionar con un cambio de comportamiento del runtime.

Las métricas clave a vigilar durante y después de la migración son: el contador de contenedores activos, el ratio de pull fallidos, la latencia de la API de tasks y los errores de shim. Con esas cuatro señales cubiertas, una migración que va mal se detecta en minutos en vez de horas.

Mi lectura

containerd 2.0 es una migración obligatoria pero no urgente para la mayoria de equipos. El mayor motor para saltar es que la 1.6 ya no tiene soporte, no que la 2.0 traiga funcionalidades imprescindibles. Si el cluster esta en 1.7 y no tiene presion regulatoria, esperar a la 2.1 (prevista para finales de 2025) puede evitar algunos bordes afilados que todavia veo.

Lo que me parece mas positivo del release es la limpieza. Retirar v1alpha2 del CRI y Schema 1 de OCI son decisiones que la comunidad llevaba postponiendo hace anios y que pagarse dividendos en mantenibilidad futura. No son cambios divertidos pero son cambios sanos.

Mi recomendacion práctica: si operas Kubernetes, mira el kubelet de todos los nodos antes de tocar nada, actualiza Calico o el CNI que uses a 1.0 y ten una ventana de mantenimiento con plan de reversion. Si operas Swarm, es mas sencillo pero vigila las imagenes antiguas. Si operas docker puro sin Swarm ni Kubernetes, la migración es casi transparente siempre que actualices Docker Engine en el mismo ciclo.

Entradas relacionadas