Container Networks – CNI (Kubernetes)

En el articulo anterior se mencionó como Docker realizo cambios en su arquitectura para delegar responsabilidades del motor de ejecución. Este articulo abordará la segunda propuesta de Container Networks que actualmente es utilizada por Kubernetes para la administración de controladores de red.

Container Network Interface (CNI)

CNI

Es una especificación neutral propuesta por CoreOS y que ha sido adoptada por proyectos como Apache Mesos, Cloud Foundry, Kubernetes y rkt.

Los plugins son implementaciones de las acciones definidas por la especificación del CNI y que son consumidas por el motor de ejecución. Los binarios de los plugins necesitan al menos el permiso de CAP_NET_ADMIN para ser ejecutados correctamente. La acción a ejecutar por el binario es especificada mediante la variable de entorno CNI_COMMAND y esta acción solo puede ser una alguna de las siguientes opciones:

  • ADD: La cual permite agregar una interfaz de red a un contenedor especifico. Esta acción puede ser ejecutada múltiples veces para proporcionar varias interfaces de red a un solo contenedor.
  • DEL: Remueve una interfaz de red especifica a un contenedor.
  • CHECK: Se utiliza por el motor de ejecución para validar que la configuración de red se mantiene según lo solicitado.
  • VERSION: Imprime la versión de CNI soportada por el plugin.

Flujo de asignación de red en Kubernetes

Kubernetes utiliza el concepto de Pod para referirse a un conjunto de uno o mas contenedores que comparten una misma dirección IP. Esta dirección IP permite la comunicación de los contenedores hacia el exterior lo cual resulta importante comprender el proceso de su asignación.

Kubelet es el componente responsable del flujo en la creación del Pod, a continuación tratare de explicar la serie de pasos realizados por el componente de Dockershim en la creacion del Pod y asignación de dirección IP. Cabe señalar que Dockershim sera eliminado en la version 1.23 de Kubernetes, pero debido a la simplicidad de su método RunPodSandbox nos permite conocer mejor el flujo.

  1. Se asegura de tener la imagen del pause container. Este contenedor nos sirve como contenedor padre de los contenedores definidos en el pod y tiene dos funciones primordiales:
    1. Como la base para compartir Linux namespaces dentro del pod.
    2. Como PID 1 para cada pod.
  2. Crea la configuración requerida por el pause container, llamado la API de Docker.
  3. Crea un checkpoint del pause container en /var/lib/dockershim/sandbox a traves del administrador de Checkpoints.
  4. Inicia el pause container, nuevamente consumiendo la API de Docker.
  5. Configura las interfaces red (loopback y default) para el pause container. Esto lo realiza a traves de una serie de llamadas a los binarios de CNI utilizando su acción ADD.

Como puede observarse, la configuración de red del pause container no se realiza a traves del API de Docker sino a traves del CNI. Estos CNIs utilizan archivos de configuración en formato JSON, para definir entradas y salidas de datos esperados. Múltiples CNI plugins pueden ser ejecutados por el motor de ejecución.