之前在论坛上发过一个求助贴:

求助,我参考git hub 项目xxproject做容器化部署,中间有双eureka高可用,但是eureka始终处于health:starting状态,从浏览器能访问到eureka控制台,证明已经启动,但容器状态就是不变成healthy,打日志发现eureka除了一直在同步状态外,没有任何异常。


求指点

1容器健康状态转化的机制和标志

2针对我遇到的问题,如何解决

这个贴子没有得到回答。关于容器的健康状态,找到了两篇文章,算是说明白了问题:


容器状态是 UP 的,应用就是健康的吗?

还真不一定!
Docker 只能从容器启动进程的返回代码判断其状态,而对于容器内部应用的运行情况基本没有了解。

执行 docker run 命令时,通常会根据 Dockerfile 中的 CMD 或 ENTRYPOINT 启动一个进程,这个进程的状态就是 docker ps STATUS 列显示容器的状态。
549.png
 

命令显示:

    有的容器正在运行,状态为 UP。

    有的容器已经正常停止了,状态是 Exited (0)。

    有的则因发生故障停止了,退出代码为非 0,例如 Exited (137)、Exited (1) 等。

即使容器状态是 UP,也不能保证应用没有问题。web server 虽然没有崩溃,但如果总是返回 HTTP 500 - Internal Server Error ,对应用来说这就是很严重的故障。

如何从应用的业务层面检查容器的状态呢? 答案是:Health Check。

Docker 支持的 Health Check 可以是任何一个单独的命令,Docker 会在容器中执行该命令,如果返回 0,容器被认为是 healthy,如果返回 1,则为 unhealthy。

对于提供 HTTP 服务接口的应用,常用的 Health Check 是通过 curl 检查 HTTP 状态码,比如:

curl --fail http://localhost:8080/ || exit 1

如果 curl 命令检测到任何一个错误的 HTTP 状态码,则返回 1,Health Check 失败。
 

 


 healthcheck命令执行的结果有以下几种:

    0: success - the container is healthy and ready for use,容器成功运行,状态健康
    1: unhealthy - the container is not working correctly,容器启动异常
    2: reserved - do not use this exit code,未使用

 

但是,按照第一篇文章以及网上其他文章示例,将healthcheck中执行的命令改为curl,在容器外自己执行是没有问题,但是eureka容器启动后的状态依然始终卡在health:starting状态。
因此有了这样一个疑问:

healthcheck中指定的指令,是在容器内执行的还是容器外执行的?

各位还真不要以为这个问题显而易见。因为查了CSDN和网上许多文章,包括docker-compose.yaml官网的文档,都没有提及这个问题。

那么,或者是官方和各位高手都认为这个问题显而易见,或者是天下文章一大抄,各路教程都是转来转去,没有实际操作过。

纸上得来终学浅,在实践中遇到坑,才能真正解决生产实践工程中的问题。

基于这个思路,在启动eureka容器后,我用docker exec -it xxxx /bin/bash,进入容器内,然后执行curl...指令,返回找不到此命令错误,执行示例项目healthcheck中指定的指令,虽然出错,但至少有这个指令。

由此可知:healthcheck中的指令在容器内执行,所以必须是容器内有的指令。也就是说,健康检测探针要打包在容器内。
总结:

1.容器的健康状态取决于healthcheck命令执行的结果。

2.healthcheck执行的命令在容器内执行。

3.很多容器内置了curl作为探针,但有些容器就是没内置。

纸上得来终觉浅,亲自操作才对容器健康检测有了真切的理解。

另外关于health-cmd Health Check 的命令,还有几个相关的参数:

    --timeout 命令超时的时间,默认 30s。

    --interval 命令执行的间隔时间,默认 30s。

    --retries 命令失败重试的次数,默认为 3,如果 3 次都失败了则会将容器标记为 unhealthy。
这里需要注意的是,timeout和interval指定的参数一定要有单位,不能只写数字,即s/m不能省略。这也是实践出来的知识点。

 

下面这两篇文章,记下来做为备忘。

 

docker容器的健康状态监控功能healthcheck


博客作为学习笔记记录,若有理解,表述错误,欢迎指出。

healthcheck是docker1.12版本引入的新功能,用于容器健康状态监测

暂时k8s不支持docker的healthcheck功能,k8s由其之前就提供的liveness和readiness功能来实现healthcheck,docker引入healthcheck功能,估计也是向k8s学习的。

 

docker 的healthcheck

设置选项

  • --interval=DURATION (default: 30s),间隔
  • --timeout=DURATION (default: 30s), 超时时间
  • --start-period=DURATION (default: 0s),初始化时间

          说明:在此期间的探测失败将不计入最大重试次数。但是,如果健康检查在启动期间成功,则认为容器已启动,所有连续的失败都将计入最大重试次数。

  • --retries=N (default: 3),当连续失败指定次数后,容器状态会变成unhealthy

格式:HEALTHCHECK [选项] CMD(分成shell格式和exec格式)。

如果有多个指令,则最后一个生效。

输出: healthcheck命令执行的结果有以下几种:

  • 0: success - the container is healthy and ready for use,容器成功运行,状态健康
  • 1: unhealthy - the container is not working correctly,容器启动异常
  • 2: reserved - do not use this exit code,未使用

 

举个栗子:

用curl来判断web服务是否正常,在dockerfile中定义healthcheck:

1. FROM nginx
2. RUN apt-get update && apt-get
3. install -y curl && rm -rf /var/lib/apt/lists/*
4. HEALTHCHECK --interval=5s --timeout=3s \
5.   CMD curl -fs http://localhost/ || exit 1

刚运行容器时,容器状态为health:starting

1. $ docker container ls
2. CONTAINER ID        IMAGE               COMMAND                  CREATED           STATUS                            PORTS               NAMES
3. 03e28eb00bd0        myweb:v1            "nginx -g 'daemon off"  3 seconds ago       Up 2 seconds (health: starting)  80/tcp, 443/tcp     web

过几秒之后,状态会变成healthy

1. $ docker container ls
2. CONTAINER ID        IMAGE               COMMAND                  CREATED            STATUS                    PORTS               NAMES
3. 03e28eb00bd0        myweb:v1            "nginx -g 'daemon off"  18 seconds ago      Up 16 seconds (healthy)   80/tcp, 443/tcp     web

健康指令的输出结果会存储在健康状态里,可以用docker inspect来查看,eg:

$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool


    1. #输出为:
    2. {
    3.     "FailingStreak": 0,
    4.     "Log": [
    5.         {
    6.             "End": "2016-11-25T14:35:37.940957051Z",
    7.             "ExitCode": 0,
    8.             "Output": "<!DOCTYPE
    9. html>\n<html>\n<head>\n<title>Welcome to
    10. nginx!</title>\n<style>\n   
    11. body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial,
    12. sans-serif;\n   
    13. }\n</style>\n</head>\n<body>\n<h1>Welcome to
    14. nginx!</h1>\n<p>If you see this page, the nginx web server is
    15. successfully installed and\nworking. Further configuration is
    16. required.</p>\n\n<p>For online documentation and support please
    17. refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial
    18. support is available at\n<a
    19. href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank
    20. you for using nginx.</em></p>\n</body>\n</html>\n",
    21.             "Start":
    22. "T14:35:37.780192565Z"
    23.         }
    24.     ],
    25.     "Status": "healthy"
    26. }

    REF:

    https://docker_practice.gitee.io/image/dockerfile/healthcheck.html

    https://docs.docker.com/engine/reference/builder/

    https://docker_practice.gitee.io/image/dockerfile/healthcheck.html

    https://docs.docker.com/engine/reference/builder/