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
NetworkAttachmentDefinition
que 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 default
Veja 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:
netdevice
para o módulo padrão de kernel padrão de VF;vfio-pci
para 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 yaml
Aqui 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.30.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 |