LinuxでIPやポート単位で簡単にトラフィックをコントロールしよう

研究でcgroupやCFSを調査しているんですが、トラフィックをコントロールするtcコマンドやqos周りを復習がてら、ツールを作ってみました。簡単という所が重要です。何をするツールかというと、「Linuxサーバ上でinboundとoutboundのトラフィック帯域をIPやプロトコル単位で好きなようにコントロールし管理する」ためのツールです。

これまでのトラフィックコントロールツールを改良

とにかく複雑でわかりにくかった印象があります。その結果、トラフィックコントロールを運用に持ち込んでも、うまく管理することができなかったのは容易に想像できます。最初はtcコマンド、次にcbq.initが使われてきました。

tcコマンドはわかりにくいので

tcコマンドがあまりにカオスすぎるので、それをcbq.initという昔ながらのラッパープログラムで使いやすくするという方法がこれまでとられてきました。しかし、cbq.initでは、クライアントからみたダウンロードしかコントロールできないので、今回作ったツールではそこを改良してinboundとoutbound両方に対応させました。

結局cbq.initもやっぱりわかりにくいので

さらに、cbq.initも適当に設定していると、いつのまにかカオスなトラフィックコントロール設定が増えてしまってはまりがちです。また、設定も直感的ではありませんでした。そこで、今回のツールはそれらを運用者がきちんと管理でき、しかるべきタイミングで安全かつ簡単に設定できるように作りました。これまでのトラフィックコントロール系のツールの問題を改良しました。

使いどころ(運用者のたしなみ)

では、どういう所で使っていくかを考えます。例えば、共有ストレージに複数のサーバをマウントしている場合では、サーバ側のトラフィックをコントロールすることで、ストレージの負荷をうまく緩和することが可能です。ストレージが高負荷でどうにもならなくなりそうだったら、いきなり上位のスイッチで全部トラフィックを絞るのではなく、特にトラフィックを使ってそうなサーバや、さらにはプロトコルにのみトラフィックをコントロールしてやるのが、できる運用者だと思います。

各種ミドルウェアの帯域を統一的にコントロール

ApacheやProftpd等のミドルウェアで個別の設定を入れるのではなく、このツール人一つでプロトコル毎にトラフィックをコントロールしたり、送信元IPで適応の有無を決定したりする所が強みだと言えます。その結果、このツールで全てのミドルウェアにおけるトラフィックコントロールを統一的に管理・運用することが可能になります。特にサーバの共有等、マルチテナント構成をとっている場合は、できるだけ悪い人を絞って、良い人には迷惑かけないように心がけるのが運用者のたしなみでしょう。

導入

