something about healthech for docker container
在 Docker compose 文件里使用健康检查的方案变迁。
背景:小厂,用不起 kubernetes,只能自己生写 docker compose 来部署 Docker 容器。以下以一个在容器里监听 tcp 端口 8090 的服务为例来描述一下我用到过的健康检查的方案的变迁。
curl
文档里都讲是
1 | # docker compose file |
这种方式,但是实际上,我经手的大多 image,都没有统一的健康检查 url,这样直接访问,很有可能出各种结果,返回的 return code 不是 200 的结果,这样的话,这个健康检查会过不去,但是服务却是好的。所以,经过研究,发现更好的应该是:
1 | # docker compose file |
当然,这个解决不了一个致命问题:好些个基础 image,都不带命令 curl
,然后我就开始了尝试下一个方案。
/proc/net/tcp
服务绑定监听端口,肯定会更新 /proc/net/tcp
这个文件,只不过端口号得转换成十六进制。就像这样:
1 | # Docker compose file |
一直工作挺好,直到某一天我遇到一个基于 openjdk:8u342
的 Docker image,跑着 java 的程序,这个 java 程序监听着端口 8090,明明工作正常,但是健康检查却过不去,进到容器里一看,/proc/net/tcp
文件里的确没有 “:1f9a”(printf "%x\n" 8090
)!
非常诡异!一顿好查。
1 | apt update && apt install -y iproute2 procps |
然后:
1 | ss -nalpt |
发现有
*:8090
但是 /proc/net/tcp
里始终没有 “:1f9a”,最后偶然间发现文件 /proc/net/tcp6
,打开看:
0: 00000000000000000000000000000000:1F9A 00000000000000000000000000000000:0000 0A 00000000:00000000
“:1F9A” 赫然在这里!
回头找原因,只能认为是 java 程序绑定监听端口时优先绑了 IPv6 的地址,但是由于 kernel 参数:net.ipv6.bindv6only=0
(缺省就是这样),从而绑在 IPv6 地址上的端口,在 IPv4 的地址上也能访问。
好吧,/proc/net/tcp
方案不是不行了,而是还要考虑到文件 /proc/net/tcp6
/dev/tcp/{hostname}/{port}
1 | # Docker compose file |
这个方案就有一个缺点:bash 可用但 sh 下不可用