docker 容器 ulimit 参数设置

综合编程 ん乖乖龙ん (源链)

这几天发现部署的一个 WebSocket 应用容器很不稳定,WebSocket 连接老是会无缘无故的批量掉线。跟踪了一下 haproxy 路由转发容器的日志,发现以下报错:

[WARNING] 311/072614 (22534) : [haproxy.main()] Cannot raise FD limit to 131116, limit is 65536.

带着这个错误信息,找到了以下帖子:

linux 最大文件描述符 fd

使用四种框架分别实现百万 websocket 常连接的服务器

这里详细地描述了如何通过调优实现 WebSocket 的百万连接,而我的应用不过几千的连接,服务器的配置也差不太多,理论上应该是完全不会有问题发生的,现在有问题肯定就是没有调优造成的。

需要解决的问题是:作者是在物理机上直接进行的调优,那么在容器里面该如何做呢?

当时的第一反应就是 docker exec 进入容器直接进行参数调整,发现会报错:

ulimit: open files: cannot modify limit: Operation not permitted

原因是:docker 容器默认移除 sys_resource(Linux 能力),因而 ulimit -n 设置只能改小无法改大,改大会报错。

详情见: 深入理解docker ulimit

那应该怎么办呢,经过对资料的一番思考与尝试(艰辛的过程就不多说了),终于找到了解决办法:

一、调整宿主机的 ulimit

# 查看文件最大的打开数
$ cat /proc/sys/fs/file-max

# 如果数值较小,则需要调大,这里我是调整为 100W

# 临时设置
$ echo 1000000 > /proc/sys/fs/file-max

# 永久设置
$ echo "fs.file-max = 1000000" >> /etc/sysctl.conf
$ echo "fs.nr_open = 1000000" >> /etc/sysctl.conf

# 修改文件,将最后 4 行的 65535 改为 1000000
$ vi /etc/security/limits.conf 

# 改成大于 1000000,这里我设置为 2000000
$ echo 2000000 > /proc/sys/fs/nr_open

# 查看当前系统使用的打开文件描述符数
$ cat /proc/sys/fs/file-nr

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 63470
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1000000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 63470
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

二、调整系统容器的 ulimit

由于应用请求需要走 haproxy 路由转发容器,这个是某云的系统容器,因此需要走特别的途径进行修改(这也算是某云的一个 Bug 吧),解决的方式也很变态,因为这个容器是使用 docker-compose 编排文件发布的,因此需要改写 docker-compose 编排文件。这里需要使用谷歌浏览器的开发工具,从前端找到对应的隐藏的系统按钮,去掉 ng-hide
属性,将按钮显示出来,就可以修改编排文件了。追加以下 yaml 文件内容即可:

ulimits:
  nofile:
    soft: 1000000
    hard: 1000000
privileged: true

系统容器重启后,使用以下命令查看系统容器的进程 ID 还会不会变化(变化说明容器挂掉重启了):

docker exec -ti  ps aux

这步看不懂的请跳过即可。

三、调整应用容器的 ulimit

应用容器我也是使用 docker-compose 编排文件启动的,而且完全受我控制,这就比较简单了,一样的处理方式,追加以下 yaml 文件内容即可:

ulimits:
  nofile:
    soft: 1000000
    hard: 1000000
privileged: true

总结

调整完成后,重启相应的容器,并进入容器用 ulimit -a
可以查看到文件打开数限制已经生效,haproxy 路由转发容器不再频繁挂掉重启,而 WebSocket 应用容器也变得稳定起来了。

经过这次的问题处理过程,我们应该对 docker 的 ulimit 重视起来,在一些复杂的应用场景下,需要将容器就看作是物理机,来考虑调优的事宜。

这一点是我们使用容器后容易忽略的事情,希望能给大家在上生产前一些警示。

参考资料

linux 最大文件描述符 fd

使用四种框架分别实现百万 websocket 常连接的服务器

深入理解docker ulimit

转载请注明出处,本文采用 CC4.0
协议授权,版权归 ん乖乖龙ん
所有。

您可能感兴趣的

How Docker container DNS works Learn about Docker DNS. How docker container DNS works? How to change nameserver in Docker container to use external DNS? Docker DNS ...
Docker环境的CI/CD Docker的最大好处之一是能够带来无缝的CI/CD流程;容器是Docker镜像的运行着的只读实例,更新容器仅仅需要更新镜像文件,然后从这个更新过的镜像重新部署容器。还有免费的工具可以监控镜像repository,并且在检测到镜像有更新的时候立即重新部署一个容器。但是,运行容器,创建以及更新镜像,这...
个人博客开发系列:文章实时保存 一般用来写东西的网站都会有一个编辑实时保存的功能。对于使用者来说是一个非常实用的功能。作为一个个人博客来说,虽然用处没那么明显,但是还是想实现一下这个功能,就当是练练手吧。 实现思路 使用 WebSocket 来进行浏览器与服务器的实时通信; 服务端使...
如何把全世界的Web浏览器连成一个超级计算机?... 黑客Ben尝试了一个非常大胆的想法,通过WebSocket将全世界的Web浏览器连接在一起,组成一个“超级计算机”,并利用这个超级计算机解决分布式问题。以下内容翻译自作者的博文。 写在前面 我们将讨论一个具有争议性的话题——如何从网站访客的浏览器中“偷”走计算资源。目前有很多讨论是关于如何利...
Design, Build and Operate Docker-based Microservic... At the recent Austin DevOps Days Conference, Flux7 CEO Aater Suleman gave a talk on the "Top Ten Considerations When Planning Docker-based Mi...
责编内容来自:ん乖乖龙ん (源链) | 更多关于

阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » docker 容器 ulimit 参数设置



专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录