以前、一度やったはずなのですが、すっかり忘れてしまっていて、結局調べることになったので、今回はここに作業ログを残しておきます。
TIME_WAITコネクションの増殖
一般的にネットワークアクセス数が極端に多いサーバでは、TIME_WAIT状態のコネクションが残留しがちです。
TIME_WAITの滞留時間が、Linuxデフォだと60秒になっているため、下記のエントリにも書きましたが、60秒の間に数十万レベルのリクエストが来るとあっという間にコネクションテーブルが埋まっていってしまうわけです。
で、別にTIME_WAITコネクションが多くなってしまうこと自体は、完全な悪というわけでもなく、 "net.ipv4.tcp_max_tw_buckets" あたりでキャップもできるし、それなりに制御して付き合っていけばいいわけですが、ローカルのTCPポートを使い切るようなケースだと、使えるローカルポートレンジは限られているので困ったりするパターンもあります。
そういえば昔、↑のエントリのような状況に出くわして、この時は諸事情で(NATしている構成ではなかったので) "net.ipv4.tcp_tw_recycle" を設定することで、TIME_WAITとなったTCPコネクションを再利用することで事なきを得たのですが、今回は検証の都合上、Linux Kernelをビルドして、TIME_WAITのコネクションが解放される時間(デフォルト: 60秒)を短くしてみます。
OS(今回の環境例)
今回使った検証環境でのサーバのOSは、LinuxのCentOS 6.4でした。
# cat /proc/version Linux version 2.6.32-358.23.2.el6.x86_64 (mockbuild@c6b9.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) ) #1 SMP Wed Oct 16 18:37:12 UTC 2013
こんな感じ。
カーネルのソースパッケージをゲットする
せっかくCentOSを使っていることもあって、公開されているカーネルのソースパッケージを取得します。
上記サイトから、該当するバージョンのリリースノートを読むと、ソースパッケージの記載場所が書いてありますので、そこからダウンロードしましょう。
CentOS 6.4だと、以下のリリースノート箇所に書いてあります。
以下のUpdateリポジトリあたりから、自分のカーネルバージョンと一致しているソースパッケージを入手します。
今回の例だと、↑の通り "/proc/version" でKernelのバージョンが "2.6.32-358.23.2.el6.x86_64" とわかりますので、以下コマンドみたいな感じでダウンロードして展開します。
# wget http://vault.centos.org/6.4/updates/Source/SPackages/kernel-2.6.32-358.23.2.el6.src.rpm # rpm -ivh kernel-2.6.32-358.23.2.el6.src.rpm
Kernelのソースコードをちょこっと修正
本来であれば、きちんとパッチ(patch)を作成すべきなのですが、今回は検証が目的だったこともあって(面倒くさいので)、tarballを展開して直接変更を加えることにします。。。
# cd ~/rpmbuild/SOURCES/ # cp linux-2.6.32-358.23.2.el6.tar.bz2 /tmp
ソースパッケージをインストールすると、"~/rpmbuild/SOURCES/"にtarファイルが展開されるので、それを/tmpにコピーしちゃいます。
# cd /tmp # tar xjvf linux-2.6.32-358.23.2.el6.tar.bz2
/tmpに移動して展開。
mv linux-2.6.32-358.23.2.el6 linux-2.6.32-358.23.3.namibuild.el6
ディレクトリファイル名を適当に変えてみました。
(更新番号をインクリメントして、野良ビルドしたので適当に文字列をくっつけました。)
cd linux-2.6.32-358.23.3.namibuild.el6
カレントディレクトリを変えて、以下のような感じでファイルを修正。
# diff -c Makefile{.bak,} *** Makefile.bak 2013-11-19 16:56:31.272668572 +0900 --- Makefile 2013-11-19 16:57:03.889668546 +0900 *************** *** 1,7 **** VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 ! EXTRAVERSION = NAME = Man-Eating Seals of Antiquity RHEL_MAJOR = 6 RHEL_MINOR = 4 --- 1,7 ---- VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 ! EXTRAVERSION = -358.23.3.namibuild.el6.x86_64 NAME = Man-Eating Seals of Antiquity RHEL_MAJOR = 6 RHEL_MINOR = 4
# diff -c include/net/tcp.h{.bak,} *** include/net/tcp.h.bak 2013-11-19 16:59:19.386668435 +0900 --- include/net/tcp.h 2013-11-19 16:59:38.649668421 +0900 *************** *** 111,118 **** */ ! #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT ! * state, about 60 seconds */ #define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN /* BSD style FIN_WAIT2 deadlock breaker. * It used to be 3min, new value is 60sec, --- 111,118 ---- */ ! #define TCP_TIMEWAIT_LEN (2*HZ) /* how long to wait to destroy TIME-WAIT ! * state, about 2 seconds */ #define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN /* BSD style FIN_WAIT2 deadlock breaker. * It used to be 3min, new value is 60sec,
上記2ファイルですね。"include/net/tcp.h"の"TCP_TIMEWAIT_LEN"の変数が、今回変更を加えたい該当箇所になります。
設定値は、ケースに応じて吟味すべきですが、今回は↑の如く、検証内容的に2秒にしました。(短いw)
# cd .. # tar cjvf linux-2.6.32-358.23.3.namibuild.el6.tar.bz2 linux-2.6.32-358.23.3.namibuild.el6
修正後、固めなおして、、、
# cp linux-2.6.32-358.23.3.namibuild.el6.tar.bz2 ~/rpmbuild/SOURCES/
固めたtarファイルを "~/rpmbuild/SOURCES/" にコピーします。
# cd ~/rpmbuild/SPECS/ # diff -c kernel.spec{.bak,} *** kernel.spec.bak 2013-11-19 17:02:26.605668280 +0900 --- kernel.spec 2013-11-19 17:03:02.633668255 +0900 *************** *** 19,25 **** %define rhel 1 %if %{rhel} ! %define distro_build 358.23.2 %define signmodules 1 %else # fedora_build defines which build revision of this kernel version we're --- 19,25 ---- %define rhel 1 %if %{rhel} ! %define distro_build 358.23.3.namibuild %define signmodules 1 %else # fedora_build defines which build revision of this kernel version we're *************** *** 171,177 **** %endif # The kernel tarball/base version ! %define kversion 2.6.32-358.23.2.el6 %define make_target bzImage --- 171,177 ---- %endif # The kernel tarball/base version ! %define kversion 2.6.32-358.23.3.namibuild.el6 %define make_target bzImage *************** *** 562,568 **** %define strip_cmd strip %endif ! Source0: linux-2.6.32-358.23.2.el6.tar.bz2 Source1: Makefile.common --- 562,568 ---- %define strip_cmd strip %endif ! Source0: linux-2.6.32-358.23.3.namibuild.el6.tar.bz2 Source1: Makefile.common
更新番号とかを変更しているので、上記のような感じで、specファイルを修正。
ここまでで、修正作業は終わりです。次はビルドでございます。
独自カーネルをビルドする
さて、ビルドすべくrpmbuildコマンドを実行すると、、、
# rpmbuild -ba kernel.spec エラー: ビルド依存性の失敗: redhat-rpm-config は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています patchutils は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています xmlto は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています asciidoc は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています binutils-devel は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています newt-devel は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています python-devel は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています perl(ExtUtils::Embed) は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています bison は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています flex は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています hmaccalc は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています
依存関係で諸々足りないパッケージを指摘されるので、、、
yum -y install redhat-rpm-config patchutils xmlto asciidoc binutils-devel newt-devel python-devel perl-ExtUtils-Embed bison flex hmaccalc
yumでインストール。
# rpmbuild -ba kernel.spec
で、再ビルド。
実行マシンにもよりますが、カーネルのビルドは結構時間がかかりますので、気長に待ちましょう。
gpg: keyring ...のところから進まない
ひょっとしたら、以下の箇所で処理が全然すすまなくなるかもしれません。
### ### Now generating a PGP key pair to be used for signing modules. ### ### If this takes a long time, you might wish to run rngd in the background to ### keep the supply of entropy topped up. It needs to be run as root, and ### should use a hardware random number generator if one is available, eg: ### ### rngd -r /dev/hwrandom ### ### If one isn't available, the pseudo-random number generator can be used: ### ### rngd -r /dev/urandom ### + gpg --homedir . --batch --gen-key /root/rpmbuild/SOURCES/genkey gpg: WARNING: unsafe permissions on homedir `.' gpg: keyring `./secring.gpg' created gpg: keyring `./pubring.gpg' created
そんな時はですね、別シェル(ターミナル)を立ち上げて、、、
# rngd -r /dev/urandom
上記コマンドを実行してentropyを供給。
# rngd -r /dev/urandom -bash: rngd: コマンドが見つかりません
もし、コマンドがない、って出力されたときは、、、
# yum -y install rng-tools # rngd -r /dev/urandom
インストールして再実行してみましょう。
ビルドが終わったらインストール、、、だが
ビルドが終わると、"~/rpmbuild/RPMS/x86_64/"にrpm一式が出来ているはずです。
# cd ../RPMS/x86_64/ # rpm -Uvh kernel-2.6.32-358.23.3.namibuild.el6.x86_64.rpm kernel-devel-2.6.32-358.23.3.namibuild.el6.x86_64.rpm kernel-headers-2.6.32-358.23.3.namibuild.el6.x86_64.rpm エラー: 依存性の欠如: kernel-firmware >= 2.6.32-358.23.3.namibuild.el6 は kernel-2.6.32-358.23.3.namibuild.el6.x86_64 に必要とされています
なので、こんな感じでインストールしようとするも、"kernel-firmware"がない、と(TT)
# cd ../../SPECS/ # rpmbuild -bb --with firmware kernel.spec
というわけで、再ビルド。しばし待つ。(要するに、最初から↑のコマンドを実行すると良いです。。。)
# cd ../RPMS/x86_64/ # rpm -Uvh kernel-2.6.32-358.23.3.namibuild.el6.x86_64.rpm kernel-devel-2.6.32-358.23.3.namibuild.el6.x86_64.rpm kernel-headers-2.6.32-358.23.3.namibuild.el6.x86_64.rpm kernel-firmware-2.6.32-358.23.3.namibuild.el6.x86_64.rpm 準備中... ########################################### [100%] 1:kernel-firmware ########################################### [ 25%] 2:kernel ########################################### [ 50%] 3:kernel-headers ########################################### [ 75%] 4:kernel-devel ########################################### [100%]
さて、やっとこさ独自ビルドしたカーネルがインストールできました。
というところで、OSを再起動します。
# cat /proc/version Linux version 2.6.32-358.23.3.namibuild.el6.x86_64 (root@haproxy-test01) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) ) #1 SMP Tue Nov 19 17:35:29 JST 2013
再起動後、ちゃんと起動してきて、独自カーネルに変わっていればOKです。
動作確認
クライアントから適当に接続要求しまくって、どうなったかを netstat で確認してみます。
Before...
# netstat -anpto ・・・・・省略・・・・・ tcp 0 0 10.50.1.62:80 10.33.56.163:47769 TIME_WAIT - timewait (8.40/0/0) tcp 0 0 10.50.1.62:80 10.33.56.171:4649 TIME_WAIT - timewait (9.04/0/0) tcp 0 0 10.50.1.62:80 10.33.56.111:11322 TIME_WAIT - timewait (0.00/0/0) tcp 0 0 10.50.1.62:80 10.33.56.189:42672 TIME_WAIT - timewait (25.83/0/0) tcp 0 0 10.50.1.62:80 10.33.56.151:1175 TIME_WAIT - timewait (38.93/0/0) tcp 0 0 10.50.1.62:80 10.33.56.190:12461 TIME_WAIT - timewait (25.89/0/0) tcp 0 0 10.50.1.62:80 10.33.56.61:2089 TIME_WAIT - timewait (26.19/0/0) tcp 0 0 10.50.1.62:80 10.33.56.45:23837 TIME_WAIT - timewait (25.44/0/0) tcp 0 0 10.50.1.62:80 10.33.56.59:30782 TIME_WAIT - timewait (40.56/0/0) tcp 0 0 10.50.1.62:80 10.33.56.167:61432 TIME_WAIT - timewait (53.22/0/0) ・・・・・省略・・・・・
After!!!
# netstat -anpto ・・・・・省略・・・・・ tcp 0 0 10.50.1.62:80 10.33.56.85:48327 TIME_WAIT - timewait (0.71/0/0) tcp 0 0 10.50.1.62:80 10.33.56.55:37193 TIME_WAIT - timewait (0.18/0/0) tcp 0 0 10.50.1.62:80 10.33.56.41:28099 TIME_WAIT - timewait (0.34/0/0) tcp 0 0 10.50.1.62:80 10.33.56.33:2009 TIME_WAIT - timewait (0.04/0/0) tcp 0 0 10.50.1.62:80 10.33.56.76:15310 TIME_WAIT - timewait (0.38/0/0) tcp 0 0 10.50.1.62:80 10.33.56.15:41482 TIME_WAIT - timewait (0.17/0/0) tcp 0 0 10.50.1.62:80 10.33.56.34:39958 TIME_WAIT - timewait (1.76/0/0) tcp 0 0 10.50.1.62:80 10.33.56.97:36784 TIME_WAIT - timewait (0.89/0/0) tcp 0 0 10.50.1.62:80 10.33.56.74:53628 TIME_WAIT - timewait (1.95/0/0) tcp 0 0 10.50.1.62:80 10.33.56.94:5927 TIME_WAIT - timewait (0.82/0/0) ・・・・・省略・・・・・
上記の通りですが、Beforeでは53秒とか滞留しているコネクションがありましたが、Afterでは設定した2秒以内におさまっています。
と、簡単ではありますが、こんな感じでTIME_WAITコネクションの数を減らすことができました。
それでは!=͟͟͞͞(๑•̀=͟͟͞͞(๑•̀д•́=͟͟͞͞(๑•̀д•́๑)=͟͟͞͞(๑•̀д•́

- 作者: Daniel P. Bovet,Marco Cesati,高橋浩和,杉田由美子,清水正明,高杉昌督,平松雅巳,安井隆宏
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2007/02/26
- メディア: 大型本
- 購入: 9人 クリック: 269回
- この商品を含むブログ (73件) を見る