Configurar la red SR-IOV

En este documento se describe cómo configurar la red de virtualización de entrada/salida de raíz única (SR-IOV) para Google Distributed Cloud. SR-IOV proporciona virtualización de E/S para que una tarjeta de interfaz de red (NIC) esté disponible como dispositivo de red en el kernel de Linux. Esto te permite gestionar y asignar conexiones de red a tus pods. El rendimiento mejora, ya que los paquetes se mueven directamente entre la NIC y el pod.

Usa esta función si necesitas una red rápida para tus cargas de trabajo de pods. SR-IOV para Google Distributed Cloud te permite configurar las funciones virtuales (VFs) en los dispositivos compatibles de los nodos de tu clúster. También puedes especificar el módulo del kernel concreto que se va a vincular a las VFs.

Esta función está disponible para clústeres que ejecutan cargas de trabajo, como los clústeres híbridos, independientes y de usuario. La función de redes SR-IOV requiere que el clúster tenga al menos dos nodos.

El proceso de configuración consta de los siguientes pasos generales:

  1. Configura el clúster para habilitar la red SR-IOV.
  2. Configura el operador SR-IOV, un SriovOperatorConfig recurso personalizado.
  3. Configura las políticas de SR-IOV y tus VFs.
  4. Crea un NetworkAttachmentDefinition recurso personalizado que haga referencia a tus VFs.

Requisitos

La función de red SR-IOV requiere que los controladores oficiales de los adaptadores de red estén presentes en los nodos del clúster. Instala los controladores antes de usar el operador SR-IOV. Además, para usar el módulo vfio-pci en tus VFs, asegúrate de que esté disponible en los nodos en los que se va a usar.

Habilitar la red SR-IOV en un clúster

Para habilitar la red SR-IOV en Google Distributed Cloud, añade el campo multipleNetworkInterfaces y el campo sriovOperator a la sección clusterNetwork del objeto Cluster y asigna el valor true a ambos campos.

apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: cluster1
spec:
  clusterNetwork:
    multipleNetworkInterfaces: true
    sriovOperator: true
...

El campo sriovOperator es mutable y se puede cambiar después de crear el clúster.

Configurar el operador SR-IOV

El recurso personalizado SriovOperatorConfig proporciona la configuración global de la función de red SR-IOV. Este recurso personalizado agrupado tiene el nombre default y está en el espacio de nombres gke-operators. El SriovOperatorConfig custom resource solo se tiene en cuenta para este nombre y espacio de nombres.

Puedes editar este objeto con el siguiente comando:

kubectl -n gke-operators edit sriovoperatorconfigs.sriovnetwork.k8s.cni.cncf.io default

A continuación, se muestra un ejemplo de configuración de un recurso personalizado SriovOperatorConfig:

apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
kind: SriovOperatorConfig
metadata:
  name: default
  namespace: gke-operators
spec:
  configDaemonNodeSelector:
    nodePool: "withSriov"
  disableDrain: false
  logLevel: 0

La sección configDaemonNodeSelector te permite limitar los nodos que puede gestionar el operador SR-IOV. En el ejemplo anterior, el operador se limita a los nodos que tienen la etiqueta nodePool: withSriov. Si no se especifica el campo configDaemonNodeSelector, se aplican las siguientes etiquetas predeterminadas:

beta.kubernetes.io/os: linux
node-role.kubernetes.io/worker: ""

El campo disableDrain especifica si se debe realizar una operación de drenaje de nodos de Kubernetes antes de reiniciar el nodo o antes de cambiar una configuración de VF específica.

Crear políticas de SR-IOV

Para configurar VFs específicos en tu clúster, debes crear un recurso personalizado en el espacio de nombres gke-operators.SriovNetworkNodePolicy

A continuación, se muestra un ejemplo de manifiesto de un recurso personalizado SriovNetworkNodePolicy:

apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: policy-1
  namespace: gke-operators
spec:
  deviceType: "netdevice"
  mtu: 1600
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0
    deviceID: "1015"
    rootDevices:
    - 0000:01:00.0
    vendor: "15b3"
  numVfs: 4
  priority: 80
  resourceName: "mlnx"

La sección nodeSelector le permite limitar aún más los nodos en los que se deben crear los VFs. Esta limitación se suma a los selectores de SriovOperatorConfig descritos en la sección anterior.

El campo deviceType especifica el módulo del kernel que se va a usar en las VFs. Las opciones disponibles para deviceType son las siguientes:

  • netdevice para el módulo de kernel estándar específico de VF
  • vfio-pci para el controlador VFIO-PCI

