生效 设置ulimit_管理好你的资源,ulimit 疑难杂症详解

0ab4d9b4e1b016d7564dd86a5333d753.gif

43c04613fc9ad7ae8ad858033ea22260.png

本文转自公众号网易游戏运维平台。

网易游戏运维专家, 10 年运维老司机, 负责网易游戏私有云平台的运维工作, 专注于运维技术能力的深入打磨, 专治运维界各类疑难杂症, 拥有强大的故障分析能力及丰富的故障解决经验。 多年来,我们陆续有业务遇到 ulimit 的各类衍生问题,无论是在 SysVinit 时代,还是 Systemd 时代,甚至在容器环境中,虽然表现不同,但根本原因还是 ulimit 问题。本文会讲下我们因 ulimit 设置遇到的各种问题,并给大家深入浅出的点透 ulimit 这一知识点,愿大家新年不踩旧坑,线上无病无灾。

SysVinit 下的 ulimit 如何生效

早年在 SysVinit 年代,我们就明白 ulimit 需要特别设置才能避免踩坑,使用的是如下的方法来设置 SysVinit 下 1 号进程的子进程的 limit。

b2af54f9bddc4c383ff15d91574be022.png

该配置文件只适用于 SysVinit,并且需要重启生效 它调整的 不是 1 号进程本身的 limit, 而是会改变 1 号进程执行 /etc/inittab 时 fork 出来的子进程的 limit,比如说 sshd 的 limit, 我们可以通过以下方法来验证调整是否生效。

5e31d301ec0e39bd84e3327f24e44bc3.png

Systemd 下的 ulimit 如何生效

后来 Systemd 开始流行了,Debian 也开始切换到 Systemd。而 Systemd 的 limit 就不在 /etc/initscript 文件中定义了,它是在 /etc/systemd/system.conf 配置中。

41fa631a7e1dad6d0cbd3fc46d54b2e0.png

  • 该配置需要重启生效

  • 与 SysVinit 不同,Systemd 这个配置会影响 1 号进程本身的 limit,所以可以直接检查 /proc/1/limits 来判断是否配置正确。

疑难杂症

1.只有 /etc/initscript 是不够的,很多应用会使用 PAM (/etc/security/limits.conf)

大约在 2010 年的时候,我们线上遇到一起故障,就是用户的 crontab 中启动的任务,遇到了 max open file 不足的故障,排查下来,我们发现 cron 会使用了 PAM 模块,它会读取 /etc/security/limits.conf 中的设置来覆盖原本的 limit 值,这部分引用定义在 /etc/pam.d/cron 中。

22c274220931a8286946ebb1b22ced16.png

解决方案很简单,就是在 /etc/security/limits.conf 中定义相关的 limit 值。

7fb183c57b0aaecb50d1cecfb7d84736.png

使用 PAM 的应用很多,比如 susudocronloginsshd 等,sshd 的情况比较特别,它的 UsePAM 参数默认值为 no。

2.在 Debian 系统中,/etc/security/limits.conf 中的 * 号通配并不匹配 root 用户

在后续的工作中,我们遇到一起比较特别的故障,背景是有台机器 sshd 应用故障了,机房同事通过 console 登录机器重启  sshd,而后续我们通过 ssh 登录来启动的应用都是非优化后的 limit 值。

排查出来的原因是 Debian 系统中,/etc/security/limits.conf 中的 * 号通配并不匹配 root 用户,机房同事通过 console 口登录 root 用户,会导致登录后的会话是默认的 limit 值,以该会话来重启 sshd 使得 sshd 继承了该会话有问题的 limit 值,进而影响后续从 ssh 登录来启动的应用,我们的游戏业务,多数以这种模式来跑起来的。

那么为什么说它特别,除了故障本身是一环扣一环,还因为 *号通配并不匹配 root 用户的行为,是 Debian 系列特有的,我们测试了 Centos 并看了 Centos 的文档,* 号是可以匹配 root 用户,但在 Debian 系统的 manpage 中,就有这么特别的一句。

6b0e2fc8a96156b9359797711633fb28.png

最终我们修正后的 /etc/security/limits.conf 配置如下

53388e37825dbc485bdf18074629489b.png

TIPS:看文档一定要看官方文档,别人的文章、其它发行版的文档,不一定是能适用的。

3.某些 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 新版本。

4.不同 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 的优先级更高,只要抓住这两点,问题都不复杂。

5adf3ceea7c09f62c6241af9fde2e358.png

常见问题

1.如何确认一个应用有没有使用了 PAM

可以查一下 /etc/pam.d/ 下面的文件,有没有对应的应用配置

29585ba45a14a8563861e11d5385efd7.png

2.如何确认当前系统是 SysVinit 还是 Systemd

查一下 /sbin/init 的信息,可以确认出来

  • SysVinit:

ca2e2cbf8afe490e6721880e2fc7aec7.png

  • Systemd:

17dde152370e6ffd3503f88ed6228274.png

  • Upstart:  

4862410a8a7414b878270648ba9518c1.png

3.如何在线修改一个进程的 limit 值

例如当我们发现 sshd 的 max open file 配置有问题,但我们又不想重启该服务,可以使用 prlimit 命令来在线调整

#当前 & nbsp;ssh  登录后的 & nbsp;max open file  异常
igi@mbp:~$ ssh myhost
igi@hostname:~$ ulimit -n -S
1024
igi@hostname:~$ ulimit -n -H
1024
igi@hostname:~$ grep 'Max open files' /proc/`pgrep -f '/usr/sbin/sshd'`/limits
Max open files 1024 1024 files
#在线调整 & nbsp;max open file
root@hostname:~# pgrep -f '/usr/sbin/sshd'
523
root@hostname:~# prlimit --pid=523 --nofile=1000000
#重新登录检查
igi@mbp:~$ ssh myhost
igi@hostname:~$ ulimit -n -S
1000000
igi@hostname:~$ ulimit -n -H
1000000
igi@hostname:~$ su
Password:
root@hostname:~# pgrep -f '/usr/sbin/sshd'
523
root@hostname:~# prlimit --pid=523 | grep NOFILE
NOFILE max number of open files 1000000 1000000

结束语

万变不离其宗,ulimit 的问题虽然有各种表现形式,只要掌握其关键点,就再也不是疑难问题。

每个进程的 limit 初始值来源,要么来自它的父进程,要么是来自 PAM,其中 PAM 的优先级更高。

2020 DevOps 线上峰会来袭~ 

d7eb8544271cfc0061c57bdc1ebf4e1f.png

近期好文:

重磅!《2020年中国 DevOps 现状调查》全面启动!

前百度资深专家:成功实践 DevOps,全靠这 5 个关键因素

国内首款 Serverless 数据库诞生!BOSS 直聘崩了!GitHub完全免费开放!| 一周IT资讯

“高效运维”公众号诚邀广大技术人员投稿, 投稿邮箱:jiachen@greatops.net,或添加联系人微信:greatops1118. 点击 ,立即报名 2020 DevOps 线上峰会,联系图片中小伙伴,可以享受  折优惠,先到先得哟~ 62048de4a07f981cba1689ed8ba6f9df.png点个“在看”,一年不宕机
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值