documentation.suse.com / SUSE Edgeドキュメント / 製品マニュアル / 通信機能の設定

41 通信機能の設定

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

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

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

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

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

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

  • 決定論的実行:

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

  • 低ジッタ:

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

  • 優先度の継承:

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

  • スレッドの割り込み:

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

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

    注記
    注記

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

41.2 低レイテンシとハイパフォーマンスのためのカーネル引数

リアルタイムカーネルを適切に動作させ、通信ワークロードを実行する際には、最高のパフォーマンスと低レイテンシ実現できるようにカーネル引数を設定することが重要です。このユースケースのカーネル引数を設定する際には、いくつかの重要な概念を念頭に置く必要があります。

  • SUSEリアルタイムカーネルを使用する際には、kthread_cpusを削除します。このパラメータは、カーネルスレッドが作成されるCPUを制御します。また、PID 1とカーネルモジュール(kmodユーザスペースヘルパ)のロードにどのCPUが許可されるかも制御します。このパラメータは認識されず、影響は何もありません。

  • isolcpusnohz_fullrcu_nocbs、およびirqaffinityを使用して、CPUコアを分離します。CPUピニング技術の包括的なリストについては、「Tunedとカーネル引数によるCPUピニング」(41.3項 「Tunedとカーネル引数によるCPUピニング」)の章を参照してください。

  • domain,nohz,managed_irqフラグをisolcpusカーネル引数に追加します。何もフラグを指定しない場合、isolcpusdomainフラグのみを指定するのと同等になります。これにより、指定したCPUがカーネルタスクを含むスケジューリングから分離されます。nohzフラグは指定されたCPUのスケジューラティックを停止し(CPUで実行できるタスクが1つのみの場合)、managed_irqフラグは指定したCPUの管理対象の外部(デバイス)割り込みのルーティングを回避します。NVMeデバイスのIRQラインはカーネルによって完全に管理されており、その結果、非分離(ハウスキーピング)コアにルーティングされることに注意してください。たとえば、このセクションの最後に示されたコマンドラインを実行すると、システムに割り当てられるキューは4つ(および管理/制御キュー)のみとなります。

    for I in $(grep nvme0 /proc/interrupts | cut -d ':' -f1); do cat /proc/irq/${I}/effective_affinity_list; done | column
    39      0       19      20      39

    この動作は、分離されたコア上で実行中の時間的制約のあるアプリケーションに対するディスク I/O による中断を防止します。ただし、ストレージに重点を置いたワークロードの場合、注意と慎重な設計が必要になる可能性があります。

  • ティック(カーネルの定期的なタイマー割り込み)を調整します。

    • skew_tick=1: ティックは同時に発生する場合があります。skew_tick=1を指定すると、すべてのCPUがタイマーティックを正確に同じタイミングで受信するのではなく、わずかにオフセットされたタイミングで発生させます。これにより、システムジッターが軽減され、より一貫性があり低い割り込み応答時間(レイテンシに敏感なアプリケーションにとって不可欠な要件)が可能になります。

    • nohz=on: アイドル状態のCPUにおける定期的なタイマーティックを停止します。

    • nohz_full=<cpu-cores>: リアルタイムアプリケーション専用の指定されたCPUにおける定期的なタイマーティックを停止します。

  • mce=offを指定して、マシンチェック例外(MCE)の処理を無効にします。MCEはプロセッサによって検出されるハードウェアエラーであり、無効にすることで、ノイズの多いログを回避できます。

  • nowatchdogを追加して、タイマーのハード割り込みコンテキストで実行されるタイマーとして実装されるソフトロックアップウォッチドッグを無効にします。有効期限が切れると(すなわち、ソフトロックアップが検出されると)、(ハード割り込みコンテキストで)警告が出力され、あらゆるレイテンシターゲットを実行します。有効期限が切れていない場合でも、タイマーリストに追加され、タイマー割り込みのオーバーヘッドがわずかに増加します。 このオプションは、NMIウォッチドッグも無効にするため、NMIが干渉できなくなります。

  • nmi_watchdog=0は、NMI (Non-Maskable Interrupt)ウォッチドッグを無効にします。 nowatchdogが使用される場合は省略できます。

  • RCU (Read-Copy-Update)は、共有データに対して多数のリーダが同時にロックなしでアクセスできるようにするカーネルメカニズムです。RCUコールバックは、一定の「猶予期間」後にトリガされる関数で、すべての以前のリーダが終了していることを確認し、古いデータを安全に再利用できるようにします。SUSEでは、特に機密性の高いワークロード向けにRCUを微調整し、これらのコールバックを専用(ピニングされた)CPUからオフロードすることで、カーネル操作が重要な時間的制約のあるタスクと干渉しないようにしています。

    • rcu_nocbsでピニングされたCPUを指定し、RCUコールバックがそのCPU上で実行されないようにします。これにより、リアルタイムワークロードのジッターとレイテンシを軽減できます。

    • rcu_nocb_pollは、コールバック処理が必要かどうかを確認するために、no-callback CPUを定期的に「ポーリング」させます。これにより、割り込みのオーバーヘッドを削減できます。

    • rcupdate.rcu_cpu_stall_suppress=1は、RCU CPUストール警告を抑制します。これは、高負荷のリアルタイムシステムでは偽陽性となる場合があります。

    • rcupdate.rcu_expedited=1は、RCU操作の猶予期間を短縮し、読み取り側のクリティカルセクションの応答性を向上させます。

    • rcupdate.rcu_normal_after_boot=1: rcu_expeditedとともに使用する場合、システム起動後にRCUが通常の(非迅速)動作に戻ることができます。

    • rcupdate.rcu_task_stall_timeout=0は、RCUタスクのストール検出機能を無効にし、長時間実行されるRCUタスクによる潜在的な警告やシステム停止を防止します。

    • rcutree.kthread_prio=99は、RCUコールバックカーネルスレッドの優先度を可能な限り最高(99)に設定し、必要に応じてRCUコールバックがスケジュールされ、迅速に処理されるようにします。

  • Metal3とCluster APIにignition.platform.id=openstackを追加し、クラスタのプロビジョニング/プロビジョニング解除が正常に実行されるようにします。これは、Openstack Ironic由来のMetal3 Pythonエージェントによって使用されます。

  • intel_pstate=passiveを削除します。このオプションは、intel_pstateを汎用cpufreqガバナと連携するように設定しますが、この連携を行うには、副作用として、ハードウェア管理P状態(HWP)を無効にします。ハードウェアのレイテンシを削減するため、このオプションはリアルタイムワークロードには推奨されません。

  • intel_idle.max_cstate=0 processor.max_cstate=1idle=pollに置き換えます。 C-Stateの遷移を回避するには、idle=pollオプションを使用してC-Stateの遷移を無効にし、CPUを最高のC-Stateに維持します。intel_idle.max_cstate=0オプションは、intel_idleを無効にするため、 acpi_idleが使用され、acpi_idle.max_cstate=1がacpi_idleの最大のC-stateを設定します。AMD64/Intel 64アーキテクチャでは、最初のACPI C-Stateは常にPOLLですが、poll_idle()関数を使用しており、定期的にクロックを読み取ることで、タイムアウト後に do_idle()でメインループを再起動する際に、若干のレイテンシが発生する可能性があります(これにはTIF_POLLタスクフラグのクリアと設定も含まれます)。 これに対して、idle=pollはタイトなループで実行され、タスクが再スケジュールされるのをビジーウェイトします。これにより、アイドル状態から抜け出すまでのレイテンシが最小化されますが、その代償としてCPUがアイドルスレッドでフルスピードで稼働し続けることになります。

  • BIOSのC1Eを無効にします。このオプションは、BIOSでC1E状態を無効にし、アイドル時にCPUがCIE状態になるのを回避します。C1E状態は、CPUがアイドル状態のときにレイテンシを発生される可能性のある低電力状態です。

