En esta nota vamos a explorar el modelo de Networking de Kubernetes en sus fundamentos y como se adaptó para su implementación en AKS y GKE.
Definiciones iniciales
Container Runtime Interface (CRI):
- Es un plugin utilizado en Kubernetes que habilita al Kubelet (proceso que corre en cada uno de los worker nodes y se comunica con el API del Control Plane) a utilizar diferentes Container Runtimes, como puede ser Containerd.
- El CRI es el principal protocolo de comunicación entre Kubelet y el Container Runtime.
- El CRI es el encargado de realizar todas las tareas de configuración de aislamiento de cada uno de los pods. Estas configuraciones estan estandarizadas.
Network Namespaces en el CRI:
- Una de las tareas que realiza el CRI es la configuración de los Network Namespaces en Linux. Los Network Namespaces son el mecanismo por el cual podemos crear entornos de red independientes dentro del mismo sistema operativo.
- Cada namespace tiene su propio stack de red: interfaces, tablas de enrutamiento, reglas de firewall, etc.
- En el contexto del Container Runtime Interface (CRI), los network namespaces se encargan de proporcionar aislamiento de red para los contenedores.
Container Network Interface (CNI):
- La CNI es una especificación para el estandar de comunicación entre los pods. Tambien se le llame Pod Network.
- Se trata de Plugins que respetan ciertos standares y pueden ser implementados en el cluster de Kubernetes como un Add On.
- CNI define cómo los plugins de red deben crear y gestionar las redes para contenedores, permitiendo la flexibilidad para que cualquier plugin compatible configure la red según las necesidades específicas del clúster.
- CNI facilita la conexión entre los pods, asignando una dirección IP única a cada uno y permitiendo la comunicación entre ellos, ya sea dentro del mismo nodo o en diferentes nodos del clúster.
- La Pod Network es Cluster-Wide.
- Algunos plugins clásicos: Calico, Flannel o Weave.
Fundamentos de Networking en Kubernetes
El networking es una parte FUNDAMENTAL del diseño e implementación de cualquier cluster de Kubernetes.
Hay 4 tipos de comunicación en los que debemos enfocarnos:
Container-to-Container
- Esto es resuelto a través de la implementación de Pods como unidad mínima de implementación de Contenedores.
- Los Cluster de Kubernetes implementan una Pod Network utilizando un Plugin de CNI como Cálico o Weaver.
- Los Contenedores dentro de un Pod pueden comunicarse directamente entre ellos a través de la interfaz de red localhost, ya que comparten la misma dirección IP y el mismo espacio de red. Esto significa que si un contenedor en un pod necesita acceder a otro, puede hacerlo directamente usando
localhost
o127.0.0.1
, lo que hace que esta comunicación sea rápida y eficiente.
Pod-to-Pod
- Tambien hace utilización de la Pod Network implementada a través del CNI Plugin.
- Cada Pod tiene su priopio Network Namespace compartido por todos los contenedores que ejecuta. Se comunican a través de localhost.
- Al ser Cluster-wide, la comunicación Pod-to-Pod permite que los pods se comuniquen entre sí, independientemente del nodo en el que se encuentran.
- Se asignan Ips unicas a cada pod, debe asignarse un rango para se utilizado por todo el cluster.
- El CNI Plugin se encaraga de actualizar y replicar en todos los nodes las tablas de enrutamiento para la comunicación entre los Pods.
- La comunicación se realiza SIN NAT.
- Podemos implementar Network Policies para la restricción de estas comunicación, que por defecto no tienen ninguna restricción en el cluster.
Pod-to-Service
- Los Pods son efimeros: pueden destruirse, crearse o modificarse segun necesitemos. No son confiables para la comunicación de red.
- Es por esto que en Kubernetes nace el concepto de Servicios, estos permiten proveer una ip (long lived) o hostname para varios backend pods. Los pods pueden cambiar pero el servicio se mantiene constante.
External-to-Service
- Para la comunicación externa puede utilizarse el Ingress, que permite a los servicios ser accedidos desde fuera del cluster.
- El ingress permite la comunicación de L7 (application). Permite utilizar en mecanismo de configuración de HTTP/S protocol-aware que entiende conceptos como URIs, hostnames, paths, entre otros. Permite mappear traffico de manera “Inteligente” a differentes backends.
- Existen differentes Ingress Controllers que podemos utilizar como NGINX, Traefix o algunos Cloud Provider specific como HTTPS Load Balancers en GCP o App Gateway en Azure.
- Tambien existe un mecanismo mas simplificado y menos configurable que es el Service Type: LoadBalancer que normalmente se integra con un LB L4 (network) en los Cloud Providers.
Asignación de IP
Dentro del Cluster las IPs son asignadas de la siguiente manera:
- El CNI Plugin asigna las IPs de los Pods.
- Kube-apiserver asigna las ips de los servicios.
- Kubelet o el cloud-controller-manager asigna las ips de los Nodos.
Kube-Proxy
- Es un componente Opcional. Ya que su trabajo puede ser sustituido por el CNI Plugin que se implemente.
- Su principal tarea es correr en cada Worker Node e implementa parte del Concepto de Servicios en Kubernetes.
- Mantiene las reglas de red en los nodos que permiten la comunicación hacia los pods desde sessiones en y fuera del cluster.
Utilización de Pods CIDR por nodo
Como hablamos anteriormente, podemos o no utilizar un rango especifico de Pods, es decir, un CIDR asignado especialmente para los Pods. Este valor es sumamente importante en la planificación de nuestro cluster ya que será el que determine la cantidad de nodos que nuestro Node Pool o cluster podrá tener.
Número de Pods por nodo
Este valor determina el tamaño de los CIDR Blocks que son asignados a cada uno de los nodos en GKE. Los pods, luego, son asignados a partir de este rango en cada uno de los nodos.
Esta configuración tiene un valor default a nivel del Cluster, pero este valor puede ser sobrescrito a nivel de cada Node Pool en el cluster.
Es decir que la creación de Nodos está limitada al numero de Pod IPs disponibles en el Pod Address Range.
El setting Max Pods per Node es immutable luego de ser asignado a un node pool. Por eso es muy importante tenerlo en cuenta en nuestra planificación del cada uno de los grupos de nodos.
Ejemplo:
Si configuras el número máximo de pods por nodo en 110 y el rango de direcciones IP secundario para los pods en el clúster en /21
, Kubernetes asignará un rango de IPs /24
a cada nodo. Esto significa que cada nodo tendrá suficiente espacio para asignar hasta 110 direcciones IP a los pods que aloje.
- En este caso, un rango
/24
tiene 256 direcciones IP posibles (2^8), mientras que el rango/21
para el clúster es más amplio y contiene múltiples subrangos/24
. - La cantidad máxima de nodos permitidos se calcula restando los bits de diferencia entre los dos rangos: 224−21=23=82^{24-21} = 2^3 = 8224−21=23=8.
- Por lo tanto, con esta configuración, el clúster puede tener un máximo de 8 nodos.
Si configuramos el número máximo de pods en 8 por nodo y configuras el rango de direcciones IP secundario para los pods en /21
, Kubernetes asignará un rango /28
a cada nodo.
- Un rango
/28
tiene 16 direcciones IP posibles (2^4), suficiente para alojar hasta 8 pods en cada nodo. - La cantidad máxima de nodos en el clúster se calcula como 228−21=27=1282^{28-21} = 2^7 = 128228−21=27=128.
- Así, con esta configuración, el clúster puede soportar hasta 128 nodos.
En el proximo posteo, vamos a ver comparar los modelos de red en GKE, AKS y EKS.
Leave a Reply