Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

9.3. 設定ツール

Red Hat Enterprise Linux ではシステムの設定に役立つツールをいくつか提供しています。本セクションでは利用できるツールを簡単に説明し、Red Hat Enterprise Linux 7 でネットワーク関連のパフォーマンスの問題を解決する場合のツールの使用例を紹介しています。
ただし、ネットワークパフォーマンスに関連する問題はハードウェアが正常に機能していない、またはインフラストラクチャーが不完全であることが原因で発生する場合もありますので注意が必要です。ツールを使用してネットワークスタックのチューニングを行う前に、まずハードウェアおよびインフラストラチャーが期待通りに動作しているか必ず確認されることを強く推奨しています。
また、ネットワークパフォーマンスの特定の問題についてはネットワークのサブシステムを再設定するのではなくアプリケーション側を変更することで解決するものもあります。一般的にはアプリケーションが posix 呼び出しを頻繁に行うよう設定すると解決することがよくあります。アプリケーション領域にデータをキュー待ちさせることになってもデータを柔軟に格納して必要に応じメモリーにスワップインしたりスワップアウトすることができるようになるためです。

9.3.1. ネットワークパフォーマンス向けの Tuned プロファイル

Tuned サービスは、特定のユースケースでパフォーマンスを向上させるために、さまざまなプロファイルを提供します。以下のプロファイルはネットワークパフォーマンの改善に役立つプロファイルになります。
  • latency-performance
  • network-latency
  • network-throughput
プロファイルについての詳細は、「tuned-adm」 を参照してください。

9.3.2. ハードウェアバッファーの設定

ハードウェアバッファーによって大量のパケットがドロップされている場合は、複数の解決策が考えられます。
入力トラフィックの速度が遅い
キューを満たす速度を下げるには、受信トラフィックのフィルター、参加するマルチキャストグループ数の削減、またはブロードキャストトラフィック量の削減を行います。受信トラフィックのフィルター方法に関する詳細はRed Hat Enterprise Linux 7 セキュリティーガイドを参照してください。マルチキャストグループの詳細は Red Hat Enterprise Linux 7 のクラスタリング関連のドキュメントを参照してください。ブロードキャストのトラフィックの詳細はRed Hat Enterprise Linux 7 システム管理者のガイドまたは設定するデバイスに関するドキュメントを参照してください。
ハードウェアバッファーキューのサイズ
キューのサイズを大きくすることでドロップされてしまうパケット数を減らしオーバーフローを防ぎます。ethtool コマンドでネットワークデバイスの rx/tx パラメーターを修正します。
# ethtool --set-ring devname value
キューのドレイン (解放) レートの変更
デバイス加重はデバイスで一度 (スケジュールされているプロセッサーのアクセス 1 回) に受信できるパケット数を参照します。dev_weight パラメーターで制御されるデバイスの重みを増やすことで、キューが排出される速度を増やすことができます。/proc/sys/net/core/dev_weight ファイルの内容を変更するか、procps-ng パッケージで提供される sysctl を使用して永続的に変更することで、このパラメーターを一時的に変更できます。
キューのドレインレートの変更は、通常、ネットワークのパフォーマンス低下を軽減する最も簡単な方法です。ただし、デバイスが一度に受信できるパケット数を増やすと、追加のプロセッサー時間が使用され、他のプロセスがスケジュールできません。そのため、パフォーマンス上の問題が発生する可能性があります。

9.3.3. 割り込みキューの設定

分析でレイテンシーが高いと、割り込みベースのパケット受信ではなく、ポーリングベースでメリットが得られます。

9.3.3.1. ビジーポーリングの設定

ビジーポーリングはソケット層のコードにネットワークデバイスの受信キューをポーリングさせ、ネットワークの割り込みは無効にすることでネットワーク受信パス内の待ち時間を低減します。これにより、割り込みおよび結果として生じるコンテキストスイッチによって生じる遅延が削除されます。ただし、CPU 使用率も増加します。ビジーポーリングは、CPU がスリープ状態にならないようにします。これにより、追加の電力消費が発生する可能性があります。
ビジーポーリングはデフォルトでは無効になっています。以下の手順で特定のソケットでのビジーポーリングを有効にします。
  • sysctl.net.core.busy_poll0 以外の値に設定します。このパラメーターはソケットのポーリングと選択用デバイスキューでパケットを待機する時間を管理します (マイクロ秒単位)。Red Hat は、50 の値を推奨します。
  • SO_BUSY_POLL ソケットオプションをソケットに追加します。
