Descripción general de la red

En esta página, se proporciona una descripción general de los aspectos principales de las herramientas de redes de Google Kubernetes Engine. Esta información le resultará útil a quienes recién están comenzando con Kubernetes, así como a operadores de clústeres o desarrolladores de aplicaciones experimentados que necesitan más conocimientos sobre las herramientas de redes de Kubernetes para diseñar mejor las aplicaciones o configurar las cargas de trabajo de Kubernetes.

Kubernetes te permite definir de manera expresa cómo se implementan tus aplicaciones, cómo las aplicaciones se comunican entre sí y con el plano de control de Kubernetes, y cómo los clientes pueden llegar a tus aplicaciones. En esta página, también se proporciona información sobre cómo GKE configura los servicios de Google Cloud, en lo que respecta a las herramientas de redes.

Cuando usas Kubernetes para organizar tus aplicaciones, es importante cambiar tu forma de pensar acerca del diseño de red de tus aplicaciones y sus hosts. Con Kubernetes, piensas en cómo se comunican los pods, los servicios y los clientes externos, en lugar de pensar en cómo se conectan tus hosts o VM.

La red definida por software (SDN) de avanzada de Kubernetes permite el enrutamiento y el reenvío de paquetes para pods, servicios y nodos a través de diferentes zonas en el mismo clúster regional. Kubernetes y Google Cloud también configuran de forma dinámica las reglas de filtrado de IP, tablas de enrutamiento y reglas de firewall en cada nodo, según el modelo declarativo de las implementaciones de Kubernetes y la configuración de clústeres en Google Cloud.

Requisitos previos

En esta página, se usa terminología relacionada con las capas de transporte, Internet y aplicación del conjunto de protocolo de Internet, incluidos HTTP y DNS, pero no es necesario ser experto en estos temas.

Además, puede que este contenido te parezca más fácil si tienes una comprensión básica de los conceptos y utilidades de administración de red de Linux, como las reglas y el enrutamiento iptables.

El modelo de herramientas de redes de Kubernetes se basa en gran medida en las direcciones IP. Los servicios, pods, contenedores y nodos se comunican mediante direcciones IP y puertos. Kubernetes proporciona tipos diferentes de balanceo de cargas para dirigir el tráfico a los pods correctos. Todos estos mecanismos se describen en detalle más adelante en esta sección. Ten en cuenta los siguientes términos mientras avanzas en la lectura:

  • ClusterIP: la dirección IP asignada a un servicio. También se la llama “IP de clúster” en otros documentos. Esta dirección es estable durante el ciclo de vida del servicio, como se explica en la sección Servicios más adelante.
  • IP de pod: la dirección IP asignada a un pod determinado. Es efímera, como se explica en la sección Pods más adelante.
  • IP de nodo: la dirección IP asignada a un nodo determinado.

Herramientas de redes dentro del clúster

En esta sección, se analizan las herramientas de redes dentro de un clúster de Kubernetes, en relación con la asignación de IP, los pods y los servicios.

Asignación de IP

Kubernetes usa varios rangos de IP para asignar direcciones IP a nodos, pods y servicios.

  • Cada nodo tiene una dirección IP asignada desde la red de la nube privada virtual (VPC) del clúster. Esta IP de nodo proporciona conectividad a partir de componentes de control, como kube-proxy y kubelet, al servidor de la API de Kubernetes. Esta IP es la conexión del nodo con el resto del clúster.
  • Cada nodo tiene un grupo de direcciones IP que GKE asigna a los pods que se ejecutan en ese nodo (un bloque CIDR /24 de forma predeterminada). Como opción, puedes especificar el rango de IP cuando creas el clúster. La característica de rango CIDR de pod flexible te permite reducir el tamaño del rango de direcciones IP de pod para los nodos de un grupo de nodos determinado.

  • Cada pod tiene una única dirección IP asignada desde el rango de CIDR de pod de su nodo. Esta dirección IP se comparte entre todos los contenedores que se ejecutan dentro del pod y los conecta a otros pods que se ejecutan en el clúster.

  • Cada servicio tiene una dirección IP, llamada ClusterIP, asignada desde la red de VPC del clúster. Tienes la opción de personalizar la red de VPC cuando creas el clúster.

Para obtener más información, visita Consideraciones para el tamaño de clústeres.

Pods

