Docker Swarm无法重新启动不健康的Selenium Hub容器

7
我使用docker swarm部署了Selenium Grid。 docker-compose.yml文件:
version: '3.7'

services:
  hub:
   image: selenium/hub:3.141.59-mercury
   ports:
     - "4444:4444"
   volumes:
     - /dev/shm:/dev/shm
   privileged: true
   environment:
     HUB_HOST: hub
     HUB_PORT: 4444
   deploy:
     resources:
       limits:
         memory: 5000M
     restart_policy:
       condition: on-failure
       window: 240s
   healthcheck:
     test: ["CMD", "curl", "-I", "http://127.0.0.1:4444/wd/hub/status"]
     interval: 1m
     timeout: 60s
     retries: 3
     start_period: 300s

  chrome:
    image:  selenium/node-chrome:latest
    volumes:
      - /dev/shm:/dev/shm
    privileged: true
    environment:
      HUB_HOST: hub
      HUB_PORT: 4444
      NODE_MAX_INSTANCES: 5
      NODE_MAX_SESSION: 5
    deploy:
      resources:
        limits:
          memory: 2800M
      replicas: 10
    entrypoint: bash -c 'SE_OPTS="-host $$HOSTNAME" /opt/bin/entry_point.sh'

问题在于当 `hub` 的状态为 `unhealthy` 时,Swarm 几乎从不重新启动它。我只注意到有几次成功重新启动了。据我所知,它应该保持重新启动状态,直到 `healthcheck` 成功或永远,但容器仅以 `unhealthy` 状态运行。
我尝试完全排除 `restart_policy`,以防它与 Swarm 模式搞混了,但没有效果。
此外:似乎当 `hub` 成功重启时,`chrome` 容器(所有副本)也会重新启动。这种关系没有在 `docker-compose.yml` 中指定,这是怎么回事?
我的设置可能出了什么问题?
更新:
当我尝试检查容器(状态为 `unhealthy` 并且没有更多的重试)时,例如 `docker container inspect $container_id --format '{{json .State.Health}}' | jq.`,或者对容器进行几乎任何其他函数操作时,都会失败并输出以下内容:
docker container inspect 1abfa546cc26 --format '{{json .State.Health}}' | jq .
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7fa114765fff m=0 sigcode=18446744073709551610