ビジーポーリングをグローバルに有効にするには、sysctl.net.core.busy_read0 以外の値に設定する必要があります。このパラメーターはソケットの読み取り用デバイスキューでパケットを待機する時間を管理します (マイクロ秒単位)。また、SO_BUSY_POLL オプションのデフォルト値も設定します。Red Hat では、ソケット数が少ない場合は 50、ソケット数が多い場合は 100 の値を推奨します。ソケット数が非常に多くなる場合は (数百以上) 代わりに epoll を使用します。
ビジーポーリング動作は次のドライバーで対応しています。また、Red Hat Enterprise Linux 7 でも対応のドライバーになります。
  • bnx2x
  • be2net
  • ixgbe
  • mlx4
  • myri10ge
Red Hat Enterprise Linux 7.1 からは次のコマンドを実行するとデバイスかビジーポーリングに対応するどうかをチェックすることもできるようになります。
# ethtool -k device | grep "busy-poll"
これが [fixed] で busy-poll: を返す場合、デバイスでビジーポーリングを使用できます。

9.3.4. ソケット受信キューの設定

分析により、ソケットキューのドレインレートが遅すぎるためにパケットがドロップされていることが示唆された場合、結果として生じるパフォーマンスの問題を軽減する方法がいくつかあります。
受信トラフィックの速度を下げる
キューに到達する前にパケットをフィルターまたは破棄したり、デバイスのウェイトを下げたりすることで、キューがいっぱいになる速度を低減します。
アプリケーションのソケットキューの深さを増やす
ソケットキューがバーストで制限されたトラフィック量を受信した場合は、ソケットキューの深さをトラフィックのバーストサイズに一致するように増やすと、パケットがドロップされるのを防ぐことができます。

9.3.4.1. 受信トラフィックの速度を下げる

受信トラフィックの速度を下げるには、受信トラフィックにフィルターをかけたり、ネットワークインターフェイスカードのデバイス加重を減らします。受信トラフィックのフィルター方法に関する詳細はRed Hat Enterprise Linux 7 セキュリティーガイドを参照してください。
デバイス加重はデバイスで一度 (スケジュールされているプロセッサーのアクセス 1 回) に受信できるパケット数を参照します。デバイスの重みは、dev_weight パラメーターによって制御されます。/proc/sys/net/core/dev_weight ファイルの内容を変更するか、procps-ng パッケージで提供される sysctl を使用して永続的に変更することで、このパラメーターを一時的に変更できます。

9.3.4.2. キューの深さを増やす

アプリケーションソケットキューの深さを増やすことは、通常、ソケットキューのドレインレートを改善する最も簡単な方法ですが、長期的な解決策になる可能性は低いです。
キューの深さを増やすには、以下の変更のいずれかを行ってソケット受信バッファーのサイズを増やします。
/proc/sys/net/core/rmem_default の値を増やす
このパラメーターは、ソケットが使用する受信バッファーのデフォルトサイズを制御します。この値は、/proc/sys/net/core/rmem_max の値以下である必要があります。
setsockopt を使用して SO_RCVBUF に大きな値を設定する
このパラメーターにより、ソケットの受信バッファーの最大サイズを制御します (バイト単位)。getsockopt システムコールを使用して、バッファーの現在の値を判断します。詳細については、socket(7) の man ページをご覧ください。

9.3.5. RSS (Receive-Side Scaling) の設定

マルチキュー受信とも呼ばれる Receive Side Scaling (RSS) は、ネットワーク受信処理を複数のハードウェアベースの受信キューに分散し、受信ネットワークトラフィックを複数の CPU で処理できるようにします。RSS を使用すると、1 つの CPU をオーバーロードして発生する受信中断プロセッシングにおけるボトルネックを緩和し、ネットワークレイテンシーを低減させることができます。
お使いのネットワークインターフェイスカードが RSS に対応しているかどうかを確認するには、複数の割り込み要求キューが /proc/interrupts 内のインターフェイスに関連付けられているかどうかを確認します。たとえば、p1p1 インターフェイスに関心がある場合は、以下のようになります。
# egrep 'CPU|p1p1' /proc/interrupts
   CPU0    CPU1    CPU2    CPU3    CPU4    CPU5
