之前在论坛上发过一个求助贴:
求助,我参考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