このドキュメントの残りの部分では、追加のパラメータ(Huge PageやIOMMUなど)について説明します。

以下は、前述の調整を含む32コアのIntelサーバのカーネル引数の例です。

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off net.ifnames=0 nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

以下は、64コアのAMDサーバのもう1つの設定例です。128個の論理プロセッサ(0-127)のうち、最初の8コア(0-7)はハウスキーピング用に指定され、残りの120コア(8-127)はアプリケーション用に固定されます。

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=575291cf-74e8-42cf-8f2c-408a20dc00b8 skew_tick=1 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack amd_iommu=on iommu=pt irqaffinity=0-7 isolcpus=domain,nohz,managed_irq,8-127 nohz_full=8-127 rcu_nocbs=8-127 mce=off nohz=on net.ifnames=0 nowatchdog nmi_watchdog=0 nosoftlockup quiet rcu_nocb_poll rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

41.3 Tunedとカーネル引数によるCPUピニング

tunedは、さまざまな事前定義済みプロファイルを使用して、システム状態を監視し、パフォーマンスを最適化するシステムチューニングツールです。主要な機能は、リアルタイムアプリケーションのなどの特定のワークロードに対してCPUコアを分離する機能です。この機能により、OSがこれらのコアを使用するのを防止し、潜在的にレイテンシが増加するのを回避します。