89:   40187       0       0       0       0       0   IR-PCI-MSI-edge   p1p1-0
90:       0     790       0       0       0       0   IR-PCI-MSI-edge   p1p1-1
91:       0       0     959       0       0       0   IR-PCI-MSI-edge   p1p1-2
92:       0       0       0    3310       0       0   IR-PCI-MSI-edge   p1p1-3
93:       0       0       0       0     622       0   IR-PCI-MSI-edge   p1p1-4
94:       0       0       0       0       0    2475   IR-PCI-MSI-edge   p1p1-5
上記の出力は、NIC ドライバーが p1p1 インターフェイスに 6 つの受信キューを作成したことを示しています(p1p1-0 から p1p1-5)。また、各キューで処理された割り込みの数と、割り込みをした CPU の数も表示されます。この場合、デフォルトではこの特定の NIC ドライバーは CPU ごとに 1 つのキューを作成するため 6 つのクエリーがあります。また、このシステムには CPU が 6 つあります。これは、NIC ドライバー間で非常に一般的なパターンです。
または、ネットワークドライバーの読み込み後に ls -1 /sys/devices/*/*/device_pci_address/msi_irqs の出力を確認することもできます。たとえば、PCI アドレスが 0000:01:00.0 のデバイスを確認する場合は、以下のコマンドでそのデバイスの割り込み要求キューを一覧表示できます。
# ls -1 /sys/devices/*/*/0000:01:00.0/msi_irqs
101
102
103
104
105
106
107
108
109
RSS はデフォルトで有効になっています。RSS のキューの数 (または、ネットワークアクティビティーを処理する CPU 数) は該当するネットワークデバイスドライバーで設定されます。bnx2x ドライバーの場合は、num_queues で設定されます。sfc ドライバーの場合は、rss_cpus パラメーターで設定されます。通常、これは /sys/class/net/デバイス/queues/rx-queue/ で設定されます。device はネットワークデバイスの名前( eth1など)で、rx-queue は適切な受信キューの名前です。
RSS を設定する場合、Red Hat は、物理 CPU コアごとにキュー数を 1 つに制限することを推奨します。ハイパースレッディングは、分析ツールで個別のコアとして表されますが、ハイパースレッディングなどの論理コアを含むすべてのコアにキューを設定することは、ネットワークパフォーマンスにあまり良い影響はありません。
有効にすると、RSS は各 CPU のがキューした処理量に基づいて、利用可能な CPU 間でネットワーク処理を均等に分散します。ただし、ethtool --show-rxfh-indir パラメーターおよび --set-rxfh-indir パラメーターを使用して、ネットワークアクティビティーの分散方法を変更し、特定タイプのネットワークアクティビティーを他のタイプよりも重要なものとして重み付けすることができます。
irqbalance デーモンを RSS と組み合わせて使用すると、ノード間のメモリー転送やキャッシュラインバウンスの可能性を減らすことができます。これにより、ネットワークパケット処理のレイテンシーが短縮されます。

9.3.6. 受信パケットステアリング (RPS) の設定

RPS (Receive Packet Steering) は RSS と似ていますが、パケットを処理するための特定の CPU に転送するのに使用されます。ただし、RPS はソフトウェアレベルで実装されており、単一のネットワークインターフェイスカードのハードウェアキューがネットワークトラフィックのボトルネックとなるのを防ぐのに役立ちます。
RPS は、ハードウェアベースの RSS と比較していくつかの利点があります。
  • RPS は、どのネットワークインターフェイスカードでも使用できます。
  • 新しいプロトコルに対応するために、ソフトウェアフィルターを RPS に簡単に追加できます。
  • RPS は、ネットワークデバイスのハードウェア割り込みレートを増やしません。ただし、プロセッサー間割り込みは導入されます。
