SR-IOV-Netzwerk einrichten

In diesem Dokument wird beschrieben, wie Sie SR-IOV-Netzwerke (Single-Root Input/Output Virtualization) für Google Distributed Cloud einrichten. SR-IOV bietet E/A-Virtualisierung, um eine Netzwerkkarte (NIC) zu erstellen, verfügbar als Netzwerkgeräte im Linux-Kernel. So können Sie Netzwerkverbindungen verwalten und Pods zuweisen. Die Leistung wird verbessert, da Pakete direkt zwischen der NIC und dem Pod verschoben werden.

Nutzen Sie dieses Feature, wenn Sie ein schnelles Netzwerk für Ihre Pod-Arbeitslasten benötigen. Mit SR-IOV für Google Distributed Cloud können Sie die virtuellen Funktionen (VFs) auf den unterstützten Geräten Ihrer Clusterknoten konfigurieren. Sie können auch das spezifische Kernel-Modul angeben, das an die VFs gebunden werden soll.

Dieses Feature ist für Cluster verfügbar, auf denen Arbeitslasten ausgeführt werden, wie z. B. Hybrid-Cluster, eigenständige Cluster und Nutzercluster. Für die SR-IOV-Netzwerkfunktion muss der Cluster mindestens zwei Knoten haben.

Der Einrichtungsprozess umfasst die folgenden allgemeinen Schritte:

  1. Konfigurieren Sie einen Cluster für SR-IOV-Netzwerke.
  2. Konfigurieren Sie den SR-IOV-Operator, eine benutzerdefinierte SriovOperatorConfig-Ressource.
  3. Richten Sie SR-IOV-Richtlinien ein und konfigurieren Sie VFs.
  4. Erstellen Sie eine benutzerdefinierte NetworkAttachmentDefinition-Ressource, die auf die VFs verweist.

Voraussetzungen

Für das SR-IOV-Netzwerkfeature müssen die offiziellen Treiber für die Netzwerkadapter auf den Clusterknoten vorhanden sein. Installieren Sie die Treiber, bevor Sie den SR-IOV-Operator verwenden. Wenn Sie das Modul vfio-pci für Ihre VFs verwenden möchten, muss das Modul auch auf den Knoten verfügbar sein, auf denen es verwendet werden soll.

SR-IOV-Netzwerk für einen Cluster aktivieren

Wenn Sie das SR-IOV-Netzwerk für die Google Distributed Cloud aktivieren möchten, fügen Sie das Feld multipleNetworkInterfaces und das Feld sriovOperator zum Abschnitt clusterNetwork des Clusterobjekts hinzu und legen Sie für beide Felder den Wert true fest.

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

Das Feld sriovOperator ist änderbar und kann nach der Clustererstellung geändert werden.

SR-IOV-Operator konfigurieren

Die benutzerdefinierte Ressource SriovOperatorConfig bietet eine globale Konfiguration für das SR-IOV-Netzwerkfeature. Diese gebündelte benutzerdefinierte Ressource hat den Namen default und befindet sich im Namespace gke-operators. Die benutzerdefinierte Ressource SriovOperatorConfig wird nur für diesen Namen und diesen Namespace berücksichtigt.

Sie können dieses Objekt mit dem folgenden Befehl bearbeiten:

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

Hier sehen Sie ein Beispiel für die Konfiguration einer benutzerdefinierten SriovOperatorConfig-Ressource:

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

Im Abschnitt configDaemonNodeSelector können Sie einschränken, welche Knoten der SR-IOV-Operator verarbeiten kann. Im vorherigen Beispiel ist der Operator auf Knoten mit dem Label nodePool: withSriov beschränkt. Wenn das Feld configDaemonNodeSelector nicht angegeben ist, werden die folgenden Standardlabels angewendet:

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

Das Feld disableDrain gibt an, ob ein Kubernetes-Knoten geleert werden soll, bevor der Knoten neu gestartet werden muss oder bevor eine bestimmte VF-Konfiguration geändert wird.

SR-IOV-Richtlinien erstellen

Damit Sie bestimmte VFs in Ihrem Cluster konfigurieren können, müssen Sie im Namespace gke-operators die benutzerdefinierte SriovNetworkNodePolicy-Ressource erstellen.

Hier ist ein Beispielmanifest für eine benutzerdefinierte SriovNetworkNodePolicy-Ressource:

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"

Im Abschnitt nodeSelector können Sie die Knoten weiter einschränken, auf denen die VFs erstellt werden müssen. Diese Einschränkung basiert auf den Selektoren aus SriovOperatorConfig, die im vorherigen Abschnitt beschrieben wurden.

