Unyablog.

のにれんのブログ

systemd 240 と Java の OOM

ArchLinux 上で Debian stretch を systemd-nspawn で立ち上げているのだが、最近 pacman -Syu したら Debian のコンテナで Java が立ち上がらなくなった。

原因

だいたいここに書いてある。

  1. systemd 240 で RLIMIT_NOFILE が大きくなった
  2. Debian の PAM では、RLIMIT_NOFILE (hard nofile)を PID 1 からコピーしている
  3. なので、ログインセッションなどでも RLIMIT_NOFILE が大きくなった
  4. ところで、Java は起動時に RLIMIT_NOFILE 分の配列を作成する
  5. このような環境だと RLIMIT_NOFILE が大きすぎるので OOM で落ちる

というもの。

Debian sid も systemd 241 なのに落ちなくてなぜだろうなと思ったら、そもそも hard nofile limit がそんなに大きくなかった。

大きくならないように、ビルド時にフラグをつけるようにしたらしい。

Arch で ulimit -H -s するとめちゃくちゃ大きかったので、特に触ってないのでしょう*1

どうするか

/etc/security/limits.conf.d に hard nofile をそれなりの値に戻すような config を置く。

今回は /etc/init.d/hogehoge なスクリプトを立ち上げるだけなので大丈夫だが、 ssh でのセッションとかでも対処するなら UsePrivilegeSeparation あたりを変えないといけないらしい(未検証)。

おまけ

この事象は systemd が立ち上げるプロセスには関係せず、pam_limits.so を経由するものに関係がある。

今回、 Elasticsearch では動いたのに Jenkins で動かなかったのは何故だろうと調べていたら、Jenkins は今も /etc/init.d/jenkins なので su 経由で起動し、PAM の影響を受けるということだった。

こういうところで違いが出るんだなあ。

*1:Arch は PAM で PID 1 をコピーしてないので(未確認)、そのような問題は起きないのだと思う(未確認)。今回は systemd-nspawn で Debian を立ち上げたために起こった。