En Kubernetes, un pod es la unidad implementable más básica dentro de un clúster de Kubernetes. Un pod ejecuta uno o más contenedores. Cero o más pods se ejecutan en un nodo. Cada nodo en el clúster es parte de un grupo de nodos. En GKE, estos nodos son máquinas virtuales que se ejecutan cada una como una instancia en Compute Engine.

Los pods también pueden adjuntarse a volúmenes de almacenamiento externo y otros recursos personalizados. En este diagrama se muestra un solo nodo que ejecuta dos pods, cada uno adjunto a dos volúmenes.

Diagrama que muestra un solo nodo que ejecuta dos pods, como se describe en el párrafo anterior

Cuando Kubernetes programa un pod con el fin de que se ejecute en un nodo, crea un espacio de nombres de red para el pod en el kernel de Linux del nodo. Este espacio de nombres de red conecta la interfaz de red física del nodo, como eth0, con el pod mediante una interfaz de red virtual, de modo que los paquetes puedan fluir hacia el pod y desde este. La interfaz de red virtual asociada en el espacio de nombres de la red raíz del nodo se conecta a un puente de Linux que permite la comunicación entre los pods en el mismo nodo. Un pod también puede enviar paquetes fuera del nodo con la misma interfaz virtual.

Kubernetes asigna una dirección IP (la IP del pod) a la interfaz de red virtual en el espacio de nombres de la red del pod desde un rango de direcciones reservadas para pods en el nodo. Este rango de direcciones es un subconjunto del rango de direcciones IP asignado al clúster para pods, que puedes configurar cuando creas un clúster.

Un contenedor que se ejecuta en un pod utiliza el espacio de nombres de red del pod. Desde el punto de vista del contenedor, el pod parece ser una máquina física con una interfaz de red. Todos los contenedores en el pod ven esta misma interfaz de red. Todos los localhost de los contenedores están conectados, a través del pod, a la interfaz de red física del nodo, como eth0.

Ten en cuenta que esta conectividad difiere de forma drástica según si usas la CNI nativa de GKE o eliges usar la implementación de Calico mediante la habilitación de la política de red cuando creas el clúster.

  • Si usas la CNI de GKE, un extremo del par de veth se conecta al pod en su espacio de nombres y el otro al dispositivo de puente de Linux, cbr0. En este caso, en el siguiente comando se muestran las diferentes direcciones MAC de pods conectadas a cbr0:

    arp -n
    

    Además, si invocas lo siguiente en el contenedor de la caja de herramientas, se muestra el final del espacio de nombres raíz de cada par de veth adjunto a cbr0:

    brctl show cbr0
    
  • Si la política de red está habilitada, un extremo del par de veth se adjunta al pod y el otro a eth0. En este caso, en el siguiente comando se muestran las diferentes direcciones MAC de pods conectadas a distintos dispositivos de veth.

    arp -n
    

    Además, si invocas lo siguiente en el contenedor de la caja de herramientas, se muestra que no hay un dispositivo puente de Linux llamado cbr0:

    brctl show
    

Las reglas de iptables, que facilitan el reenvío dentro del clúster, difieren de un proceso a otro. Es importante tener esto en cuenta durante la solución detallada de problemas de conectividad.

De manera predeterminada, cada pod tiene acceso ilimitado a todos los otros pods que se ejecutan en todos los nodos del clúster, pero puedes limitar el acceso entre los pods. Kubernetes elimina y recrea pods regularmente. Esto sucede cuando se actualiza un grupo de nodos, cuando se cambia la configuración expresa del pod o la imagen de un contenedor, o cuando un nodo deja de estar disponible. Por lo tanto, la dirección IP de un pod es un detalle de implementación en el que no debes confiar. Kubernetes proporciona direcciones IP estables con servicios.

Servicios

En Kubernetes, puedes asignar pares clave-valor arbitrarios, denominados etiquetas, a cualquier recurso de Kubernetes. Kubernetes usa etiquetas para agrupar varios pods relacionados en una unidad lógica denominada un "servicio". Un servicio tiene una dirección IP y puertos estables, y proporciona un balanceo de cargas entre el conjunto de pods cuyas etiquetas coinciden con todas las etiquetas que defines en el selector de etiquetas cuando creas el servicio.

