目次にジャンプページナビゲーションにジャンプ: 前のページ[アクセスキーp]/次のページ[アクセスキーn]
documentation.suse.com / SUSE Edgeドキュメント / 製品マニュアル / 通信機能の設定

30 通信機能の設定

このセクションでは、ATIPがデプロイされたクラスタの通信事業者固有の機能について記述および説明します。

ダイレクトネットワークプロビジョニングのデプロイメント方法を使用します。この方法については、ATIPの自動プロビジョニング(第31章 「完全に自動化されたダイレクトネットワークプロビジョニング)に関するセクションで説明しています。

このセクションでは、次のトピックについて説明します。

30.1 リアルタイム用のカーネルイメージ

リアルタイムカーネルイメージは必ずしも標準カーネルより優れているとは限りません。リアルタイムカーネルは、特定のユースケース用に調整された別のカーネルです。低レイテンシを実現するために調整されていますが、その結果、スループットが犠牲になります。リアルタイムカーネルは一般的な用途には推奨されませんが、ここでは低レイテンシが重要な要因である通信ワークロード用のカーネルとして推奨されています。

主に4つの機能があります。

  • 決定論的実行:

    予測可能性の向上 — 高負荷状態でも重要なビジネスプロセスが期限内に確実に完了し、常に高品質なサービスを提供します。高優先度プロセスのために重要なシステムリソースを保護することで、時間に依存するアプリケーションの予測可能性を向上できます。

  • 低ジッタ:

    高度に決定論的な技術に基づいてジッタが低く抑えられているため、アプリケーションと実世界との同期を維持できます。これは、継続的に繰り返し計算を行う必要があるサービスで役立ちます。

  • 優先度の継承:

    優先度の継承とは、優先度の高いプロセスがある状況において、そのプロセスがタスクを完了するためには優先度の低いプロセスが完了するのを待つ必要がある場合に、優先度の低いプロセスが高優先度を一時的に引き受ける機能です。SUSE Linux Enterprise Real Timeは、ミッションクリティカルなプロセスにおけるこのような優先度の逆転の問題を解決します。

  • スレッドの割り込み:

    一般的なオペレーティングシステムでは、割り込みモードで実行中のプロセスはプリエンプト可能ではありません。SUSE Linux Enterprise Real Timeでは、このような割り込みをカーネルスレッドでカプセル化して割り込み可能にし、ユーザが定義した高優先度プロセスでハード割り込みとソフト割り込みをプリエンプトできます。

    ここでは、SLE Micro RTのようなリアルタイムイメージをインストール済みの場合、カーネルリアルタイムはすでにインストールされています。リアルタイムカーネルイメージはSUSE Customer Centerからダウンロードできます。

    注記
    注記

    リアルタイムカーネルの詳細については、SUSE Real Timeを参照してください。

30.2 CPU調整設定

CPU調整設定を使用すると、リアルタイムカーネルが使用するCPUコアを分離できます。OSがリアルタイムカーネルと同じコアを使用しないようにすることが重要です。OSがそのコアを使用すると、リアルタイムカーネルの遅延が増加するためです。

この機能を有効にして設定するには、まず、分離するCPUコアのプロファイルを作成します。ここでは、コア1-30および33-62を分離しています。

$ echo "export tuned_params" >> /etc/grub.d/00_tuned

$ echo "isolated_cores=1-30,33-62" >> /etc/tuned/cpu-partitioning-variables.conf

$ tuned-adm profile cpu-partitioning
Tuned (re)started, changes applied.

次に、GRUBオプションを変更して、CPUコアと、CPUの使用法に関するその他の重要なパラメータを分離する必要があります。現在のハードウェア仕様で次のオプションをカスタマイズすることが重要です。

パラメータ説明

isolcpus

1-30、33-62

コア1-30および33-62を分離します。

skew_tick

1

このオプションを使用すると、カーネルは分離されたCPU全体でタイマー割り込みをずらすことができます。

nohz

on

このオプションを使用すると、カーネルはシステムがアイドル状態のときに1つのCPU上でタイマーティックを実行できます。

nohz_full

1-30、33-62

カーネルブートパラメータは、完全なdynticksとCPU分離の設定を行うための現在の主要インタフェースです。

rcu_nocbs