この機能を有効にして設定するには、まず、分離するCPUコアのプロファイルを作成します。この例では、64コアのうち、60コア(1-30、33-62)をアプリケーション専用にし、残りの4コアをハウスキーピングに使用します。分離されたCPUの設計は、リアルタイムアプリケーションに大きく依存することに注意してください。

$ 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

domain、nohz、​managed_irq、1-30、​33-62

コア1-30と3-62を分離します。domainは、これらのCPUが分離ドメインに属していることを示します。nohzは、これらの分離されたCPUがアイドル状態である場合にティックレス操作を有効にし、割り込みを減らします。managed_irqは、ピニングされたCPUがIRQの対象とならないように分離します。これは、ほとんどのIRQをハウスキーピングコアに指定するirqaffinity=0-7を考慮しています。

skew_tick

1

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

nohz

on

有効にすると、カーネルの定期的なタイマー割り込み(「ティック」)は、アイドル状態のCPUコアで停止します。これにより、主にハウスキーピング用CPU (0、31、32、63)にメリットをもたらします。これにより、電力が節約され、汎用コアでの不要なウェイクアップが削減されます。

nohz_full

1-30、33-62

分離されたコアの場合、これによりティックが停止され、CPUが単一のアクティブなタスクを実行している場合でも停止されます。つまり、CPUは完全なティックレスモード(または「dyntick」)で動作します。カーネルは、実際に必要な場合にのみタイマー割り込みを発生させます。

rcu_nocbs

1-30、33-62

このオプションは、指定のCPUコアからRCUコールバック処理をオフロードします。

rcu_nocb_poll

 

このオプションを設定すると、no-RCU-callback CPUは、他のCPUによって明示的にウェイクアップされるのではなく、コールバック処理が必要かどうかを確認するために定期的に「ポーリング」します。これにより、割り込みオーバーヘッドを削減できます。

irqaffinity

0、31、32、63

このオプションを使用すると、カーネルはハウスキーピング用コアに割り込みを実行できるようになります。

idle

poll

これにより、アイドル状態から抜け出すまでのレイテンシが最小化されますが、その代償として、CPUがアイドルスレッドでフルスピードで稼働し続けることになります。

nmi_watchdog

0

このオプションはNMIウォッチドッグのみを無効にします。nowatchdogが設定されている場合は省略できます。

nowatchdog

 

このオプションは、タイマーのハード割り込みコンテキストで実行されるタイマーとして実装されるソフトロックアップウォッチドッグを無効にします。

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

上記パラメータを使用して/etc/default/grubファイルを編集します。ファイルは次のようになります。

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off net.ifnames=0 nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

GRUB設定を更新します。

$ transactional-update grub.cfg
$ reboot

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

$ cat /proc/cmdline

CPU設定を調整するために使用可能な別のスクリプトがあります。これは基本的には次の手順を実行します。

  • CPUガバナーをパフォーマンスに設定します。

  • 分離されたCPUへのタイマーのマイグレーションの設定を解除します。

  • kdaemonスレッドをハウスキーピング用CPUに移行します。

  • 分離したCPUレイテンシを可能な限り低い値に設定します。

  • vmstatの更新を300秒に遅延させます。

スクリプトは、SUSE Edge for Telcoサンプルリポジトリで入手できます。

41.4 CNI設定

41.4.1 Cilium

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

cni:
- cilium

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

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

cni:
- multus
- cilium
注記
注記

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

41.5 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.7.0-build20240816
        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をインストールします。

helm install sriov-crd oci://registry.suse.com/edge/charts/sriov-crd -n sriov-network-operator
helm install sriov-network-operator oci://registry.suse.com/edge/charts/sriov-network-operator -n sriov-network-operator
  • デプロイしたリソースの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.4.0", "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: ""

41.6 DPDK

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

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

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

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

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

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

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

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

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

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

パラメータ説明

iommu

pt

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

intel_iommuまたはamd_iommu

on

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

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

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off net.ifnames=0 nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=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

41.7 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またはamd_iommu

on

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

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

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off net.ifnames=0 nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=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=

41.8 Huge Page

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

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

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

  • カーネルパラメータ