goroutine 0 [idle]:
runtime: unknown pc 0x7fa114765fff
stack: frame={sp:0x7ffe5e0f1a08, fp:0x0} stack=[0x7ffe5d8f2fc8,0x7ffe5e0f1ff0)
00007ffe5e0f1908:  73752f3a6e696273  732f3a6e69622f72 
00007ffe5e0f1918:  6e69622f3a6e6962  2a3a36333b30303d 
00007ffe5e0f1928:  3b30303d616b6d2e  33706d2e2a3a3633 
00007ffe5e0f1938:  2a3a36333b30303d  3b30303d63706d2e 
00007ffe5e0f1948:  67676f2e2a3a3633  2a3a36333b30303d 
00007ffe5e0f1958:  333b30303d61722e  3d7661772e2a3a36 
00007ffe5e0f1968:  2e2a3a36333b3030  333b30303d61676f 
00007ffe5e0f1978:  7375706f2e2a3a36  2a3a36333b30303d 
00007ffe5e0f1988:  3b30303d7870732e  0000000000000000 
00007ffe5e0f1998:  3a36333b30303d66  2a3a36333b30303d 
00007ffe5e0f19a8:  3b30303d616b6d2e  33706d2e2a3a3633 
00007ffe5e0f19b8:  2a3a36333b30303d  3b30303d63706d2e 
00007ffe5e0f19c8:  67676f2e2a3a3633  2a3a36333b30303d 
00007ffe5e0f19d8:  333b30303d61722e  3d7661772e2a3a36 
00007ffe5e0f19e8:  2e2a3a36333b3030  333b30303d61676f 
00007ffe5e0f19f8:  7375706f2e2a3a36  0000000000000002 
00007ffe5e0f1a08: <8000000000000006  fffffffe7fffffff 
00007ffe5e0f1a18:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a28:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a38:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a48:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a58:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a68:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a78:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a88:  ffffffffffffffff  00007fa114acd6e0 
00007ffe5e0f1a98:  00007fa11476742a  0000000000000020 
00007ffe5e0f1aa8:  0000000000000000  0000000000000000 
00007ffe5e0f1ab8:  0000000000000000  0000000000000000 
00007ffe5e0f1ac8:  0000000000000000  0000000000000000 
00007ffe5e0f1ad8:  0000000000000000  0000000000000000 
00007ffe5e0f1ae8:  0000000000000000  0000000000000000 
00007ffe5e0f1af8:  0000000000000000  0000000000000000 
runtime: unknown pc 0x7fa114765fff
stack: frame={sp:0x7ffe5e0f1a08, fp:0x0} stack=[0x7ffe5d8f2fc8,0x7ffe5e0f1ff0)
00007ffe5e0f1908:  73752f3a6e696273  732f3a6e69622f72 
00007ffe5e0f1918:  6e69622f3a6e6962  2a3a36333b30303d 
00007ffe5e0f1928:  3b30303d616b6d2e  33706d2e2a3a3633 
00007ffe5e0f1938:  2a3a36333b30303d  3b30303d63706d2e 
00007ffe5e0f1948:  67676f2e2a3a3633  2a3a36333b30303d 
00007ffe5e0f1958:  333b30303d61722e  3d7661772e2a3a36 
00007ffe5e0f1968:  2e2a3a36333b3030  333b30303d61676f 
00007ffe5e0f1978:  7375706f2e2a3a36  2a3a36333b30303d 
00007ffe5e0f1988:  3b30303d7870732e  0000000000000000 
00007ffe5e0f1998:  3a36333b30303d66  2a3a36333b30303d 
00007ffe5e0f19a8:  3b30303d616b6d2e  33706d2e2a3a3633 
00007ffe5e0f19b8:  2a3a36333b30303d  3b30303d63706d2e 
00007ffe5e0f19c8:  67676f2e2a3a3633  2a3a36333b30303d 
00007ffe5e0f19d8:  333b30303d61722e  3d7661772e2a3a36 
00007ffe5e0f19e8:  2e2a3a36333b3030  333b30303d61676f 
00007ffe5e0f19f8:  7375706f2e2a3a36  0000000000000002 
00007ffe5e0f1a08: <8000000000000006  fffffffe7fffffff 
00007ffe5e0f1a18:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a28:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a38:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a48:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a58:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a68:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a78:  ffffffffffffffff  ffffffffffffffff 
00007ffe5e0f1a88:  ffffffffffffffff  00007fa114acd6e0 
00007ffe5e0f1a98:  00007fa11476742a  0000000000000020 
00007ffe5e0f1aa8:  0000000000000000  0000000000000000 
00007ffe5e0f1ab8:  0000000000000000  0000000000000000 
00007ffe5e0f1ac8:  0000000000000000  0000000000000000 
00007ffe5e0f1ad8:  0000000000000000  0000000000000000 
00007ffe5e0f1ae8:  0000000000000000  0000000000000000 
00007ffe5e0f1af8:  0000000000000000  0000000000000000 

goroutine 1 [running, locked to thread]:
runtime.systemstack_switch()
    /usr/local/go/src/runtime/asm_amd64.s:311 fp=0xc00009c720 sp=0xc00009c718 pc=0x565171ddf910
runtime.newproc(0x565100000000, 0x56517409ab70)
    /usr/local/go/src/runtime/proc.go:3243 +0x71 fp=0xc00009c768 sp=0xc00009c720 pc=0x565171dbdea1
runtime.init.5()
    /usr/local/go/src/runtime/proc.go:239 +0x37 fp=0xc00009c788 sp=0xc00009c768 pc=0x565171db6447
runtime.init()
    <autogenerated>:1 +0x6a fp=0xc00009c798 sp=0xc00009c788 pc=0x565171ddf5ba
runtime.main()
    /usr/local/go/src/runtime/proc.go:147 +0xc2 fp=0xc00009c7e0 sp=0xc00009c798 pc=0x565171db6132
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1337 +0x1 fp=0xc00009c7e8 sp=0xc00009c7e0 pc=0x565171de1a11

