Docker 的健康检测机制
对于容器而言,最简单的健康检查是进程级的健康检查,即检验进程是否存活。DockerDaemon会自动监控容器中的PID1进程,如果dockerrun命令中指明了restartpolicy,可以根据策略自动重启已结束的容器。在很多实际场景下,仅使用进程级健康检查机制还远远不够。比如,容器进程虽然依旧运行却由于应用死锁无法继续响应用户请求,这样的问题是无法通过进程监控发现的。
通常我们为了防止容器断电或异常关闭后不能自动开机,我们可以加上
--restart=always
例如
[root@aliyun~]#dockerrun--restart=always-d--nameblog-d-v/www:/www-v/wwwlogs:/var/log/wwwlogs-p65423:65422-p80:80-p443:443677 7714a84063ee6d405c80b891254bba0e5930f5d271c5ad76cfd6e2f0058d8056
这样容器就可以自动重启,但是有时候程序进入死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法提供服务了。在1.12以前,Docker不会检测到容器的这种状态,从而不会重新调度,导致可能会有部分容器已经无法提供服务了却还在接受用户请求。
而自1.12之后,Docker提供了HEALTHCHECK指令,通过该指令指定一行命令,用这行命令来判断容器主进程的服务状态是否还正常,从而比较真实的反应容器实际状态。
当在一个镜像指定了HEALTHCHECK指令后,用其启动容器,初始状态会为starting,在HEALTHCHECK指令检查成功后变为healthy,如果连续一定次数失败,则会变为unhealthy。
HEALTHCHECK支持下列选项:
- –interval=<间隔>:两次健康检查的间隔,默认为30秒;
- –timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认30秒;
- –retries=<次数>:当连续失败指定次数后,则将容器状态视为unhealthy,默认3次。和CMD,ENTRYPOINT一样,HEALTHCHECK只可以出现一次,如果写了多个,只有最后一个生效。
在HEALTHCHECK[选项]CMD后面的命令,格式和ENTRYPOINT一样,分为shell格式,和exec格式。命令的返回值决定了该次健康检查的成功与否:0:成功;1:失败;2:保留,不要使用这个值。
下面我们看下这个dockerfile文件
FROMcentos LABELmaintainer"awenEmail:" WORKDIR/opt/ COPYCentOS7-Base-163.repo/etc/yum.repos.d/CentOS-Base.repo COPYnginx/etc/init.d/nginx ENVNGINX_V=1.13.5\ OPENSSL_V=1.0.2l\ PCRE_V=8.41\ ZLIB_V=1.2.11 RUNyum-yupdate\ &&yum-yinstallopenssh-serveropensslgccgcc-c++pcre-developenssl-develzlib-develwgetmakeperltarnet-tools\ &&wget-c-4https://nginx.org/download/nginx-$NGINX_V.tar.gz\ &&wget-c-4https://www.openssl.org/source/openssl-$OPENSSL_V.tar.gz\ &&wget-c-4ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-$PCRE_V.tar.gz\ &&wget-c-4http://zlib.net/zlib-$ZLIB_V.tar.gz\ &&groupadd-rwww&&useradd-r-gwwwwww\ &&tarzxvfzlib-$ZLIB_V.tar.gz\ &&cdzlib-$ZLIB_V\ &&./configure\ &&make\ &&makeinstall\ &&cd/opt\ &&tarzxvfpcre-$PCRE_V.tar.gz\ &&cdpcre-$PCRE_V\ &&./configure\ &&make\ &&makeinstall\ &&cd/opt\ &&tarzxvfopenssl-$OPENSSL_V.tar.gz\ &&tarzxvfnginx-$NGINX_V.tar.gz\ &&cdnginx-$NGINX_V\ &&./configure--prefix=/usr/local/nginx--user=www--group=www--with-pcre=/opt/pcre-$PCRE_V--with-http_ssl_module--with-zlib=/opt/zlib-$ZLIB_V--with-openssl=/opt/openssl-$OPENSSL_V--with-http_v2_module--with-http_ssl_module\ &&make\ &&makeinstall\ &&rm-rf/opt/*\ &&mkdir-p/usr/local/nginx/ssl\ &&mkdir-p/usr/local/nginx/conf/vhost\ &&mkdir-p/var/log/wwwlogs/\ &&mkdir-p/www/\ &&ssh-keygen-trsa-f/etc/ssh/ssh_host_rsa_key-N''\ &&ssh-keygen-tdsa-f/etc/ssh/ssh_host_dsa_key-N''\ &&ssh-keygen-tecdsa-f/etc/ssh/ssh_host_ecdsa_key-N''\ &&ssh-keygen-ted25519-f/etc/ssh/ssh_host_ed25519_key-N''\ &&echo"RSAAuthenticationyes">>/etc/ssh/sshd_config\ &&echo"PubkeyAuthenticationyes">>/etc/ssh/sshd_config\ &&sed-i"s/PasswordAuthenticationyes/PasswordAuthenticationno/g"/etc/ssh/sshd_config\ &&sed-i"s/UsePAMyes/UsePAMno/g"/etc/ssh/sshd_config\ &&sed-i"s/#Port22/Port65422/g"/etc/ssh/sshd_config\ &&yumcleanall\ &&mkdir/var/run/sshd\ &&chmod+x/etc/init.d/nginx\ &&rm-rf/root/*.cfg\ &&echo"Asia/Shanghai">/etc/localtime COPYssl/*/usr/local/nginx/ssl/ COPYvhost/*/usr/local/nginx/conf/vhost/ COPYnginx.conf/usr/local/nginx/conf/ COPYssh/*/root/.ssh/ VOLUME["/www","/var/log/wwwlogs","/usr/local/nginx/ssl","/usr/local/nginx/conf/vhost"] EXPOSE6542280443 HEALTHCHECKCMDcurl-fshttp://localhost/||exit1 ENTRYPOINT/etc/init.d/nginxstart&&chown-Rwww:www/var/log/wwwlogs/&&/usr/sbin/sshd-D
其中
HEALTHCHECKCMDcurl-fshttp://localhost/||exit1
就是增加的健康监测配置,然后编译后启动,查看进程会发现其状态是starting
[root@aliyun~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 7714a84063ee677"/bin/sh-c'/etc/ini"3secondsagoUp2seconds(health:starting)0.0.0.0:80->80/tcp,0.0.0.0:443->443/tcp,0.0.0.0:65423->65422/tcpblog
稍等查看,会发现其状态为healthy
[root@aliyun~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 7714a84063ee677"/bin/sh-c'/etc/ini"AboutaminuteagoUpAboutaminute(healthy)0.0.0.0:80->80/tcp,0.0.0.0:443->443/tcp,0.0.0.0:65423->65422/tcpblog
我们可以通过inspect查看最近3次的状态
[root@aliyun~]#dockerinspect--format'{{json.State.Health}}'blog|python-mjson.tool { "FailingStreak":0, "Log":[ { "End":"2017-10-11T11:15:27.516562686+08:00", "ExitCode":0, "Output":"\r\n301MovedPermanently \r\n\r\n \r\n 301MovedPermanently
nginx \r\n\r\n