Huge Pageを有効にするには、次のカーネルパラメータを追加する必要があります。この例では、40個の1Gページを設定していますが、Huge Pageのサイズと正確な数は、アプリケーションのメモリ要件に合わせて調整する必要があります。

パラメータ説明

hugepagesz

1G

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

hugepages

40

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

default_hugepagesz

1G

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

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

default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0

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
...

41.9 KubernetesでのCPUピニング

41.9.1 前提条件

こちらのセクション(41.3項 「Tunedとカーネル引数によるCPUピニング」)で説明したパフォーマンスプロファイルに合わせてCPUが調整されていること。

41.9.2 CPUピニング用のKubernetesの設定

RKE2クラスタでCPU管理を実装するためにkubelet引数を設定します。次の例のような設定ブロックを/etc/rancher/rke2/config.yamlファイルに追加します。kubelet-reservedおよび system-reserved引数でハウスキーピング用CPUコアを指定していることを確認します。

kubelet-arg:
- "cpu-manager-policy=static"
- "cpu-manager-policy-options=full-pcpus-only=true"
- "cpu-manager-reconcile-period=0s"
- "kubelet-reserved=cpu=0,31,32,63"
- "system-reserved=cpu=0,31,32,63"

41.9.3 ワークロードにピニングされた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"

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

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

41.10.1 NUMAノードの特定

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

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

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

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

41.11 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:
  chart: oci://registry.suse.com/edge/charts/metallb
  targetNamespace: metallb-system
  version: 303.0.0+up0.14.9
  createNamespace: true
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: endpoint-copier-operator
  namespace: kube-system
spec:
  chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
  targetNamespace: endpoint-copier-operator
  version: 303.0.0+up0.2.1
  createNamespace: true
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

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

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)」を確認してください。

41.13 Precision Time Protocol

Precision Time Protocol (PTP)は、 電気電子学会(IEEE)によって開発されたネットワークプロトコルで、コンピュータネットワークにおけるサブマイクロ秒単位の時間同期を可能にします。PTPは、その誕生以来数十年にわたり、多くの業界で利用されてきました。最近では、5Gネットワークの重要な要素として、通信ネットワークにおける採用が急増しています。比較的シンプルなプロトコルであるものの、アプリケーションに応じて設定が大幅に異なります。そのため、複数のプロファイルが定義され標準化されています。

このセクションでは、通信事業者固有のプロファイルのみについて説明します。そのため、NICにタイムスタンプ機能とPTPハードウェアクロック(PHC)が搭載されていることを前提とします。現在、すべての通信事業者グレードのネットワークアダプタにはハードウェアPTPサポートが付属していますが、以下のコマンドでその機能を確認できます。

# ethtool -T p1p1
Time stamping parameters for p1p1:
Capabilities:
        hardware-transmit
        software-transmit
        hardware-receive
        software-receive
        software-system-clock
        hardware-raw-clock
PTP Hardware Clock: 0
Hardware Transmit Timestamp Modes:
        off
        on
Hardware Receive Filter Modes:
        none
        all

p1p1を、PTPに使用されるインタフェースの名前に置き換えます。

以下のセクションでは、SUSE EdgeにPTPをインストールして設定する方法について具体的に説明しますが、PTPの基本的な概念を理解していることが前提となります。PTPの概要と、SUSE Edge for Telcoに含まれる実装については、https://documentation.suse.com/sles/html/SLES-all/cha-tuning-ptp.htmlを参照してください。

41.13.1 PTPソフトウェアコンポーネントのインストール

SUSE Edge for Telcoでは、PTP実装がlinuxptpパッケージで提供されています。このパッケージには次の2つのコンポーネントが含まれています。

  • ptp4l: NIC上のPHCを制御し、PTPプロトコルを実行するデーモン

  • phc2sys: NIC上のPTP同期PHCとシステムクロックとの同期を維持するデーモン

システム同期が完全に機能するには、両方のデーモンが必要であり、セットアップに従って正しく設定する必要があります。詳細については、41.13.2項 「通信事業者のデプロイメント向けPTPの設定」を参照してください。

ダウンストリームクラスタにPTPを統合する最も簡単で最良の方法は、Edge Image Builder (EIB)定義ファイルのpackageListの下にlinuxptpパッケージを追加することです。 これにより、クラスタプロビジョニング中にPTPコントロールプレーンソフトウェアが自動的にインストールされます。パッケージのインストールの詳細については、EIBのドキュメント(3.3.4項 「RPMパッケージの設定」)を参照してください。

以下に、linuxptpを使用したEIBマニフェストのサンプルを示します。

