IDCF テックブログ

IDCF テックブログ

クラウド・データセンターを提供するIDCフロンティアの公式テックブログ

IDCFクラウドでのマルチキューネットワーク

f:id:tafujish:20170127205753p:plain

仮想環境や古いサーバーだと上記画像のように、CPU使用率が特定のコアに偏ることがあると思います。特に2番のCPUのsi(ソフトウェア割り込み)の値のみ大きいです。このような場合、マルチキューネットワークに対応することで複数のCPUコアを利用することができるためネットワーク性能をスケールすることができます。

この話はしばしば質問いただきますが、IDCFクラウドの仮想マシンのNICはRSS(Receive Side Scaling)に標準で対応しているので、マルチキューネットワークのためにこれといった操作や設定は不要です。

「以上です。」
で終わってしまいそうな話ですが、以下ではもう少し踏み込んでみるので、CPUの各コアの利用が偏っている場合は次を参照ください。だいたい多い話として、irqbalanceが入っていなかったり、ダイナミックスケール後の話だったり、ISOから作った仮想マシンだったりします。



1) RSSに対応しているか確認するには

RSSはNIC側で複数のキューを持ち、複数のCPUコアを活用できます。

IDCFから提供しているテンプレートから仮想マシンを作成すると、標準でRSSに対応したNICである「vmxnet3」が搭載されています。vmxnet3であることの確認は、

# ethtool -i ens160
driver: vmxnet3
version: 1.4.7.0-k-NAPI
~略~

※ens160はネットワークインターフェース名(eth0等適宜置き換えてください)

driverがvmxnet3であれば、このNICはRSS対応となります。

では、具体的にマルチキューになっているか確認しましょう。

# ls /sys/class/net/ens160/queues/
rx-0  rx-1  rx-2  rx-3  tx-0  tx-1  tx-2  tx-3

※ens160はネットワークインターフェース名(eth0等適宜置き換えてください)

rx-0からrx-3の4つが受信キュー、tx-0からtx-3の4つが送信キューです。
仮想マシンのCPUのコア数と同じ数のキューが有効になっています。(この仮想マシンはHighcpu.L8の4コアマシン)

この4つのキューが、どこのCPUコアに割り当てられてるかは次のように確認できます。

# cat /proc/interrupts | grep ens160
  56:         39          0          0      44516   PCI-MSI-edge      ens160-rxtx-0
  57:          7      44132          0          0   PCI-MSI-edge      ens160-rxtx-1
  58:         16          0      44175          0   PCI-MSI-edge      ens160-rxtx-2
  59:         28          0          0      44739   PCI-MSI-edge      ens160-rxtx-3
~略~

※ens160はネットワークインターフェース名(eth0等適宜置き換えてください)

割り込みのカウントが上がっているところを見ると、0番のキューはCPUの3番、1番のキューはCPUの1番、2番のキューはCPUの2番、3番のキューはCPUの3番に割り当てられてます。
この環境はCentOS7.3ですが、0番のCPUが使われておらず、3番のCPUに2つのキューが割り当てられています。このあたり、気になる方は、次の 2) を参照ください。

では、この環境に負荷をかけて、CPUの使用率を確認します。

f:id:tafujish:20170127205755p:plain

上記のキューの割り当ての通り、0番のCPUの負荷は低く、3番のCPUの負荷が高くなっています。
ここまで確認したように動いていれば、RSSが正常に機能しています。
NICがvmxnet3で、キューの数もCPUコア数に応じた数があるのに、CPUの使用率が異なる場合、キューが各CPUに割り当てられていない可能性があります。そのようなときはirqbalanceをyumやaptでインストールして動かしてみてください。

執筆時点のIDCFクラウドの標準テンプレートだと、CentOS6.xと7.xでははじめからirqbalacneがインストールされていますが、Ubuntu16.04ではインストールされていません。

2) CPU0番コアが使われていないとき

先述のとおり、RSSが機能しており、irqbalanceが各CPUコアにキューを割り当てているのに、0番のCPUが使われないのは、irqbalanceが0番のCPUに割り当てないためです。
CnetOS6.xでは0番にも割り当てますが、CentOS7.xやUbuntu16.04では0番に割り当てられません。

偏りが問題ないレベルであれば、そのまま利用いただいて問題ないですが、カツカツにCPUリソースを消費していて偏りが困る場合は、キューの割り当て先CPUを手動で変更することもできます。

まずは、割当先を変更したい0番のキューのIRQ番号確認します。ここでは56番です。