El resourceName define el nombre con el que se representan los VFs en el nodo de Kubernetes.

Una vez completado el proceso de configuración, los nodos de clúster seleccionados contendrán el recurso definido, tal como se muestra en el siguiente ejemplo (fíjate en gke.io/mlnx):

apiVersion: v1
kind: Node
metadata:
  name: worker-01
spec:

status:
  allocatable:
    cpu: 47410m
    ephemeral-storage: "210725550141"
    gke.io/mlnx: "4"
    hugepages-1Gi: "0"
    hugepages-2Mi: "0"
    memory: 59884492Ki
    pods: "250"
  capacity:
    cpu: "48"
    ephemeral-storage: 228651856Ki
    gke.io/mlnx: "4"
    hugepages-1Gi: "0"
    hugepages-2Mi: "0"
    memory: 65516492Ki
    pods: "250"

El operador siempre añadirá el prefijo gke.io/ a todos los recursos que definas con SriovNetworkNodePolicy.

Especificar un selector de NIC

Para que SriovNetworkNodePolicy funcione correctamente, especifica al menos un selector en la sección nicSelector. Este campo contiene varias opciones sobre cómo identificar funciones físicas (PFs) específicas en los nodos del clúster. La mayor parte de la información que requiere este campo se detecta automáticamente y se guarda en el SriovNetworkNodeState recurso personalizado. Habrá un objeto por cada nodo que pueda gestionar este operador.

Usa el siguiente comando para ver todos los nodos disponibles:

kubectl -n gke-operators get sriovnetworknodestates.sriovnetwork.k8s.cni.cncf.io -o yaml

Este es un ejemplo de nodo:

apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
kind: SriovNetworkNodeState
metadata:
  name: worker-01
  namespace: gke-operators
spec:
  dpConfigVersion: "6368949"
status:
  interfaces:
  - deviceID: "1015"
    driver: mlx5_core
    eSwitchMode: legacy
    linkSpeed: 10000 Mb/s
    linkType: ETH
    mac: 1c:34:da:5c:2b:9c
    mtu: 1500
    name: enp1s0f0
    pciAddress: "0000:01:00.0"
    totalvfs: 4
    vendor: 15b3
  - deviceID: "1015"
    driver: mlx5_core
    linkSpeed: 10000 Mb/s
    linkType: ETH
    mac: 1c:34:da:5c:2b:9d
    mtu: 1500
    name: enp1s0f1
    pciAddress: "0000:01:00.1"
    totalvfs: 2
    vendor: 15b3
  syncStatus: Succeeded

Definir la partición de funciones físicas

Presta especial atención al campo pfNames de la sección nicSelector. Además de definir el PF exacto que se va a usar, te permite especificar los VFs exactos que se van a usar para el PF especificado y el recurso definido en la política.

Veamos un ejemplo:

apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: policy-1
  namespace: gke-operators
spec:
  deviceType: "netdevice"
  mtu: 1600
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0#3-6
    deviceID: "1015"
    rootDevices:
    - 0000:01:00.0
    vendor: "15b3"
  numVfs: 7
  priority: 80
  resourceName: "mlnx"