Das Feld deviceType gibt das Kernelmodul an, das für die VFs verwendet werden soll. Für deviceType sind folgende Optionen verfügbar:

  • netdevice für ein VF-spezifisches Standard-Kernel-Modul
  • vfio-pci für den VFIO-PCI-Treiber

Der resourceName definiert, mit welchem Namen die VFs auf dem Kubernetes-Knoten dargestellt werden.

Nach Abschluss der Konfiguration enthalten die ausgewählten Clusterknoten die definierte Ressource, wie im folgenden Beispiel gezeigt. Beachten Sie die 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"

Der Operator fügt jeder Ressource, die Sie mit SriovNetworkNodePolicy definieren, immer das Präfix gke.io/ hinzu.

NIC-Selektor angeben

Damit SriovNetworkNodePolicy ordnungsgemäß funktioniert, geben Sie mindestens einen Selektor im Abschnitt nicSelector an. Dieses Feld enthält mehrere Optionen zum Identifizieren bestimmter physischer Funktionen (PFs) in Ihren Clusterknoten. Die meisten Informationen, die für dieses Feld erforderlich sind, werden für Sie ermittelt und in der benutzerdefinierten Ressource SriovNetworkNodeState gespeichert. Für jeden Knoten, den dieser Operator verarbeiten kann, gibt es ein Objekt.

Mit dem folgenden Befehl rufen Sie alle verfügbaren Knoten auf:

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

Hier ein Beispiel für einen Knoten:

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

Partitionierung physischer Funktionen festlegen

Achten Sie dabei besonders auf das Feld pfNames im Abschnitt nicSelector. Sie können nicht nur die genaue zu verwendende PF angeben, sondern auch die genauen VFs, die für die angegebene PF und die in der Richtlinie definierten Ressource verwendet werden sollen.

Beispiel:

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"

Im vorherigen Beispiel verwendet die Ressource gke.io/mlnx nur die VFs mit den Nummern 3 bis 6 und zeigt nur vier verfügbare VFs an. Da die VFs immer aus dem Index mit null erstellt werden, muss die angeforderte Anzahl von VFs (numVfs) mindestens so hoch sein wie der Wert beim Schließen des Bereichs (gerechnet ab null). Diese Nummerierungslogik ist der Grund, warum numVfs im vorherigen Beispiel auf 7 gesetzt wurde. Wenn Sie einen Bereich von 3 bis 4 festlegen (enp65s0f0#3-4), muss numVfs mindestens 5 sein.

Wenn die Partitionierung nicht angegeben ist, definiert numVfs den verwendeten VF-Bereich, der immer bei null beginnt. Wenn Sie beispielsweise numVfs=3 festlegen, ohne die Partitionierung anzugeben, werden die VF-Bereiche 0-2 verwendet.

Informationen zur Richtlinienpriorität

Sie können mehrere SriovNetworkNodePolicy-Objekte angeben, um verschiedene Anbieter oder unterschiedliche VF-Konfigurationen zu verarbeiten. Die Verwaltung mehrerer Objekte und Anbieter kann zu Problemen führen, wenn mehrere Richtlinien auf dieselbe PF verweisen. Um solche Situationen zu vermeiden, löst das Feld priority die Konflikte auf Knotenbasis.

Die Priorisierungslogik für überlappende PF-Richtlinien lautet folgendermaßen:

  1. Eine Richtlinie mit höherer Priorität überschreibt nur eine Richtlinie mit niedrigerer Priorität, wenn sich die PF-Partitionierung überschneidet.

  2. Richtlinien mit derselben Priorität werden zusammengeführt:

    1. Richtlinien werden nach Name sortiert und in dieser Reihenfolge verarbeitet
    2. Richtlinien mit überlappender PF-Partitionierung werden überschrieben
    3. Richtlinien mit nicht überlappender PF-Partitionierung werden zusammengeführt und sind alle vorhanden

Eine Richtlinie mit hoher Priorität ist eine mit einem niedrigeren numerischen Wert im Feld priority. Beispielsweise ist die Priorität für eine Richtlinie mit priority: 10 höher als für eine Richtlinie mit priority: 20.

In den folgenden Abschnitten finden Sie Richtlinienbeispiele für verschiedene Partitionierungskonfigurationen.

Partitionierte PF

Das Bereitstellen der folgenden zwei SriovNetworkNodePolicy-Manifeste führt zu zwei verfügbaren Ressourcen: gke.io/dev-kernel und gke.io/dev-vfio. Jede Ressource hat zwei VFs, die sich nicht überschneiden.

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"

Überlappende PF-Partitionierung

Durch die Bereitstellung der folgenden zwei SriovNetworkNodePolicy-Manifeste ist nur die Ressource gke.io/dev-vfio verfügbar. Der VF-Bereich policy-1 ist 0-2, was sich mit policy-2 überschneidet. Aufgrund der Benennung wird policy-2 nach policy-1 verarbeitet. Daher ist nur die in policy-2 angegebene Ressource gke.io/dev-vfio verfügbar.

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"

Nicht überlappende PF-Partitionierung mit unterschiedlichen Prioritäten

Das Bereitstellen der folgenden zwei SriovNetworkNodePolicy-Manifeste führt zu zwei verfügbaren Ressourcen: gke.io/dev-kernel und gke.io/dev-vfio. Jede Ressource hat zwei VFs, die sich nicht überschneiden. Obwohl policy-1 eine höhere Priorität als policy-2 hat, da die PF-Partitionierung nicht überlappt, führen wir die beiden Richtlinien zusammen.

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"

Einrichtungsstatus der SR-IOV-Richtlinie prüfen

Wenn Sie die SR-IOV-Richtlinien anwenden, können Sie die endgültige Konfiguration der Knoten in der benutzerdefinierten Ressource SriovNetworkNodeState für den jeweiligen Knoten verfolgen und ansehen. Im Abschnitt status stellt das Feld syncStatus die aktuelle Phase für den Konfigurations-Daemon dar. Der Status Succeeded zeigt an, dass die Konfiguration abgeschlossen ist. Der Abschnitt spec der benutzerdefinierten Ressource SriovNetworkNodeState definiert den endgültigen Zustand der VFs-Konfiguration für diesen Knoten anhand der Anzahl der Richtlinien und ihrer Prioritäten. Alle erstellten VFs werden im Abschnitt status für die angegebenen PFs aufgeführt.

Hier ein Beispiel für eine benutzerdefinierte SriovNetworkNodeState-Ressource:

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

Benutzerdefinierte NetworkAttachmentDefinition-Ressource erstellen

Nachdem Sie die VFs erfolgreich im Cluster konfiguriert haben und diese im Kubernetes-Knoten als Ressource angezeigt werden, müssen Sie ein NetworkAttachmentDefinition erstellen, das auf die Ressource verweist. Erstellen Sie den Verweis mit der Annotation k8s.v1.cni.cncf.io/resourceName. Das folgende Beispiel zeigt ein NetworkAttachmentDefinition-Manifest, das auf die Ressource gke.io/mlnx verweist:

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"
      }
    }'