1-30、33-62

このオプションを使用すると、カーネルはシステムがアイドル状態のときに1つのCPU上でRCUコールバックを実行できます。

kthread_cpus

0、31、32、63

このオプションを使用すると、システムがアイドル状態のときに1つのCPU上でkthreadsを実行できます。

irqaffinity

0、31、32、63

このオプションを使用すると、システムがアイドル状態のときに1つのCPU上で割り込みを実行できます。

processor.max_cstate

1

このオプションを使用すると、アイドル状態のときにCPUがスリープ状態になるのを防ぎます。

intel_idle.max_cstate

0

このオプションを使用すると、intel_idleドライバが無効になり、acpi_idleを使用できるようになります。

上記の値を使用することで、60個のコアを分離し、4個のコアをOSに使用します。

次のコマンドでGRUB設定を変更し、上記の変更を次回ブート時に適用します。

/etc/default/grubファイルを編集し、上記のパラメータを追加します。

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

GRUB設定を更新します。

$ transactional-update grub.cfg
$ reboot

再起動後にパラメータが適用されていることを検証するには、次のコマンドを使用してカーネルコマンドラインを確認できます。

$ cat /proc/cmdline

30.3 CNI設定

30.3.1 Cilium

CiliumはATIPのデフォルトのCNIプラグインです。RKE2クラスタでCiliumをデフォルトのプラグインとして有効にするには、/etc/rancher/rke2/config.yamlファイルに次の設定が必要です。

cni:
- cilium

これはコマンドライン引数でも指定できます。具体的には、/etc/systemd/system/rke2-serverファイルのサーバの行に--cni=ciliumを追加します。

次のセクション(30.4項 「SR-IOV」)で説明するSR-IOV Network Operatorを使用するには、Multusとともに、CiliumCalicoなどの別のCNIプラグインをセカンダリプラグインとして使用します。

cni:
- multus
- cilium
注記
注記

CNIプラグインの詳細については、「Network Options (ネットワークオプション)」を参照してください。

30.4 SR-IOV

SR-IOVを使用すると、ネットワークアダプタなどのデバイスで、そのリソースへのアクセスをさまざまなPCIeハードウェア機能の間で分離することができます。SR-IOVをデプロイするにはさまざまな方法がありますが、ここでは2つの方法を示します。

  • オプション1: SR-IOV CNIデバイスプラグインと設定マップを使用して適切に設定する。

  • オプション2 (推奨): Rancher PrimeからSR-IOV Helmチャートを使用してこのデプロイメントを簡単に行えるようにする。

オプション1 - SR-IOV CNIデバイスプラグインと設定マップをインストールして適切に設定する

  • デバイスプラグインの設定マップを準備する

設定マップに入力する情報をlspciコマンドから取得します。

$ lspci | grep -i acc
8a:00.0 Processing accelerators: Intel Corporation Device 0d5c

$ lspci | grep -i net
19:00.0 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.1 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.2 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.3 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
51:00.0 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:00.1 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:01.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)

設定マップはJSONファイルで構成され、このファイルで、フィルタを使用して検出を行うデバイスを記述し、インタフェースのグループを作成します。フィルタとグループを理解することが重要です。フィルタはデバイスを検出するために使用され、グループはインタフェースを作成するために使用されます。

フィルタを設定することもできます。

  • vendorID: 8086 (Intel)

  • deviceID: 0d5c (アクセラレータカード)

  • driver: vfio-pci (ドライバ)

  • pfNames: p2p1 (物理インタフェース名)

フィルタを設定して、より複雑なインタフェース構文に一致させることもできます。次に例を示します。

  • pfNames: ["eth1#1,2,3,4,5,6"]または[eth1#1-6] (物理インタフェース名)

グループに関連して、FECカード用のグループを1つと、Intelカード用のグループを1つ作成し、さらに、ユースケースに応じてプレフィックスを作成することもできます。

  • resourceName: pci_sriov_net_bh_dpdk

  • resourcePrefix: Rancher.io

リソースグループを検出して作成し、一部のVFをPodに割り当てる組み合わせは多数あります。

注記
注記

フィルタとグループの詳細については、「sriov-network-device-plugin (sr-iovネットワークデバイスプラグイン)」を参照してください。

フィルタとグループを設定して、ハードウェアとユースケースに応じたインタフェースに一致させると、使用する例が次の設定マップに表示されます。

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [
            {
                "resourceName": "intel_fec_5g",
                "devicetype": "accelerator",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["0d5d"]
                }
            },
            {
                "resourceName": "intel_sriov_odu",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p1"]
                }
            },
            {
                "resourceName": "intel_sriov_oru",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p2"]
                }
            }
        ]
    }
  • daemonsetファイルを準備して、デバイスプラグインをデプロイします。

