乐趣区

关于后端:docker-容器健康检查

        如何优雅的对 Docker 容器进行健康检查

自 1.12 版本之后,Docker 引入了原生的健康检查实现。对于容器而言,最简略的健康检查是过程级的健康检查,即测验过程是否存活。Docker Daemon 会主动监控容器中的 PID1 过程,如果 docker run 命令中指明了 restart policy,能够依据策略主动重启已完结的容器。在很多理论场景下,仅应用过程级健康检查机制还远远不够。比方,容器过程尽管仍旧运行却因为利用死锁无奈持续响应用户申请,这样的问题是无奈通过过程监控发现的。

容器启动之后,初始状态会为 starting (启动中)。Docker Engine 会期待 interval 工夫,开始执行健康检查命令,并周期性执行。如果单次查看返回值非 0 或者运行须要比指定 timeout 工夫还长,则本次查看被认为失败;如果健康检查间断失败超过了 retries 重试次数,状态就会变为 unhealthy (不衰弱)。

注:

  1. 一旦有一次健康检查胜利,Docker 会将容器置回 healthy (衰弱)状态
  2. 当容器的衰弱状态发生变化时,Docker Engine 会收回一个 health_status 事件。通过查看容器监控状态有以下两种形式

1. Dockerfile 形式

能够在 Dockerfile 中申明利用本身的衰弱检测配置。HEALTHCHECK 指令申明了衰弱检测命令,用这个命令来判断容器主过程的服务状态是否失常,从而比拟实在的反馈容器理论状态。

HEALTHCHECK 指令格局:

  • HEALTHCHECK [选项] CMD < 命令 >:设置查看容器健康状况的命令
  • HEALTHCHECK NONE:如果根底镜像有健康检查指令,应用这行能够屏蔽掉

注:在 Dockerfile 中 HEALTHCHECK 只能够呈现一次,如果写了多个,只有最初一个失效。

应用蕴含 HEALTHCHECK 指令的 Dockerfile 构建进去的镜像,在实例化 Docker 容器的时候,就具备了衰弱状态查看的性能。启动容器后会主动进行健康检查。

参数参考:

https://docs.docker.com/engin…

HEALTHCHECK 反对下列选项:

  • –interval=< 距离 >:两次健康检查的距离,默认为 30 秒;
  • –timeout=< 距离 >:健康检查命令运行超时工夫,如果超过这个工夫,本次健康检查就被视为失败,默认 30 秒;
  • –retries=< 次数 >:当间断失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。
  • –start-period=< 距离 >: 利用的启动的初始化工夫,在启动过程中的健康检查生效不会计入,默认 0 秒;

参数作用解释如下:

运行状态查看首先会在容器启动后的 interval 秒内运行,而后在前一次查看实现后的 interval 秒内再次运行。

如果一次状态查看破费的工夫超过 timeout 秒,则认为这次查看失败。

容器的运行状态查看间断失败 retries 次才会被视为不衰弱。

start period 为须要工夫启动的容器提供初始化工夫。在此期间的探测失败将不计入最大重试次数。

然而,如果在启动期间健康检查胜利,则认为容器已启动,所有间断失败的状况都将计算到最大重试次数。

在 HEALTHCHECK [选项] CMD 前面的命令,格局和 ENTRYPOINT 一样,分为 shell 格局,和 exec 格 式。命令的返回值决定了该次健康检查的胜利与否:

  • 0:胜利;
  • 1:失败;
  • 2:保留值,不要应用

假如有个镜像是个最简略的 Web 服务,咱们心愿减少健康检查来判断其 Web 服务是否在失常工作,咱们能够用 curl 来帮忙判断,其 Dockerfile 的 HEALTHCHECK 能够这么写:

FROM nginx:1.23
HEALTHCHECK --interval=5s --timeout=3s  --retries=3 \
    CMD curl -fs http://localhost/ || exit 1

这里设置了每 5 秒查看一次(这里为了试验所以距离十分短,理论应该绝对较长),如果健康检查命令超过 3 秒没响应,并且重试 3 次都没响应就视为失败,并且应用 curl -fs http://localhost/ || exit 1 作为健康检查命令。
应用 docker build 来构建这个镜像:

