您现在的位置是:首页 >技术杂谈 >如何对Docker容器进行健康检查网站首页技术杂谈

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

margu_168 2024-10-15 00:01:03
简介如何对Docker容器进行健康检查

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

熟悉使用过kubernetes的人应该知道,kubernetes支持对pod进行健康检查的功能,这对生产业务来说其实是非常有用处的,能快速发现服务不可用,并进行快速重启恢复。其实不使用kubernetes这种容器管理工具,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、 docker run 方式

这种方式是在 docker run 命令中,直接指明 healthcheck 相关设置,该方法修改起来比较方便快捷,但是要求使用者对命令行使用比较熟练。

[root@k8s-m1 ~]# docker ps -l
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS                        PORTS     NAMES
80726f760696   nginx     "/docker-entrypoint.…"   About a minute ago   Up About a minute (healthy)   80/tcp    nginx-test
[root@k8s-m1 ~]#  docker run  -d --name=nginx-test --health-cmd="curl http://localhost/ || exit 1" --health-interval=5s --health-retries=6  --health-timeout=3s nginx

对命令行不熟悉的,可以通过执行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
功能失效

▍2、 Dockerfile 方式

可以在 Dockerfile 中通过使用HEALTHCHECK声明应用自身的健康检测配置。HEALTHCHECK配置了健康检测命令,用这个命令来判断容器主进程的服务状态是否正常,从而比较真实的反应容器实际运行状况。

HEALTHCHECK
指令格式:

  • HEALTHCHECK [选项] CMD <命令>
    设置检查容器健康状况的命令,注意CMD一直有
  • HEALTHCHECK NONE
    如果基础镜像有健康检查指令,可以通过该配置屏蔽

注 :和cmd、entrypoint一样,在 Dockerfile 中HEALTHCHECK只可以出现一次,如果写了多个,只有最后一个生效。
HEALTHCHECK 返回值,决定了该次健康检查的成功与否:0:成功;1:失败;2:保留(不要使用这个值)

使用包含HEALTHCHECK指令的 Dockerfile 构建出来的镜像,在实例化 Docker 容器的时候,就具备了健康状态检查的功能。启动容器后会自动进行健康检查。

参数说明:

HEALTHCHECK 支持下列选项:

  • --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
  • --timeout=<间隔>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
  • --retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认3次,如果正常的话好像会一直检查下去,可自行测试。
  • --start-period=<间隔>: 应用的启动的初始化时间,在启动过程中的健康检查失效不会计入,默认 0 秒,需要一定启动时间的服务最好设置;

假设有个镜像是个最简单的 nginx 服务,我们希望增加健康检查来判断其 nginx服务是否在正常工作,我们可以使用 curl 来帮助检查测试, Dockerfile 的HEALTHCHECK可以简单这么写:

[root@k8s-m1 ~]vim Dockerfile
FROM nginx
HEALTHCHECK --interval=5s --timeout=3s  CMD curl  http://localhost/ || exit 1

[root@k8s-m1 ~]docker build -t nginx:v1 .
[root@k8s-m1 ~]docker run -d --name webtest -p 80:80 nginx:v1  
[root@k8s-m1 ~]# docker ps -l
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS                            PORTS                NAMES
c4dcff064e99   nginx:v1   "/docker-entrypoint.…"   5 seconds ago   Up 4 seconds (health: starting)   0.0.0.0:80->80/tcp   webtest
[root@k8s-m1 ~]# docker ps -l
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS                   PORTS                NAMES
c4dcff064e99   nginx:v1   "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds (healthy)   0.0.0.0:80->80/tcp   webtest
[root@k8s-m1 ~]# 

这里设置了每 5 秒检查一次,如果健康检查命令超过 3 秒没响应,并且重试 3 次都没响应就视为失败,并且使用curl http://localhost/ || exit 1,可以根据自己的业务自行调整检查命令。构建好后启动一个容器实例,看到最初的状态为(health: starting),在等待几秒钟后,再次docker ps -l,就可以看到健康状态变化为了(healthy)

当然如果健康检查连续失败超过了重试次数,状态就会变为(unhealthy)

为了帮助排障,健康检查命令的输出(包括stdout以及stderr)都会被存储于健康状态里,可以用 docker inspect来查看。

[root@k8s-m1 ~]#  docker inspect --format '{{json .State.Health}}' webtest | python -m json.tool
{
    "Status": "healthy",
    "FailingStreak": 0,
    "Log": [
        {
            "Start": "2023-06-12T10:33:48.163431699+08:00",
            "End": "2023-06-12T10:33:48.303906069+08:00",
            "ExitCode": 0,
            "Output": "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   615  100   615    0     0   600k      0 --:--:-- --:--:-- --:--:--  600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
"

▍3、 docker-composer 方式

在 docker-compose 中,可以使用以下方式来实现对容器的健康状况检查(下面以nginx为例,也可以参考Harbor的docker-compose文件):

version: '3'
services:
  myapp:
    image: nginx
    container_name: healthcheck
    healthcheck:
      test: ["CMD", "curl", "-fs", "http://localhost/"]
      interval: 6s
      timeout: 3s
      retries: 3

#设置初次检查等待6s,每次检查超时设置为3s,总共检查3次,如果3次都失败则判断为健康检查不通过。过程中有一次检查通过则判断为健康。

执行成功后,等待数秒查询容器的状态:

[root@k8s-m1 hewei]# docker ps -l
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS                            PORTS     NAMES
46e1d11e2431   nginx     "/docker-entrypoint.…"   3 seconds ago   Up 3 seconds (health: starting)   80/tcp    healthcheck
[root@k8s-m1 hewei]# docker ps -l
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                            PORTS     NAMES
46e1d11e2431   nginx     "/docker-entrypoint.…"   6 seconds ago   Up 8 seconds (health: starting)   80/tcp    healthcheck

[root@k8s-m1 hewei]# docker-compose  ps
   Name                  Command                  State       Ports 
--------------------------------------------------------------------
healthcheck   /docker-entrypoint.sh ngin ...   Up (healthy)   80/tcp

更复杂的使用请自行探索,一般也很少单独使用。更多docker容器和运维方面的知识请前往博客主页。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。