En el siguiente diagrama, se muestran dos servicios independientes, cada uno de los cuales se compone de varios pods. Todos los pods del diagrama tienen la etiqueta app=demo, pero sus otras etiquetas son diferentes. El servicio “frontend” hace coincidir todos los pods con app=demo y component=frontend, mientras que el servicio “users” los hace coincidir con app=demo y component=users. El Client Pod no coincide exactamente con ninguno de los dos selectores de servicio, por lo que no forma parte de ninguno de los servicios. Sin embargo, el Client Pod puede comunicarse con cualquiera de los servicios porque se ejecuta en el mismo clúster.

Diagrama de dos servicios independientes, como se describe en el párrafo anterior

Kubernetes asigna una dirección IP estable y confiable a cada servicio recientemente creado (el ClusterIP) del grupo de direcciones IP disponibles del servicio del clúster. Kubernetes también asigna un nombre de host al ClusterIP mediante la adición de una entrada de DNS. El ClusterIP y el nombre de host son únicos dentro del clúster y no cambian a lo largo del ciclo de vida del servicio. Kubernetes solo libera el ClusterIP y el nombre de host si el servicio se borra de la configuración del clúster. Puedes acceder a un pod en buen estado que esté ejecutando tu aplicación con ClusterIP o el nombre de host del servicio.

A primera vista, un servicio podría parecer un punto único de falla para tus aplicaciones. Sin embargo, Kubernetes distribuye tráfico de la manera más equitativa posible en todo el conjunto de pods, que se ejecuta en muchos nodos. Por esto, un clúster puede resistir una interrupción que afecta a uno o más nodos (pero no a todos).

Kubernetes administra la conectividad entre pods y servicios con el componente kube-proxy, que se ejecuta en cada nodo. kube-proxy, que no es un proxy en línea, sino un controlador de balanceo de cargas basado en salida, mira el servidor de la API de Kubernetes y asigna de forma continua el ClusterIP a pods en buen estado. Para esto, agrega y quita reglas NAT de destino (DNAT) al subsistema iptables del nodo. Cuando un contenedor que se ejecuta en un pod envía tráfico a un ClusterIP de servicio, el nodo selecciona un pod de manera aleatoria y direcciona el tráfico a ese pod.

Cuando configuras un servicio, puedes optar por volver a asignar el puerto de escucha mediante la definición de valores para port y targetPort.

  • El port es por donde los clientes llegan a la aplicación.
  • El targetPort es el puerto en el que la aplicación está escuchando el tráfico dentro del pod.

Para administrar la reasignación de este puerto, kube-proxy agrega y quita reglas iptables en el nodo.

En este diagrama, se muestra el flujo de tráfico desde un pod de cliente a un pod de servidor en un nodo diferente. El cliente se conecta al servicio en 172.16.12.100:80. El servidor de API de Kubernetes mantiene una lista de pods que ejecutan la aplicación. En el proceso kube-proxy, se usa esta lista en cada nodo para crear una regla iptables con el fin de dirigir el tráfico a un pod apropiado (como 10.255.255.202:8080). El pod cliente no necesita conocer la topología del clúster ni ningún detalle sobre los pods individuales o contenedores dentro de él.

Diagrama que muestra a un cliente que se conecta a un servicio y se direcciona a un pod, como se describe en el párrafo anterior

Herramientas de redes fuera del clúster

En esta sección se explica cómo el tráfico desde fuera del clúster llega a las aplicaciones que se ejecutan dentro de un clúster de Kubernetes. Esta información es importante a la hora de diseñar las cargas de trabajo y las aplicaciones de tu clúster.

Ya leíste sobre cómo Kubernetes usa los servicios para proporcionar direcciones IP estables a aplicaciones que se ejecutan dentro de pods. De forma predeterminada, los pods no exponen una dirección IP externa, ya que kube-proxy administra todo el tráfico de cada nodo. Los pods y sus contenedores pueden comunicarse con libertad, pero las conexiones fuera del clúster no pueden acceder al servicio. Por ejemplo, en la ilustración anterior, los clientes fuera del clúster no pueden acceder al servicio frontend a través de su ClusterIP.

GKE proporciona tres tipos diferentes de balanceadores de cargas para controlar el acceso y distribuir el tráfico entrante en tu clúster de la manera más equitativa posible. Puedes configurar un servicio para usar varios tipos de balanceadores de cargas de forma simultánea.

  • Los balanceadores de cargas externos administran el tráfico que viene desde fuera del clúster y fuera de tu red de nube privada virtual (VPC) de Google Cloud. Usa reglas de reenvío asociadas con la red de Google Cloud para enrutar el tráfico a un nodo de Kubernetes.
  • Los balanceadores de cargas internos administran el tráfico que viene de la misma red de VPC. Al igual que los balanceadores de cargas externos, usan reglas de reenvío asociadas con la red de Google Cloud para enrutar el tráfico a un nodo de Kubernetes.
  • Los balanceadores de cargas de HTTP(S) son balanceadores de cargas externos especializados que se usan para el tráfico de HTTP(S). Usan un recurso Ingress en lugar de una regla de reenvío para direccionar el tráfico a un nodo de Kubernetes.