docker build -t myweb:v1 .

构建好后启动容器:

docker run -d --name web myweb:v1

当运行该镜像后,能够通过 docker container ls 看到最后的状态为(health: starting):

docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                            PORTS               NAMES
7068d793c6e4        myweb:v1            "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds (health: starting)   80/tcp              web

在期待几秒钟后,再次 docker container ls,就会看到衰弱状态变动为了(healthy):

$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS               NAMES
7068d793c6e4        myweb:v1            "/docker-entrypoint.…"   18 seconds ago      Up 16 seconds (healthy)   80/tcp               web

如果健康检查间断失败超过了重试次数,状态就会变为 (unhealthy)。
为了帮忙排障,健康检查命令的输入(包含 stdout 以及 stderr)都会被存储于衰弱状态里,能够用 docker inspect 来查看。

$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool
{
    "FailingStreak": 0,
    "Log": [
        {
            "End": "2022-08-20T14:02:38.19224648+08:00",
            "ExitCode": 0,
            "Output": "xxx",
            "Start": "2022-08-20T14:02:38.116041192+08:00"
        },
        {
            "End": "2022-08-20T14:02:43.271105619+08:00",
            "ExitCode": 0,
            "Output": "xxx",
            "Start": "2022-08-20T14:02:43.200932585+08:00"
        }
    ],
    "Status": "healthy"
}

2. docker run 形式

另外一种办法是在 docker run 命令中,间接指明 healthcheck 相干策略:

$ docker run  -d \
    --name=myweb \
    --health-cmd="curl -fs http://localhost/ || exit 1" \
    --health-interval=5s \
    --health-retries=12 \
    --health-timeout=2s \
    nginx:1.23

通过执行 docker run –help | grep health 命令查看相干的参数及解释如下:

  • –health-cmd string:运行查看健康状况的命令
  • –health-interval duration:运行间隔时间(ms|s|m|h)(缺省为 0s)
  • –health-retries int:须要报告不衰弱的间断失败次数
  • –health-start-period duration:容器在开始衰弱重试倒计时之前初始化的起始周期(ms|s|m|h)(默认 0)
  • –health-timeout duration:容许一次查看运行的最大工夫(ms|s|m|h)(默认为 0s)
  • –no-healthcheck:禁用任何容器指定的 HEALTHCHECK,会使得 Dockerfile 构建进去的 HEALTHCHECK 性能生效。
    如果是以 supervisor 来治理容器的多个服务,想通过子服务的状态来判断容器的监控状态,能够应用 supervisorctl status 来做判断,比方:

    $ docker run --rm -d \
      --name=myweb \
      --health-cmd="supervisorctl status" \
      --health-interval=5s \
      --health-retries=3 \
      --health-timeout=2s \
      nginx:v1

依照此参数的设置,如果 supervisorctl status 查看子服务有一个不为失常的 RUNNING 状态,那么在期待大概 15 秒左右,容器的监控状态就会从 (healthy) 变为(unhealthy)

3. docker-composer 形式

在 docker-composer 中,能够应用以下形式来实现对容器的健康状况查看(以通过 supervisor 治理子过程的容器为例):

version: '3'
services:
  web:
    image: nginx:v1
    container_name: web
    healthcheck:
      test: ["CMD", "supervisorctl", "status"]
      interval: 5s
      timeout: 2s
      retries: 3

执行胜利后,期待数秒查问容器的状态:

$ docker-compose ps
Name              Command                  State                 Ports
--------------------------------------------------------------------------------
web    supervisord -c /etc/superv ...   Up (healthy)   443/tcp, 80/tcp

当通过手动 supervisorctl stop 停掉外面的一些子服务,导致外面的子服务状态不全为 RUNNING 状态时,再查看容器的状态:

healthcheck:
   disable: true

本文转载自:「seafog 的博客」,原文:https://url.hi-linux.com/mgvKJ,版权归原作者所有。

本文由 mdnice 多平台公布

退出移动版