コアダンプの数だけ強くなれるよ

見習いエンジニアの備忘log

GoogleのTCP BBRでLinuxサーバーの高速化を試す

GoogleさんがLinuxに実装したTCPの輻輳制御モジュールでTCP通信がどのくらい高速化されるのか試してみる。環境はVirtualBox上にインストールしたCentOS7(64bit)。

具体的にはVMを2つ作成しiperfを使ってVM間のTCP通信性能がどのくらい変わるのか見てみる。

BBRとは

BBRはGoogleが開発したTCP輻輳制御アルゴリズムおよびぞれを実装したプログラムであり従来より高速に通信ができますよ!という事らしい。

news.mynavi.jp


BBRの導入

BBRを使うためにはまずBBRに対応したカーネルにバージョンを上げる必要がある。

事前準備

カーネルのコンパイルに下記パッケージが必要になるのでインストールしておく。

$ sudo yum install bc ncurses-devel openssl-devel
カーネルのダウンロード

まずは公式のThe Linux Kernel Archivesからソースコードを持ってくる。
下記stable版のURLを確認してLinuxマシンにダウンロードする。

f:id:segmentation-fault:20170729165054p:plain

$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.12.4.tar.xz


ダウンロードが出来たらファイルを解凍し展開する。

$ xz -dv linux-4.12.4.tar.xz
$ tar xvf linux-4.12.4.tar
カーネルのコンフィグ

展開したディレクトに入り現在のカーネルコンフィグをコピーする。

$ cd linux-4.12.4
$ uname -a
Linux localhost.localdomain 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
$
$cp /boot/config-3.10.0-327.el7.x86_64 .config


旧コンフィグを引き継ぐためにmake oldconfigを実行する。コンフィグ設定内容についての大量の質問が対話形式で行われるが面倒なのですべてdefault(すべてEnterキー)にする。

$ make oldconfig
scripts/kconfig/conf  --oldconfig Kconfig
.config:600:warning: symbol value 'm' invalid for CPU_FREQ_STAT
.config:837:warning: symbol value 'm' invalid for NF_CT_PROTO_DCCP
.config:839:warning: symbol value 'm' invalid for NF_CT_PROTO_SCTP
.config:840:warning: symbol value 'm' invalid for NF_CT_PROTO_UDPLITE
.config:858:warning: symbol value 'm' invalid for NF_NAT_PROTO_DCCP
.config:859:warning: symbol value 'm' invalid for NF_NAT_PROTO_UDPLITE
.config:860:warning: symbol value 'm' invalid for NF_NAT_PROTO_SCTP
*
* Restart config...
*
*
* General setup
*
...(以降、ひたすらEnterキーを連打)


旧コンフィグを引き継いだらBBRのコンフィグ(defaultでは無効になっている)を有効にして.configを上書きする。

$ make menuconfig


ネットワークの項目から辿りBBRの項目を探して有効化する。
f:id:segmentation-fault:20170729170509p:plain
f:id:segmentation-fault:20170729170512p:plain
f:id:segmentation-fault:20170729170516p:plain
f:id:segmentation-fault:20170729170522p:plain
f:id:segmentation-fault:20170729170525p:plain
f:id:segmentation-fault:20170729170530p:plain

コンパイル~インストール

コンフィグ設定が完了したのでコンパイルしインストールする。

$ make
$ sudo make modules_install
$ sudo make install


インストールまで終わったらgrubのメニューにインストールしたカーネルが存在するか確認する。

$ sudo cat /etc/grub2.cfg
...(途中略)
menuentry 'CentOS Linux (4.12.4) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-e99ba373-abbc-4e11-a579-60f426ebcbb2' {
...(途中略)
        linux16 /vmlinuz-4.12.4 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8
        initrd16 /initramfs-4.12.4.img
}
...(途中略)
起動確認

Linuxマシン(VM)を再起動してgrubの画面でインストールしたカーネルを選択し起動する。

f:id:segmentation-fault:20170729171619p:plain


ログイン後に起動中のカーネルを確認して一致していればOK。

$ uname -a
Linux localhost.localdomain 4.12.4 #1 SMP Fri Jul 28 23:58:47 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux
TCP輻輳制御の変更

BBRを有効にするにはカーネルパラメータを変更してBBRを有効にする必要がある。net.ipv4.tcp_congestion_controlをbbrに設定して再起動すると有効になる。

