Skip to main content

Container Network Interface (CNI)

Hasta el momento, exploramos cómo funcionan los network namespaces, cómo conectar varios de estos namespaces en una red de bridge, cómo crear pares (cables virtuales) con interfaces virtuales, cómo anexar cada extremo al namespace y al bridge, cómo asignar IP y levantarlos, y cómo habilitar el NAT o IP masquerading para comunicación externa.

Observamos también cómo Docker sigue un proceso similar, pero usando estándares de nomenclatura diferentes. Otras soluciones de contenedores resuelven sus desafíos de red de manera similar, incluyendo Kubernetes.

Todas estas soluciones intentan resolver los mismos problemas de forma diferente, pero acaban siguiendo los mismos pasos. ¿Por qué no crear un enfoque estándar único?

Fue en ese escenario que surgió el programa Bridge, que encapsula todos los pasos necesarios para conectar un contenedor a una red de bridge.

Usando un comando simple como:

bridge add 2353245 /var/run/netns/2353245

El container runtime queda liberado de la responsabilidad de implementar esta tarea. Por ejemplo, si un runtime de contenedor invoca el bridge pasando los siguientes parámetros bridge add <container_id> <namespace>, eso sería suficiente.

Si quisieras crear un programa de este tipo para ti mismo, tal vez para un nuevo tipo de red, ¿qué argumentos y comandos deberías pasar? ¿Cómo garantizarías que el programa funcione correctamente con los runtimes existentes? ¿Cómo tener certeza de que runtimes de contenedores como Kubernetes o rkt invocarían tu programa correctamente? Aquí es donde la definición de estándares se vuelve crucial.

CNI es un conjunto de estándares que define cómo los programas deben ser desarrollados para resolver los desafíos de red en un ambiente de runtime de contenedores.

Los programas son llamados plugins. En este caso, el programa bridge al cual nos referimos es un plugin para CNI. CNI define cómo el plugin debe ser desarrollado y cómo los runtimes de contenedores deben invocarlo.

CNI asigna un conjunto de responsabilidades tanto a los runtimes de contenedores como a los plugins. Para los runtimes de contenedores, CNI especifica que son responsables por crear un namespace de red para cada contenedor. Luego, los runtimes deben identificar las redes a las cuales los contenedores deben conectarse e invocar los plugins durante la creación (add) y exclusión (del) de los contenedores. Además, CNI estipula la configuración de los plugins en el ambiente del runtime de contenedores usando un archivo JSON.

Por su parte, los plugins deben soportar argumentos de línea de comando como add, del y check, aceptando parámetros como el namespace de red. También son responsables por la asignación de direcciones IP a los contenedores, por la configuración de rutas necesarias para la comunicación entre contenedores en la red y por la especificación de los resultados en un formato particular. Desde que tanto los runtimes de contenedores como los plugins cumplan estas directrices, pueden coexistir armoniosamente.

CNI incluye un conjunto de plugins soportados, como Bridge, VLAN, IP VLAN, MAC VLAN, WINDOWS, Host Local y DHCP. Además, hay otros plugins disponibles de terceros, como Weave, Flannel, Cilium, VMware NXC, Calico, entre otros. Todos estos implementan las normas de CNI, permitiendo que cualquier runtime de contenedor trabaje con cualquiera de estos plugins.

Sin embargo, Docker no implementa CNI, sino CNM (Container Network Model), que representa el modelo de red de contenedores. CNM es otro estándar que intenta resolver desafíos de red de contenedores similares a CNI, pero con algunas diferencias. Debido a esas diferencias, los plugins CNI no se integran nativamente a Docker. Esto significa que no puedes ejecutar un contenedor Docker y especificar el plugin de red para usar CNI y especificar uno de estos plugins. Pero esto no significa que no puedas usar Docker con CNI de ninguna forma. Basta trabajar alrededor de eso, como creando un contenedor Docker sin ninguna configuración de red y después invocando manualmente el plugin del bridge. Eso es prácticamente lo que Kubernetes hace cuando crea contenedores Docker: los crea sin red y entonces invoca los plugins CNI configurados que cuidan del resto de la configuración.