Linuxカーネルパラメータの設定とチューニング、デフォルト値の調べ方

概要
1. カーネルパラメータの設定
2. 主なチューニングパラメータ
3. パラメータのデフォルト値の調べ方

1. カーネルパラメータの設定

カーネルパラメータは、次の2箇所で設定できます。
①/etc/sysctl.conf
設定ファイルに記述します。
システム起動時に反映されるため、恒久的に適用したい場合にはsysctl.conf に記述します

②/proc 以下
/proc 以下の各ディレクトリツリーのファイル内に必要な値を記述する即時反映されるが、再起動すると設定が元に戻ります。
一時的に反映したい場合に記述します

• /procファイルシステム
Linuxの最も特徴的な点として、
「システムの状態を”ファイル”という単位で扱う事ができる」ことです。

/proc 以下にシステムの現在の状態が記述されているファイルが存在します。
[/proc/net]

$ cd /proc/net
$ ls
anycast6   icmp           ip6_mr_vif   netfilter  ptype      rt_acct    softnet_stat  udplite
arp        if_inet6       ip_mr_cache  netlink    raw        rt_cache   stat          udplite6
connector  igmp           ip_mr_vif    netstat    raw6       snmp       tcp           unix
dev        igmp6          ipv6_route   packet     route      snmp6      tcp6          wireless
dev_mcast  ip6_flowlabel  mcfilter     protocols  rpc        sockstat   udp           xfrm_stat
dev_snmp6  ip6_mr_cache   mcfilter6    psched     rt6_stats  sockstat6  udp6

• /etc/sysctl.conf
/proc 以下に存在するカーネルパラメータを恒久的に反映させるための設定ファイルです。

[/etc/sysctl.conf 一部抜粋]

# Kernel sysctl configuration file for Red Hat Linux
#
# For binary values, 0 is disabled, 1 is enabled.  See sysctl(8) and
# sysctl.conf(5) for more details.

# Controls IP packet forwarding
net.ipv4.ip_forward = 0

# Controls source route verification
net.ipv4.conf.default.rp_filter = 1

# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0

# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0

# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1

# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1

# Disable netfilter on bridges.

• /etc/sysctl.confと/proc/sys配下の関係
/proc/sys以下のパス名は「/」の代わりに「.」で区切って指定します

例.
/proc/sys/net/ipv4/ip_forward
→ /etc/sysctl.confのnet.ipv4.ip_forwardに相当

• sysctlコマンド
sysctl.conf ファイルの反映や設定されているカーネルパラメータ一覧を表示します。

$ sysctl
usage:  sysctl [-n] [-e] variable ...
        sysctl [-n] [-e] [-q] -w variable=value ...
        sysctl [-n] [-e] -a
        sysctl [-n] [-e] [-q] -p <file>   (default /etc/sysctl.conf)
        sysctl [-n] [-e] -A
オプション 説明
-n キーの名前は表示せず、値だけ表示する。
-e 不明なキーについてのエラーを無視する。
-N 名前のみを表示する。 プログラム補完を持つシェルで役立つ。
-q 値のセットを標準出力に表示しない。
-w 変数=パラメータ sysctlの設定を変更する場合には、このオプションを指定する。
-p 指定されたファイルから読み込んだ内容をsysctl設定にロードする (ファイル指定がなければ /etc/sysctl.conf から)。
-a 現在利用できる全ての値を表示する。
-A 現在利用できる全ての値を表形式で表示する。

ちなみに利用できるカーネルパラメータは757個あります。

# uname -r
2.6.32-573.7.1.el6.x86_64
$ sudo sysctl -a | wc -l
757

2. 主なチューニングパラメータ
チューニングパラメータの例は以下になります。主にNginxを使うWebサービスを想定しています。
*2016/1/17(日)追記: パラメータを追加しました

パラメータ 説明
fs.file-max = 99002 ファイルディスクリプタの最大数。外部からのアクセスが多い場合には多く設定しておかないとアクセス遅延などの問題が発生する。
vm.swappiness = 1 メモリのスワップの度合い。値が高いほどスワップの頻度が高くなる。
net.ipv4.ip_local_port_range = 10000 61000 サーバ内部で使用するポート番号の範囲。リバースプロキシなどで使用している場合には、1024から65535とする。
net.core.rmem_max = 16777216 TCPの受信バッファサイズの最大値。
net.core.wmem_max = 16777216 TCPの送信バッファサイズの最大値。
net.core.rmem_default = 16777216 TCPの受信バッファサイズのデフォルト値。
net.core.wmem_default = 16777216 TCPの送信バッファサイズのデフォルト値。
net.core.optmem_max = 40960 補助バッファサイズの最大値。
net.ipv4.tcp_rmem = 4096 87380 16777216 TCPの受信バッファサイズ。左から最小値、デフォルト値、最大値。
net.ipv4.tcp_wmem = 4096 65536 16777216 TCPの送信バッファサイズ。左から最小値、デフォルト値、最大値。
net.core.netdev_max_backlog = 50000 パケット受信時にキューにつなぐことのできるパケットの最大数。
net.ipv4.tcp_max_syn_backlog = 30000 SYNに対するSYN/ACKの応答待ちに使うソケットの最大数。
net.ipv4.tcp_max_tw_buckets = 2000000 TIME_WAIT 状態にあるソケットの最大数。
net.ipv4.tcp_tw_reuse = 1 TCPのTIME_WAITを再利用するかどうか。TIME_WAITはソケットオープン状態であるため、多数残存するとパフォーマンスに大きな影響が出る。
net.ipv4.tcp_tw_recycle = 1 TCPのTIME_WAITの再利用を高速化するかどうか。*1
net.ipv4.tcp_fin_timeout = 10 TCPのFINを送信してからのタイムアウト時間。
net.ipv4.tcp_slow_start_after_idle = 0 通信がアイドル状態になった後にスロースタート(*2)させるかどうか。
net.ipv4.udp_rmem_min = 8192 UDPの受信バッファサイズの最小値。
net.ipv4.udp_wmem_min = 8192 UDPの送信バッファサイズの最小値。
net.ipv4.conf.all.send_redirects = 0 全てのインターフェイスで全てのIPv4 ICMPリダイレクトパケットを送信させるかどうか。
net.ipv4.conf.all.accept_redirects = 0 全てのインターフェイスで全てのIPv4 ICMPリダイレクトパケットを受信させるかどうか。
net.ipv4.conf.all.accept_source_route = 0 ソースルーティング(*3)オプションが付加されたパケットを許可するかどうか。
net.ipv4.conf.all.log_martians = 1 偽装、不正パケットのリダイレクトをログに記録するかどうか。