# cat /proc/interrupts|grep ens160
  56:         39          0          0     268151   PCI-MSI-edge      ens160-rxtx-0
~略~

※ens160はネットワークインターフェース名(eth0等適宜置き換えてください)

次に現在の割当先を念のため確認します。ここで先ほど調べたIRQ番号を入れます。ここでは、「8」となってますがビットで記載されているので、3番のCPUに割り当てとなっています。
(ちなみに、0番のCPUは「1」、1番のCPUは「2」、2番のCPUは「4」となります)

# cat /proc/irq/56/smp_affinity
00000000,00000000,00000000,00000008

0番のCPU(値としては「1」)に割り当て、確認します。

# echo 1 > /proc/irq/56/smp_affinity
# cat /proc/irq/56/smp_affinity
00000000,00000000,00000000,00000001

この状態で負荷をかけるときれいに分散されました。

f:id:tafujish:20170127205757p:plain

この設定はOS再起動で消えてしまうので、必要だったらOS起動時のスクリプトに記載ください。
また、irqbalanceがデーモンとして動いていると変更した設定を戻されてしまうので、irqbalanceのサービスを止めるかONESHOTの設定にする必要があります。

3) ダイナミックスケール後の対応

IDCFクラウドでダイナミックスケールした後、増えたCPUのコアがちゃんと使われていないというような質問をしばしばいただきます。

実はダイナミックスケールによりCPUのコアが増えたとしても、RSSのキューの数が増えないため、増えたCPUコアをNICが使うことはありません。
増えたCPUコア分のキューを増やすには、vmxnet3のモジュールをいったん削除し、再度追加することで認識できます。

# modprobe -r vmxnet3; modprobe vmxnet3

ただ、この方法だとモジュールを削除するので瞬断が発生します。
それが難しい場合は、以下の4)のようにRPS/RFSでマルチキュー化でしのぎ、次回OS再起動時にRSSに戻るという方法もあると思います。

4) RSS対応してないときはRPS/RFSで

RSSはNICの方が対応しているマルチキューネットワークであり、NIC(今回だとvmxnet3)が対応している必要があります。IDCFクラウドでは、vmxnet3以外のNICも利用可能です。

  • テンプレートインポート時にe1000かpcnet32を選択することもできます
  • ISOインストールでの仮想マシンはデフォルトでe1000となります

このように、vmxnet3以外のときは、OS側でマルチキューネットワークに対応させます。具体的には、 RPS(Receive Packet Steering)、RFS(Receive Flow Steering)です。

では具体的な設定を紹介します。
例えば、以下のようなe1000のNICでキューが1つしかない、4コア仮想マシンの環境があったとします。デバイス名はens35とします(eth0等適宜置き換えてください)。

# ethtool -i ens35
driver: e1000
version: 7.3.21-k8-NAPI
~略~

# ls /sys/class/net/ens35/queues/
rx-0  tx-0

まずはRPSの設定です。入力している「f」は4コアすべて利用するときでビット計算となってます。例えば、2コアのときは「3」、8コアのときは「ff」となります。

# echo f > /sys/class/net/ens35/queues/rx-0/rps_cpus

次にRFSです。rps_sock_flow_entriesの値は、一般的に「32768」が推奨されています。
一方で、rps_flow_cntは、rps_sock_flow_entries÷受信キューの数となります。e1000のこの環境ではキューは1つのため、rps_sock_flow_entriesと同じ値となります。

# echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
# echo 32768 > /sys/class/net/ens35/queues/rx-0/rps_flow_cnt

以上ですが、上記設定はネットワークインターフェース毎に設定が必要なので、複数NICがある場合はその分実行ください。また、これらの設定はOS再起動で消えてしまうので、必要だったらOS起動時のスクリプトに記載ください。

5) e1000のテンプレートをvmxnet3に変える

先述のとおり、e1000でもRPS/RFSでマルチキューネットワークは利用できますが、設定が面倒だとか何らかの理由でvmxnet3に置き換えたいときもあると思います。

そのときは、テンプレートを一度エクスポートしていただき、再度インポートしていただければ、インポート時の設定で下図のようにNICの種類を指定することが可能ですので、こちらもご検討ください。

f:id:tafujish:20170127205758p:plain

まとめ

長くなりましたが、基本的にはRSS標準対応なので、手間なくそのままご利用いただけます。もしCPUのコアが偏っているようであれば、上記ご参照ください。

Copyright © IDC Frontier Inc.