RPS は、/sys/class/net/ デバイス /queues/rx-queue/rps_cpus ファイルでネットワークデバイスと受信キュー ごとに設定されます。device はネットワークデバイスの名前( eth0など)、rx-queue は適切な受信キューの名前です( rx-0 など)。
rps_cpus ファイルのデフォルト値は 0 です。この値の場合は RPS は無効です。したがってネットワーク割り込みを処理する CPU がパケットも処理します。
RPS を有効にするには、指定されたネットワークデバイスからのパケットを処理し、キューを受信する CPU で適切な rps_cpus ファイルを設定します。
rps_cpus ファイルはコンマ区切りの CPU ビットマップを使用します。したがって、CPU がインターフェイスの受信キューの割り込みを処理できるようにするには、プレースホルダー内のその位置の値を 1 に設定します。たとえば、CPU 0、1、2、および 3 で割り込みを処理するには、rps_cpus の値を f (16 進数の場合は 15)に設定します。バイナリー表現では、15 は 00001111 (1+2+4+8)です。
単一送信キューを持つネットワークデバイスには、同じメモリードメインの CPU を使用するように RPS を設定することで、最善のパフォーマンスを実現できます。NUMA 以外のシステムでは、利用可能な CPU がすべて使用できることを意味します。ネットワーク割り込みレートが非常に高い場合には、ネットワーク割り込みを処理する CPU を除くと、パフォーマンスが向上することがあります。
複数キューのネットワークデバイスでは、通常、RPS と RSS の両方を設定する利点はありません。これは、RSS はデフォルトで CPU を各受信キューにマップするように設定されるためです。ただし、CPU よりもハードウェアキューの方が少ない場合、および同一メモリードメインの CPU を使用するように RPS が設定されている場合は、RPS が利点ももたらす可能性があります。

9.3.7. RFS (Receive Flow Steering) の設定

Receive Flow Steering (RFS) は RPS の動作を拡張し、CPU キャッシュのヒットレートを増やし、ネットワークレイテンシーを低減します。RPS はキューの長さのみに基づいてパケットを転送し、RFS は RPS バックエンドを使用して最も適切な CPU を算出します。次にパケットを消費するアプリケーションの場所に基づいてパケットを転送します。これにより、CPU キャッシュの効率が上がります。
RFS はデフォルトで無効になっています。RFS を有効にするには、以下の 2 つのファイルを編集する必要があります。
/proc/sys/net/core/rps_sock_flow_entries
このファイルの値を同時にアクティブになるであろう接続の予測最大数に設定します。中程度のサーバー負荷には 32768 の値が推奨されます。入力した値はすべて直近の 2 の累乗で切り上げられます。
/sys/class/net/device/queues/rx-queue/rps_flow_cnt
device を、設定するネットワークデバイスの名前( eth0など)に置き換え、rx-queue を設定する受信キュー( rx-0 など)に置き換えます
このファイルの値を、rps_sock_flow_entries の値を N で割った値に設定します。ここでの N は、デバイスの受信キューの数です。たとえば、rps_flow_entries32768 に設定され、16 の設定済み受信キューがある場合は、rps_flow_cnt2048 に設定する必要があります。単一キューデバイスの場合、rps_flow_cnt の値は rps_sock_flow_entries の値と同じです。
1 つの送信者から受信したデータは複数の CPU に送信されません。1 つの送信元から受信するデータ量が 1 つの CPU が処理できるものよりも大きい場合は、割り込みの数や CPU の処理量を減らすために、より大きなフレームサイズを設定します。NIC オフロードオプション または高速 CPU について検討してください。
numactl または taskset を RFS と併用して、アプリケーションを特定のコア、ソケット、または NUMA ノードに固定することを検討してください。これにより、パケットが順番に処理されるようにします。

9.3.8. アクセラレート RFS の設定

アクセラレート RFS は、ハードウェア補助を追加することで、RFS の速度を強化します。RFS と同様に、パケットはパケットを使用するアプリケーションの場所に基づいて転送されます。ただし、従来の RFS とは異なり、パケットはデータを消費するスレッドに対してローカルとなる CPU に直接送信されます。つまりアプリケーションを実行している CPU、またはキャッシュ階層内のその CPU にローカルとなる CPU のいずれかになります。
RFS は、以下の条件が満たされている場合にのみ利用できます。
  • アクセラレート RFS がネットワークインターフェイスカード対応になっていること。アクセラレート RFS は、ndo_rx_flow_steer() netdevice 関数をエクスポートするカードでサポートされています。
  • ntuple フィルターを有効にする必要があります。
これらの条件が満たされると、従来の RFS 設定に基づいて、キューマッピングへの CPU が自動的に消費されます。つまり、キューマッピングへの CPU は各受信キューに対してドライバーによって設定された IRQ 機関に基づいて重複排除されます。従来の RFS の設定方法については、「RFS (Receive Flow Steering) の設定」 を参照してください。
Red Hat では RFS を使用すべき状況でネットワークインターフェイスカードがハードウェアアクセラレートに対応している場合は常にアクセラレート RFS の使用を推奨しています。