タイトルのままです。
概要
もうタイトルで伝えたいことは書ききったのですが、せっかくなので経緯を述べておきます。
AWS FargateでNginxとLaravelコンテナをデプロイしていました。
以前、パフォーマンスチューニングでNginxのconfigファイルの設定について、こちらの記事を参考にゴニョゴニョしていたのですが、それからしばらくたった後、あることに気づきました。以下はfargateにNginxコンテナをデプロイした直後のコンテナログです。
[alert] 29#29: setrlimit(RLIMIT_NOFILE, 180000) failed (1: Operation not permitted)
なんとworker_rlimit_nofile
の設定が失敗している!?
原因追求したところ、どうやら上で設定している180000
という数字がよくなかったようです。
原因
Fargateにコンテナをデプロイするには、「タスク定義」を設定する必要がありますが、このタスク定義で設定していたulimits
値を超えていたことが原因でした。
"containerDefinitions": [
{
"ulimits": [
{
"name": "nofile",
"softLimit": 65536,
"hardLimit": 65536
}
],
}
ここでulimits値をソフト/ハード共に65536
に設定しているので、worker_rlimit_nofileの値は**"65536以下"**にする必要があるようです。
nginx.confファイルを再設定後、無事にこのエラーは解消されました。
#worker_rlimit_nofile 180000; コメントアウト
worker_rlimit_nofile 65536;
events {
#worker_rlimit_nofileの値を3で割った数
worker_connections 21800;
}
このworker_rlimit_nofileの値は、woeker_processes
の数によって変わるので注意が必要です。
今回のコンテナはCPUが1個でprocess数も1つの想定だったので、ulimit値とイコールにしています。
ちなみになぜ当初worker_rlimit_nofile値を180000
にしていたのかについてですが、fargateコンテナでcat /proc/sys/fs/file-max
コマンドを叩き、「OSのファイルディスクリプタの最大数」として表示された数375274
の2で割った数を設定していたからでした。
Fargateではその考え方は通用せず、タスク定義のulimits値=「1プロセスのファイルディスクリプタの最大数」が優先される、ということですね。
ちなみにFargateコンテナ上でulimit -Sn
(ソフトulimitを確認するコマンド)を叩いたところ、確かに65536
となっていました。
簡単にファイルディスクリプタ関連の用語についてまとめますと
用語 | 意味 |
---|---|
ファイルディスクリプタ | OS上でファイルに振られる番号で、ファイルを識別するための目印 |
OSで扱えるファイルディスクリプタ上限 | OSで開くことのできる最大ファイル数。cat /proc/sys/fs/file-max で確認可能 |
ソフトulimit | 1プロセスあたり使用できるファイルディスクリプタの上限。一般ユーザーも設定可能(ただしハードulimitの数値以下まで)。ulimit -Sn で確認可能 |
ハードulimit | 1プロセスあたり使用できるファイルディスクリプタの上限。rootユーザーのみ設定可能。ulimit -Hn で確認可能。 |
worker_rlimit_nofile | Nginxで設定するパラメータ。1workerあたりで開ける最大ファイル数を設定する。 |
ちなみに余談ですがFargateではタスク定義でulimit値を設定してやらないとデフォルトで以下の値に設定されますので気をつけましょうね。
ソフトulimt | 1024 |
ハードulimt | 4096 |
感想
やはりFargateは奥深い・・・。