apiVersion: 1.0
image:
  imageType: RAW
  arch: x86_64
  baseImage: {micro-base-rt-image-raw}
  outputImageName: eibimage-slmicrort-telco.raw
operatingSystem:
  time:
    timezone: America/New_York
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
    enable:
      - ptp4l
      - phc2sys
  users:
    - username: root
      encryptedPassword: ${ROOT_PASSWORD}
  packages:
    packageList:
      - jq
      - dpdk
      - dpdk-tools
      - libdpdk-23
      - pf-bb-config
      - open-iscsi
      - tuned
      - cpupower
      - linuxptp
    sccRegistrationCode: ${SCC_REGISTRATION_CODE}
注記
注記

SUSE Edge for Telcoに含まれるlinuxptpパッケージでは、デフォルトでptp4lおよびphc2sysが有効になりません。プロビジョニング時にシステム固有の設定ファイルがデプロイされている場合は(41.13.3項 「Cluster APIの統合」を参照)、これらを有効にする必要があります。上記の例のように、マニフェストのsystemdセクションに追加して有効にしてください。

EIBのドキュメントで説明されている通常のプロセスに従って、イメージを構築し(3.4項 「イメージの構築」)、そのイメージを使用してクラスタをデプロイします。EIBを初めて使用する場合は、第11章 「Edge Image Builderから開始してください。

41.13.2 通信事業者のデプロイメント向けPTPの設定

多くの通信事業者向けアプリケーションでは、わずかな偏差で厳格な位相と時刻同期が求められるため、通信事業者向けの2つのプロファイルが定義されました(ITU-T G.8275.1とITU-T G.8275.2)。これら両プロファイルは、同期メッセージの送信頻度が高く、代替Best Master Clock Algorithm (BMCA)の使用など、他の特徴的な特性を備えています。このような動作は、ptp4lが使用する設定ファイルに特定の設定を必要とします。これらの設定は以下のセクションで参照用に提供されています。

注記
注記
  • 両セクションは、タイムレシーバー設定の通常のクロックの場合のみを対象としてます。

  • このようなプロファイルは、適切に計画されたPTPインフラストラクチャで使用する必要があります。

  • 特定のPTPネットワークには、追加の設定の調整が必要な場合があります。必要に応じて、提供された例を確認して調整してください。

41.13.2.1 PTPプロファイルITU-T G.8275.1

G.8275.1プロファイルには、次の特徴があります。

  • Ethernet上で直接実行し、完全なネットワークサポートが必要です(隣接するノード/スイッチはPTPをサポートしている必要があります)。

  • デフォルトのドメイン設定は24です。

  • データセットの比較は、G.8275.xアルゴリズムと、priority2以降の localPriority値に基づいています。

次のコンテンツを/etc/ptp4l-G.8275.1.confという名前のファイルにコピーします。

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2			255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout		3
serverOnly                      0
ptp_dst_mac                     01:80:C2:00:00:0E
network_transport               L2

ファイルが作成されたら、デーモンが正常に起動するように/etc/sysconfig/ptp4lで参照される必要があります。これを行うには、 OPTIONS=行を次のように変更します。

OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"

より正確な説明は次のとおりです。

  • -fには、使用する設定ファイルのファイル名が必要です。この場合は/etc/ptp4l-G.8275.1.conf

  • -iには、使用するインタフェースの名前が必要です。$IFNAMEを実際のインタフェース名に置き換えます。

  • --message_tagは、システムログ内のptp4l出力を適切に特定できるようにし、オプションです。

上記の手順が完了したら、ptp4lデーモンを(再)起動する必要があります。

# systemctl restart ptp4l

次のコマンドを使用してログを調べ、同期ステータスを確認します。

# journalctl -e -u ptp4l

41.13.2.2 PTPプロファイルITU-T G.8275.2

G.8275.2プロファイルには、次の特徴があります。

  • IP上で実行し、完全なネットワークサポートは不要です(隣接するノード/スイッチはPTPをサポートしていない場合があります)。

  • デフォルトのドメイン設定は44です。

  • データセットの比較は、G.8275.xアルゴリズムと、priority2以降の localPriority値に基づいています。

次のコンテンツを/etc/ptp4l-G.8275.2.confという名前のファイルにコピーします。

