41 通信機能の設定 #
このセクションでは、SUSE Edge for Telcoを介してデプロイされたクラスタの通信事業者固有の機能の設定について記述および説明します。
ダイレクトネットワークプロビジョニングのデプロイメント方法を使用します。この方法については、自動化されたプロビジョニング(第42章 「完全に自動化されたダイレクトネットワークプロビジョニング」)に関するセクションで説明しています。
このセクションでは、次のトピックについて説明します。
リアルタイム用のカーネルイメージ(41.1項 「リアルタイム用のカーネルイメージ」): リアルタイムカーネルで使用するカーネルイメージ。
低レイテンシとハイパフォーマンスのためのカーネル引数(41.2項 「低レイテンシとハイパフォーマンスのためのカーネル引数」): 通信ワークロードを最大のパフォーマンスと低レイテンシで実行するために、リアルタイムカーネルによって使用されるカーネル引数。
Tunedとカーネル引数によるCPUピニング(41.3項 「Tunedとカーネル引数によるCPUピニング」): カーネル引数とTunedプロファイルを使用してCPUを分離します。
CNI設定(41.4項 「CNI設定」): Kubernetesクラスタで使用するCNI設定。
SR-IOV設定(41.5項 「SR-IOV」): Kubernetesワークロードで使用するSR-IOV設定。
DPDK設定(41.6項 「DPDK」): システムで使用するDPDK設定。
vRANアクセラレーションカード(41.7項 「vRANアクセラレーション(
Intel ACC100/ACC200
)」): Kubernetesワークロードで使用するアクセラレーションカードの設定。Huge Page (41.8項 「Huge Page」): Kubernetesワークロードで使用するHuge Pageの設定。
KubernetesでのCPUピニング(41.9項 「KubernetesでのCPUピニング」): CPUピニングを活用するようにKubernetesとアプリケーションを設定する。
NUMA対応のスケジューリング設定(41.10項 「NUMA対応のスケジューリング」): Kubernetesワークロードで使用するNUMA対応のスケジューリング設定。
Metal LB設定(41.11項 「MetalLB」): Kubernetesワークロードで使用するMetal LB設定。
プライベートレジストリ設定(41.12項 「プライベートレジストリ設定」): Kubernetesワークロードで使用するプライベートレジストリ設定。
Precision Time Protocolの設定(41.13項 「Precision Time Protocol」): 実行中のPTP通信事業者プロファイルの設定ファイル。
41.1 リアルタイム用のカーネルイメージ #
リアルタイムカーネルイメージは必ずしも標準カーネルより優れているとは限りません。リアルタイムカーネルは、特定のユースケース用に調整された別のカーネルです。低レイテンシを実現するために調整されていますが、その結果、スループットが犠牲になります。リアルタイムカーネルは一般的な用途には推奨されませんが、ここでは低レイテンシが重要な要因である通信ワークロード用のカーネルとして推奨されています。
主に4つの機能があります。
決定論的実行:
予測可能性の向上 — 高負荷状態でも重要なビジネスプロセスが期限内に確実に完了し、常に高品質なサービスを提供します。高優先度プロセスのために重要なシステムリソースを保護することで、時間に依存するアプリケーションの予測可能性を向上できます。
低ジッタ:
高度に決定論的な技術に基づいてジッタが低く抑えられているため、アプリケーションと実世界との同期を維持できます。これは、継続的に繰り返し計算を行う必要があるサービスで役立ちます。
優先度の継承:
優先度の継承とは、優先度の高いプロセスがある状況において、そのプロセスがタスクを完了するためには優先度の低いプロセスが完了するのを待つ必要がある場合に、優先度の低いプロセスが高優先度を一時的に引き受ける機能です。SUSE Linux Enterprise Real Timeは、ミッションクリティカルなプロセスにおけるこのような優先度の逆転の問題を解決します。
スレッドの割り込み:
一般的なオペレーティングシステムでは、割り込みモードで実行中のプロセスはプリエンプト可能ではありません。SUSE Linux Enterprise Real Timeでは、このような割り込みをカーネルスレッドでカプセル化して割り込み可能にし、ユーザが定義した高優先度プロセスでハード割り込みとソフト割り込みをプリエンプトできます。
ここでは、
SUSE Linux Micro RT
のようなリアルタイムイメージをインストール済みの場合、カーネルリアルタイムはすでにインストールされています。リアルタイムカーネルイメージはSUSE Customer Centerからダウンロードできます。
41.2 低レイテンシとハイパフォーマンスのためのカーネル引数 #
リアルタイムカーネルを適切に動作させ、通信ワークロードを実行する際には、最高のパフォーマンスと低レイテンシ実現できるようにカーネル引数を設定することが重要です。このユースケースのカーネル引数を設定する際には、いくつかの重要な概念を念頭に置く必要があります。
SUSEリアルタイムカーネルを使用する際には、
kthread_cpus
を削除します。このパラメータは、カーネルスレッドが作成されるCPUを制御します。また、PID 1とカーネルモジュール(kmodユーザスペースヘルパ)のロードにどのCPUが許可されるかも制御します。このパラメータは認識されず、影響は何もありません。isolcpus
、nohz_full
、rcu_nocbs
、およびirqaffinity
を使用して、CPUコアを分離します。CPUピニング技術の包括的なリストについては、「Tunedとカーネル引数によるCPUピニング」(41.3項 「Tunedとカーネル引数によるCPUピニング」)の章を参照してください。domain,nohz,managed_irq
フラグをisolcpus
カーネル引数に追加します。何もフラグを指定しない場合、isolcpus
はdomain
フラグのみを指定するのと同等になります。これにより、指定した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=1
をidle=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を分離します。 |
skew_tick | 1 | このオプションを使用すると、カーネルは分離されたCPU全体でタイマー割り込みをずらすことができます。 |
nohz | on | 有効にすると、カーネルの定期的なタイマー割り込み(「ティック」)は、アイドル状態のCPUコアで停止します。これにより、主にハウスキーピング用CPU
( |
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 | このオプションは、タイマーのハード割り込みコンテキストで実行されるタイマーとして実装されるソフトロックアップウォッチドッグを無効にします。 |
次のコマンドで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
とともに、Cilium
やCalico
などの別のCNIプラグインをセカンダリプラグインとして使用します。
cni:
- multus
- cilium
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に割り当てる組み合わせは多数あります。
フィルタとグループを設定して、ハードウェアとユースケースに応じたインタフェースに一致させると、使用する例が次の設定マップに表示されます。
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
ファイルを準備して、デバイスプラグインをデプロイします。
このデバイスプラグインは、複数のアーキテクチャ(arm
、amd
、ppc64le
)をサポートしています。したがって、同じファイルを異なるアーキテクチャに使用して、各アーキテクチャに複数の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" }
FEC
はintel.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
)から作成され、ドライバdeviceType
とMTU
が設定されます。
resourceName
フィールドには特殊文字を含めないでください。また、このフィールドはクラスタ全体で一意である必要があります。この例では、dpdk
をsr-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
)ドライバが含まれています。
キューマネージャはロックなしのキューを実装します。
バッファマネージャは固定サイズのバッファを事前割り当てします。
メモリマネージャは、メモリ内にオブジェクトのプールを割り当て、リングを使用してフリーオブジェクトを格納します。オブジェクトがすべての
DRAM
チャンネルに均等に分散されるようにします。ポールモードドライバ(
PMD
)は、非同期通知なしで動作するように設計されているため、オーバーヘッドが軽減されます。パケット処理を開発するためのヘルパである一連のライブラリとしてのパケットフレームワーク。
次の手順では、DPDK
を有効にする方法と、DPDK
インタフェースが使用するNIC
からVF
を作成する方法を示します。
DPDK
パッケージをインストールします。
$ transactional-update pkg install dpdk dpdk-tools libdpdk-23
$ reboot
カーネルパラメータ:
DPDKを使用するには、ドライバをいくつか使用して、カーネルの特定のパラメータを有効にします。
パラメータ | 値 | 説明 |
---|---|---|
iommu | pt | このオプションを使用すると、DPDKインタフェースに |
intel_iommuまたはamd_iommu | on | このオプションを使用すると、 |
これらのパラメータを有効にするには、各パラメータを/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
カーネルモジュールを読み込み、NIC
でSR-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つのVF
をPF
から作成し、次の手順に従って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
はそのメモリ領域をプロセスが使用中であるとマークします。効率を高めるために、CPU
はRAM
をチャンクで割り当てます。多くのプラットフォームでは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つあります。
BestEffort
QoSクラス:CPU
に対して要求または制限を定義していない場合、Podはシステムで使用できる最初のCPU
でスケジュールされます。BestEffort
QoSクラスを使用する例を次に示します。spec: containers: - name: nginx image: nginx
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"
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
が表示されています。
NUMA
はBIOS
で有効にする必要があります。dmesg
にブート時のNUMA初期化レコードがない場合、カーネルリングバッファ内のNUMA
関連のメッセージが上書きされた可能性があります。
41.11 MetalLB #
MetalLB
は、ベアメタルKubernetesクラスタ用のロードバランサの実装であり、L2
やBGP
などの標準ルーティングプロトコルをアドバタイズプロトコルとして使用します。ベアメタル環境では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を再起動します。
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役割のネゴシエーションを開始するはずです。