Configura interfaces de red múltiples para Pods

En este documento, se describe cómo configurar Google Distributed Cloud para proporcionar varias interfaces de red, varias NIC, para tus Pods. La función de varias NIC para Pods puede ayudar a separar el tráfico del plano de control del tráfico del plano de datos, lo que crea aislamiento entre los planos. Las interfaces de red adicionales también habilitan la capacidad de multidifusión para tus Pods. Los clústeres de usuario admiten varias NIC para los clústeres; no está permitido en los clústeres de administrador.

El aislamiento del plano de red es importante para los sistemas que usan la virtualización de funciones de red (NFV), como una red definida por software en una red de área extensa (SD-WAN), un agente de seguridad para el acceso a la nube (CASB) y firewalls de última generación (NG-FW). Estos tipos de NFV dependen del acceso a interfaces múltiples para mantener los planos de datos y de control separados.

La configuración de interfaces de red múltiples admite la asociación de interfaces de red con grupos de nodos, lo que puede proporcionar beneficios de rendimiento. Por ejemplo, un clúster puede contener una combinación de tipos de nodo. Cuando agrupas máquinas de alto rendimiento en un grupo de nodos, puedes crear interfaces adicionales al grupo de nodos para mejorar el flujo de tráfico.

Configura interfaces de red múltiples

En general, hay tres pasos para configurar interfaces de red múltiples para los Pods:

  1. Habilita varias NIC para tu clúster de usuario mediante los campos multipleNetworkInterfaces y enableDataplaneV2 en el archivo de configuración del clúster.

  2. Especifica interfaces de red con la sección additionalNodeInterfaces en el archivo de configuración del clúster y crea uno o más recursos personalizados de NetworkAttachmentDefinition.

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

Habilitar varias NIC

Habilita varias NIC para tus Pods mediante la configuración de los campos multipleNetworkInterfaces y enableDataplaneV2 en el archivo de configuración del clúster de usuario como true.

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

Especifica 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, esta es una parte de un archivo de configuración del clúster de usuario que muestra una interfaz de red de nodo 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 más recursos personalizados NetworkAttachmentDefinition (NAD) en tu clúster de usuario en el que especifiques interfaces de red adicionales. Las NetworkAttachmentDefinitions corresponden a las redes que están disponibles para tus Pods. En el siguiente ejemplo, se muestra un manifiesto para 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

Asigna interfaces de red a un Pod

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

En el siguiente ejemplo, se asignan dos interfaces de red al Pod samplepod. Las interfaces de red se especifican mediante 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:
  ...

Restringe las interfaces de red a un conjunto de nodos

Si no deseas que un NetworkAttachmentDefinition sea aplicable a un clúster completo, puedes limitar su funcionalidad a un conjunto de nodos.

Puedes agrupar los nodos del clúster mediante la etiqueta estándar asignada al nodo o en tu propia etiqueta personalizada. Luego, puedes especificar la etiqueta del nodo en el manifiesto NetworkAttachmentDefinition con la anotación k8s.v1.cni.cncf.io/nodeSelector. GKE en VMware fuerza la implementación de cualquier Pod que haga referencia a este recurso personalizado 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 que se indica en NetworkAttachmentDefinition y se fuerza la implementación de todos los Pods que tienen asignada la red gke-network-1 a 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 

Reemplaza lo siguiente:

  • NODE_NAME: es el nombre del nodo que deseas etiquetar.
  • LABEL_KEY: es la clave que se usará para la etiqueta.
  • LABEL_VALUE: es el valor de la etiqueta.

En este ejemplo, se le asigna la etiqueta environment=production al nodo my-node:

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

Medidas de seguridad

Una NetworkAttachmentDefinition proporciona acceso completo a una red, por lo que los administradores de clústeres deben tener cuidado cuando proporcionen el acceso de creación, actualización o eliminación a otros usuarios. Si un NetworkAttachmentDefinition determinado debe estar aislado, puedes especificar un espacio de nombres no predeterminado cuando lo crees, en el que solo los Pods de ese espacio de nombres pueden acceder a él.

En el siguiente diagrama, los Pods del espacio de nombres default no pueden acceder a la interfaz de red en el 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 complementos de CNI compatibles con la función de varias NIC para Google Distributed Cloud. Usa solo los siguientes complementos cuando especifiques una NetworkAttachmentDefinition.

