通过Consul进行容器的健康检查

目录

作者:杨冬 欢迎转载,也请保留这段声明。谢谢!
出处:https://andyyoung01.github.io/http://andyyoung01.16mb.com/

使用Consul不但可以进行服务配置和服务发现,它还支持对容器的健康检查。本篇我们探索一下Consul监控容器的一种方式——使用脚本文件进行服务的监视。

通过运行一个脚本文件,根据其返回值设置健康状态,脚本的返回值如果为0则表示健康,1表示warning,任何其它值表示critical。可以在一开始定义服务的时候一同注册健康检查,或者使用一个不同的API调用,就像这里这样。本篇的运行环境继续使用“使用Consul进行服务发现”文章中的环境,有两个节点,一个运行了Consul server agent(机器名:centos7-A,ip:192.168.71.167),另一个运行了Consul client agent(机器名:centos7,ip:192.168.71.131)。
首先创建一个bash脚本文件,确认从服务返回的HTTP状态码是200 OK。服务端口是从传入脚本的参数的service ID中查找到的:

1
2
3
4
5
6
7
8
9
10
[yangdong@centos7 ~]$ cat >check <<'EOF'
#!/bin/sh
set -o errexit
set -o pipefail
SVC_ID="$1"
SVC_PORT=\
"$(wget -qO - 172.17.0.1:8500/v1/catalog/service/files | jq '.[0] | {ServicePort: .ServicePort}' | jq .ServicePort)"
wget -qsO - "localhost:$SVC_PORT"
echo "Success!"
EOF

然后将此脚本拷贝到consul-client容器内部:

[yangdong@centos7 ~]$ cat check | docker exec -i consul_client \
sh -c 'cat > /check && chmod +x /check'

通过下面的命令得到想要进行监视的服务的ServiceID:

[yangdong@centos7 ~]$ curl -sSL 172.17.0.1:8500/v1/catalog/service/files \
| python -m json.tool | grep ServiceID
    "ServiceID": "centos7-reg:reverent_mcnulty:80",

再创建一个健康检查定义文件来发送到Consul HTTP API:

[yangdong@centos7 ~]$ cat >health.json <<'EOF'
{
"Name": "filescheck",
"ServiceID": "centos7-reg:reverent_mcnulty:80",
"Script": "/check centos7-reg:reverent_mcnulty:80",
"Interval": "10s"
}
EOF

将此健康检查定义文件提交到Consul client agent:

[yangdong@centos7 ~]$ curl -X PUT --data-binary @health.json \
  172.17.0.1:8500/v1/agent/check/register

等待一段时间后,查看一下刚才注册的健康状态检查的情况:

[yangdong@centos7 ~]$ curl -sSL 172.17.0.1:8500/v1/health/service/files | python -m json.tool | head -n 15
[
    {
        "Checks": [
            {
                "CheckID": "filescheck",
                "CreateIndex": 2026,
                "ModifyIndex": 4158,
                "Name": "filescheck",
                "Node": "centos7",
                "Notes": "",
                "Output": "/check: line 5: jq: not found\n",
                "ServiceID": "centos7-reg:reverent_mcnulty:80",
                "ServiceName": "files",
                "Status": "critical"
            },

上面的输出显示健康状态检查的结果是critical,在这种情况下,Consul自动将失败的服务从DNS服务列表中剔除,所以通过Consul DNS并不能查询到该服务:

[yangdong@centos7 ~]$ dig @172.17.0.1 files.service.consul srv +short

上面这种特性在生产环境中对于将失败的服务器自动从多个服务后端剔除非常有用。

避免健康检查状态的丢失——对于每次健康检查脚本的执行,Consul只在脚本监视的Server状态有变化时才同步脚本执行结果的输出,或者是直到5分钟后才再次输出。因为健康检查的初始状态是critical,前边这个健康检查一开始的状态也是critical,所以你需要等待5分钟之后才能得到Output的内容。

再回到前面的健康检查状态的Output,它提示没有找到jq命令。这是因为我们在容器中运行Consul,所有的健康状态检查也是在容器中进行的。所以,就如同之前需要把健康检查脚本拷贝进入容器一样,也需要确保容器中安装了需要的命令。在这个示例中,consul容器里并没有安装jq命令,所以我们需要手动安装:

[yangdong@centos7 ~]$ docker exec consul_client sh -c 'apk update && apk add jq'
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
v3.4.3-107-g111e702 [http://dl-cdn.alpinelinux.org/alpine/v3.4/main]
v3.4.3-62-gaaf1b40 [http://dl-cdn.alpinelinux.org/alpine/v3.4/community]
OK: 5970 distinct packages available
(1/1) Installing jq (1.5-r1)
Executing busybox-1.24.2-r11.trigger
OK: 7 MiB in 17 packages

上面的命令通过Alpine Linux的包管理器安装了jq命令。下面测试一下它能否正常使用:

[yangdong@centos7 ~]$ docker exec -it consul_client sh
/ # wget -qO - 172.17.0.1:8500/v1/catalog/service/files | jq '.[0] | {ServicePort: .ServicePort}' | jq .ServicePort
8000
/ # ./check centos7-reg:reverent_mcnulty:80
Success!

上面的命令都没有问题,我们就可以通过Consul的REST API再次检查容器的健康状态,看看它的status是否从critical变成passing:

[yangdong@centos7 ~]$ curl -sSL 172.17.0.1:8500/v1/health/service/files | python -m json.tool | head -n 15
[
    {
        "Checks": [
            {
                "CheckID": "filescheck",
                "CreateIndex": 2026,
                "ModifyIndex": 4644,
                "Name": "filescheck",
                "Node": "centos7",
                "Notes": "",
                "Output": "Success!\n",
                "ServiceID": "centos7-reg:reverent_mcnulty:80",
                "ServiceName": "files",
                "Status": "passing"
            },

好了,健康状态检查终于成功了。
这个例子是使用脚本进行健康状态监测的,Consul还支持其它两种监测方式——检查HTTP的返回状态码和检查Time to Live状态。结合上面三种方式,可以构建出十分强大的监测系统。

Consul是一个非常大的主题。它还包含一个web界面可以用来与其交互。不过各种知识都是相通的。之前关于使用etcd的键值存储的知识可以类比到使用Consul进行键值存储;服务发现的知识可以类比到其它提供DNS接口的工具(如SkyDNS等)。