rax    0x0
rbx    0x6
rcx    0x7fa114765fff
rdx    0x0
rdi    0x2
rsi    0x7ffe5e0f1990
rbp    0x5651736b13d5
rsp    0x7ffe5e0f1a08
r8     0x0
r9     0x7ffe5e0f1990
r10    0x8
r11    0x246
r12    0x565175ae21a0
r13    0x11
r14    0x565173654be8
r15    0x0
rip    0x7fa114765fff
rflags 0x246
cs     0x33
fs     0x0
gs     0x0


为了解决这个问题,我尝试应用了以下解决方案:https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting。但是它没有起到任何作用,因此我猜测原因可能不同。在我的系统上,journalctl -u docker 日志中充满了这些记录:
 level=warning msg="Health check for container c427cfd49214d394cee8dd2c9019f6f319bc6637cfb53f0c14de70e1147b5fa6 error: context deadline exceeded"
2个回答

3

首先,我会省略restart_policy。Swarm模式将为您恢复失败的容器,并且该策略在Swarm模式之外处理,可能会导致意外行为。接下来,要调试健康检查,由于您已经配置了多个重试、超时和启动周期,可以检查容器。例如,您可以运行以下命令:

docker container inspect $container_id --format '{{json .State.Health}}' | jq .

这将输出容器的当前状态,包括随时间记录的任何健康检查结果日志。如果显示容器失败超过3次并且处于不健康状态,则检查服务状态:

docker service inspect $service_name --format '{{json .UpdateStatus}}' | jq .

这应该显示当前是否正在进行更新,以及更改的推出是否导致任何问题。

另一个需要注意的是内存限制。如果没有相应的内存预留,调度程序可能会将限制用作预留(我需要测试一下),如果您没有10G可用且未被其他容器保留的内存,则调度程序可能无法重新安排服务。解决这个问题的简单方法是在调度容器时指定要始终在节点上可用的较小预留量。例如:

   deploy:
     resources:
       limits:
         memory: 5000M
       reservations:
         memory: 1000M

根据最新的调试输出:

docker container inspect 1abfa546cc26 --format '{{json .State.Health}}' | jq .
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7fa114765fff m=0 sigcode=18446744073709551610

这表明主机本身或Docker引擎引起了问题,而不是容器的配置。如果还没有,请确保您正在运行docker的最新稳定版本。最后一次检查是19.03.9。我会在/var/log/中检查其他操作系统日志以查找主机上的任何其他错误。我会检查是否达到了资源限制,例如内存和任何与进程/线程相关的sysctl设置(例如kernel.pid_max)。对于docker,我还建议保持内核和systemd版本更新,并在更新后重新启动以应用更改。
我还建议查看this unix.se post上的同一错误,其中有其他可尝试的方法。
如果这些都没有帮助,您可以向类似的开放问题贡献详细信息以重现您的场景:

谢谢!但这并没有真正回答我的问题——健康检查调试并不是必需的,我知道它为什么失败了,而且这是预期的。我只是希望它一直重复运行,直到成功为止。我对可用内存很有把握——它是存在的。 - user1935987
你可能有想法如何在Swarm重启时防止节点重新启动吗?如果我手动重启hub容器,chrome节点容器不会重新启动。 - user1935987
调试健康检查和服务状态可以帮助理解为什么Swarm没有重新启动容器。 - BMitch
之前尝试过,但不起作用。我在问题中添加了错误描述。 - user1935987

0
对于第一个问题,Swarm 期望在 N 次重试失败后重新启动不健康的容器。如果您想深入了解此问题,请使用以下命令监视 Docker 事件。
docker events --filter event=health_status

关于第二个问题:无论何时重新启动中心,所有节点都会重新启动,这是预期的,因为中心保持与所有节点的会话,并且当您重新启动中心时,它会重置所有会话并设置新节点。

是的,我知道。问题是根据文档,它必须重启直到成功,不是吗? - user1935987
它应该是并将会尝试。 - nischay goyal
是的,理论上应该这样,但实际上并没有发生,这就是为什么会有这个问题。关于第二个问题 - 有什么办法让节点在中心重启时不重新启动吗?如果我使用 docker restart *container_id* 手动重启中心,节点就不会重新启动。所以我猜测是Swarm在重新启动它们。 - user1935987

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接