当前位置: 首页 > 科技观察

Docker容器健康状态检查

时间:2023-03-15 18:34:02 科技观察

Docker原生健康检查能力从1.12版本开始,Docker引入了原生健康检查实现。对于容器来说,最简单的健康检查就是进程级别的健康检查,检查进程是否存活。DockerDaemon会自动监控容器中的PID1进程。如果dockerrun命令中指定了重启策略,则可以根据策略自动重启结束的容器。在很多实际场景中,仅仅使用进程级别的健康检查机制是远远不够的。比如容器进程虽然还在运行,但是由于应用死锁,无法继续响应用户请求。此类问题无法通过进程监控发现。容器启动后,初始状态为starting(正在启动)。DockerEngine会等待间隔时间,开始执行健康检查命令,并周期性执行。如果单个检查返回非零值或运行时间超过指定的超时时间,则该检查被视为失败。如果健康检查连续失败超过重试次数,状态将变为不健康。注意:一旦健康检查成功,Docker会将容器恢复到健康(healthy)状态。当容器的健康状态发生变化时,DockerEngine会发出一个health_status事件。查看容器的监控状态有两种方式:1.Dockerfile方式可以在Dockerfile中声明应用自身的健康检测配置。HEALTHCHECK命令声明了健康检查命令,用于判断容器主进程的服务状态是否正常,更真实的反映容器的实际状态。HEALTHCHECK指令格式:HEALTHCHECK[option]CMD:设置检查容器健康状态的命令HEALTHCHECKNONE:如果基础镜像有健康检查指令,用这一行屏蔽掉注意:HEALTHCHECK只能出现一次在Dockerfile中,如果写入了多个,则只有最后一个生效。使用包含HEALTHCHECK命令的Dockerfile构建的镜像,在Docker容器实例化时,具有检查健康状态的功能。启动容器后会自动执行健康检查。参数参考:https://docs.docker.com/engine/reference/builder/#healthcheckHEALTHCHECK支持以下选项:--interval=:两次健康检查的时间间隔,默认为30秒;--timeout=<间隔>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查将被视为失败,默认为30秒;--retries=<次数>:当连续失败指定次数时,容器状态将被视为不健康,默认为3次。--start-period=:应用程序启动的初始化时间。启动过程中健康检查失败不计入,默认0秒;该参数的作用解释如下:在容器启动后,将首先在interval秒内执行运行状态检查,在上一次检查完成后的interval秒内运行。如果状态检查花费的时间超过超时秒数,则认为状态检查失败。容器的健康检查在被认为不健康之前会连续重试失败。启动期为需要时间启动的容器提供初始化时间。在此期间的探测失败将不计入最大重试次数。但是,如果在启动过程中健康检查成功,则认为容器已启动,并且所有连续失败都计入最大重试次数。HEALTHCHECK[option]CMD后面的命令格式和ENTRYPOINT一样,分为shell格式和exec格式。命令的返回值决定健康检查是否成功:0:成功;1:失败;2:保留值,不要使用假设一个镜像是最简单的web服务,我们希望加入健康检查来判断它的web服务我们可以使用curl来帮助判断服务是否正常工作。Dockerfile的HEALTHCHECK可以这样写:FROMnginx:1.23HEALTHCHECK--interval=5s--timeout=3s--retries=3\CMDcurl-fshttp://localhost/||exit1这里设置为每5秒检查一次(这里间隔实验很短,实际应该比较长),如果健康检查命令超过3秒没有响应,重试后没有响应3times将其视为失败,并使用curl-fshttp://localhost/||exit1作为健康检查命令。使用dockerbuild构建此映像:dockerbuild-tmyweb:v1。构建完成后,启动容器:dockerrun-d--namewebmyweb:v1运行镜像后,可以通过dockercontainerls查看初始状态(health:starting):dockercontainerlsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES7068d793c6e4myweb:v1"/docker-entrypoint.…"3秒前Up2秒(health:starting)80/tcpweb等几秒后,再次dockercontainerls,会看到健康状态变成了(healthy):$dockercontainerlsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES7068d793c6e4myweb:v1"/docker-entrypoint.…"18秒前Up16秒(healthy)80/tcp如果web健康检查连续失败并超过重试次数,则状态将更改为(不健康)。为了帮助排除故障,健康检查命令的输出(包括stdout和stderr)将存储在健康状态中,可以使用dockerinspect查看。$dockerinspect--format'{{json.State.Health}}'网页|python-mjson.tool{"FailingStreak":0,"Log":[{"End":"2022-08-20T14:02:38.19224648+08:00","ExitCode":0,"Output":"xxx","开始":"2022-08-20T14:02:38.116041192+08:00"},{"结束":"2022-08-20T14:02:43.271105619+08:00","退出代码":0,"输出":"xxx","开始":"2022-08-20T14:02:43.200932585+08:00"}],"状态":"健康"}2.dockerrun另一种方法是直接在dockerrun命令中指定healthcheck相关策略:$dockerrun-d\--name=myweb\--health-cmd="curl-fshttp://localhost/||exit1"\--health-interval=5s\--health-retries=12\--health-timeout=2s\nginx:1.23通过执行dockerrun--help|grephealth命令查看相关参数,其解释如下:--health-cmdstring:运行命令查看健康状态-health-intervalduration:运行间隔时间(ms|s|m|h)(默认为0s)--health-retriesint:连续不健康报告失败的次数--health-start-periodduration:开始健康重试倒计时前容器初始化的起始周期(ms|s|m|h)(default0)--health-timeoutduration:允许检查运行的最长时间(ms|s|m|h)(default0s)--no-healthcheck:禁用任何容器指定的HEALTHCHECK会使Dockerfile构建的HEALTHCHECK函数失效如果supervisor用于管理容器的多个服务,想通过子服务的状态来判断容器的监控状态,可以使用supervisorctlstatus来判断,例如:$dockerrun--rm-d\--name=myweb\--health-cmd="supervisorctlstatus"\--health-interval=5s\--health-retries=3\--health-timeout=2s\nginx:v1根据对于这个参数的设置,如果supervisorctlstatus检查子服务有异常RUNNING状态,那么在等待大概15秒后,容器的监控状态会由(健康)变为(不健康)3.docker-composer方法在docker-composer中,可以使用以下方法来实现检查容器的健康状态(以通过supervisor管理子进程的容器为例):version:'3'services:web:image:nginx:v1container_name:webhealthcheck:test:["CMD","supervisorctl","status"]间隔:5stimeout:2sretries:3执行成功后,等待几秒,查询容器状态:$docker-composepsNameCommandStatePorts----------------------------------------------------------------------------websupervisord-c/etc/superv...Up(healthy)443/tcp,80/tcp当里面的一些子服务被手动supervisorctlstop停止时,子服务里面服务状态不都是RUNNING的时候,查看容器的状态:#docker-composepsName命令状态端口----------------------------------------------------------------------------------websupervisord-c/etc/superv...启动(不健康)443/TCP,80/TCP