En el ejemplo anterior, el recurso gke.io/mlnx solo usa VFs numerados del 3 al 6 y muestra solo cuatro VFs disponibles. Como los VFs siempre se crean a partir del índice cero, el número de VFs que solicites, numVfs, debe ser al menos tan alto como el valor de cierre del intervalo (contando desde cero). Por este motivo, en el ejemplo anterior, numVfs se ha definido como 7. Si defines un intervalo de 3 a 4 (enp65s0f0#3-4), tu numVfs debe ser al menos 5.

Si no se especifica la partición, numVfs define el intervalo de VFs que se está usando, que siempre empieza por cero. Por ejemplo, si defines numVfs=3 sin especificar particiones, se usan las VFs 0-2.

Acerca de la prioridad de las políticas

Puedes especificar varios objetos SriovNetworkNodePolicy para gestionar diferentes proveedores o configuraciones de VF. Gestionar varios objetos y proveedores puede resultar problemático cuando varias políticas hacen referencia al mismo PF. Para gestionar estas situaciones, el campo priority resuelve los conflictos por nodo.

Esta es la lógica de priorización de las políticas de PF superpuestas:

  1. Una política de mayor prioridad sobrescribe una de menor prioridad solo cuando la partición de PF se solapa.

  2. Las políticas con la misma prioridad se combinan:

    1. Las políticas se ordenan por nombre y se procesan en ese orden
    2. Las políticas con particiones de PF superpuestas se sobrescriben
    3. Las políticas con partición de PF no superpuesta se combinan y se presentan todas

Una política de alta prioridad es aquella que tiene un valor numérico más bajo en el campo priority. Por ejemplo, la prioridad es mayor para una política con priority: 10 que para una política con priority: 20.

En las siguientes secciones se ofrecen ejemplos de políticas para diferentes configuraciones de partición.

PF particionada

Si se implementan los dos manifiestos SriovNetworkNodePolicy siguientes, habrá dos recursos disponibles: gke.io/dev-kernel y gke.io/dev-vfio. Cada recurso tiene dos VFs que no se solapan.

kind: SriovNetworkNodePolicy
metadata:
  name: policy-1
spec:
  deviceType: "netdevice"
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0#0-1
  numVfs: 2
  priority: 70
  resourceName: "dev-kernel"
kind: SriovNetworkNodePolicy
metadata:
  name: policy-2
spec:
  deviceType: "vfio-pci"
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0#2-3
  numVfs: 4
  priority: 70
  resourceName: "dev-vfio"

Partición de PF solapada

Si se implementan los dos manifiestos SriovNetworkNodePolicy siguientes, solo estará disponible el recurso gke.io/dev-vfio. El intervalo de VF de policy-1 es 0-2, que se solapa con policy-2. Debido a la nomenclatura, policy-2 se procesa después de policy-1. Por lo tanto, solo está disponible el recurso especificado en policy-2, gke.io/dev-vfio.

kind: SriovNetworkNodePolicy
metadata:
  name: policy-1
spec:
  deviceType: "netdevice"
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0
  numVfs: 3
  priority: 70
  resourceName: "dev-kernel"
kind: SriovNetworkNodePolicy
metadata:
  name: policy-2
spec:
  deviceType: "vfio-pci"
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0#2-3
  numVfs: 4
  priority: 70
  resourceName: "dev-vfio"

Partición de PF no superpuesta con diferentes prioridades

Si se implementan los dos manifiestos SriovNetworkNodePolicy siguientes, habrá dos recursos disponibles: gke.io/dev-kernel y gke.io/dev-vfio. Cada recurso tiene dos VFs que no se solapan. Aunque policy-1 tiene una prioridad mayor que policy-2, como las particiones de PF no se solapan, combinamos las dos políticas.

kind: SriovNetworkNodePolicy
metadata:
  name: policy-1
spec:
  deviceType: "netdevice"
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0
  numVfs: 2
  priority: 10
  resourceName: "dev-kernel"
kind: SriovNetworkNodePolicy
metadata:
  name: policy-2
spec:
  deviceType: "vfio-pci"
  nodeSelector:
    baremetal.cluster.gke.io/node-pool: node-pool-1
  nicSelector:
    pfNames:
    - enp65s0f0#2-3
  numVfs: 4
  priority: 70
  resourceName: "dev-vfio"

Comprobar el estado de configuración de la política de SR-IOV

Cuando apliques las políticas de SR-IOV, podrás monitorizar y ver la configuración final de los nodos en el recurso personalizado SriovNetworkNodeState del nodo específico. En la sección status, el campo syncStatus representa la fase actual del daemon de configuración. El estado Succeeded indica que la configuración ha finalizado. La sección spec del recurso personalizado SriovNetworkNodeState define el estado final de la configuración de las VFs de ese nodo en función del número de políticas y sus prioridades. Todos los VFs creados se mostrarán en la sección status de los PFs especificados.

Aquí tienes un ejemplo de recurso personalizado SriovNetworkNodeState:

apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
kind: SriovNetworkNodeState
metadata:
  name: worker-02
  namespace: gke-operators
spec:
  dpConfigVersion: "9022068"
  interfaces:
  - linkType: eth
    name: enp1s0f0
    numVfs: 2
    pciAddress: "0000:01:00.0"
    vfGroups:
    - deviceType: netdevice
      policyName: policy-1
      resourceName: mlnx
      vfRange: 0-1
status:
  interfaces:
  - Vfs:
    - deviceID: "1016"
      driver: mlx5_core
      mac: 96:8b:39:d8:89:d2
      mtu: 1500
      name: enp1s0f0np0v0
      pciAddress: "0000:01:00.2"
      vendor: 15b3
      vfID: 0
    - deviceID: "1016"
      driver: mlx5_core
      mac: 82:8e:65:fe:9b:cb
      mtu: 1500
      name: enp1s0f0np0v1
      pciAddress: "0000:01:00.3"
      vendor: 15b3
      vfID: 1
    deviceID: "1015"
    driver: mlx5_core
    eSwitchMode: legacy
    linkSpeed: 10000 Mb/s
    linkType: ETH
    mac: 1c:34:da:5c:2b:9c
    mtu: 1500
    name: enp1s0f0
    numVfs: 2
    pciAddress: "0000:01:00.0"
    totalvfs: 2
    vendor: 15b3
  - deviceID: "1015"
    driver: mlx5_core
    linkSpeed: 10000 Mb/s
    linkType: ETH
    mac: 1c:34:da:5c:2b:9d
    mtu: 1500
    name: enp1s0f1
    pciAddress: "0000:01:00.1"
    totalvfs: 2
    vendor: 15b3
  syncStatus: Succeeded

Crear un recurso personalizado NetworkAttachmentDefinition

Una vez que hayas configurado correctamente las VFs en el clúster y sean visibles en el nodo de Kubernetes como un recurso, tendrás que crear un NetworkAttachmentDefinition que haga referencia al recurso. Haz la referencia con una anotación k8s.v1.cni.cncf.io/resourceName. Aquí tienes un ejemplo de manifiesto de NetworkAttachmentDefinition que hace referencia al recurso gke.io/mlnx:

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-sriov-1
  annotations:
    k8s.v1.cni.cncf.io/resourceName: gke.io/mlnx
spec:
  config: '{
      "cniVersion": "0.3.0",
      "name": "mynetwork",
      "type": "sriov",
      "ipam": {
        "type": "whereabouts",
        "range": "21.0.108.0/21",
        "range_start": "21.0.111.16",
        "range_end": "21.0.111.18"
      }
    }'

