运行命令变成僵尸后,Docker容器拒绝被杀死

首先是第一件事。我的系统信息和版本:

$ lsb_release -a

No LSB modules are available.

Distributor ID: Ubuntu

Description: Ubuntu 13.04

Release: 13.04

Codename: raring

$ sudo docker version

Client version: 0.9.0

Go version (client): go1.2.1

Git commit (client): 2b3fdf2

Server version: 0.9.0

Git commit (server): 2b3fdf2

Go version (server): go1.2.1

$ lxc-version

lxc version: 0.9.0

$ uname -a

Linux ip-10-0-2-86 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

容器中的进程变成僵尸之后,我无法停止容器。升级到docker 0.9.0后,我在服务器上看到大量僵尸。例:

$ ps axo stat,ppid,pid,comm | grep -w defunct

Zl 25327 25332 node <defunct>

$ pstree -p

init(1)─┬

├─sh(819)───docker(831)─┬

├─lxc-start(25327)───node(25332)───{node}(25378)

我可以看到 lxc-

start(25327)没有在节点进程25332上调用wait()来保持僵尸存活。所以我检查了strace在做什么,它似乎卡在了epoll_wait。stract实际上一开始就卡住了,只是显示了这一点:

$sudo strace -ir -ttt -T -v -p 25327

Process 25327 attached - interrupt to quit (when asked to kill)

0.000103 [ 7fe59b9d34b3] epoll_wait(8,

但是在我运行sudo docker kill 3da5764b7bc9358之后,我得到了更多输出:

 0.000103 [    7fe59b9d34b3] epoll_wait(8, {{EPOLLIN, {u32=21673408, u64=21673408}}}, 10, 4294967295) = 1 <8.935002>

8.935097 [ 7fe59bcaff60] accept(4, 0, NULL) = 9 <0.000035>

0.000095 [ 7fe59bcafeb3] fcntl(9, F_SETFD, FD_CLOEXEC) = 0 <0.000027>

0.000083 [ 7fe59b9d401a] setsockopt(9, SOL_SOCKET, SO_PASSCRED, [1], 4) = 0 <0.000027>

0.000089 [ 7fe59b9d347a] epoll_ctl(8, EPOLL_CTL_ADD, 9, {EPOLLIN, {u32=21673472, u64=21673472}}) = 0 <0.000023>

0.000087 [ 7fe59b9d34b3] epoll_wait(8, {{EPOLLIN, {u32=21673472, u64=21673472}}}, 10, 4294967295) = 1 <0.000026>

0.000090 [ 7fe59bcb0130] recvmsg(9, {msg_name(0)=NULL, msg_iov(1)=[{"\3\0\0\0\0\0\0\0", 8}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=773, uid=0, gid=0}}, msg_flags=0}, 0) = 8 <0.000034>

0.000128 [ 7fe59bcb019d] sendto(9, "\0\0\0\0\0\0\0\0\364b\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 24, 0, NULL, 0) = 24 <0.000029>

0.000090 [ 7fe59b9d34b3] epoll_wait(8, {{EPOLLIN|EPOLLHUP, {u32=21673472, u64=21673472}}}, 10, 4294967295) = 1 <0.000018>

0.000091 [ 7fe59bcb0130] recvmsg(9, {msg_name(0)=NULL, msg_iov(1)=[{"\3\0\0\0\0\0\0\0", 8}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=0, uid=0, gid=0}}, msg_flags=0}, 0) = 0 <0.000026>

0.000122 [ 7fe59b9d347a] epoll_ctl(8, EPOLL_CTL_DEL, 9, NULL) = 0 <0.000037>

0.000084 [ 7fe59bcafd00] close(9) = 0 <0.000048>

0.000103 [ 7fe59b9d34b3] epoll_wait(8, {{EPOLLIN, {u32=21673408, u64=21673408}}}, 10, 4294967295) = 1 <1.091839>

1.091916 [ 7fe59bcaff60] accept(4, 0, NULL) = 9 <0.000035>

0.000093 [ 7fe59bcafeb3] fcntl(9, F_SETFD, FD_CLOEXEC) = 0 <0.000027>

0.000083 [ 7fe59b9d401a] setsockopt(9, SOL_SOCKET, SO_PASSCRED, [1], 4) = 0 <0.000026>

0.000090 [ 7fe59b9d347a] epoll_ctl(8, EPOLL_CTL_ADD, 9, {EPOLLIN, {u32=21673504, u64=21673504}}) = 0 <0.000032>

0.000100 [ 7fe59b9d34b3] epoll_wait(8, {{EPOLLIN, {u32=21673504, u64=21673504}}}, 10, 4294967295) = 1 <0.000028>

0.000088 [ 7fe59bcb0130] recvmsg(9, {msg_name(0)=NULL, msg_iov(1)=[{"\3\0\0\0\0\0\0\0", 8}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=774, uid=0, gid=0}}, msg_flags=0}, 0) = 8 <0.000030>

0.000125 [ 7fe59bcb019d] sendto(9, "\0\0\0\0\0\0\0\0\364b\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 24, 0, NULL, 0) = 24 <0.000032>

0.000119 [ 7fe59b9d34b3] epoll_wait(8, {{EPOLLIN|EPOLLHUP, {u32=21673504, u64=21673504}}}, 10, 4294967295) = 1 <0.000071>

0.000139 [ 7fe59bcb0130] recvmsg(9, {msg_name(0)=NULL, msg_iov(1)=[{"\3\0\0\0\0\0\0\0", 8}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=0, uid=0, gid=0}}, msg_flags=0}, 0) = 0 <0.000018>

