consul服务注册与健康检查
一、Consul的服务注册
- 服务注册: 可以使用api接口工具postman或者ApiPost来注册一个服务,新建一个PUT请求方法,输入地址http://<consul url>/v1/agent/service/register这个url,然后配置Headers信息(key=Content-Type, value=application/json) 然后配置我们提供的body信息,配置完成执行发送请求
配置body中的row信息 { "Name": "服务名", "ID": "服务id", "Tags":["标签信息1","标签信息2","标签信息3"], "Address":"127.0.0.1", #/你想输入什么ip都可以(因为现在没有健康检查) "Port":"8080" }
- 删除服务:直接换个url,加上服务名然后执行发送请求(也是PUT方法)
http:<consul url>/v1/agent/service/deregister/服务名
二、consul监控检查
- Script check
通过执行外部应用进行健康检查,这种外部程序具有退出代码,并可能产生一些输出;脚本按照指定时间间隔来调用,类似于Nagios插件系统,脚本输入输出限制在4K以内。默认情况下,脚本超时时间为30s 可以通过timeoute来配置
{ "service": { "name": "web", "tags": ["rails"], "port": 80, "checks": [{ "id": "mem-util", // 检查项id "name": "Memory utilization", // 检查项名字 "args": ["/usr/local/bin/check_mem.py", "-limit", "256MB"], //这里是我们要执行的命令,第一个参数是命令或者脚本名,后面跟着任意个参数 "interval": "10s", // 每10秒执行一次命令 "timeout": "1s" // 命令执行超时时间 }] } }
{ "service": { "name": "web", "tags": ["rails"], "port": 80, "checks": [{ "args": ["curl", "localhost"], // 执行curl命令,数组第2到第N个元素,代表命令参数 "interval": "10s" // 每10秒执行一次命令 }] } }
为了安全考虑,如果健康检查使用执行命令方式,在启动consul的时候支持下面两种参数:
- -enable-script-checks 允许通过配置文件和http api注册的服务,执行命令检查健康状态
- -enable-local-script-checks 禁止通过http api注册的服务,执行命令健康检查状态,只允许通过配置文件注册的服务,执行命令。
建议生产环境使用-enable-local-script-checks 参数启动consul agent
- 基于HTTP请求
定时以GET请求方法,请求指定url,http请求返回状态码2xx表示正常,其他状态码表示异常,这种检查将按照预设的时间间隔创建一个http get请求。http响应代码来标示服务所处状态,任何2xx状态码表示正常,429表示告警---有很多请求,其他表示失败。
这种类型的检查应使用curl或者外部程序来处理http操作,默认情况下,http checks中,请求超时时间等于调用请求时间的间隔时间,最大10s。有可能使用指定的http check,可以自由配置timeout时间,输入输出在4k以内,大于将被截断。
{ "check": { "id": "api", "name": "HTTP API on port 5000", "http": "https://localhost:5000/health", "tls_server_name": "", "tls_skip_verify": false, "method": "POST", "header": { "Content-Type": ["application/json"] }, "body": "{\"method\":\"health\"}", "interval": "10s", "timeout": "1s" } }
{ "service": { "name": "web", "tags": ["rails"], "port": 80, "checks": [{ "id": "api", // 健康检查项的id,唯一 "name": "HTTP API on port 5000", // 检查项的名字 "http": "https://localhost:5000/health", // 定期访问的Url,通过这个url请求结果确定服务是否正常 "tls_skip_verify": false, // 关闭tls验证 "method": "POST", // 设置http请求方式,默认是GET "header": { // 可以自定义请求头,可以不配置 "x-foo": ["bar", "baz"] }, "interval": "10s", // 定期检查的时间间隔,这里是10秒 "timeout": "1s" // 请求超时时间,1秒 }] } }
- 基于TCP请求
基于tcp请求方式,就是定时,向指定的地址,建立tcp连接,连接成功就代表服务正常,否则代表异常。
将按照预设的时间间隔与指定的IP/Hostname和端口建立一个TCP连接,服务的状态依赖于TCP连接是否成功---如果连接成功,则状态为success;否则状态为critical。如果一个Hostname解析为一个ipv4和一个ipv6,将尝试连接这两个地址,第一次连接成功则服务状态就是success。
如果希望通过这种方式利用外部脚本执行健康检查,那么脚本应该采用netcat或者简单的socket操作。
默认情况下,TCP checks中,请求超时时间等于调用请求的间隔时间,大于10s,也可以自定义
{ "check": { "id": "ssh", "name": "SSH TCP on port 22", "tcp": "localhost:22", "interval": "10s", "timeout": "1s" } }
{ "service": { "name": "web", "tags": ["rails"], "port": 80, "checks": [{ "id": "ssh", // 检查项目id "name": "SSH TCP on port 22", // 检查项名字 "tcp": "localhost:22", // tcp连接地址,ip+port "interval": "10s", // 定义建立连接的时间间隔是10秒 "timeout": "1s" // 超时时间是1秒 }] } }
- 基于UDP 检查
UDP检查会定期指示consul代理将UDP数据报发送到指定的IP/HOST_NAME和端口,等待尝试之间的时间间隔,如果从目标UDP服务器收到任何响应,则检查状态为成功。任何其他结果都会将状态设置为critical 默认情况下,UDP 检查配置为请求超时等于 10 秒。要配置自定义 UDP 检查超时值,请在检查定义中指定超时字段。如果存在任何读取超时,则检查仍被认为是正常的。 以下服务定义文件片段是 UDP 检查定义的示例:
{ "check": { "id": "dns", "name": "DNS UDP on port 53", "udp": "localhost:53", "interval": "10s", "timeout": "1s" } }
- 基于H2ping check
{ "check": { "id": "h2ping-check", "name": "h2ping", "h2ping": "localhost:22222", "interval": "10s", "h2ping_use_tls": false } }
- 基于grpc请求
如果微服务是基于grpc协议,可以使用grpc协议检测服务是否正常
{ "service": { "name": "web", "tags": ["rails"], "port": 80, "checks": [{ "id": "mem-util", // 检查项目id "name": "Service health status", // 检查项名字 "grpc": "127.0.0.1:12345", // grpc地址,ip+port "grpc_use_tls": true, "interval": "10s" // 10秒检测一次 }] } }
- 基于Timeto Live(TTL)
这种checks为给定TTL保留了最后一种状态,checks的状态必须通过HTTP接口周期性更新,如果外部接口没有更新状态,那么状态就会被认定为异常。
这种机制,在概念上类似"死人开关",需要服务周期性汇报健康状态,比如,一个健康的app可以周期性的将状态put到http端;如果app出现问题,那么TTL将过期,健康检查将进入Critical状态。用来为给定check更新健康信息的endpoint都是pass endpoint和fail endpoint
TTL checks同时会将其最后已知状态更新至磁盘,这允许agent通过重启后恢复到已知的状态,通过TTL端上一次check来维持健康状态的有效性。
{ "check": { "id": "web-app", "name": "WebApp Status", "notes": "Webapp does a curl internally every 10 seconds", "ttl": "30s" } }
- Docker
这种检查依赖于调用封装在docker容器内的外部程序。运行的docker通过docker Exec API来触发外部应用。
consul Agent用户访问Docker HTTP API或 UNIX套接字。consul使用$DOCKER_HOST来确定Docker API端点,应用程序将运行,并对在容器内运行的服务执行健康检查,并返回适当的退出码,Check按照指定的时间间隔调用。
如果在同一个host主机上又多重shell,那么同样需要配置shell参数。
{ "check": { "id": "mem-util", "name": "Memoryutilization", "docker_container_id": "f972c95ebf0e", "shell": "/bin/bash", "script": "/usr/local/bin/check_mem.py", "interval": "10s" } }
MultipleCheck Definitions
多个check定义,可以使用字段“checks”,示例:
{ "checks": [ { "id": "chk1", "name": "mem", "script": "/bin/check_mem", "interval": "5s" }, { "id": "chk2", "name": "/health", "http": "http://localhost:5000/health", "interval": "15s" }, { "id": "chk3", "name": "cpu", "script": "/bin/check_cpu", "interval": "10s" }, ... ] }
每一种check都必须包含name,id和notes两个是可选的。如果没有提供id,那么id会被设置为name。在一个节点中,check的ID都必须是唯一的。如果名字是冲突的,那么ID就应该设置。
字段Notes主要是增强checks的可读性。Script check中,notes字段可以由脚本生成。同样,适用HTTP接口更新TTL check的外部程序一样可以设置notes字段