cda*_*uth 51 linux limit fork thread docker
我正在 Arch Linux(内核 4.3.3-2)上运行一个带有多个容器的 docker 服务器。自从我上次重新启动后,容器内的 docker 服务器和随机程序都崩溃了,并显示一条关于无法创建线程或(较少)fork 的消息。具体的错误信息因程序而异,但大多数似乎都提到了具体的错误Resource temporarily unavailable。有关一些示例错误消息,请参见本文末尾。
现在有很多人收到了这个错误信息,并且有很多人对他们做出了回应。真正令人沮丧的是,每个人似乎都在猜测如何解决问题,但似乎没有人指出如何确定存在问题的众多可能原因中的哪一个。
我收集了这 5 个可能的错误原因以及如何验证它们不存在于我的系统中:
/proc/sys/kernel/threads-max( source ) 中配置的线程数有系统范围的限制。在我的情况下,这设置为60613.ulimit -s( source )配置的。我的壳的极限曾经是8192,但我已经通过将增加其* soft stack 32768成/etc/security/limits.conf,因此它ulimit -s现在的回报32768。我也增加了它的码头工人,过程将LimitSTACK=33554432进入/etc/systemd/system/docker.service(源,和我核实,该限制适用通过查看/proc/<pid of docker>/limits,并通过运行ulimit -s一个泊坞窗容器内。ulimit -v. 在我的系统上,它设置为unlimited,并且我的 3 GB 内存中有 80% 是空闲的。ulimit -u。在这种情况下,线程算作进程(源)。在我的系统上,限制设置为30306,对于 docker 守护进程和 docker 容器内部,限制为1048576。当前运行的线程数可以通过运行ls -1d /proc/*/task/* | wc -l或运行ps -elfT | wc -l(source)找到。在我的系统上,它们介于700和之间800。ulimit -n. 在我的系统和 docker 内部,限制设置为1048576. 可以使用lsof | wc -l(source)找到打开文件的数量,在我的系统上它大约是30000.看起来在上次重新启动之前我运行的是内核 4.2.5-1,现在我运行的是 4.3.3-2。降级到 4.2.5-1 修复了所有问题。其他提到这个问题的帖子是this和this。我已经打开了Arch Linux的错误报告。
内核中发生了什么变化可能导致这种情况?
以下是一些示例错误消息:
Crash dump was written to: erl_crash.dump
Failed to create aux thread
Run Code Online (Sandbox Code Playgroud)
Jan 07 14:37:25 edeltraud docker[30625]: runtime/cgo: pthread_create failed: Resource temporarily unavailable
Run Code Online (Sandbox Code Playgroud)
dpkg: unrecoverable fatal error, aborting:
fork failed: Resource temporarily unavailable
E: Sub-process /usr/bin/dpkg returned an error code (2)
Run Code Online (Sandbox Code Playgroud)
test -z "/usr/include" || /usr/sbin/mkdir -p "/tmp/lib32-popt/pkg/lib32-popt/usr/include"
/bin/sh: fork: retry: Resource temporarily unavailable
/usr/bin/install -c -m 644 popt.h '/tmp/lib32-popt/pkg/lib32-popt/usr/include'
test -z "/usr/share/man/man3" || /usr/sbin/mkdir -p "/tmp/lib32-popt/pkg/lib32-popt/usr/share/man/man3"
/bin/sh: fork: retry: Resource temporarily unavailable
/bin/sh: fork: retry: No child processes
/bin/sh: fork: retry: Resource temporarily unavailable
/bin/sh: fork: retry: No child processes
/bin/sh: fork: retry: No child processes
/bin/sh: fork: retry: Resource temporarily unavailable
/bin/sh: fork: retry: Resource temporarily unavailable
/bin/sh: fork: retry: No child processes
/bin/sh: fork: Resource temporarily unavailable
/bin/sh: fork: Resource temporarily unavailable
make[3]: *** [install-man3] Error 254
Run Code Online (Sandbox Code Playgroud)
Jan 07 11:04:39 edeltraud docker[780]: time="2016-01-07T11:04:39.986684617+01:00" level=error msg="Error running container: [8] System error: fork/exec /proc/self/exe: resource temporarily unavailable"
Run Code Online (Sandbox Code Playgroud)
[Wed Jan 06 23:20:33.701287 2016] [mpm_event:alert] [pid 217:tid 140325422335744] (11)Resource temporarily unavailable: apr_thread_create: unable to create worker thread
Run Code Online (Sandbox Code Playgroud)
cda*_*uth 52
该问题是由TasksMaxsystemd 属性引起的。它是在 systemd 228 中引入的,并使用了在 linux 内核 4.3 中引入的 cgroups pid 子系统。512因此,如果内核 4.3 或更高版本正在运行,则 systemd中会启用 的任务限制。该功能在此处宣布并在此拉取请求中引入,默认值由此拉取请求设置。将我的内核升级到 4.3 后,systemctl status docker显示Tasks一行:
# systemctl status docker
? docker.service - Docker Application Container Engine
Loaded: loaded (/etc/systemd/system/docker.service; disabled; vendor preset: disabled)
Active: active (running) since Fri 2016-01-15 19:58:00 CET; 1min 52s ago
Docs: https://docs.docker.com
Main PID: 2770 (docker)
Tasks: 502 (limit: 512)
CGroup: /system.slice/docker.service
Run Code Online (Sandbox Code Playgroud)
设置TasksMax=infinity在[Service]部分docker.service解决了这个问题。docker.service通常在 中/usr/share/systemd/system,但也可以将其放入/复制,/etc/systemd/system以避免被包管理器覆盖。
docker 示例 systemd 文件的拉取请求正在增加TasksMax,并且Arch Linux 错误报告正试图为该包实现相同的目标。有一些额外的讨论正在进行对Arch Linux的论坛,并在有关LXC的Arch Linux的错误报告。
DefaultTasksMax可以[Manager]在/etc/systemd/system.conf(或/etc/systemd/user.conf用于用户运行的服务)部分中用于控制 的默认值TasksMax。
Systemd 还对从登录外壳运行的程序应用限制。这些默认为4096每个用户(将增加到12288),并UserTasksMax在[Login]部分配置/etc/systemd/logind.conf。
小智 7
cdauth 的答案是正确的,但还有另一个细节需要添加。
在我的带有 systemd 229 和 4.3 内核的 Ubuntu 16.04 系统上,默认情况下对会话范围强制执行 512 pid 限制,即使 UserTasksMax 设置为新的、增加的默认值 12288 也是如此。因此,任何用户会话范围都限制为 512 个线程。
我发现消除限制的唯一方法是设置DefaultTasksMax=unlimited和/etc/systemd/system.conf(systemctl daemon-reexec或重新启动)。
systemctl status您可以通过发出、选择会话范围和来检查是否发生这种情况cat /sys/fs/cgroup/pids/user.slice/user-${UID}.slice/session-FOO.scope/pids.max。