# Telecom G.8275.2 example configuration
[global]
domainNumber                    44
priority2			255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             0
serverOnly                      0
hybrid_e2e                      1
inhibit_multicast_service       1
unicast_listen                  1
unicast_req_duration            60
logSyncInterval                 -5
logMinDelayReqInterval          -4
announceReceiptTimeout		2
#
# Customize the following for slave operation:
#
[unicast_master_table]
table_id                        1
logQueryInterval                2
UDPv4                           $PEER_IP_ADDRESS
[$IFNAME]
unicast_master_table            1

次のプレースフォルダを必ず置き換えます。

  • $PEER_IP_ADDRESS - 同期を提供するマスタまたは境界クロックなど、通信する次のPTPノードのIPアドレス。

  • $IFNAME - ptp4lにPTPに使用するインタフェースを示します。

ファイルが作成されると、デーモンが正常に起動するように、PTPに使用するインタフェースの名前とともに、/etc/sysconfig/ptp4lで参照される必要があります。これを行うには、OPTIONS=行を次のように変更します。

OPTIONS="-f /etc/ptp4l-G.8275.2.conf --message_tag ptp-8275.2"

より正確な説明は次のとおりです。

  • -fには、使用する設定ファイルのファイル名が必要です。この場合は、/etc/ptp4l-G.8275.2.confです。

  • --message_tagは、システムログ内のptp4l出力を適切に特定できるようにし、オプションです。

上記の手順が完了したら、ptp4lデーモンを(再)起動する必要があります。

# systemctl restart ptp4l

次のコマンドを使用してログを調べ、同期ステータスを確認します。

# journalctl -e -u ptp4l

41.13.2.3 phc2sysの設定

必須ではありませんが、phc2sysに移る前に、ptp4lの設定を完全に完了しておくことをお勧めします。phc2sysは設定ファイルを必要とせず、その実行パラメータはptp4lと同様に、/etc/sysconfig/ptp4lに存在するOPTIONS=変数を通じてのみ制御できます。

OPTIONS="-s $IFNAME -w"

ここで、$IFNAMEはシステムクロックのソースとして使用される、ptp4lですでに設定されているインタフェースの名前です。これはソースPHCを識別するために使用されます。

41.13.3 Cluster APIの統合

クラスタが管理クラスタおよびダイレクトネットワークプロビジョニングを通じてデプロイされるときは常に、プロビジョニング時に設定ファイルと/etc/sysconfig内の2つの設定変数の両方をホスト上にデプロイできます。以下は、同じG.8275.1設定ファイルをすべてのホスト上にデプロイする、変更されたRKE2ControlPlaneオブジェクトに焦点を当てたクラスタ定義の抜粋です。

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  serverConfig:
    cni: canal
  agentConfig:
    format: ignition
    cisProfile: cis
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
        storage:
          files:
            - path: /etc/ptp4l-G.8275.1.conf
              overwrite: true
              contents:
                inline: |
                  # Telecom G.8275.1 example configuration
                  [global]
                  domainNumber                    24
                  priority2                       255
                  dataset_comparison              G.8275.x
                  G.8275.portDS.localPriority     128
                  G.8275.defaultDS.localPriority  128
                  maxStepsRemoved                 255
                  logAnnounceInterval             -3
                  logSyncInterval                 -4
                  logMinDelayReqInterval          -4
                  announceReceiptTimeout          3
                  serverOnly                      0
                  ptp_dst_mac                     01:80:C2:00:00:0E
                  network_transport               L2
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/ptp4l
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): ptp4l settings
                  ## Type:           string
                  ## Default:        "-i eth0 -f /etc/ptp4l.conf"
                  ## ServiceRestart: ptp4l
                  #
                  # Arguments when starting ptp4l(8).
                  #
                  OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/phc2sys
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): phc2sys settings
                  ## Type:           string
                  ## Default:        "-s eth0 -w"
                  ## ServiceRestart: phc2sys
                  #
                  # Arguments when starting phc2sys(8).
                  #
                  OPTIONS="-s $IFNAME -w"
              mode: 0644
              user:
                name: root
              group:
                name: root
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

上記の定義は、他の変数に加え、第42章 「完全に自動化されたダイレクトネットワークプロビジョニングで説明されているように、インタフェース名と他のCluster APIオブジェクトで補完する必要があります。

注記
注記
  • このアプローチは、クラスタのハードウェアが均一であり、インタフェース名を含め、すべてのホスト上で同じ設定が必要な場合にのみ便利です。

  • 代替アプローチが可能であり、今後のリリースで取り上げる予定です。

この時点で、ホストには機能していて実行中のPTPスタックがあり、PTP役割のネゴシエーションを開始するはずです。

Documentation survey