Cuando el tráfico llega a un nodo de Kubernetes, se maneja de la misma manera, independientemente del tipo de balanceador de cargas. El balanceador de cargas no tiene conocimiento sobre qué nodos del clúster están ejecutando pods para su servicio. En cambio, equilibra el tráfico en todos los nodos del clúster, incluso en los que no ejecutan el pod relevante. En un clúster regional, la carga se distribuye en todos los nodos, en todas las zonas para la región del clúster. Cuando el tráfico se direcciona a un nodo, el nodo direcciona el tráfico a un pod, que puede estar ejecutándose en el mismo nodo o en uno diferente. El nodo reenvía el tráfico a un pod elegido al azar mediante las reglas iptables que kube-proxy administra en el nodo.

En el diagrama siguiente, el balanceador de cargas de la red dirige el tráfico al nodo central, y el tráfico se redirecciona a un pod en el primer nodo.

Diagrama que muestra el tráfico que se direcciona desde un nodo a un pod en otro nodo, como se describe en el párrafo anterior

Cuando un balanceador de cargas envía tráfico a un nodo, el tráfico podría desviarse hacia un pod en un nodo diferente. Esto requiere saltos de red adicionales. Si deseas evitar los saltos adicionales, puedes especificar que el tráfico vaya a un pod que se encuentre en el mismo nodo que recibe el tráfico inicialmente.

Para especificar que el tráfico vaya a un pod en el mismo nodo, configura externalTrafficPolicy como Local en tu manifiesto de servicio de la siguiente manera:

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: demo
    component: users
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

Cuando configuras externalTrafficPolicy como Local, el balanceador de cargas envía tráfico solo a los nodos que tienen un pod en buen estado que pertenece al servicio. El balanceador de cargas usa una verificación de estado para determinar qué nodos tienen los pods adecuados.

Balanceador de cargas externo

Si tu servicio necesita ser accesible desde fuera del clúster y de tu red de VPC, puedes configurar tu servicio como un LoadBalancer. Para esto, establece el campo type del servicio como LoadBalancer cuando definas el servicio. Luego, GKE aprovisiona un balanceador de cargas de red frente al servicio. El balanceador de cargas de red conoce todos los nodos de tu clúster y configura las reglas de firewall de tu red de VPC para permitir conexiones al servicio desde fuera de la red VPC, mediante el uso de la dirección IP externa del servicio. Puedes asignar una dirección IP externa estática al servicio. Para obtener más información, visita Configura nombres de dominio con direcciones IP estáticas.

Detalles técnicos

Cuando se usa el balanceador de cargas externo, el tráfico que llega se enruta en principio a un nodo mediante una regla de reenvío asociada con la red de Google Cloud. Después de que el tráfico llega al nodo, el nodo usa su tabla NAT iptables para elegir un pod. kube-proxy administra las reglas iptables en el nodo.

Balanceador de cargas interno

Para el tráfico que necesita llegar a tu clúster desde dentro de la misma red de VPC, puedes configurar tu servicio, de manera que aprovisione un balanceador de cargas interno. El balanceador de cargas interno elige una dirección IP de la subred de VPC de tu clúster en lugar de una dirección IP externa. Las aplicaciones o los servicios dentro de la red de VPC pueden usar esta dirección IP para comunicarse con servicios dentro del clúster.

Detalles técnicos

Google Cloud proporciona la funcionalidad de balanceo de cargas interno. Cuando el tráfico llega a cierto nodo, ese nodo usa su tabla NAT iptables para elegir un pod, incluso si el pod está en un nodo diferente. kube-proxy administra las reglas iptables en el nodo.

Para obtener más información sobre los balanceadores de cargas internos, visita la documentación del balanceador de cargas interno.

Balanceador de cargas de HTTP(S)

