Linux ファイル・ディスクリプタ制限のチューニング
3月 16, 2022AmazonLinux_CentOS,OperatingSystem
概要
- Linux オペレーティング・システムでは、ファイル・ディスクリプタという仕組みが使われます。ファイル・ディスクリプタによって、標準入出力やブロックデバイス、ソケットなどが擬似ファイルとして処理されます。ファイル・ディスクリプタは、プロセス毎に管理され、
/proc/プロセス番号/fd/
に保持されます。 - ソケットとは、ネットワーク通信で用いられるファイル・ディスクリプタです。ネットワーク通信では、コネクション毎にファイル・ディスクリプタが作成されます。クライアントからの同時接続が多いシステムの場合、ファイル・ディスクリプタも多く必要になります。
- このファイル・ディスクリプタは、同時にオープンできる数が制限されています。Webサーバーで’Too many open files’ のエラー等に遭遇して、ファイル・ディスクリプタ制限のチューニングが必要な状況を想定しています。また、ファイル・ディスクリプタのチューニングは、目的によって方法が異なるため難解です。本記事では、ポイントを整理して、現在オープンされているファイル・ディスクリプタの数を調査する方法、現在の制限を確認する方法、制限を変更する方法を紹介します。
現在オープンされているファイル・ディスクリプタの数を調査する
- 現在オープンされているファイル・ディスクリプタの数を調査するには、/proc/プロセス番号/fd/ 配下を調べる方法と、lsof コマンドを使用する方法があります。
- httpdをモチーフとしています。先ず、プロセス番号を調べ、次に/proc/プロセス番号/fd/ 配下の数をカウントします。
$ ps -ef | grep httpd
root 3263 1 0 09:47 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 3264 3263 0 09:47 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 3265 3263 0 09:47 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 3267 3263 0 09:47 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 3268 3263 0 09:47 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 3269 3263 0 09:47 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
ec2-user 4160 4119 0 11:53 pts/1 00:00:00 grep --color=auto httpd
$ sudo ls -l /proc/3263/fd | wc -l
14
$ sudo ls -l /proc/3263/fd
total 0
lr-x------ 1 root root 64 Mar 15 09:47 0 -> /dev/null
lrwx------ 1 root root 64 Mar 15 09:47 1 -> socket:[20667]
l-wx------ 1 root root 64 Mar 15 09:47 10 -> /var/log/httpd/access_log
l-wx------ 1 root root 64 Mar 15 09:47 11 -> /var/log/httpd/ssl_access_log
l-wx------ 1 root root 64 Mar 15 09:47 12 -> /var/log/httpd/ssl_request_log
l-wx------ 1 root root 64 Mar 15 09:47 2 -> /var/log/httpd/error_log
lrwx------ 1 root root 64 Mar 15 09:47 3 -> socket:[20683]
lrwx------ 1 root root 64 Mar 15 09:47 4 -> socket:[20684]
lrwx------ 1 root root 64 Mar 15 09:47 5 -> socket:[20693]
lrwx------ 1 root root 64 Mar 15 09:47 6 -> socket:[20694]
lr-x------ 1 root root 64 Mar 15 09:47 7 -> pipe:[20739]
l-wx------ 1 root root 64 Mar 15 09:47 8 -> pipe:[20739]
l-wx------ 1 root root 64 Mar 15 09:47 9 -> /var/log/httpd/ssl_error_log
- あるいは、lsof コマンドで同様の結果が得られます。lsof コマンド出力結果の FDカラムが数字から始まる行をカウントします。数字+r はread-onlyで開いているファイル、数字+w はwrite-onlyで開いているファイル、数字+u はread/writeで開いてるファイルを表します。FDが数字以外(cwd|rtd|txt|mem|DEL)を除外することで、カウントできます。
$ sudo lsof -c httpd | egrep -v "cwd|rtd|txt|mem|DEL"
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 3263 root 0r CHR 1,3 0t0 6758 /dev/null
httpd 3263 root 1u unix 0xffff88801cacf000 0t0 20667 socket
httpd 3263 root 2w REG 202,1 2841 8746116 /var/log/httpd/error_log
httpd 3263 root 3u sock 0,8 0t0 20683 protocol: TCP
httpd 3263 root 4u IPv6 20684 0t0 TCP *:http (LISTEN)
httpd 3263 root 5u sock 0,8 0t0 20693 protocol: TCP
httpd 3263 root 6u IPv6 20694 0t0 TCP *:https (LISTEN)
httpd 3263 root 7r FIFO 0,11 0t0 20739 pipe
httpd 3263 root 8w FIFO 0,11 0t0 20739 pipe
httpd 3263 root 9w REG 202,1 905 8746118 /var/log/httpd/ssl_error_log
httpd 3263 root 10w REG 202,1 0 8747163 /var/log/httpd/access_log
httpd 3263 root 11w REG 202,1 0 8744739 /var/log/httpd/ssl_access_log
httpd 3263 root 12w REG 202,1 0 8744749 /var/log/httpd/ssl_request_log
httpd 3264 apache 0r CHR 1,3 0t0 6758 /dev/null
httpd 3264 apache 1u unix 0xffff88801cacf000 0t0 20667 socket
httpd 3264 apache 2w REG 202,1 2841 8746116 /var/log/httpd/error_log
httpd 3264 apache 3u sock 0,8 0t0 20683 protocol: TCP
httpd 3264 apache 4u unix 0xffff88801c508000 0t0 20753 /run/httpd/cgisock.3263
httpd 3264 apache 5u sock 0,8 0t0 20693 protocol: TCP
httpd 3264 apache 7r FIFO 0,11 0t0 20739 pipe
httpd 3264 apache 8w FIFO 0,11 0t0 20739 pipe
httpd 3264 apache 9w REG 202,1 905 8746118 /var/log/httpd/ssl_error_log
httpd 3264 apache 10w REG 202,1 0 8747163 /var/log/httpd/access_log
httpd 3264 apache 11w REG 202,1 0 8744739 /var/log/httpd/ssl_access_log
httpd 3264 apache 12w REG 202,1 0 8744749 /var/log/httpd/ssl_request_log
** 省略 **
- httpd全体で使用しているファイル・ディスクリプタの数をカウントします。他に動作する主要なサービスがなく、現在オープンの数が後述するファイル・ディスクリプタの制限より十分に小さければ、チューニングは不要ですね。
$ sudo lsof -c httpd | egrep -v "cwd|rtd|txt|mem|DEL" | grep -v COMMAND | wc -l
85
現在のファイル・ディスクリプタの制限を確認する
OS 全体のファイル・ディスクリプタの制限確認
- 先ず、現在のOSが利用できるファイル・ディスクリプタの制限を確認します。次のコマンドを実行します。
$ cat /proc/sys/fs/file-max
46423
あるいは
$ sudo sysctl -a | grep file-max
fs.file-max = 46423
プロセスのファイル・ディスクリプタの制限確認
- 次に、現在のユーザーが利用できるファイル・ディスクリプタ数の制限を確認します。次のコマンドを実行します。-S はSoftLimit、-H はHardLimit です。
$ ulimit -Sn
65535
$ ulimit -Hn
65535
ファイル・ディスクリプタの制限を変更する
OS 全体のファイル・ディスクリプタの制限変更 (/etc/sysctl.conf)
- ファイル・ディスクリプタの制限を変更します。システムが動作する合理的な数に増やします。
- 先ず、OSが利用できるファイル・ディスクリプタの制限を変更します。次のコマンドを実行します。
- 次の行を/etc/sysctl.confファイルに追記します。valueは、設定する制限です。
- fs.file-max = value
- 次のコマンドを実行して、変更を適用します。
- /sbin/sysctl -p
- 次の行を/etc/sysctl.confファイルに追記します。valueは、設定する制限です。
$ cat /proc/sys/fs/file-max
46423
$ sudo su -
# vi /etc/sysctl.conf
-----
fs.file-max = 65535 <-- 追記
-----
# logout
$ cat /etc/sysctl.conf
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
fs.file-max = 65535
$ sudo /sbin/sysctl -p
fs.file-max = 65535
$ cat /proc/sys/fs/file-max
65535
プロセスのファイル・ディスクリプタの制限変更 (/etc/security/limits.conf)
- 次に、個々のプロセスが利用できるファイル・ディスクリプタの制限を変更します。-S はSoftLimit、-H はHardLimit であり、SoftLimitはHardLimit以下の範囲で一般ユーザが変更可能、HardLimitはrootのみ変更可能です。
- なお、ulimit は実行したシェルおよびそのシェルから起動された子プロセスに対して、一時的に設定が変更されます。
$ ulimit -Sn 32768
$ ulimit -Hn 32768
$ ulimit -Sn
32768
$ ulimit -Hn
32768
- ユーザーの制限を恒久的に設定する場合、/etc/security/limits.conf に制限値を記入します。ユーザー名と制限を指定します。特に再起動は必要なく、次回ログインしたユーザーは、変更後の設定が反映されます。
$ sudo vi /etc/security/limits.conf
ec2-user soft nofile 32768 <== 追記
ec2-user hard nofile 32768 <== 追記
# End of file
プロセス(デーモン)のファイル・ディスクリプタの制限変更 (systemd)
- ユーザーが起動するプロセスではなく、デーモンの制限を恒久的に設定する場合、
/etc/security/limits.conf
では効果がありません。サービスやOS再起動時に設定が保持されません。 - systemd にdrop-in のユニット構成ファイル (
/etc/systemd/system/[サービス名].d/limits.conf
) を作成し、追加の制限を定義します。これは、drpo-in という仕組みで、メインのユニット構成ファイルのパラメータを上書きすることができます。 - デーモンに現在設定されている制限を確認するには、
/proc/プロセス番号/limits
にて確認可能です。
** 変更前 **
$ ps -ef | grep httpd
root 2789 1 0 02:38 ? 00:00:01 /usr/sbin/httpd -DFOREGROUND
apache 2823 2789 0 02:38 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 2824 2789 0 02:38 ? 00:00:04 /usr/sbin/httpd -DFOREGROUND
apache 2827 2789 0 02:38 ? 00:00:04 /usr/sbin/httpd -DFOREGROUND
apache 2828 2789 0 02:38 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 2829 2789 0 02:38 ? 00:00:04 /usr/sbin/httpd -DFOREGROUND
ec2-user 5874 5847 0 12:21 pts/0 00:00:00 grep --color=auto httpd
$ cat /proc/2789/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 10485760 10485760 bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes unlimited unlimited processes
Max open files 65535 65535 files
Max locked memory unlimited unlimited bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 30446 30446 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
- systemd にdrop-in のユニット構成ファイルを作成し、設定の再読み込みおよびサービスのrestartを行います。
- サービス再起動後に、
systemctl status httpd.service
の出力結果に、Drop-In として追加したユニット構成ファイルが表示されています。
$ systemctl status httpd.service
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2022-03-16 02:38:59 UTC; 9h ago
Docs: man:httpd.service(8)
Main PID: 2789 (httpd)
Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec: 0 B/sec"
CGroup: /system.slice/httpd.service
tq2789 /usr/sbin/httpd -DFOREGROUND
tq2823 /usr/sbin/httpd -DFOREGROUND
tq2824 /usr/sbin/httpd -DFOREGROUND
tq2827 /usr/sbin/httpd -DFOREGROUND
tq2828 /usr/sbin/httpd -DFOREGROUND
mq2829 /usr/sbin/httpd -DFOREGROUND
Mar 16 02:38:59 hostname systemd[1]: Starting The Apache HTTP Se....
Mar 16 02:38:59 hostname httpd[2789]: AH00558: httpd: Could not r...
Mar 16 02:38:59 hostname systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.
$ sudo mkdir -p /etc/systemd/system/httpd.service.d
$ sudo vi /etc/systemd/system/httpd.service.d/00-limits.conf
$ cat /etc/systemd/system/httpd.service.d/00-limits.conf
[Service]
LimitNOFILE=32768:32768
$ sudo systemctl daemon-reload
$ sudo systemctl restart httpd.service
$ systemctl status httpd.service
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/httpd.service.d
mq00-limits.conf
Active: active (running) since Wed 2022-03-16 12:28:00 UTC; 1min 39s ago
Docs: man:httpd.service(8)
Main PID: 5970 (httpd)
Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec: 0 B/sec"
CGroup: /system.slice/httpd.service
tq5970 /usr/sbin/httpd -DFOREGROUND
tq5971 /usr/sbin/httpd -DFOREGROUND
tq5972 /usr/sbin/httpd -DFOREGROUND
tq5974 /usr/sbin/httpd -DFOREGROUND
tq5975 /usr/sbin/httpd -DFOREGROUND
mq5976 /usr/sbin/httpd -DFOREGROUND
Mar 16 12:28:00 hostname systemd[1]: Stopped The Apache HTTP Server.
Mar 16 12:28:00 hostname systemd[1]: Starting The Apache HTTP Se....
Mar 16 12:28:00 hostname httpd[5970]: AH00558: httpd: Could not r...
Mar 16 12:28:00 hostname systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.
- 以下の通り、Max open files の制限が変更されました。
** 変更後 **
$ ps -ef | grep httpd
root 5970 1 0 12:28 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5971 5970 0 12:28 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5972 5970 0 12:28 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5974 5970 0 12:28 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5975 5970 0 12:28 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5976 5970 0 12:28 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
ec2-user 6329 5847 0 12:30 pts/0 00:00:00 grep --color=auto httpd
$ cat /proc/5970/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 10485760 10485760 bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes unlimited unlimited processes
Max open files 32768 32768 files
Max locked memory unlimited unlimited bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 30446 30446 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
参考資料
AmazonLinux_CentOS,OperatingSystem
Posted by takaaki