docker 组成 : hundreds of health check processes not terminated

标签 docker docker-compose health-check

docker compose:数百个健康检查进程未终止。

services:
  tomcat:
    ...
    healthcheck:
      test:
        - CMD-SHELL
        - curl --fail http://localhost:8080 || exit 1
      interval: 5s
      timeout: 5s
      retries: 30

ps 辅助 | grep curl

tomcat    939765  0.0  0.0      0     0 ?        Z    08:46   0:00 [curl] <defunct>
tomcat    939824  0.0  0.0      0     0 ?        Z    08:46   0:00 [curl] <defunct>
tomcat    939904  0.0  0.0      0     0 ?        Z    08:47   0:00 [curl] <defunct>
tomcat    939962  0.0  0.0      0     0 ?        Z    08:47   0:00 [curl] <defunct>
tomcat    940038  0.0  0.0      0     0 ?        Z    08:47   0:00 [curl] <defunct>
tomcat    940094  0.0  0.0      0     0 ?        Z    08:47   0:00 [curl] <defunct>
tomcat    940321  0.0  0.0      0     0 ?        Z    08:48   0:00 [curl] <defunct>
tomcat    940380  0.0  0.0      0     0 ?        Z    08:48   0:00 [curl] <defunct>
tomcat    940460  0.0  0.0      0     0 ?        Z    08:48   0:00 [curl] <defunct>
tomcat    940516  0.0  0.0      0     0 ?        Z    08:48   0:00 [curl] <defunct>
tomcat    940600  0.0  0.0      0     0 ?        Z    08:49   0:00 [curl] <defunct>
tomcat    940657  0.0  0.0      0     0 ?        Z    08:49   0:00 [curl] <defunct>
tomcat    940734  0.0  0.0      0     0 ?        Z    08:49   0:00 [curl] <defunct>
tomcat    940875  0.0  0.0      0     0 ?        Z    08:49   0:00 [curl] <defunct>
tomcat    940955  0.0  0.0      0     0 ?        Z    08:50   0:00 [curl] <defunct>
tomcat    941013  0.0  0.0      0     0 ?        Z    08:50   0:00 [curl] <defunct>
tomcat    941102  0.0  0.0      0     0 ?        Z    08:50   0:00 [curl] <defunct>
tomcat    941162  0.0  0.0      0     0 ?        Z    08:50   0:00 [curl] <defunct>
tomcat    941244  0.0  0.0      0     0 ?        Z    08:51   0:00 [curl] <defunct>
tomcat    941332  0.0  0.0      0     0 ?        Z    08:51   0:00 [curl] <defunct>
tomcat    941392  0.0  0.0      0     0 ?        Z    08:51   0:00 [curl] <defunct>
tomcat    941474  0.0  0.0      0     0 ?        Z    08:51   0:00 [curl] <defunct>
tomcat    941532  0.0  0.0      0     0 ?        Z    08:52   0:00 [curl] <defunct>
tomcat    941609  0.0  0.0      0     0 ?        Z    08:52   0:00 [curl] <defunct>
tomcat    941671  0.0  0.0      0     0 ?        Z    08:52   0:00 [curl] <defunct>
tomcat    941749  0.0  0.0      0     0 ?        Z    08:52   0:00 [curl] <defunct>
tomcat    941810  0.0  0.0      0     0 ?        Z    08:53   0:00 [curl] <defunct>
....

tomcat    941895  0.0  0.2  22364  8436 ?        S    08:53   0:00 curl --fail http://localhost:8080
tomcat    941954  0.0  0.2  22364  8512 ?        S    08:53   0:00 curl --fail http://localhost:8080
tomcat    942032  0.0  0.2  22364  8384 ?        S    08:53   0:00 curl --fail http://localhost:8080
tomcat    942238  0.0  0.2  22364  8528 ?        S    08:54   0:00 curl --fail http://localhost:8080
tomcat    942316  0.0  0.2  22364  8552 ?        S    08:54   0:00 curl --fail http://localhost:8080
tomcat    942377  0.0  0.2  22364  8496 ?        S    08:55   0:00 curl --fail http://localhost:8080
tomcat    942452  0.0  0.2  22364  8360 ?        S    08:55   0:00 curl --fail http://localhost:8080
...

