Configurar varias interfaces de red para pods

En este documento se describe cómo configurar Google Distributed Cloud (solo software) para VMware con el fin de proporcionar varias interfaces de red (multi-NIC) a tus pods. La función de varias NICs para pods puede ayudar a separar el tráfico del plano de control del tráfico del plano de datos, lo que crea un aislamiento entre los planos. Las interfaces de red adicionales también habilitan la función de multidifusión para tus pods. Se admite la función de varias NICs para pods en clústeres de usuarios, pero no en clústeres de administrador.

Esta página está dirigida a especialistas en redes que instalan, configuran y ofrecen asistencia para equipos de redes. Para obtener más información sobre los roles habituales y las tareas de ejemplo a las que hacemos referencia en el contenido de Google Cloud , consulta Roles y tareas de usuario habituales de GKE.

El aislamiento del plano de red es importante para los sistemas que usan virtualizaciones de funciones de red (NFVs), como las redes definidas por software en una red de área amplia (SD-WAN), un agente de seguridad de acceso a la nube (CASB) y cortafuegos de nueva generación (NG-FWs). Estos tipos de NFVs dependen del acceso a varias interfaces para mantener separados los planos de control y de datos.

La configuración de varias interfaces de red permite asociar interfaces de red con grupos de nodos, lo que puede mejorar el rendimiento. Por ejemplo, un clúster puede contener una combinación de tipos de nodos. Cuando agrupas máquinas de alto rendimiento en un grupo de nodos, puedes crear interfaces adicionales en el grupo de nodos para mejorar el flujo de tráfico.

Configurar varias interfaces de red

Por lo general, hay tres pasos para configurar varias interfaces de red para tus pods:

  1. Habilita la opción de varias NICs en tu clúster de usuarios mediante los campos multipleNetworkInterfaces y enableDataplaneV2 del archivo de configuración del clúster.

  2. Especifica las interfaces de red con la sección additionalNodeInterfaces del archivo de configuración del clúster y crea uno o varios recursos personalizados NetworkAttachmentDefinition.

  3. Asigna interfaces de red a los pods con la anotación k8s.v1.cni.cncf.io/networks.

Habilitar varias NICs

Para habilitar la función de varias NICs en tus pods, asigna el valor true a los campos multipleNetworkInterfaces y enableDataplaneV2 del archivo de configuración del clúster de usuarios.

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
  ...

Especificar interfaces de red

En el archivo de configuración del clúster, especifica interfaces de red de nodos adicionales en la sección additionalNodeInterfaces.

Por ejemplo, a continuación se muestra una parte de un archivo de configuración de clúster de usuarios que muestra una interfaz de red de nodos adicional:

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
network:
  serviceCIDR: "10.96.0.0/20"
  podCIDR: "192.168.0.0/16"
  vCenter:
    networkName: network-private310
  ...
  # New multiple network configs
  additionalNodeInterfaces:
  - networkName: "gke-network-1"
    ipBlockFilePath: "my-block-yaml"
    type: static

Después de crear un clúster con la configuración anterior, debes crear uno o varios recursos personalizados de NetworkAttachmentDefinition (NAD) en tu clúster de usuario, donde especificarás interfaces de red adicionales. Los NetworkAttachmentDefinitions corresponden a las redes que están disponibles para tus Pods. En el siguiente ejemplo se muestra un manifiesto de un NetworkAttachmentDefinition:

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-1
  namespace: default
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "ipvlan",
  "master": "ens224", # defines the node interface that this Pod interface would map to
  "mode": "l2",
  "ipam": {
    "type": "whereabouts",
    "range": "172.16.0.0/24"
   }
}'

Guarda el manifiesto como un archivo YAML (por ejemplo, my-nad.yaml) y crea el NetworkAttachmentDefinition:

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] apply -f my-nad.yaml

Asignar interfaces de red a un pod

Usa la anotación k8s.v1.cni.cncf.io/networks para asignar una o varias interfaces de red a un pod. Cada interfaz de red se especifica con un espacio de nombres y el nombre de un NetworkAttachmentDefinition, separados por una barra diagonal (/). Usa una lista separada por comas para especificar varias interfaces de red.

