我正在 Arch Linux(内核 4.3.3-2)上运行一个带有多个容器的 docker 服务器。自从我上次重新启动以来,docker 服务器和容器中的随机程序都崩溃了,并显示一条有关无法创建线程或(不太常见)分叉的消息。具体的错误信息根据程序的不同而有所不同,但大多数似乎都提到了具体的错误Resource temporarily unavailable
。请参阅本文末尾的一些错误消息示例。
现在有很多人收到过这个错误消息,并且有很多人对此做出了回应。真正令人沮丧的是,每个人似乎都在猜测如何解决这个问题,但似乎没有人指出如何解决确认问题的多种可能原因中存在哪一种。
我收集了导致错误的 5 种可能原因以及如何验证它们是否出现在我的系统上:
- (
/proc/sys/kernel/threads-max
来源)。就我而言,这设置为60613
. - 每个线程都在堆栈中占用一些空间。堆栈大小限制使用
ulimit -s
(来源)。我的 shell 的限制曾经是,但我通过放入8192
增加了它,所以现在它返回了。我还通过放入(* soft stack 32768
/etc/security/limits.conf
ulimit -s
32768
LimitSTACK=33554432
/etc/systemd/system/docker.service
来源,并且我通过查看并在 docker 容器内/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
(来源)。在我的系统上,它们位于700
和之间800
。 - 打开文件的数量是有限制的,根据一些说法来源s 在创建线程时也相关。该限制是使用配置的
ulimit -n
。在我的系统和 docker 内部,限制设置为1048576
.可以使用lsof | wc -l
(来源),在我的系统上它是关于30000
.
看起来在上次重新启动之前我运行的是内核 4.2.5-1,现在我运行的是 4.3.3-2。降级到 4.2.5-1 可以解决所有问题。其他提到该问题的帖子是这和这。我已经开了一个Arch Linux 的错误报告。
内核中发生了什么变化可能导致这种情况?
以下是一些错误消息示例:
Crash dump was written to: erl_crash.dump
Failed to create aux thread
Jan 07 14:37:25 edeltraud docker[30625]: runtime/cgo: pthread_create failed: Resource temporarily unavailable
dpkg: unrecoverable fatal error, aborting:
fork failed: Resource temporarily unavailable
E: Sub-process /usr/bin/dpkg returned an error code (2)
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
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"
[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
答案1
该问题是由TasksMax
系统属性。它是在 systemd 228 中引入的,并利用了 cgroups pid 子系统,该子系统是在 linux 内核 4.3 中引入的。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
部分TasksMax=infinity
中的设置修复了问题。通常位于 中,但也可以将其放入/复制以避免它被包管理器覆盖。[Service]
docker.service
docker.service
/usr/share/systemd/system
/etc/systemd/system
A拉取请求TasksMax
docker 示例 systemd 文件正在增加,并且Arch Linux 错误报告正试图为该包实现同样的目标。正在进行一些额外的讨论在 Arch Linux 论坛上和在关于 lxc 的 Arch Linux 错误报告中。
DefaultTasksMax
[Manager]
可以在in 部分/etc/systemd/system.conf
(或用户运行的服务)中使用/etc/systemd/user.conf
来控制 的默认值TasksMax
。
Systemd 还对从登录 shell 运行的程序施加限制。这些默认为4096
每个用户(将是增加到12288
)并配置为UserTasksMax
在[Login]
部分/etc/systemd/logind.conf
。
答案2
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
。
答案3
看完之后这线。
这个解决方案对我有用:docker -d --exec-opt native.cgroupdriver=cgroupfs
.我实际上将其添加OPTIONS
到/etc/sysconfig/docker
...
答案4
[3178:4:0817/094911.485035:ERROR:platform_thread_posix.cc(155)] pthread_create: Resource temporarily unavailable (11)
我能够通过podman run
使用--pids-limit=-1
参数解决这个问题