このデバイスプラグインは、複数のアーキテクチャ(armamdppc64le)をサポートしています。したがって、同じファイルを異なるアーキテクチャに使用して、各アーキテクチャに複数のdaemonsetをデプロイできます。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sriov-device-plugin
  namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-sriov-device-plugin-amd64
  namespace: kube-system
  labels:
    tier: node
    app: sriovdp
spec:
  selector:
    matchLabels:
      name: sriov-device-plugin
  template:
    metadata:
      labels:
        name: sriov-device-plugin
        tier: node
        app: sriovdp
    spec:
      hostNetwork: true
      nodeSelector:
        kubernetes.io/arch: amd64
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      serviceAccountName: sriov-device-plugin
      containers:
      - name: kube-sriovdp
        image: rancher/hardened-sriov-network-device-plugin:v3.5.1-build20231009-amd64
        imagePullPolicy: IfNotPresent
        args:
        - --log-dir=sriovdp
        - --log-level=10
        securityContext:
          privileged: true
        resources:
          requests:
            cpu: "250m"
            memory: "40Mi"
          limits:
            cpu: 1
            memory: "200Mi"
        volumeMounts:
        - name: devicesock
          mountPath: /var/lib/kubelet/
          readOnly: false
        - name: log
          mountPath: /var/log
        - name: config-volume
          mountPath: /etc/pcidp
        - name: device-info
          mountPath: /var/run/k8s.cni.cncf.io/devinfo/dp
      volumes:
        - name: devicesock
          hostPath:
            path: /var/lib/kubelet/
        - name: log
          hostPath:
            path: /var/log
        - name: device-info
          hostPath:
            path: /var/run/k8s.cni.cncf.io/devinfo/dp
            type: DirectoryOrCreate
        - name: config-volume
          configMap:
            name: sriovdp-config
            items:
            - key: config.json
              path: config.json
  • 設定マップとdaemonsetを適用すると、デバイスプラグインがデプロイされ、インタフェースが検出されてPodで使用できるようになります。

    $ kubectl get pods -n kube-system | grep sriov
    kube-system  kube-sriov-device-plugin-amd64-twjfl  1/1  Running  0  2m
  • Podで使用するノードでインタフェースが検出されて利用可能であることを確認します。

    $ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq
    {
      "cpu": "64",
      "ephemeral-storage": "256196109726",
      "hugepages-1Gi": "40Gi",
      "hugepages-2Mi": "0",
      "intel.com/intel_fec_5g": "1",
      "intel.com/intel_sriov_odu": "4",
      "intel.com/intel_sriov_oru": "4",
      "memory": "221396384Ki",
      "pods": "110"
    }
  • FECintel.com/intel_fec_5gで、値は1です。

  • Helmチャートを使用せずに、デバイスプラグインと設定マップを使用してデプロイした場合、VFは、intel.com/intel_sriov_oduまたはintel.com/intel_sriov_oruです。

重要
重要

ここにインタフェースがない場合、そのインタフェースをPodで使用することはできないため、続行しても意味がありません。まず、設定マップとフィルタを確認して問題を解決してください。

オプション2 (推奨) - Rancherを使用し、SR-IOV CNIおよびデバイスプラグイン用のHelmチャートを使用したインストール

  • Helmがない場合は入手します。

$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
  • SR-IOVをインストールします。

この部分は2つの方法で実行できます。CLIを使用する方法と、Rancher UIを使用する方法です。

CLIからのオペレータのインストール
helm repo add suse-edge https://suse-edge.github.io/charts
helm install sriov-crd suse-edge/sriov-crd -n sriov-network-operator
helm install install sriov-network-operator suse-edge/sriov-network-operator -n sriov-network-operator
Rancher UIからのオペレータのインストール

