Neste documento, descrevemos como configurar uma rede de virtualização de entrada/saída (SR-IOV) de raiz única para o Google Distributed Cloud. O SR-IOV fornece virtualização de E/S para disponibilizar uma placa de interface de rede (NIC, na sigla em inglês) como dispositivos de rede no kernel do Linux. Isso permite que você gerencie e atribua conexões de rede aos pods. O desempenho é aprimorado conforme os pacotes se movem diretamente entre a NIC e o pod.
Use esse recurso se você precisar de uma rede rápida para as cargas de trabalho do pod. O SR-IOV para o Google Distributed Cloud permite configurar as funções virtuais (VFs) nos dispositivos compatíveis dos nós do cluster. Também é possível especificar o módulo específico do kernel para vincular às VFs.
Esse recurso está disponível para clusters que executam cargas de trabalho, como clusters híbridos, independentes e de usuário. O recurso de rede SR-IOV requer que o cluster tenha pelo menos dois nós.
O processo de configuração consiste nas seguintes etapas de alto nível:
- Configurar o cluster para ativar a rede SR-IOV;
- Configurar o operador SR-IOV, um recurso personalizado
SriovOperatorConfig; - Definir políticas de SR-IOV e configurar as VFs;
- Criar um recurso personalizado
NetworkAttachmentDefinitionque faz referência às VFs.
Requisitos
O recurso de rede SR-IOV exige que os drivers oficiais para os adaptadores
de rede estejam presentes nos nós do cluster. Instale os drivers antes de usar
o operador SR-IOV. Além disso, para usar o módulo vfio-pci nas VFs, verifique
se o módulo está disponível nos nós em que será usado.
Ativar a rede SR-IOV para um cluster
Para ativar a rede SR-IOV no Google Distributed Cloud, adicione o campo
multipleNetworkInterfaces
e o campo
sriovOperator
à seção clusterNetwork do objeto Cluster e defina os dois 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.
Configurar o operador SR-IOV
O recurso personalizado SriovOperatorConfig fornece configuração global para o
recurso de rede SR-IOV. Esse recurso personalizado empacotado tem o nome default
e está no namespace gke-operators. O recurso
personalizado SriovOperatorConfig segue apenas esse nome e namespace.
É possível editar este objeto com o seguinte comando:
kubectl -n gke-operators edit sriovoperatorconfigs.sriovnetwork.k8s.cni.cncf.io defaultVeja 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 seção configDaemonNodeSelector permite limitar os nós que o operador
SR-IOV pode processar. No exemplo anterior, o operador é limitado apenas aos
nós que têm um rótulo nodePool: withSriov. Se o campo
configDaemonNodeSelector não for especificado, os seguintes rótulos padrão serão aplicados:
beta.kubernetes.io/os: linux
node-role.kubernetes.io/worker: ""
O campo disableDrain especifica se é necessário executar uma operação
de drenagem do nó do Kubernetes antes da reinicialização do nó ou antes da alteração
de uma configuração específica da VF.
Criar políticas SR-IOV
Para configurar VFs específicas no cluster, você precisa criar um
recurso personalizado SriovNetworkNodePolicy no namespace gke-operators.
Veja um exemplo de manifesto para um 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"
A seção nodeSelector permite limitar ainda mais os nós em que as VFs
precisam ser criadas. Essa limitação está acima dos seletores do
SriovOperatorConfig descrito na seção anterior.
O campo deviceType especifica o módulo do kernel a ser usado para as VFs. As opções
disponíveis para deviceType são:
netdevicepara o módulo padrão de kernel padrão de VF;vfio-pcipara o driver VFIO-PCI.
O resourceName define o nome das VFs representadas no
nó do Kubernetes.
Após a conclusão do processo de configuração, os nós de cluster selecionados
conterão o recurso definido, conforme apresentado no exemplo a seguir (observe o
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 sempre adicionará o prefixo gke.io/ a todos os recursos que você definir
com SriovNetworkNodePolicy.
Especifique um seletor de NIC
Para que a SriovNetworkNodePolicy funcione corretamente, especifique pelo menos um
seletor na seção nicSelector. Esse campo contém várias opções sobre
como identificar funções físicas específicas (PFs, na sigla em inglês) nos nós do cluster. A maioria
das informações exigidas por esse campo é descoberta para você e salva no
recurso personalizado SriovNetworkNodeState. Haverá um objeto por cada nó
que esse operador pode manipular.
Use o seguinte comando para ver todos os nós disponíveis:
kubectl -n gke-operators get sriovnetworknodestates.sriovnetwork.k8s.cni.cncf.io -o yamlAqui está 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
Definir o particionamento da função física
Preste atenção especial ao campo pfNames da seção nicSelector. Além de
definir o PF exato a ser usado, ele permite especificar os VFs exatos
a serem usados para o PF especificado e o recurso definido na política.
Veja 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 numeradas de 3 a 6
e mostra apenas quatro VFs disponíveis. Como as VFs são sempre criadas a partir do
índice zero, o número solicitado de VFs, numVfs, precisa ser pelo menos tão alto
quanto o valor de fechamento do intervalo (contando a partir de zero). Essa lógica de numeração é o motivo de
numVfs ser definido como 7 no exemplo anterior. Se você definir um intervalo de 3 a 4
(enp65s0f0#3-4), numVfs precisará ser pelo menos 5.
Quando o particionamento não é especificado, o numVfs define o intervalo de VFs que
está sendo usado, que sempre começa em zero. Por exemplo, se você definir numVfs=3
sem especificar o particionamento, as VFs 0-2 serão usadas.
Entenda a prioridade da política
É possível especificar vários objetos SriovNetworkNodePolicy para lidar com vários fornecedores ou diferentes configurações de VF. O gerenciamento de vários objetos e fornecedores
pode se tornar complicado quando várias políticas fazem referência ao mesmo PF. Para lidar com essas situações, o campo priority resolve os conflitos por nó.
Veja a lógica de priorização para as políticas de PF sobrepostas:
Uma política de prioridade mais alta substitui uma com prioridade mais baixa somente quando há sobreposição do particionamento PF.
As políticas de mesma prioridade são mescladas:
- As políticas são classificadas por nome e processadas nessa ordem
- As políticas com particionamento de PF sobreposto são substituídas
- As políticas com particionamento de PF não sobreposto são mescladas e todas estão presentes
Uma política de alta prioridade é aquela com valor numérico mais baixo no campo priority. Por exemplo, a prioridade é maior para uma política com priority: 10
do que para uma política com priority: 20.
Nas seções a seguir, fornecemos exemplos de políticas para diferentes configurações de particionamento.
PF particionada
A implantação dos dois manifestos SriovNetworkNodePolicy a seguir resulta em dois
recursos disponíveis: gke.io/dev-kernel e gke.io/dev-vfio. Cada recurso tem dois VFs que não são sobrepostos.
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"
Particionamento de PF sobreposto
A implantação dos dois manifestos SriovNetworkNodePolicy a seguir resulta na disponibilização apenas do recurso gke.io/dev-vfio. O intervalo de VF policy-1 é 0-2, que se sobrepõe a policy-2. Devido a essa nomeação, policy-2 é processado depois de policy-1. Portanto, 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 prioridades diferentes
A implantação dos dois manifestos SriovNetworkNodePolicy a seguir resulta em dois recursos disponíveis: gke.io/dev-kernel e gke.io/dev-vfio. Cada recurso tem dois VFs que não são sobrepostos. Ainda que policy-1 tenha maior prioridade que policy-2, como o particionamento de PF não se sobrepõe, mesclamos 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"
Verificar o status da configuração da política SR-IOV
Ao aplicar as políticas de SR-IOV, é possível rastrear e visualizar a configuração
final dos nós no recurso personalizado SriovNetworkNodeState para
o nó específico. Na seção status, o campo syncStatus representa
o estágio atual do daemon de configuração. O estado Succeeded indica
que a configuração foi concluída. A seção spec do
recurso personalizado SriovNetworkNodeState define o estado final da configuração
das VFs para esse nó, com base no número de políticas e nas prioridades
delas. Todas as VFs criadas serão listadas na seção status para as
PFs especificadas.
Veja um exemplo 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
Criar um recurso personalizado NetworkAttachmentDefinition
Depois de configurar as VFs no cluster e elas ficarem visíveis no
nó do Kubernetes como um recurso, você precisará 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.
Veja um exemplo de 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"
}
}'
A NetworkAttachmentDefinition precisa ter a sriov como o tipo de CNI.
Faça referência a todos os recursos personalizados NetworkAttachmentDefinition implantados nos
pods com uma anotação k8s.v1.cni.cncf.io/networks.
Veja um exemplo de como referenciar o recurso personalizado
NetworkAttachmentDefinition anterior em um pod:
apiVersion: v1
kind: Pod
metadata:
name: samplepod
annotations:
k8s.v1.cni.cncf.io/networks: gke-sriov-1
spec:
containers:
...
Ao fazer referência a um recurso personalizado NetworkAttachmentDefinition em cargas de trabalho,
você não precisa se preocupar com as definições de recursos dos pods ou com a colocação em
nós específicos, o que é feito automaticamente.
O exemplo a seguir 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 seções a seguir contêm informações para ajudar a configurar a rede SR-IOV.
Reinicializações de nó
Quando o operador SR-IOV configura os nós, pode ser necessário reiniciá-los. É possível reinicializar os nós durante a configuração da VF ou do kernel. A configuração do kernel envolve ativar a compatibilidade com a funcionalidade de SR-IOV no sistema operacional.
Adaptadores de rede suportados
A tabela a seguir lista os adaptadores de rede compatíveis com clusters da versão 1.33.x:
| Nome | ID do fornecedor | ID do dispositivo | ID do dispositivo da 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 | 1.592 | 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 integrado ao ConnectX-6 Dx | 15b3 | a2d6 | 101e |
| Broadcom bnxt BCM57414 2x25G | 14e4 | 16d7 | 16dc |
| Broadcom bnxt BCM75508 2x100G | 14e4 | 1750 | 1806 |