El NetworkAttachmentDefinition debe tener el sriov como tipo de CNI. Haz referencia a cualquier recurso personalizado NetworkAttachmentDefinition desplegado en tus pods con una anotación k8s.v1.cni.cncf.io/networks.

A continuación, se muestra un ejemplo de cómo hacer referencia al recurso personalizado NetworkAttachmentDefinition anterior en un pod:

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

Cuando haces referencia a un recurso personalizado de NetworkAttachmentDefinition en cargas de trabajo, no tienes que preocuparte por las definiciones de recursos de los pods ni por la colocación en nodos específicos, ya que se hace automáticamente.

En el ejemplo siguiente se muestra un recurso personalizado NetworkAttachmentDefinition con una configuración de VLAN. En este ejemplo, todos los VF pertenecen a la VLAN 100:

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-sriov-vlan-100
  annotations:
    k8s.v1.cni.cncf.io/resourceName: gke.io/mlnx
spec:
  config: '{
      "cniVersion": "0.3.0",
      "name": "mynetwork",
      "type": "sriov",
      "vlan": 100,
      "ipam": {
        "type": "whereabouts",
        "range": "21.0.100.0/21"
      }
    }'

Información adicional

En las siguientes secciones se incluye información para ayudarte a configurar la red SR-IOV.

Reinicios de nodos

Cuando el operador de SR-IOV configura los nodos, es posible que sea necesario reiniciar los nodos. Es posible que tengas que reiniciar los nodos durante la configuración de VF o del kernel. La configuración del kernel implica habilitar la compatibilidad con la función SR-IOV en el sistema operativo.

Adaptadores de red compatibles

En la siguiente tabla se indican los adaptadores de red compatibles con los clústeres de la versión 1.33.x:

Nombre ID de proveedor ID del dispositivo ID de dispositivo VF
Intel i40e XXV710 8086 158a 154c
Intel i40e 25G SFP28 8086 158b 154c
Intel i40e 10G X710 SFP 8086 1572 154c
Intel i40e XXV710 N3000 8086 0d58 154c
Intel i40e 40G XL710 QSFP 8086 1583 154c
Intel ice Columbiaville E810-CQDA2 2CQDA2 8086 1592 1889
Intel ice Columbiaville E810-XXVDA4 8086 1593 1889
Intel ice Columbiaville E810-XXVDA2 8086 159b 1889
Nvidia mlx5 ConnectX-4 15b3 1013 1014
Nvidia mlx5 ConnectX-4LX 15b3 1015 1016
Nvidia mlx5 ConnectX-5 15b3 1017 1018
Nvidia mlx5 ConnectX-5 Ex 15b3 1019 101a
Nvidia mlx5 ConnectX-6 15b3 101b 101c
Nvidia mlx5 ConnectX-6_Dx 15b3 101d 101e
Nvidia mlx5 MT42822 BlueField-2 integrated ConnectX-6 Dx 15b3 a2d6 101e
Broadcom bnxt BCM57414 2x25G 14e4 16d7 16dc
Broadcom bnxt BCM75508 2x100G 14e4 1750 1806