クラスタがインストールされたら、Rancher UIにアクセスできるようになり、[Apps (アプリ)]タブでRancher UIからSR-IOVオペレータをインストールできます。

注記
注記

必ず、正しいネームスペースを選択してオペレータをインストールしてください(例: sriov-network-operator)。

+ image::features_sriov.png[sriov.png]

  • デプロイしたリソースのcrdとPodを確認します。

$ kubectl get crd
$ kubectl -n sriov-network-operator get pods
  • ノードのラベルを確認します。

すべてのリソースが実行されていると、ラベルがノードに自動的に表示されます。

$ kubectl get nodes -oyaml | grep feature.node.kubernetes.io/network-sriov.capable

feature.node.kubernetes.io/network-sriov.capable: "true"
  • daemonsetを確認し、新しいsriov-network-config-daemonおよびsriov-rancher-nfd-workerがアクティブで準備できていることを確認します。

$ kubectl get daemonset -A
NAMESPACE             NAME                            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                                           AGE
calico-system            calico-node                     1         1         1       1            1           kubernetes.io/os=linux                                  15h
sriov-network-operator   sriov-network-config-daemon     1         1         1       1            1           feature.node.kubernetes.io/network-sriov.capable=true   45m
sriov-network-operator   sriov-rancher-nfd-worker        1         1         1       1            1           <none>                                                  45m
kube-system              rke2-ingress-nginx-controller   1         1         1       1            1           kubernetes.io/os=linux                                  15h
kube-system              rke2-multus-ds                  1         1         1       1            1           kubernetes.io/arch=amd64,kubernetes.io/os=linux         15h

数分後(更新に最大で10分かかる可能性があります)、ノードが検出されて、SR-IOVの機能が設定されます。

$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -A
NAMESPACE             NAME     AGE
sriov-network-operator   xr11-2   83s
  • 検出されたインタフェースを確認します。

検出されたインタフェースはネットワークデバイスのPCIアドレスである必要があります。この情報は、ホストでlspciコマンドを使用して確認します。

$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -n kube-system -oyaml
apiVersion: v1
items:
- apiVersion: sriovnetwork.openshift.io/v1
  kind: SriovNetworkNodeState
  metadata:
    creationTimestamp: "2023-06-07T09:52:37Z"
    generation: 1
    name: xr11-2
    namespace: sriov-network-operator
    ownerReferences:
    - apiVersion: sriovnetwork.openshift.io/v1
      blockOwnerDeletion: true
      controller: true
      kind: SriovNetworkNodePolicy
      name: default
      uid: 80b72499-e26b-4072-a75c-f9a6218ec357
    resourceVersion: "356603"
    uid: e1f1654b-92b3-44d9-9f87-2571792cc1ad
  spec:
    dpConfigVersion: "356507"
  status:
    interfaces:
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f0
      mtu: 1500
      name: p2p1
      pciAddress: "0000:51:00.0"
      totalvfs: 128
      vendor: "8086"
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f1
      mtu: 1500
      name: p2p2
      pciAddress: "0000:51:00.1"
      totalvfs: 128
      vendor: "8086"
    syncStatus: Succeeded
kind: List
metadata:
  resourceVersion: ""
注記
注記

ここでインタフェースが検出されていない場合は、インタフェースが次の設定マップに存在することを確認してください。

$ kubectl get cm supported-nic-ids -oyaml -n sriov-network-operator

ここにデバイスがない場合は、設定マップを編集して、検出すべき適切な値を追加します(sriov-network-config-daemonデーモンセットの再起動が必要になります)。

  • NetworkNodeポリシーを作成してVFを設定します。

VF (numVfs)がデバイス(rootDevices)から作成され、ドライバdeviceTypeMTUが設定されます。

注記
注記

resourceNameフィールドには特殊文字を含めないでください。また、このフィールドはクラスタ全体で一意である必要があります。この例では、dpdksr-iovと組み合わせて使用するため、deviceType: vfio-pciを使用しています。dpdkを使用しない場合は、deviceTypeをdeviceType: netdevice (デフォルト値)にする必要があります。

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: policy-dpdk
  namespace: sriov-network-operator
