はじめに
こんにちは、酸素です。
弊社で運用しているデータセンター内の一部スイッチでは、LAG(リンクアグリゲーション)を構築しています。
LAGを構築することでケーブルやポートの故障に対する冗長性が確保できるほか、通信帯域を広げることが可能となります。
先日、スイッチ間以外にもLinuxサーバー同士でも簡単に構築できるということを知ったので、試してみようと思います。
環境
本記事では、下記の環境で進めていきます。
NetworkManager: 1.40.16
LAGの構築
それでは、LAGの設定等を行っていきます。
今回は
①2台のサーバーそれぞれで仮想NIC"bond0"を作成
②物理NIC"eno3","eno4"をbond0に所属させる
という手順で行います。
現状、各インターフェースは1Gbpsでリンクアップしているため、LAGを構築した際は理論上2Gbpsの通信が行えるようになります。
構築イメージ
まずは仮想NIC"bond0"を作成します。
作成すると、NetworkManagerのプロファイル一覧でTYPE=bondとして表示されるようになります。
# nmcli connection add type bond ifname bond0 con-name bond0 \
bond.options "mode=802.3ad,miimon=100,lacp_rate=fast"
# nmcli connection show
NAME UUID TYPE DEVICE
eno1 XXXXX-XXXXX-XXXXX-XXXX-XXXXXXX ethernet eno1
bond0 YYYYY-YYYYY-YYYYY-YYYY-YYYYYYY bond bond
・・・
次に物理NIC"eno3"と"eno4"をbond0に所属させます。
作成後はbond-slave-"interface-name"という名前でプロファイルが作られます。
# nmcli connection add type ethernet ifname eno3 master bond0
# nmcli connection add type ethernet ifname eno4 master bond0
# nmcli connection show
NAME UUID TYPE DEVICE
eno1 XXXXX-XXXXX-XXXXX-XXXX-XXXXXXX ethernet eno1
bond-slave-eno3 AAAAA-AAAAA-AAAAA-AAAA-AAAAAAA ethernet eno3
bond-slave-eno4 BBBBB-BBBBB-BBBBB-BBBB-BBBBBBA ethernet eno4
bond0 YYYYY-YYYYY-YYYYY-YYYY-YYYYYYY bond bond
上記の設定により、OSはeno3とeno4を一つのデバイスとして扱えるようになったので、bond0にIPアドレスを割り当てます。
# nmcli connection modify bond0 \
ipv4.method manual \
ipv4.addresses 192.168.10.10/24 \
ipv4.never-default yes
# nmcli connection down bond0
# nmcli connection up bond0
# ip addr show bond0
234: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.10.10/24 brd 192.168.10.255 scope global noprefixroute bond0
valid_lft forever preferred_lft forever
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link tentative noprefixroute
valid_lft forever preferred_lft forever
ここまで完了しましたら、もう片方のサーバーでも同様の設定を行います。
なお、対向のIPアドレスは192.168.10.20を割り当てます。
LAGの確認
実際にリンクアップするところまで確認できたので、通信帯域が広がっているか調べてみます。
iperf3コマンドを使ってで通信帯域を確認してみます。
server01で下記を実行
# iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.10.20, port 41912
[ 5] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 41922
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 108 MBytes 904 Mbits/sec
[ 5] 1.00-2.00 sec 112 MBytes 941 Mbits/sec
[ 5] 2.00-3.00 sec 112 MBytes 941 Mbits/sec
[ 5] 3.00-4.00 sec 112 MBytes 941 Mbits/sec
[ 5] 4.00-5.00 sec 112 MBytes 941 Mbits/sec
[ 5] 5.00-6.00 sec 112 MBytes 941 Mbits/sec
[ 5] 6.00-7.00 sec 112 MBytes 941 Mbits/sec
[ 5] 7.00-8.00 sec 112 MBytes 941 Mbits/sec
[ 5] 8.00-9.00 sec 112 MBytes 941 Mbits/sec
[ 5] 9.00-10.00 sec 112 MBytes 941 Mbits/sec
[ 5] 10.00-10.04 sec 4.75 MBytes 941 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.04 sec 1.10 GBytes 938 Mbits/sec receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
※もう一方のserver02では下記コマンドを実行
# iperf3 -c 192.168.10.10
今回、1000BASE-Tを2本使ってLAGを構築したはずなのに、1Gbps弱しか出ていないことが分かります。
原因としては、server02で実行したiperf3コマンドの形式ではTCPセッションは1本しか張られず、通信に使用される物理NICも1つとなるためです。
対策として、server02で実行するコマンドで下記のようにして、セッション数を4本に増やしてみます。
# iperf3 -c 192.168.10.10 -P 4
・server01側の出力
# iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.10.20, port 60582
[ 5] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 60586
[ 8] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 60588
[ 10] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 60602
[ 12] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 60608
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.01 sec 27.2 MBytes 227 Mbits/sec
[ 8] 0.00-1.01 sec 27.1 MBytes 226 Mbits/sec
[ 10] 0.00-1.01 sec 27.1 MBytes 226 Mbits/sec
[ 12] 0.00-1.01 sec 27.1 MBytes 226 Mbits/sec
[SUM] 0.00-1.01 sec 109 MBytes 906 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
(長いので省略)
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 5] 10.01-10.04 sec 1.00 MBytes 237 Mbits/sec
[ 8] 10.01-10.04 sec 1.00 MBytes 237 Mbits/sec
[ 10] 10.01-10.04 sec 1.00 MBytes 237 Mbits/sec
[ 12] 10.01-10.04 sec 1.00 MBytes 237 Mbits/sec
[SUM] 10.01-10.04 sec 4.00 MBytes 946 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.04 sec 281 MBytes 235 Mbits/sec receiver
[ 8] 0.00-10.04 sec 281 MBytes 234 Mbits/sec receiver
[ 10] 0.00-10.04 sec 281 MBytes 234 Mbits/sec receiver
[ 12] 0.00-10.04 sec 280 MBytes 234 Mbits/sec receiver
[SUM] 0.00-10.04 sec 1.10 GBytes 938 Mbits/sec receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
しかし、セッション数を4本に増やしても、各セッションが250Mbps弱となり、合計としても変わらず1Gbps弱しか出ていないようです...
この原因としては、下記の設定が入っているためです。
# cat /proc/net/bonding/bond0 | grep -i transmit
Transmit Hash Policy: layer2 (0)
LACPは、任意の通信に対して特定のルール(Transmit Policy)に従ってハッシュ値を生成し、そのハッシュ値によって採用する物理NICを決定します。
上記のようなルールの場合、layer2とある通り送信元・宛先macアドレスの値を使ってハッシュ値を生成します。
先ほどのiperf3コマンドのテストでは、4つのセッション全ての送信元と宛先は同一のbondingデバイス(各サーバーのbond0)であるため、ハッシュ値も全て同じ値となります。
※出力内容は割愛しますが、iperf3実行中に別のターミナルを作成して下記コマンドを実行すると、明らかに片方のデバイスに通信が偏っていることが確認できます。
watch -n1 "ip -s link show eno3; echo; ip -s link show eno4"
ですので、複数のセッションの通信を各物理NICに分散させるには、Transmit PolicyをL4であるポートを基準にハッシュ値を生成させる必要があります。
送信元・宛先ポートのみでハッシュ値を生成するルールはないため、今回はlayer3+4というルールを使います。
# nmcli connection modify bond0 \
bond.options "mode=802.3ad,miimon=100,lacp_rate=fast,xmit_hash_policy=layer3+4"
# nmcli connection down bond0
# nmcli connection up bond0
# cat /proc/net/bonding/bond0 | grep -i "transmit"
Transmit Hash Policy: layer3+4 (1)
Transmit Policyがlayer3+4に変わったので、再度iperf3を実行してみます
・server01側の出力
# iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.10.20, port 44084
[ 5] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 44092
[ 8] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 44094
[ 10] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 44100
[ 12] local 192.168.10.10 port 5201 connected to 192.168.10.20 port 44110
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 54.2 MBytes 453 Mbits/sec
[ 8] 0.00-1.00 sec 54.2 MBytes 453 Mbits/sec
[ 10] 0.00-1.00 sec 54.1 MBytes 452 Mbits/sec
[ 12] 0.00-1.00 sec 54.1 MBytes 452 Mbits/sec
[SUM] 0.00-1.00 sec 217 MBytes 1.81 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
(長いので省略)
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 5] 10.00-10.04 sec 2.12 MBytes 469 Mbits/sec
[ 8] 10.00-10.04 sec 2.12 MBytes 469 Mbits/sec
[ 10] 10.00-10.04 sec 2.12 MBytes 469 Mbits/sec
[ 12] 10.00-10.04 sec 2.12 MBytes 469 Mbits/sec
[SUM] 10.00-10.04 sec 8.50 MBytes 1.88 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.04 sec 561 MBytes 469 Mbits/sec receiver
[ 8] 0.00-10.04 sec 561 MBytes 469 Mbits/sec receiver
[ 10] 0.00-10.04 sec 561 MBytes 469 Mbits/sec receiver
[ 12] 0.00-10.04 sec 561 MBytes 469 Mbits/sec receiver
[SUM] 0.00-10.04 sec 2.19 GBytes 1.88 Gbits/sec receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
セッションが綺麗に2つずつに分かれ、2Gbps弱ほどの通信ができました。
※上記の検証では送信元・宛先IPアドレスは同一であり、宛先ポートも1つですので、送信元ポートのみでハッシュ値が変化します。送信元ポートによっては全セッションで同じ物理NICが選択される可能性もあります。これはセッション数を増やすことで偏りを無くすことができます。
最後に
「AlmalinuxでLAGを組んでみた」という内容ながら、Transmit Policyによる物理NICの選択など、LACP自体の設定についての知見が溜まりました...(笑)
他にも、bond.optionで指定した"miimon"の値の違いによる、障害時の挙動の変化なども試してみたかったのですが、長くなりすぎるのでまたの機会とさせていただきます。m(__)m
スイッチほどLAGを組む機会は無いかもしれませんが、参考になれば幸いです。