Die NetworkAttachmentDefinition muss sriov als CNI-Typ haben. Verweisen Sie mit der Annotation k8s.v1.cni.cncf.io/networks auf alle bereitgestellten benutzerdefinierten NetworkAttachmentDefinition-Ressourcen in Ihren Pods.

Hier ist ein Beispiel dafür, wie Sie auf die vorherige benutzerdefinierte NetworkAttachmentDefinition-Ressource in einem Pod verweisen:

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

Wenn Sie in Arbeitslasten auf eine benutzerdefinierte NetworkAttachmentDefinition-Ressource verweisen, müssen Sie sich keine Gedanken über die Ressourcendefinitionen der Pods oder die Platzierung in bestimmten Knoten machen, da dies automatisch für Sie erledigt wird.

Das folgende Beispiel zeigt eine benutzerdefinierte NetworkAttachmentDefinition-Ressource mit einer VLAN-Konfiguration. In diesem Beispiel gehört jede VF zum 100-VLAN:

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"
      }
    }'

Weitere Informationen

Die folgenden Abschnitte enthalten Informationen zum Konfigurieren eines SR-IOV-Netzwerks.

Neustart von Knoten

Wenn der SR-IOV-Operator die Knoten konfiguriert, müssen die Knoten möglicherweise neu gestartet werden. Während der VF- oder Kernel-Konfiguration ist möglicherweise ein Neustart der Knoten erforderlich. Die Kernel-Konfiguration umfasst die Unterstützung der SR-IOV-Funktionalität im Betriebssystem.

Unterstützte Netzwerkadapter

In der folgenden Tabelle sind die unterstützten Netzwerkadapter für Cluster der Version 1.30.x aufgeführt:

Name Anbieter-ID Geräte-ID VF-Geräte-ID
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 integrated ConnectX-6 Dx 15b3 a2d6 101e
Broadcom bnxt BCM57414 2x25G 14e4 16d7 16dc
Broadcom Bnxt BCM75508 2x100G 14e4 1750 1806