spec:
  nodeSelector:
    feature.node.kubernetes.io/network-sriov.capable: "true"
  resourceName: intelnicsDpdk
  deviceType: vfio-pci
  numVfs: 8
  mtu: 1500
  nicSelector:
    deviceID: "1592"
    vendor: "8086"
    rootDevices:
    - 0000:51:00.0
  • 設定を検証します。

$ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq
{
  "cpu": "64",
  "ephemeral-storage": "256196109726",
  "hugepages-1Gi": "60Gi",
  "hugepages-2Mi": "0",
  "intel.com/intel_fec_5g": "1",
  "memory": "200424836Ki",
  "pods": "110",
  "rancher.io/intelnicsDpdk": "8"
}
  • sr-iovネットワークを作成します(別のネットワークが必要な場合のオプション)。

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: network-dpdk
  namespace: sriov-network-operator
spec:
  ipam: |
    {
      "type": "host-local",
      "subnet": "192.168.0.0/24",
      "rangeStart": "192.168.0.20",
      "rangeEnd": "192.168.0.60",
      "routes": [{
        "dst": "0.0.0.0/0"
      }],
      "gateway": "192.168.0.1"
    }
  vlan: 500
  resourceName: intelnicsDpdk
  • 作成されたネットワークを確認します。

$ kubectl get network-attachment-definitions.k8s.cni.cncf.io -A -oyaml

apiVersion: v1
items:
- apiVersion: k8s.cni.cncf.io/v1
  kind: NetworkAttachmentDefinition
  metadata:
    annotations:
      k8s.v1.cni.cncf.io/resourceName: rancher.io/intelnicsDpdk
    creationTimestamp: "2023-06-08T11:22:27Z"
    generation: 1
    name: network-dpdk
    namespace: sriov-network-operator
    resourceVersion: "13124"
    uid: df7c89f5-177c-4f30-ae72-7aef3294fb15
  spec:
    config: '{ "cniVersion":"0.3.1", "name":"network-dpdk","type":"sriov","vlan":500,"vlanQoS":0,"ipam":{"type":"host-local","subnet":"192.168.0.0/24","rangeStart":"192.168.0.10","rangeEnd":"192.168.0.60","routes":[{"dst":"0.0.0.0/0"}],"gateway":"192.168.0.1"}
      }'
kind: List
metadata:
  resourceVersion: ""

30.5 DPDK

DPDK (データプレーン開発キット)は、パケットの高速処理用の一連のライブラリとドライバです。DPDKは、広範なCPUアーキテクチャ上で実行されるパケット処理ワークロードを高速化するために使用されます。DPDKには、データプレーンライブラリと、以下のために最適化されたネットワークインタフェースコントローラ(NIC)ドライバが含まれています。

  1. キューマネージャはロックなしのキューを実装します。

  2. バッファマネージャは固定サイズのバッファを事前割り当てします。

  3. メモリマネージャは、メモリ内にオブジェクトのプールを割り当て、リングを使用してフリーオブジェクトを格納します。オブジェクトがすべてのDRAMチャンネルに均等に分散されるようにします。

  4. ポールモードドライバ(PMD)は、非同期通知なしで動作するように設計されているため、オーバーヘッドが軽減されます。

  5. パケット処理を開発するためのヘルパである一連のライブラリとしてのパケットフレームワーク。

次の手順では、DPDKを有効にする方法と、DPDKインタフェースが使用するNICからVFを作成する方法を示します。

  • DPDKパッケージをインストールします。

$ transactional-update pkg install dpdk22 dpdk22-tools libdpdk-23
$ reboot
  • カーネルパラメータ:

DPDKを使用するには、ドライバをいくつか使用して、カーネルの特定のパラメータを有効にします。

パラメータ説明

iommu

pt

このオプションを使用すると、DPDKインタフェースにvfioドライバを使用できます。

intel_iommu

on

このオプションを使用すると、VFvfioを使用できます。

これらのパラメータを有効にするには、各パラメータを/etc/default/grubファイルに追加します。

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

GRUBの設定を更新し、システムを再起動して変更を適用します。

$ transactional-update grub.cfg
$ reboot
  • vfio-pciカーネルモジュールを読み込み、NICSR-IOVを有効にします。

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • NICから仮想機能(VF)をいくつか作成します。