En el siguiente ejemplo, se asignan dos interfaces de red al pod samplepod. Las interfaces de red se especifican mediante los nombres de dos NetworkAttachmentDefinitions, gke-network-1 y gke-network-2, que se crearon en el espacio de nombres default.

---
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: default/gke-network-1,default/gke-network-2
spec:
  containers:
  ...

Restringir interfaces de red a un conjunto de nodos

Si no quieres que un NetworkAttachmentDefinition se aplique a todo un clúster, puedes limitar su funcionalidad a un conjunto de nodos.

Puedes agrupar los nodos del clúster usando la etiqueta estándar asignada al nodo o una etiqueta personalizada. A continuación, puedes especificar la etiqueta del nodo en el manifiesto NetworkAttachmentDefinition mediante la anotación k8s.v1.cni.cncf.io/nodeSelector. Google Distributed Cloud obliga a que los pods que hagan referencia a este recurso personalizado se implementen en los nodos que tengan esta etiqueta.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: LABEL_KEY=LABEL_VALUE
  name: gke-network-1
spec:
...

En el siguiente ejemplo se muestra la etiqueta my-label=multinicNP indicada en NetworkAttachmentDefinition y se fuerza la implementación de todos los pods a los que se ha asignado la red gke-network-1 en los nodos que tienen esta etiqueta.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: my-label=multinicNP
  name: gke-network-1
spec:
...

Para aplicar una etiqueta personalizada a un nodo, usa el comando kubectl label nodes:

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes NODE_NAME LABEL_KEY=LABEL_VALUE 

Haz los cambios siguientes:

  • NODE_NAME: el nombre del nodo que estás etiquetando.
  • LABEL_KEY: la clave que se va a usar para la etiqueta.
  • LABEL_VALUE: el valor de la etiqueta.

En este ejemplo, el nodo my-node recibe la etiqueta environment=production:

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes my-node environment=production

Problemas de seguridad

Un NetworkAttachmentDefinition proporciona acceso completo a una red, por lo que los administradores de clústeres deben tener cuidado al proporcionar acceso de creación, actualización o eliminación a otros usuarios. Si un NetworkAttachmentDefinition determinado tiene que aislarse, puedes especificar un espacio de nombres no predeterminado al crearlo, de forma que solo los pods de ese espacio de nombres puedan acceder a él.

En el siguiente diagrama, los pods del espacio de nombres default no pueden acceder a la interfaz de red del espacio de nombres privileged.

Uso de espacios de nombres para aislar el tráfico de red.

Complementos de CNI admitidos

En esta sección se enumeran los plugins de CNI compatibles con la función de varias NICs de Google Distributed Cloud. Usa solo los siguientes complementos al especificar un NetworkAttachmentDefinition.

Creación de interfaces:

  • ipvlan
  • macvlan
  • bridge

Complementos de Meta:

  • portmap
  • sbr
  • tuning

Complementos de IPAM:

  • host-local
  • static
  • whereabouts

Configuración de rutas

Un pod con uno o varios NetworkAttachmentDefinitions asignados tiene varias interfaces de red. De forma predeterminada, la tabla de enrutamiento del Pod en esta situación se amplía solo con las interfaces adicionales disponibles localmente de los NetworkAttachmentDefinitions asignados. Los paquetes destinados a la pasarela predeterminada siguen configurados para usar la interfaz predeterminada del pod, eth0. Puedes modificar este comportamiento con los siguientes complementos de CNI:

  • sbr
  • static
  • whereabouts

Por ejemplo, puede que quieras que la mayor parte del tráfico pase por la puerta de enlace predeterminada, lo que significa que el tráfico se enviará a través de la interfaz de red predeterminada. Sin embargo, quieres que un tráfico específico pase por una de las interfaces no predeterminadas. Puede ser difícil desambiguar el tráfico en función de la IP de destino (enrutamiento normal), ya que el mismo endpoint está disponible en ambos tipos de interfaz. En este caso, el enrutamiento basado en la fuente (SBR) puede ser útil.

Complemento SBR

