Configure a rede SR-IOV

Este documento descreve como configurar a rede de virtualização de entrada/saída de raiz única (SR-IOV) para o Google Distributed Cloud. A SR-IOV oferece virtualização de E/S para disponibilizar uma placa de rede (NIC) como dispositivos de rede no kernel do Linux. Isto permite-lhe gerir e atribuir ligações de rede aos seus pods. O desempenho é melhorado à medida que os pacotes se movem diretamente entre a NIC e o pod.

Use esta funcionalidade se precisar de uma rede rápida para as cargas de trabalho do pod. O SR-IOV para o Google Distributed Cloud permite-lhe configurar as funções virtuais (VFs) nos dispositivos suportados dos nós do cluster. Também pode especificar o módulo do kernel específico a associar aos VFs.

Esta funcionalidade está disponível para clusters que executam cargas de trabalho, como clusters híbridos, autónomos e de utilizadores. A funcionalidade de rede SR-IOV requer que o cluster tenha, pelo menos, dois nós.

O processo de configuração consiste nos seguintes passos gerais:

  1. Configure o cluster para ativar a rede SR-IOV.
  2. Configure o operador SR-IOV, um SriovOperatorConfig recurso personalizado.
  3. Configure políticas de SR-IOV e configure as suas VFs.
  4. Crie um NetworkAttachmentDefinitionrecurso personalizado que faça referência aos seus VFs.

Requisitos

A funcionalidade de rede SR-IOV requer que os controladores oficiais dos adaptadores de rede estejam presentes nos nós do cluster. Instale os controladores antes de usar o operador SR-IOV. Além disso, para usar o módulo vfio-pci para os seus VFs, certifique-se de que o módulo está disponível nos nós onde vai ser usado.

Ative a rede SR-IOV para um cluster

Para ativar a rede SR-IOV para o Google Distributed Cloud, adicione o campo multipleNetworkInterfaces e o campo sriovOperator à secção clusterNetwork do objeto Cluster e defina ambos os campos como true.

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

O campo sriovOperator é mutável e pode ser alterado após a criação do cluster.

Configure o operador SR-IOV

O recurso personalizado SriovOperatorConfig fornece a configuração global para a funcionalidade de rede SR-IOV. Este recurso personalizado agrupado tem o nome default e está no espaço de nomes gke-operators. O recurso personalizado SriovOperatorConfig é respeitado apenas para este nome e espaço de nomes.

Pode editar este objeto com o seguinte comando:

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

Segue-se um exemplo de uma configuração de 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

A secção configDaemonNodeSelector permite-lhe limitar os nós que o operador SR-IOV pode processar. No exemplo anterior, o operador está limitado apenas aos nós que têm uma etiqueta nodePool: withSriov. Se o campo configDaemonNodeSelector não for especificado, são aplicadas as seguintes etiquetas predefinidas:

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

O campo disableDrain especifica se deve ser realizada uma operação de esvaziamento do nó do Kubernetes antes de o nó ter de ser reiniciado ou antes de uma configuração de VF específica ser alterada.

Crie políticas de SR-IOV

Para configurar VFs específicos no cluster, tem de criar um SriovNetworkNodePolicy recurso personalizado no espaço de nomes gke-operators.

Segue-se um exemplo de manifesto para um SriovNetworkNodePolicy recurso personalizado:

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"

A secção nodeSelector permite-lhe limitar ainda mais os nós nos quais os VFs têm de ser criados. Esta limitação é adicional aos seletores do elemento SriovOperatorConfig descritos na secção anterior.

O campo deviceType especifica o módulo do kernel a usar para os VFs. As opções disponíveis para deviceType são:

  • netdevice para o módulo de kernel padrão específico do VF
  • vfio-pci para o controlador VFIO-PCI

O elemento resourceName define o nome pelo qual os VFs são representados no nó do Kubernetes.