たとえば、2つの異なるNICに対してVFを作成するには、次のコマンドが必要です。

$ echo 4 > /sys/bus/pci/devices/0000:51:00.0/sriov_numvfs
$ echo 4 > /sys/bus/pci/devices/0000:51:00.1/sriov_numvfs
  • 新しいVFをvfio-pciドライバにバインドします。

$ dpdk-devbind.py -b vfio-pci 0000:51:01.0 0000:51:01.1 0000:51:01.2 0000:51:01.3 \
                              0000:51:11.0 0000:51:11.1 0000:51:11.2 0000:51:11.3
  • 設定が正しく適用されたことを確認します。

$ dpdk-devbind.py -s

Network devices using DPDK-compatible driver
============================================
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:11.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:21.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:31.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio

Network devices using kernel driver
===================================
0000:19:00.0 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em1 drv=bnxt_en unused=igb_uio,vfio-pci *Active*
0000:19:00.1 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em2 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.2 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em3 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.3 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em4 drv=bnxt_en unused=igb_uio,vfio-pci
0000:51:00.0 'Ethernet Controller E810-C for QSFP 1592' if=eth13 drv=ice unused=igb_uio,vfio-pci
0000:51:00.1 'Ethernet Controller E810-C for QSFP 1592' if=rename8 drv=ice unused=igb_uio,vfio-pci

30.6 vRANアクセラレーション(Intel ACC100/ACC200)

4Gから5Gネットワークへの移行に伴い、多くの通信サービスプロバイダが仮想化無線アクセスネットワーク(vRAN)アーキテクチャを採用して、チャンネル容量を増やし、エッジベースのサービスとアプリケーションのデプロイメントを容易にしようとしています。vRANソリューションは、ネットワーク上のリアルタイムのトラフィックと需要の量に応じて容量を柔軟に増減できるため、低レイテンシのサービスを提供するのに理想的です。

4Gおよび5Gで最も計算負荷が高いワークロードの1つがRANレイヤ1 (L1)のFECです。これは、信頼性の低い通信チャンネルやノイズの多い通信チャンネルでのデータ伝送エラーを解消するものです。FEC技術は、4Gまたは5Gデータの一定数のエラーを検出して訂正することで、再送信の必要性を解消します。FECアクセラレーショントランザクションにはセルの状態情報が含まれないため、簡単に仮想化でき、プールするメリットとセルの容易な移行が実現します。

  • カーネルパラメータ

vRANアクセラレーションを有効にするには、次のカーネルパラメータを有効にする必要があります(まだ存在しない場合)。

パラメータ説明

iommu

pt

このオプションを使用すると、DPDKインタフェースにvfioを使用できます。

intel_iommu

on

このオプションを使用すると、VFにvfioを使用できます。

GRUBファイル/etc/default/grubを変更して、これらのパラメータをカーネルコマンドラインに追加します。

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

GRUBの設定を更新し、システムを再起動して変更を適用します。

$ transactional-update grub.cfg
$ reboot

再起動後にパラメータが適用されていることを確認するには、コマンドラインを確認します。

$ cat /proc/cmdline
  • vfio-pciカーネルモジュールを読み込み、vRANアクセラレーションを有効にします。

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • インタフェース情報Acc100を取得します。

$ lspci | grep -i acc
8a:00.0 Processing accelerators: Intel Corporation Device 0d5c
  • 物理インタフェース(PF)をvfio-pciドライバにバインドします。

$ dpdk-devbind.py -b vfio-pci 0000:8a:00.0
  • 仮想機能(VF)を物理インタフェース(PF)から作成します。

2つのVFPFから作成し、次の手順に従ってvfio-pciにバインドします。

$ echo 2 > /sys/bus/pci/devices/0000:8a:00.0/sriov_numvfs
$ dpdk-devbind.py -b vfio-pci 0000:8b:00.0
  • 提案された設定ファイルを使用してacc100を設定します。

