疑难杂症篇之 ulimit

4. 某些 Systemd 版本会导致 max open file 在设置为 infinity 时只有 65536

有一次,在一台 Debian8 的机器上,发现了这样一个问题,在 Systemd 下面,设置了 DefaultLimitNOFILE = infinity , 但 1 号进程及其它子进程 max open file 只有 65536,而非预期的等于 fs.nr_open 默认值 1048576 。最后排查出原因,其实是 Systemd 的一个 bug(https://github.com/systemd/systemd/commit/6385cb31ef443be3e0d6da5ea62a267a49174688)

解决方案就是直接定义明确的 DefaultLimitNOFILE 值或是升级到 Systemd 新版本。

5. 不同 PAM 版本会有不同的默认 limit 值处理逻辑

去年我们线上的容器业务 (胖容器),也遇到 ulimit 相关的故障。业务从 Debian8 容器升级到 Debian9 容器后,发现 soft nofile limit 值不正确导致了问题。表现为在容器中 su 后,Debian9 容器出现了未优化的 soft nofile limit 值,Debian8 容器则可以正常地应用到宿主的 soft nofile limit 值。排查发现,我们所使用的容器镜像并没有打包 /etc/security/limits.conf 文件(官方镜像也没有)。在没有配置 /etc/security/limits.conf 文件的情况下,Debian8 下的 PAM 版本,会直接使用容器的 1 号进程的 soft nofile limit 值;而 Debian 9 的 PAM 版本,则会使用 FD_SETSIZE 宏定义中的值,相当于在编译阶段就确定好的默认值,默认为 1024。

解决方案很简单,就是打包上正确的 /etc/security/limits.conf 文件,即使 Debian8 也打包上,方便统一管理。

相关变更及 bug:

  • https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=783105

  • https://metadata.ftp-master.debian.org/changelogs//main/p/pam/pam_1.3.1-5_changelog

排查要点

每个进程的 limit 初始值来源,要么来自它的父进程,要么是来自 PAM,其中 PAM 的优先级更高,只要抓住这两点,问题都不复杂。