$ cat /proc/sys/net/ipv4/tcp_congestion_control
cubic
$ sudo cp /etc/sysctl.d/99-sysctl.conf  /etc/sysctl.d/99-sysctl.conf.orig
$ sudo vi /etc/sysctl.d/99-sysctl.conf
$ diff /etc/sysctl.d/99-sysctl.conf.orig /etc/sysctl.d/99-sysctl.con
+net.ipv4.tcp_congestion_control = bbr
$ sudo reboot


再起動後にbbrが有効になっていればOK。

$ cat /proc/sys/net/ipv4/tcp_congestion_control
bbr
$ lsmod |grep bbr
tcp_bbr                16384  0

性能測定環境の構築

iperfのインストール

性能測定用のツールは下記を使用する。

iperf.fr

f:id:segmentation-fault:20170729172454p:plain


URLを確認したらwgetでダウンロードしインストールする。

$ wget https://iperf.fr/download/fedora/iperf3-3.1.3-1.fc24.x86_64.rpm
$ sudo rpm -ivh iperf3-3.1.3-1.fc24.x86_64.rpm
VMのクローン作製

カーネルのアップデート、iperfのインストールまで完了したらVMを複製する。

f:id:segmentation-fault:20170729172511p:plain
f:id:segmentation-fault:20170729172525p:plain
f:id:segmentation-fault:20170729172528p:plain
f:id:segmentation-fault:20170729172531p:plain


性能測定

BBR対応のカーネルと測定ツールが用意できたので実際に通信性能を計測してみる。測定は下記パターンで実施して比較してみる。

測定パターン
(1) CentOS7デフォルトのカーネル
(2) アップデート後のカーネル(BBR無し)
(3) アップデート後のカーネル(BBR有り)

構成図

測定は下記のVM間で行う。

f:id:segmentation-fault:20170729175801p:plain

内部ネットワークの設定

用意した2つのVMで通信するために両VM共に内部ネットワークのアダプターを作成する。

f:id:segmentation-fault:20170729172624p:plain


それぞれ下記の固定IPを設定する。

VM1(クライアント側)

$  ip address show dev enp0s9
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:1d:b8:43 brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.1/16 brd 172.16.255.255 scope global enp0s9
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe1d:b843/64 scope link
       valid_lft forever preferred_lft forever


VM2(サーバ側)

$ ip address show dev enp0s9
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:ff:86:a7 brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.2/16 brd 172.16.255.255 scope global enp0s9
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:feff:86a7/64 scope link
       valid_lft forever preferred_lft forever
測定結果

iperfをオプション指定はせずに各パターンで実行した。

$ iperf -s            #サーバ側
$ iperf -c 172.16.0.2 #クライアント側


結果サマリ

CentOS7デフォルトのカーネル
$iper3 -c 172.16.0.2
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  2.14 GBytes  1.84 Gbits/sec  4680             sender
[  4]   0.00-10.00  sec  2.14 GBytes  1.84 Gbits/sec                  receiver

アップデート後のカーネル(BBR無し)
$iper3 -c 172.16.0.2
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  2.41 GBytes  2.07 Gbits/sec  3967             sender
[  4]   0.00-10.00  sec  2.40 GBytes  2.07 Gbits/sec                  receiver

アップデート後のカーネル(BBR有り)
$iper3 -c 172.16.0.2
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  3.09 GBytes  2.65 Gbits/sec  120610             sender
[  4]   0.00-10.00  sec  3.08 GBytes  2.65 Gbits/sec                  receiver


結果まとめ

# 計測パターン 帯域(Gbits/sec) TCP再送数
1 CentOS7デフォルトのカーネル 1.84 4680
2 アップデート後のカーネル(BBR無し) 2.07 3970
3 アップデート後のカーネル(BBR有り) 2.65 120610


BBR無しでも最新のカーネルではTCPの通信性能は上がってるぽい(?)
BBR有りの場合は帯域は向上して見えるがTCPの再送が30倍になっているのが少し気になるところ。

まとめ

確かにBBRによってTCP通信の高速化が期待できそうな結果となった。TCPという昔から存在する技術(いい意味で枯れた技術)に性能向上のアプローチをしていること、実装が600行程のソースコードで書かれたモジュールによって実現している点が面白い。ソースコードをじっくり読んでもっと理解を深めたい。


[参考]
www.linuxmaster.jp
github.com
dev.classmethod.jp