0.000112 [ 7fe59b9d347a] epoll_ctl(8, EPOLL_CTL_DEL, 9, NULL) = 0 <0.000028>

0.000076 [ 7fe59bcafd00] close(9) = 0 <0.000027>

0.000096 [ 7fe59b9d34b3] epoll_wait(8,

然后我查看了epoll_wait正在等待什么,看起来像文件8(我猜这是从epoll_wait(8, {{EPOLLIN, {u32=21673408,

u64=21673408}}}, 10, 4294967295) = 1 <8.935002>形式上int epoll_wait(int epfd,

struct epoll_event *events, int maxevents, int timeout);

$ cat /proc/25327/fdinfo/8

pos: 0

flags: 02000002

tfd: 7 events: 19 data: 14ab830

tfd: 4 events: 19 data: 14ab5c0

还根据上面的tfd添加了7和4(不确定tfd的真正含义)

$ cat /proc/25327/fdinfo/4

pos: 0

flags: 02000002

$ cat /proc/25327/fdinfo/7

pos: 0

flags: 02000002

sigmask: fffffffe7ffbfab7

$ cd /proc/25327/fd

$ ls -al

lr-x------ 1 root root 64 Mar 13 22:28 0 -> /dev/null

lrwx------ 1 root root 64 Mar 13 22:28 1 -> /dev/pts/17

lrwx------ 1 root root 64 Mar 13 22:28 2 -> /dev/pts/17

l-wx------ 1 root root 64 Mar 13 22:28 3 -> /var/log/lxc/3da5764b7bc935896a72abc9371ce68d4d658d8c70b56e1090aacb631080ec0e.log

lrwx------ 1 root root 64 Mar 13 22:28 4 -> socket:[48415]

lrwx------ 1 root root 64 Mar 14 00:03 5 -> /dev/ptmx

lrwx------ 1 root root 64 Mar 14 00:03 6 -> /dev/pts/18

lrwx------ 1 root root 64 Mar 14 00:03 7 -> anon_inode:[signalfd]

lrwx------ 1 root root 64 Mar 14 00:03 8 -> anon_inode:[eventpoll]

有关套接字的信息:

$ sudo netstat -anp | grep 48415

Proto RefCnt Flags Type State I-Node PID/Program name Path

unix 2 [ ACC ] STREAM LISTENING 48415 25327/lxc-start @/var/lib/lxc/3da5764b7bc935896a72abc9371ce68d4d658d8c70b56e1090aacb631080ec0e/command

在docker.log中似乎确实存在一种通用模式,所有不停止的容器都具有以下签名:

2014/03/16 16:33:15 Container beb71548b3b23ba3337ca30c6c2efcbfcaf19d4638cf3d5ec5b8a3e4c5f1059a failed to exit within 0 seconds of SIGTERM - using the force

2014/03/16 16:33:25 Container SIGKILL failed to exit within 10 seconds of lxc-kill beb71548b3b2 - trying direct SIGKILL

在这一点上,我不知道下一步该怎么做。关于如何找出导致这些容器无法退出的原因的任何建议?我还应该收集其他数据吗?我也将SIGCHLD发送给该过程,但无济于事。

更多数据:将日志添加到节点进程的末尾,我们在容器中使用start命令开始:

Mon Mar 17 2014 20:52:52 GMT+0000 (UTC) process: main process = exit code: 0

这是来自docker的日志:

2014/03/17 20:52:52 Container f8a3d55e0f... failed to exit within 0 seconds of SIGTERM - using the force

2014/03/17 20:53:02 Container SIGKILL failed to exit within 10 seconds of lxc-kill f8a3d55e0fd8 - trying direct SIGKILL

时间戳显示进程已退出@ 20:52:52

使用本地和lxc泊坞窗驱动程序都会发生这种情况。

编辑:复制步骤!

将其变成bash脚本,然后运行并观看几乎50%的容器变成僵尸!

CNT=0

while true

do

echo $CNT

DOCK=$(sudo docker run -d -t anandkumarpatel/zombie_bug ./node index.js)

sleep 60 && sudo docker stop $DOCK > out.log &

sleep 1

CNT=$(($CNT+1))

if [[ "$CNT" == "50" ]]; then

exit

fi

done

回答:

更改为最新内核可解决此问题

发现确切的内核差异:

REPRO:linux-image-3.8.0-31-generic

没有REPRO:linux-image-3.8.0-32-generic

我认为这是解决方法:

+++ linux-3.8.0/kernel/pid_namespace.c

@@ -181,6 +181,7 @@

int nr;

int rc;

struct task_struct *task, *me = current;

+ int init_pids = thread_group_leader(me) ? 1 : 2;

/* Don't allow any more processes into the pid namespace */

disable_pid_allocation(pid_ns);

@@ -230,7 +231,7 @@

*/

for (;;) {

set_current_state(TASK_UNINTERRUPTIBLE);

- if (pid_ns->nr_hashed == 1)

+ if (pid_ns->nr_hashed == init_pids)

break;

schedule();

}

来自这里:https

:

//groups.google.com/forum/#!msg/fa.linux.kernel/u4b3n4oYDQ4/GuLrXfDIYggJ

将要升级所有我们的服务器,以重现这一点,看看是否仍然存在。

以上是 运行命令变成僵尸后,Docker容器拒绝被杀死 的全部内容, 来源链接: utcz.com/qa/426752.html

回到顶部