Após a conclusão do processo de configuração, os nós do cluster selecionados contêm o recurso definido, conforme apresentado no exemplo seguinte (repare no 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"

O operador adiciona sempre o prefixo gke.io/ a todos os recursos que definir com SriovNetworkNodePolicy.

Especifique um seletor de NIC

Para que o elemento SriovNetworkNodePolicy funcione corretamente, especifique, pelo menos, um seletor na secção nicSelector. Este campo contém várias opções sobre como identificar funções físicas (PFs) específicas nos nós do cluster. A maioria das informações necessárias para este campo é descoberta automaticamente e guardada no recurso personalizado SriovNetworkNodeState. Vai existir um objeto para cada nó que este operador pode processar.

Use o seguinte comando para ver todos os nós disponíveis:

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

Segue-se um exemplo de um nó:

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

Defina a partição de funções físicas

Preste especial atenção ao campo pfNames da secção nicSelector. Além de definir o PF exato a usar, permite-lhe especificar os VFs exatos a usar para o PF especificado e o recurso definido na política.

Segue-se um exemplo:

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"

No exemplo anterior, o recurso gke.io/mlnx usa apenas VFs numerados de 3 a 6 e mostra apenas quatro VFs disponíveis. Uma vez que os VFs são sempre criados a partir do índice zero, o número de VFs pedido, numVfs, tem de ser, pelo menos, tão elevado quanto o valor de fecho do intervalo (a contar do zero). Esta lógica de numeração explica por que motivo numVfs está definido como 7 no exemplo anterior. Se definir um intervalo de 3 a 4 (enp65s0f0#3-4), o seu numVfs tem de ser, pelo menos, 5.

Quando a partição não é especificada, o numVfs define o intervalo de VFs que está a ser usado, que começa sempre a partir de zero. Por exemplo, se definir numVfs=3 sem especificar a partição, são usados VFs 0-2.

Compreenda a prioridade das políticas

Pode especificar vários objetos SriovNetworkNodePolicy para processar vários fornecedores ou diferentes configurações de VF. A gestão de vários objetos e fornecedores pode tornar-se problemática quando várias políticas fazem referência ao mesmo PF. Para lidar com estas situações, o campo priority resolve os conflitos por nó.

Segue-se a lógica de priorização para políticas de PF sobrepostas:

  1. Uma política de prioridade mais elevada substitui uma política de prioridade mais baixa apenas quando a partição de PF se sobrepõe.

  2. As políticas com a mesma prioridade são unidas:

    1. As políticas são ordenadas por nome e processadas nessa ordem
    2. As políticas com partição de PF sobreposta são substituídas
    3. As políticas com partição de PF não sobreposta são unidas e todas estão presentes

Uma política de prioridade elevada é aquela com um valor numérico mais baixo no campo priority. Por exemplo, a prioridade é mais elevada para uma política com priority: 10 do que para uma política com priority: 20.

As secções seguintes fornecem exemplos de políticas para diferentes configurações de partição.

AP particionada

A implementação dos dois manifestos SriovNetworkNodePolicy seguintes resulta em dois recursos disponíveis: gke.io/dev-kernel e gke.io/dev-vfio. Cada recurso tem dois VFs que não se sobrepõem.

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"

Partição de PF sobreposta

A implementação dos dois manifestos SriovNetworkNodePolicy seguintes resulta na disponibilidade apenas do recurso gke.io/dev-vfio. O intervalo de VF de policy-1 é 0-2, que se sobrepõe a policy-2. Devido à nomenclatura, policy-2 é processado depois de policy-1. Por conseguinte, apenas o recurso especificado em policy-2, gke.io/dev-vfio, está disponível.

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"

Particionamento de PF não sobreposto com diferentes prioridades

A implementação dos dois manifestos SriovNetworkNodePolicy seguintes resulta em dois recursos disponíveis: gke.io/dev-kernel e gke.io/dev-vfio. Cada recurso tem dois VFs que não se sobrepõem. Embora policy-1 tenha uma prioridade mais elevada do que policy-2, uma vez que a partição de PF não se sobrepõe, vamos unir as duas 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"

Verifique o estado da configuração da política SR-IOV

Quando aplica as políticas de SR-IOV, pode acompanhar e ver a configuração final dos nós no recurso personalizado SriovNetworkNodeState para o nó específico. Na secção status, o campo syncStatus representa a fase atual do daemon de configuração. O estado Succeeded indica que a configuração está concluída. A secção spec do recurso personalizado SriovNetworkNodeState define o estado final da configuração dos VFs para esse nó, com base no número de políticas e nas respetivas prioridades. Todas as VFs criadas são apresentadas na secção status para os PFs especificados.

Segue-se um exemplo de um SriovNetworkNodeStaterecurso personalizado:

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

Crie um NetworkAttachmentDefinition recurso personalizado

Depois de configurar com êxito as VFs no cluster e estas ficarem visíveis no nó do Kubernetes como um recurso, tem de criar um NetworkAttachmentDefinition que faça referência ao recurso. Faça a referência com uma anotação k8s.v1.cni.cncf.io/resourceName. Segue-se um exemplo de um manifesto NetworkAttachmentDefinition que faz referência ao 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"
      }
    }'

O NetworkAttachmentDefinition tem de ter o sriov como tipo de CNI. Referencie quaisquer NetworkAttachmentDefinitionrecursos personalizados implementados nos seus pods com uma anotação k8s.v1.cni.cncf.io/networks.

Segue-se um exemplo de como referenciar o recurso personalizado NetworkAttachmentDefinition anterior num pod:

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

Quando faz referência a um recurso personalizado NetworkAttachmentDefinition em cargas de trabalho, não tem de se preocupar com as definições de recursos dos pods nem com o posicionamento em nós específicos, uma vez que isto é feito automaticamente.

O exemplo seguinte mostra um recurso personalizado NetworkAttachmentDefinition com uma configuração de VLAN. Neste exemplo, cada VF pertence à 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"
      }
    }'

Informações adicionais

As secções seguintes contêm informações para ajudar a configurar a rede SR-IOV.

Reinícios do nó

Quando o operador SR-IOV configura os nós, estes podem ter de ser reiniciados. Pode ser necessário reiniciar os nós durante a configuração do VF ou do kernel. A configuração do kernel envolve a ativação do suporte da funcionalidade SR-IOV no sistema operativo.

Adaptadores de rede suportados

A tabela seguinte indica os adaptadores de rede suportados para clusters da versão 1.33.x:

Nome ID do fornecedor ID do dispositivo ID do 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