El complemento sbr permite que la aplicación controle las decisiones de enrutamiento. La aplicación controla lo que se usa como dirección IP de origen de la conexión que establece. Cuando la aplicación decide usar la dirección IP de NetworkAttachmentDefinition como IP de origen, los paquetes llegan a la tabla de enrutamiento adicional que ha configurado sbr. La tabla de sbr enrutamiento envía el tráfico a través de su propia pasarela predeterminada, que pasará por la interfaz de NetworkAttachmentDefinition. La IP de la pasarela predeterminada de esa tabla se controla con el campo gateway de los complementos whereabouts o static. El complemento sbr se ejecuta como un complemento encadenado. Para obtener más información sobre el complemento sbr, incluido el uso, consulta Complemento de enrutamiento basado en la fuente.

En el siguiente ejemplo se muestra "gateway":"21.0.111.254" definido en whereabouts y sbr definido como complemento encadenado después de ipvlan:

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
192.168.0.64 dev eth0 scope link
# ip route list table 100
default via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1

Complementos de ubicación y estáticos

El complemento whereabouts es básicamente una extensión del complemento static y ambos comparten la configuración de enrutamiento. Para ver un ejemplo de configuración, consulta el complemento de gestión de direcciones IP estáticas. Puedes definir una pasarela y una ruta para añadirlas a la tabla de enrutamiento del Pod. Sin embargo, no puedes modificar la puerta de enlace predeterminada del pod de esta forma.

En el siguiente ejemplo se muestra la adición de "routes": [{ "dst": "172.31.0.0/16" }] en NetworkAttachmentDefinition:

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
172.31.0.0/16 via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1
192.168.0.64 dev eth0 scope link

Ejemplos de configuración

En esta sección se ilustran algunas de las configuraciones de red habituales que admite la función de varias NICs.

Un único archivo adjunto de red utilizado por varios pods:

Un solo adjunto de red usado por varios pods.

Varias conexiones de red usadas por un solo pod:

Varias conexiones de red usadas por un solo pod.

Varias asociaciones de red que apuntan a la misma interfaz usada por un solo pod:

Hay varios adjuntos de red que apuntan a la misma interfaz usada por un solo pod.

Se ha usado el mismo archivo de red varias veces en un solo pod:

Se ha usado el mismo archivo adjunto de red varias veces en un solo pod.

Solucionar problemas

Si las interfaces de red adicionales están mal configuradas, los pods a los que se les asignan no se inician. En esta sección se explica cómo encontrar información para solucionar problemas con la función de varias NICs.

Consultar eventos de Pod

Multus informa de los errores a través de los eventos de los pods de Kubernetes. Usa el siguiente comando kubectl describe para ver los eventos de un pod concreto:

kubectl describe pod POD_NAME

Consultar registros

En cada nodo, puedes encontrar los registros de Whereabouts y Multus en las siguientes ubicaciones:

  • /var/log/whereabouts.log
  • /var/log/multus.log

Revisar las interfaces de Pod

Usa el comando kubectl exec para comprobar tus interfaces de Pod. Una vez que se hayan aplicado correctamente los NetworkAttachmentDefinitions, las interfaces de Pod tendrán el siguiente aspecto:

user@node1:~$ kubectl exec samplepod-5c6df74f66-5jgxs -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: net1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:82:3e:f0 brd ff:ff:ff:ff:ff:ff
    inet 21.0.103.112/21 scope global net1
       valid_lft forever preferred_lft forever
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 36:23:79:a9:26:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.2.191/32 scope global eth0
       valid_lft forever preferred_lft forever

Obtener el estado de un pod

Usa kubectl get para obtener el estado de la red de un pod determinado:

kubectl get pods POD_NAME -oyaml

A continuación, se muestra un ejemplo de salida que muestra el estado de un pod con varias redes:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    k8s.v1.cni.cncf.io/network-status: |-
      [{
          "name": "",
          "interface": "eth0",
          "ips": [
              "192.168.1.88"
          ],
          "mac": "36:0e:29:e7:42:ad",
          "default": true,
          "dns": {}
      },{
          "name": "default/gke-network-1",
          "interface": "net1",
          "ips": [
              "21.0.111.1"
          ],
          "mac": "00:50:56:82:a7:ab",
          "dns": {}
      }]
    k8s.v1.cni.cncf.io/networks: gke-network-1