$ pf_bb_config ACC100 -c /opt/pf-bb-config/acc100_config_vf_5g.cfg
Tue Jun  6 10:49:20 2023:INFO:Queue Groups: 2 5GUL, 2 5GDL, 2 4GUL, 2 4GDL
Tue Jun  6 10:49:20 2023:INFO:Configuration in VF mode
Tue Jun  6 10:49:21 2023:INFO: ROM version MM 99AD92
Tue Jun  6 10:49:21 2023:WARN:* Note: Not on DDR PRQ version  1302020 != 10092020
Tue Jun  6 10:49:21 2023:INFO:PF ACC100 configuration complete
Tue Jun  6 10:49:21 2023:INFO:ACC100 PF [0000:8a:00.0] configuration complete!
  • FEC PFから作成した新しいVFを確認します。

$ dpdk-devbind.py -s
Baseband devices using DPDK-compatible driver
=============================================
0000:8a:00.0 'Device 0d5c' drv=vfio-pci unused=
0000:8b:00.0 'Device 0d5d' drv=vfio-pci unused=

Other Baseband devices
======================
0000:8b:00.1 'Device 0d5d' unused=

30.7 Huge Page

プロセスがRAMを使用すると、CPUはそのメモリ領域をプロセスが使用中であるとマークします。効率を高めるために、CPURAMをチャンクで割り当てます。多くのプラットフォームでは4Kバイトがチャンクのデフォルト値です。これらのチャンクをページと呼び、ディスクなどにスワップできます。

プロセスのアドレススペースは仮想であるため、CPUとオペレーティングシステムは、どのページがどのプロセスに属していて、各ページがどこに保管されているかを覚えておく必要があります。ページ数が多いほど、メモリマッピングの検索に時間がかかります。プロセスが1GBのメモリを使用する場合、検索するエントリは262,144個になります(1GB / 4K)。1つのページテーブルエントリが8バイトを消費する場合、2MB (262,144 * 8)を検索することになります。

最新のCPUアーキテクチャはデフォルトより大きいページをサポートしているので、CPU/OSが検索するエントリが減少します。

  • カーネルパラメータ

Huge Pageを有効にするには、次のカーネルパラメータを追加する必要があります。

パラメータ説明

hugepagesz

1G

このオプションを使用すると、Huge Pageを1Gに設定できます

hugepages

40

前に定義したHuge Pageの数です

default_hugepagesz

1G

Huge Pageを取得するためのデフォルト値です

GRUBファイル/etc/default/grubを変更して、これらのパラメータをカーネルコマンドラインに追加します。

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

GRUBの設定を更新し、システムを再起動して変更を適用します。

$ transactional-update grub.cfg
$ reboot

再起動後にパラメータが適用されていることを検証するには、次のコマンドラインを確認できます。

$ cat /proc/cmdline
  • Huge Pageの使用

Huge Pageを使用するには、Huge Pageをマウントする必要があります。

$ mkdir -p /hugepages
$ mount -t hugetlbfs nodev /hugepages

Kubernetesワークロードをデプロイし、リソースとボリュームを作成します。

...
 resources:
   requests:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
   limits:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
...
...
volumeMounts:
  - name: hugepage
    mountPath: /hugepages
...
volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages
...

30.8 CPUピニング設定

  • 要件

    1. こちらのセクション(30.2項 「CPU調整設定」)で説明したパフォーマンスプロファイルに合わせてCPUが調整されていること。

    2. 次のブロック(例)を/etc/rancher/rke2/config.yamlファイルに追加して、RKE2クラスタのkubeletにCPU管理の引数が設定されていること。

kubelet-arg:
- "cpu-manager=true"
- "cpu-manager-policy=static"
- "cpu-manager-policy-options=full-pcpus-only=true"
- "cpu-manager-reconcile-period=0s"
- "kubelet-reserved=cpu=1"
- "system-reserved=cpu=1"
  • KubernetesでのCPUピニングの使用

kubeletで定義された静的ポリシーを使ってCPUピニング機能を使用する方法は、ワークロードに対して定義した要求と制限に応じて3つあります。

  1. BestEffort QoSクラス: CPUに対して要求または制限を定義していない場合、Podはシステムで使用できる最初のCPUでスケジュールされます。

    BestEffort QoSクラスを使用する例を次に示します。

    spec:
      containers:
      - name: nginx
        image: nginx
  2. Burstable QoSクラス: CPUに対して要求を定義し、その要求が制限と同じではない場合、またはCPUの要求がない場合。

    Burstable QoSクラスを使用する例を次に示します。

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
          requests:
            memory: "100Mi"

    または

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
            cpu: "2"
          requests:
            memory: "100Mi"
            cpu: "1"
  3. Guaranteed QoSクラス: CPUに対して要求を定義し、その要求が制限と同じである場合。

    Guaranteed QoSクラスを使用する例を次に示します。

    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: "200Mi"
              cpu: "2"
            requests:
              memory: "200Mi"
              cpu: "2"