Creación de la interfaz:

  • ipvlan
  • macvlan
  • bridge

Complementos de Meta:

  • portmap
  • sbr
  • tuning

Complementos de IPAM:

  • host-local
  • static
  • whereabouts

Configuración de ruta

Un Pod con una o más NetworkAttachmentDefinitions asignadas tiene interfaces de red múltiples. De forma predeterminada, la tabla de enrutamiento del Pod en esta situación se extiende con las interfaces adicionales disponibles de forma local solo de NetworkAttachmentDefinitions asignadas. Los paquetes vinculados a la puerta de enlace predeterminada aún están configurados para usar la interfaz predeterminada del Pod, eth0. Puedes modificar este comportamiento mediante los siguientes complementos de CNI:

  • sbr
  • static
  • whereabouts

Por ejemplo, es posible que desees que la mayor parte del tráfico pase por la puerta de enlace predeterminada, lo que significa que el tráfico pasará por la interfaz de red predeterminada. Sin embargo, deseas que un tráfico específico pase por una de las interfaces no predeterminadas. Puede ser difícil quitar la ambigüedad del tráfico según la IP de destino (enrutamiento normal), porque el mismo extremo está disponible en ambos tipos de interfaces. En este caso, el enrutamiento basado en la fuente (SBR) puede ayudar.

Complemento SBR

El complemento sbr otorga a la aplicación control sobre las decisiones de enrutamiento. La aplicación controla lo que se usa como la dirección IP de origen de la conexión que establece. Cuando la aplicación elige usar la dirección IP de NetworkAttachmentDefinition para su IP de origen, los paquetes llegan a la tabla de enrutamiento adicional sbr configurada. La tabla de enrutamiento sbr envía tráfico a través de su propia puerta de enlace predeterminada, que pasará por la interfaz de NetworkAttachmentDefinition. La IP de la puerta de enlace predeterminada dentro de esa tabla se controla con el campo gateway dentro de los complementos whereabouts o static. El complemento sbr se ejecuta como un complemento en cadena. Para obtener más información sobre el complemento sbr, incluida la información de uso, consulta Complemento de enrutamiento basado en la fuente.

En el siguiente ejemplo, se muestra "gateway":"21.0.111.254" configurado en whereabouts y sbr configurado como complemento en cadena 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 static y whereabouts

El complemento whereabouts es, en esencia, una extensión del complemento static, y ambos comparten la configuración de enrutamiento. Para ver un ejemplo de configuración, consulta Complemento static de administración de dirección IP. Puedes definir una puerta de enlace y una ruta para agregar a la tabla de enrutamiento del Pod. Sin embargo, no puedes modificar la puerta de enlace predeterminada del Pod de esta manera.

En el siguiente ejemplo, se muestra la adición de "routes": [{ "dst": "172.31.0.0/16" }] en la 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 opciones de configuración de red comunes compatibles con la función de varias NIC.

Adjunto de red único usado por varios Pods:

Único adjunto de red que usan varios Pods.

Varios adjuntos de red usados por un solo Pod:

Un solo Pod usa adjuntos de red múltiples.

Varios adjuntos de red que apuntan a la misma interfaz usados por un solo Pod:

Varios adjuntos de red que apuntan a la misma interfaz que usa un solo Pod.

El mismo adjunto de red usado varias veces por un solo Pod:

Un solo Pod usa el mismo adjunto de red varias veces.

Solucionar problemas

Si las interfaces de red adicionales están configuradas de forma incorrecta, no se inician los Pods a los que se asignen. En esta sección, se destaca cómo encontrar información para solucionar problemas con la función de varias NIC.

Verifica los eventos del Pod

Multus informa fallas a través de los eventos de Pods de Kubernetes. Usa el siguiente comando de kubectl describe para ver los eventos de un Pod determinado:

kubectl describe pod POD_NAME

Verifica los registros

Para cada nodo, puedes encontrar los registros de whereabouts y Multus en las siguientes ubicaciones:

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

Revisa las interfaces del Pod

Usa el comando kubectl exec para verificar las interfaces de los Pods. Una vez que las NetworkAttachmentDefinitions se aplican de forma correcta, las interfaces del Pod se ven como el siguiente resultado:

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

Obtén el estado del Pod

Usa kubectl get para recuperar el estado de la red de un Pod determinado:

kubectl get pods POD_NAME -oyaml

A continuación, verás un resultado de muestra del 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