*1: net.ipv4.tcp_tw_recycleはトラブルの原因になるので使い方には注意してください。
「net.ipv4.tcp_tw_recycle」を有効にするのは(場合によっては)やめた方がいい - pullphone's blog
*2: TCPでコネクションを確立した後、データの送信量を徐々に増やすことで効率的に通信するための仕組み。
*3: ネットワーク通信において、データの送信者が送信先のみでなく中継地点も指定する経路制御の方式。

3. パラメータのデフォルト値の調べ方
*2016/1/17(日)追記: 新たに項目として追加しました

パッケージのkernel-docをインストールします。

$ sudo yum install kernel-doc

インストール先は/usr/share/doc以下になります。*フォルダ名はkernel-doc-2.6.32

次にデフォルト値を調べたいカーネルパラメータ名で文字列(grep)検索をします。

例. net.ipv4.tcp_slow_start_after_idleの場合

$ cd /usr/share/doc/kernel-doc-2.6.32
$ grep -rnw 'Documentation' -e "tcp_slow_start_after_idle"
Documentation/networking/ip-sysctl.txt:412:tcp_slow_start_after_idle - BOOLEAN
$vi Documentation/networking/ip-sysctl.txt

------------------------------------------------------------------------
412 tcp_slow_start_after_idle - BOOLEAN
413         If set, provide RFC2861 behavior and time out the congestion
414         window after an idle period.  An idle period is defined at
415         the current RTO.  If unset, the congestion window will not
416         be timed out after an idle period.
417         Default: 1
------------------------------------------------------------------------

面倒な方法ですが、よければ参考にしてください。

• 補足 - TCPの状態遷移について

f:id:eno0514:20150622013508g:plain
参照: 基礎から学ぶWindowsネットワーク:第16回 信頼性のある通信を実現するTCPプロトコル(3) (3/4) - @IT

■CLOSED 
図の一番上(と一番下)にあるCLOSEDは、netstatでは表示されない。未使用もしくは使用済みのTCB(Transmission Control Block。TCPの各接続の内部状態を保存しているデータ構造)がこれに該当する。

■LISTEN 
パッシブ・オープンで、待ち受け状態(リッスン状態)になっていることを表す。アクティブ・オープンのSYNを受けて「SYN_RECEIVED」へ遷移する。

■SYN_RECEIVED 
アクティブ・オープンのSYNに対してACKとSYNで応答し、それに対するACKを待っている状態。ACKを受信すると「ESTABLISHED」へ遷移する。

■SYN_SENT 
アクティブ・オープンで、SYNを送信した状態。SYNとACKを受信すれば、ACKを送信して「ESTABLISHED」へ遷移する。

■ESTABLISHED 
TCP接続が確立した状態。データの送受信を行うことができる。FINを受けたり、上位アプリケーションからクローズが呼び出されたりすると、クローズ処理へ遷移する。

■FIN_WAIT_1 
アクティブ・クローズの最初の段階。FINを送信して、それに対する応答を待っている状態。

■FIN_WAIT_2 
送信したFINに対するACKを受け取った状態。送信側のクローズ処理が終了し、相手からのFINを受信するのを待っている状態。

■CLOSING 
アクティブ・クローズでFINを送信した後、ACKが戻ってくるよりも先に、相手からもFINを受けた状態。両方でほぼ同時にアクティブ・クローズ処理を開始するとこの状態になる。送信したFINのACKを待って、「TIME_WAIT」へ遷移する。

■TIME_WAIT 
「CLOSING」でACKを受けた状態。アクティブ・クローズ後のタイムアウト待ち状態。同じシーケンス番号やポート番号などを再利用しないように、しばらく待ってから(ネットワーク上で遅れていたパケットがこの時間内に到着する可能性があるので、それと衝突しないように待つ)、「CLOSED」へ遷移して終了する。
※TIME_WAITでは、ソケットがクローズしない。つまり、システム的にはセッションが保持されたままになる。

■CLOSE_WAIT 
パッシブ・クローズの状態。送信側にFINを送信して「LAST_ACK」へ遷移する。

■LAST_ACK 
「CLOSE_WAIT」で送信したFINに対するACKを待つ状態。ACKの受信後、「CLOSED」へ遷移する。

以上になります。

参考:
覚えておきたいカーネルパラメータの変更方法 - Qiita
@IT:/procによるLinuxチューニング [前編](1/2)
Blog Alpha Networking: kernelチューニング
TCPの状態遷移 - Qiita