2011年10月12日水曜日

TIME_WAITのチューニングとkernelリビルド for CentOS 6.0



久しぶりにSRPMからkernelリビルドしてみたので、
過去を振り返りつつ手順をメモ。

ソーシャルゲームや外部のAPIを使用するサービスなどにありがちなんですが、
Webサーバは、受けるHTTPリクエストが多くなると、
外部のWebサーバにHTTPリクエストを送る処理も多くなったりします。
その場合に問題となるのが、tcpのコネクションです。

TIME_WAIT状態のコネクションが多くなると、
接続できる数は上限があるので、接続できたりできなかったり不安定な状態になります。
そうなると、まあ担当者はかなりテンパってますね。
でも負荷的にはサーバはテンパってなかったりします。

TIME_WAIT多発対策はざっくり


  • サーバ増強

    • 緊急対応ということで、あくまで一時的な対応。富豪ならこれでよし。

  • 使用できるTCPポート番号を増やした

    • 増加量が上回る場合は、焼け石に水。

  • tcp_tw_recycleを有効にしてコネクションの再利用

    • パケットのタイムスタンプの影響で外部との通信で問題あり

  • TIME_WAITの値を60秒→15秒に変更

    • TIME_WAITが減り安定動作



そんなわけで、TIME_WAITのチューニングで落ち着きました。
CentOS 5.3でTIME_WAITを15秒にしたカーネルを数年利用していますが、
とくに問題もなく安定しています。

手間だったのは、
この設定変更をするためには、カーネルのリビルドが必要となるため、
全てのサーバに適用するため数台ずつ停止し少しずつ適用していきました。

以下、CentOS 6.0のTIME_WAIT 15秒版カーネルのリビルド手順です。
CentOS5.3の頃と手順はあまり変わらないですが、
少しパスの変更があったようです。


参考 centosとfedora projectのwiki
http://wiki.centos.org/HowTos/RebuildSRPM
http://fedoraproject.org/wiki/Building_a_custom_kernel


TIME_WAITのチューニングとkernelリビルド手順 for CentOS 6.0
1. rpmのビルドに必要なモジュールのインストール


yum install rpm-build.x86_64 \
redhat-rpm-config.noarch \
patchutils.x86_64 \
elfutils-libelf-devel.x86_64 \
binutils-devel.x86_64 \
hmaccalc.x86_64 \
rng-tools.x86_64

他にgccなども必要です


2. SRPM(カーネル)の入手と解凍


cd /usr/local/src
wget http://mirror.centos.org/centos/6.0/updates/SRPMS/kernel-2.6.32-71.29.1.el6.src.rpm
rpm -ivh kernel-2.6.32-71.29.1.el6.src.rpm


3. パッチの作成


■パッチ作成のためのソースをコピーする
cd ~/rpmbuild/SPECS
rpmbuild -bp kernel.spec
cd ~/rpmbuild/BUILD
cp -r ~/rpmbuild/BUILD/kernel-2.6.32-71.29.1.el6/linux-2.6.32-71.29.1.el6.x86_64 ~/rpmbuild/BUILD/kernel-2.6.32-71.29.1.el6.orig
cp -r ~/rpmbuild/BUILD/kernel-2.6.32-71.29.1.el6/linux-2.6.32-71.29.1.el6.x86_64 ~/rpmbuild/BUILD/kernel-2.6.32-71.29.1.el6.new


rpmbuild中にPGPの鍵作成に時間がかかりすぎる場合は、
次のコマンドを別コンソールで実行する。

rngd -r /dev/urandom

特にOS新規インストールのサーバは、この画面から進まない・・・。


### Now generating a PGP key pair to be used for signing modules.
### ---------------- 途中 省略 ---------------
### 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 `.'




■tcp.hファイルを修正する
cd ~/rpmbuild/BUILD
vi kernel-2.6.32-71.29.1.el6.new/include/net/tcp.h

次の1行を修正する。(TIME_WAITを60秒→15秒)
修正前
#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
修正後
#define TCP_TIMEWAIT_LEN (15*HZ) /* how long to wait to destroy TIME-WAIT

■パッチを作成する
diff -uNrp kernel-2.6.32-71.29.1.el6.orig kernel-2.6.32-71.29.1.el6.new > ../SOURCES/tcph.patch


4. ビルドの準備


■パッチを適用するためkernel.specファイルを修正する
cd ~/rpmbuild/SPECS
vi kernel.spec

修正前
# % define buildid .local
修正後
%define buildid .tcp15

※新カーネルインストールの際にkernel-firmwareの同じbuildid版を要求されたのでやめました。

# empty final patch file to facilitate testing of kernel patches
Patch00: tcph.patch  ←追加
Patch999999: linux-kernel-test.patch

ApplyOptionalPatch tcph.patch  ←追加
ApplyOptionalPatch linux-kernel-test.patch

5. TIME_WAIT変更版カーネルのビルド


rpmbuild -ba kernel.spec


6. カーネルのアップデート


cd ~/rpmbuild/RPMS/x86_64
rpm -Uvh --force kernel-2.6.32-71.29.1.el6.x86_64.rpm kernel-2.6.32-71.29.1.el6.x86_64.rpm

再起動
reboot


7. TIME_WAITの確認


1秒間隔でウォッチ
watch -n 1 "netstat -a | grep http"

次のようにTIME_WAITになるので、
15秒後に消えたら動作しています。

Every 1.0s: netstat -a | grep http tcp 0 0 *:http *:* LISTEN
tcp 0 0 ::ffff:192.168.xxx.xxx:http ::ffff:192.168.xxx.xxx:30439 TIME_WAIT



以上、とくにかくリビルドに時間かかるので、時間に余裕があるときに放置しながらがよいかと思います。




0 件のコメント:

コメントを投稿