Muchas aplicaciones, como las API de servicios web RESTful, se comunican mediante HTTP(S). Puedes permitir que clientes externos a tu red de VPC accedan a este tipo de aplicación con un recurso Ingress de Kubernetes. Un recurso Ingress te permite asignar nombres de host y rutas de URL a servicios dentro del clúster. Cuando usas un balanceador de cargas de HTTP(S), debes configurar el servicio para usar un NodePort, así como un ClusterIP. Cuando el tráfico accede al servicio en una IP de nodo en el NodePort, GKE direcciona el tráfico a un pod en buen estado para el servicio. Puedes especificar un NodePort o permitir que GKE asigne de manera aleatoria un puerto sin usar.

Cuando creas el recurso Ingress, GKE aprovisiona un balanceador de cargas de HTTP(S) en el proyecto de Google Cloud. El balanceador de cargas envía una solicitud a la dirección IP de un nodo en el NodePort. Una vez que la solicitud llega al nodo, el nodo usa su tabla NAT iptables para elegir un pod. kube-proxy administra las reglas iptables en el nodo.

En esta definición de Ingress, se direcciona el tráfico para demo.example.com a un servicio llamado frontend en el puerto 80, y para demo-backend.example.com a un servicio llamado users en el puerto 8080.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo
spec:
  rules:
  - host: demo.example.com
    http:
      paths:
      - backend:
          serviceName: frontend
          servicePort: 80
  - host: demo-backend.example.com
    http:
      paths:
      - backend:
          serviceName: users
          servicePort: 8080

Para obtener más información, consulta Balanceo de cargas HTTP(s) con Ingress.

Detalles técnicos

Cuando creas un objeto Ingress, el controlador de Ingress de GKE configura un balanceador de cargas de HTTP(S) de Google Cloud según las reglas del manifiesto de Ingress y los manifiestos de servicio asociados. El cliente envía una solicitud al balanceador de cargas de HTTP(S). El balanceador de cargas es un proxy real; elige un nodo y reenvía la solicitud a la combinación NodeIP:NodePort de ese nodo. El nodo usa su tabla de NAT iptables para elegir un pod. kube-proxy administra las reglas iptables en el nodo.

Limita la conectividad a pods y servicios

De manera predeterminada, todos los pods que se ejecutan dentro del mismo clúster pueden comunicarse libremente. Sin embargo, puedes limitar la conectividad dentro de un clúster de diferentes maneras, según lo que necesites.

Limita el acceso entre pods

Puedes limitar el acceso entre pods con una política de red. Las definiciones de políticas de red te permiten restringir la entrada y la salida de pods según una combinación arbitraria de etiquetas, rangos de IP y números de puerto. De manera predeterminada, no hay una política de red, por lo que se permite todo el tráfico entre pods en el clúster. Tan pronto creas la primera política de red en un espacio de nombres, se deniega todo el resto del tráfico.

Visita Crea una política de red de clúster para obtener más detalles sobre cómo especificar la política.

Después de crear una política de red, debes habilitarla de manera explícita para el clúster. Si deseas obtener más información, visita Cómo configurar políticas de red para aplicaciones.

Limita el acceso a un balanceador de cargas externo

Si tu servicio usa un balanceador de cargas externo, el tráfico desde cualquier dirección IP externa puede acceder a tu servicio de manera predeterminada. Para restringir qué rangos de direcciones IP pueden acceder a los extremos dentro de tu clúster, debes configurar la opción loadBalancerSourceRanges cuando configuras el servicio. Puedes especificar varios rangos y actualizar la configuración de un servicio en ejecución en cualquier momento. La instancia de kube-proxy que se ejecuta en cada nodo configura las reglas de iptables de ese nodo para denegar todo el tráfico que no coincida con los loadBalancerSourceRanges especificados. No se crea ninguna regla de firewall de VPC.

Limita el acceso a un balanceador de cargas de HTTP(S)

Si tu servicio usa el balanceador de cargas de HTTP(S), puedes usar una política de seguridad de Google Cloud Armor para limitar qué direcciones IP externas pueden acceder a tu servicio y qué respuestas mostrar cuando se niega el acceso debido a la política de seguridad. Puedes configurar Stackdriver Logging para registrar información sobre estas interacciones.

Si una política de seguridad de Google Cloud Armor no es muy precisa, puedes habilitar Identity-Aware Proxy en tus extremos para implementar la autenticación y autorización basadas en el usuario en tu aplicación. Si quieres obtener más información, consulta el instructivo detallado para configurar IAP.

Próximos pasos