即使在检查容器健康之后,健康检查器是否还会继续定期运行?

“curl”进程没有终止的原因是什么?

最佳答案

查看此输出,我将其读为 curl命令未在 5 秒内完成并被终止,并且主容器进程未设置为处理它获得对未自行启动的子进程的责任的情况。

我怀疑您可以采取两件事来解决此问题:

  1. 修复您的应用程序,以便其及时响应运行状况检查。它不应该处于接受连接但等待超过 5 秒才能应答的状态。
  2. 使用 init: true 启动您的容器.

我认为发生的情况取决于 Linux (Unix) 进程如何工作的一些非常具体的细节。 CMD-SHELL健康检查由 Docker 作为容器进程命名空间中的附加进程注入(inject),方式与 docker exec 相同。 。但更具体地说,有两个进程:一个包装器 sh运行命令管道的进程,以及 curl命令作为子进程。

/bin/sh -c 'curl --fail http://localhost:8080 || exit 1'
+-- curl --fail http://localhost:8080

当达到超时时,Docker 将终止进程。不过,它并不具体了解子进程,因此它向 sh 发送信号。过程。如果它仍然没有终止,Docker 会向它发送 SIGTERM,相当于 kill -9 的 Unix 信号。 ,shell进程就不复存在了。

curl 会发生什么?过程?它的父级曾经是 sh过程,但那已经消失了。这里的标准 Unix 规则是,它被移动为“init”进程的子进程,进程 ID 为 1。在 Docker 上下文中,主容器进程(如果有的话,则为 ENTRYPOINT,如果有,则为 CMD)不是)就是这个过程。

最终是curl过程将完成,也许有自己的超时。这里的标准 Unix 规则是,大部分进程都会清理,但其进程表条目仍保留,并且其父进程可以等待(2) 并找出其状态代码。已退出但尚未等待的进程是“僵尸”进程;这是您的流程条目的长列表,其中包含 Z在状态栏中和 <defunct>在线的末尾。值得注意的是,这些不使用内存或文件句柄或其他资源,仅处理表条目。

这些东西的组合加起来是:容器中的主进程是进程ID 1;进程 ID 1 预计为“init”进程;进程ID 1有时会意外地让子进程附加到它,但它本身并没有启动,并且需要在它们之后进行清理(“收获僵尸”)。如果您的主进程是 Tomcat 服务器,并且它没有监视其他子进程(或 SIGCHLD 信号),那么您将以您所看到的方式泄漏进程。

撰写 init: true选项将主容器命令包装在轻量级 init 进程中,默认 Tini 。如果进程 1 需要获取僵尸,Tini 就会这样做,并且它会处理一些围绕信号的情况。这几乎就是它的全部功能,但它是一个重要的功能。

关于 docker 组成 : hundreds of health check processes not terminated,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77105400/

相关文章:

docker-compose - 使用 docker-compose 时如何为运行容器建立实时日志输出

asp.net-core - 运行状况检查 UI 中的 webhook 有什么用?

docker - Podman 缺少健康检查

Docker 映射端口并暴露给特定主机

GCP 上的 Docker 持久卷

nginx - Github webhook 的 Jenkins 自动构建不起作用

用于引用 bitnami 图像的容器 docker-compose.yml 的 azure webapp

docker - HEALTHCHECK失败时Docker容器会发生什么

jenkins - Jenkins Pipeline 的 Docker 插件 - uid 1005 不存在用户

docker - 允许在使用 docker-machine 配置的主机中进行不安全的注册表