ファイル群はここにあります。この中に、/etcと/usrというディレクトリがあるので、git cloneした後にそれを適応したいサーバの/に展開して下さい。CentOSでしか試していません。その際には、独自PerlライブラリであるSystem::Baseを使っているので、それを使えるように以下のRPMをインストールします。(rpmforgeを見れるようにしておくこと

[program lang=’bash’ escaped=’true’]

yum --enablerepo=rpmforge install perl-Class-Accessor perl-Jcode
[/program]

これで、System::Baseモジュールに必要なモジュールは揃います。

使い方概要

では実際に使い方を説明します。

[program lang=’bash’ escaped=’true’]

cd /usr/local/sbin/
[/program]

を実行後、トラフィックコントロールツールを実行します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --help
[/program]

すると以下のようにusageが出ます。

[program lang=’bash’ escaped=’true’]

    usage: ./qos-control.pl --method|-m METHOD --ip|-i SERVER_IP --direction|-d DIRECTION --traffic|-t BANDWIDTH [--eth|-e INTREFACE] [--protocol|-p PROTOCOL] [--src|-s SRC_IP]

        -m, --method        set method                  (view clear set)
        -i, --ip            set server ip
        -d, --direction     set direction               (out in)
        -t, --traffic       set traffic bandwidth Mbps  (1 2 4 8 16)
        -e, --eth           set interface               (eth0 eth1 eth2 eth3)
        -p, --protocol      set protocol                (https smtp ssh imaps imap all ftp http pop3 pop3s)
        -s, --src           set src ip
        -c, --clsid         set clsid only clear method
        -h, --help          display this help and exit
        -v, --version       display version and exit
[/program]

運用者が安全に使えるように、トラフィックコントロールのパラメータは限定しています。オプションにはインターフェイスやサーバ内で複数のIPを設定していた場合にも対応できるようなオプションをできるだけ実装しているので、それらを工夫して設定すると多くの状況に対応できると思います。特定のIPからのアクセスのみにトラフィックコントロールを適応したい場合は–srcオプションを使ってください。

outbound設定追加

ではまず、サーバにトラフィックコントロールの設定が入っていない事を確認します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method view --ip 172.16.71.46
[/program]

実行結果。

[program lang=’bash’ escaped=’true’]

nothing
[/program]

上記のようにnotingと出力されれば、何も設定されていません。では、例えば、サーバのoutbound方向(クライアントからみてダウンロード)の全てのトラフィックを16Mbpsに制限したい場合は、以下のコマンドを実行します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method=set --ip=172.16.71.46 --direction=out --traffic=16
[/program]

オプションは、–methodなら-m等、shortオプションにも対応しています。上記を実行すると、以下のように出力を得られます。

[program lang=’bash’ escaped=’true’]

*** old [172.16.71.46] settings ***
--------------------------
nothing
--------------------------

Setting ... OK

*** current [172.16.71.46] settings ***
------------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
------------------------------
[/program]

無事設定されたようです。試しにhttpでクライアントから何かファイルをダウンロードすると16Mbpsが上限になっているのを確認できると思います。 では、さらにftpだけはoutboundを8Mbpsにしたい場合は、追加で以下のコマンドを実行します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method=set --ip=172.16.71.46 --direction=out --traffic=8 --protocol=ftp
[/program]

すると、以下のような出力が得られます。

[program lang=’bash’ escaped=’true’]

*** old [172.16.71.46] settings ***
--------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
--------------------------

Setting ... OK

*** current [172.16.71.46] settings ***
------------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
------------------------------
[/program]

これによって、全てのoutbound方向のトラフィックは16Mbpsに制限されているが、ftpのみ8Mbpsに制限されていることになります。ftpソフト等でファイルのダウンロードで確認してみて下さい。対応しているプロトコルは以下になります。

[program lang=’bash’ escaped=’true’]

-p, --protocol      set protocol                (https smtp ssh imaps imap all ftp http pop3 pop3s)
[/program]

inbound設定追加

次に、inbound側(クライアントからみてアップロード)も設定してみます。オプションはほとんど一緒で、例えば、inbound側のトラフィックを8Mbpsに制限したい場合は以下のコマンドを実行します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method=set --ip=172.16.71.46 --direction=in --traffic=8
[/program]

すると、以下の出力が得られます。

[program lang=’bash’ escaped=’true’]

*** old [172.16.71.46] settings ***
--------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
--------------------------

Setting ... OK

*** current [172.16.71.46] settings ***
------------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->8Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
------------------------------
[/program]

さらに、inboundのhttpを4Mbpsに制限します。同様に以下のようなコマンドを実行します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method=set --ip=172.16.71.46 --direction=in --traffic=4 --protocol=http
[/program]

すると以下のようになります。

[program lang=’bash’ escaped=’true’]

*** old [172.16.71.46] settings ***
--------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->8Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
--------------------------

Setting ... OK

*** current [172.16.71.46] settings ***
------------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->8Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
CLSID->1067     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46:80      src_ip->nothing
------------------------------
[/program]

実際に試してみると、トラフィックが制限されていることがわかると思います。

設定済みのパラメータ変更

また、一時的にinboundのトラフィックを8Mbpsから4Mbpsに変更したい場合は、以下のように実行します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method=set --ip=172.16.71.46 --direction=in --traffic=4
[/program]

すると、以下のように元ある設定を自動的に検出して変更してくれます。

[program lang=’bash’ escaped=’true’]

*** old [172.16.71.46] settings ***
--------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->8Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
CLSID->1067     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46:80      src_ip->nothing
--------------------------

Setting ... OK

*** current [172.16.71.46] settings ***
------------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
CLSID->1067     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46:80      src_ip->nothing
------------------------------
[/program]

設定の削除

最後に、outbound側のftpの設定を消したくなった場合は以下のように、まず現在の設定を確認します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method=view --ip=172.16.71.46
[/program]

設定が出力されます。

[program lang=’bash’ escaped=’true’]

CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
CLSID->1067     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46:80      src_ip->nothing
[/program]

そして、この中から消したい設定のCLSIDを見つけます。今回はoutbound側のftpの設定なので、CLSIDは5302であることが分かります。その設定を消します。

[program lang=’bash’ escaped=’true’]

./qos-control.pl --method=clear --ip=172.16.71.46 --clsid=5302
[/program]

以下の出力と共に消すことができました。

[program lang=’bash’ escaped=’true’]

*** old [172.16.71.46] settings ***
--------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->5302     interface->eth0       direction->out        bandwidth->8Mbps     server_ip_port>172.16.71.46:20      src_ip->nothing
CLSID->1067     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46:80      src_ip->nothing
--------------------------

Setting Clear ... OK

*** current [172.16.71.46] settings ***
--------------------------
CLSID->5047     interface->eth0       direction->out        bandwidth->16Mbps     server_ip_port>172.16.71.46         src_ip->nothing
CLSID->0047     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46         src_ip->nothing
CLSID->1067     interface->eth0       direction->in         bandwidth->4Mbps      server_ip_port>172.16.71.46:80      src_ip->nothing
--------------------------
[/program]

以上が、今回作ったLinuxのtcコマンドのラッパーのcbq.initをさらに改良してラッパーしたツールの使い方です。是非、これで簡単にLinuxのサーバのトラフィックをコントロールして、運用者もコーディングに時間を使えるようにして下さい。

「LinuxでIPやポート単位で簡単にトラフィックをコントロールしよう」への2件のフィードバック

コメントは受け付けていません。