30.9 NUMA対応のスケジューリング

Non-Uniform Memory AccessまたはNon-Uniform Memory Architecture (NUMA)は、SMP (マルチプロセッサ)アーキテクチャにおいて使用される物理メモリ設計であり、メモリアクセス時間がプロセッサからのメモリの相対的な位置によって異なります。NUMAでは、プロセッサは専用のローカルメモリに、非ローカルメモリ、つまり別のプロセッサにローカルなメモリや複数のプロセッサで共有されているメモリよりも高速にアクセスできます。

30.9.1 NUMAノードの特定

NUMAノードを特定するには、システムで次のコマンドを使用します。

$ lscpu | grep NUMA
NUMA node(s):                       1
NUMA node0 CPU(s):                  0-63
注記
注記

この例では、NUMAノードが1つだけあり、64個のCPUが表示されています。

NUMABIOSで有効にする必要があります。dmesgにブート時のNUMA初期化レコードがない場合、カーネルリングバッファ内のNUMA関連のメッセージが上書きされた可能性があります。

30.10 MetalLB

MetalLBは、ベアメタルKubernetesクラスタ用のロードバランサの実装であり、L2BGPなどの標準ルーティングプロトコルをアドバタイズプロトコルとして使用します。ベアメタル環境ではKubernetesサービスタイプLoadBalancerを使用する必要があるため、Kubernetesクラスタ内のサービスを外部に公開するために使用できるのは、ネットワークロードバランサです。

RKE2クラスタでMetalLBを有効にするには、次の手順を実行する必要があります。

  • 次のコマンドを使用してMetalLBをインストールします。

$ kubectl apply <<EOF -f
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: metallb
  namespace: kube-system
spec:
  repo: https://metallb.github.io/metallb/
  chart: metallb
  targetNamespace: metallb-system
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: endpoint-copier-operator
  namespace: kube-system
spec:
  repo: https://suse-edge.github.io/endpoint-copier-operator
  chart: endpoint-copier-operator
  targetNamespace: endpoint-copier-operator
EOF
  • IpAddressPoolおよびL2advertisementの設定を作成します。

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: kubernetes-vip-ip-pool
  namespace: metallb-system
spec:
  addresses:
    - 10.168.200.98/32
  serviceAllocation:
    priority: 100
    namespaces:
      - default
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ip-pool-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
    - kubernetes-vip-ip-pool
  • VIPを公開するためのエンドポイントサービスを作成します。

apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: rke2-api
    port: 9345
    protocol: TCP
    targetPort: 9345
  - name: k8s-api
    port: 6443
    protocol: TCP
    targetPort: 6443
  sessionAffinity: None
  type: LoadBalancer
  • VIPが作成され、MetalLBのPodが実行中であることを確認します。

$ kubectl get svc -n default
$ kubectl get pods -n default

30.11 プライベートレジストリ設定

Containerdをプライベートレジストリに接続するように設定し、そのプライベートレジストリを使用して各ノードにプライベートイメージをプルできます。

起動時に、RKE2は、registries.yamlファイルが/etc/rancher/rke2/に存在するかどうかを確認し、このファイルで定義されたレジストリを使用するようにcontainerdに指示します。プライベートレジストリを使用するには、このファイルを、レジストリを使用する各ノードにルートとして作成します。

プライベートレジストリを追加するには、ファイル/etc/rancher/rke2/registries.yamlを作成して次の内容を設定します。

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    auth:
      username: xxxxxx # this is the registry username
      password: xxxxxx # this is the registry password
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

または、認証を使用しない場合は次のように設定します。

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

レジストリの変更を有効にするには、ノード上でRKE2を起動する前にこのファイルを設定するか、または設定した各ノードでRKE2を再起動します。

注記
注記

詳細については、「Containerd Registry Configuration | RKE2 (Containerdのレジストリ設定 | RKE2)」を確認してください。