漏了监控:Zabbix对Eureka instance状态监控
背景
在正式开始介绍监控之前,我们先来了解下我们微服务架构使用的两个组件,这两个组件是我们本次监控需求的来源。
Eureka
Eureka作为Spring Cloud的注册中心,主要提供服务注册与发现的能力。
Eureka 采用 CS(Client/Server,客户端/服务器) 架构,它包括以下两大组件:
-
Eureka Server :Eureka服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务注册到 Eureka Server。Eureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务的信息,这些可用服务可以在 Eureka Server 的管理界面中直观看到。
-
Eureka Client :Eureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。
Apollo
Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
而Spring Cloud配置中心集成git仓库、svn仓库等配置源统一获取系统配置参数,由Spring Cloud Config Client消费。其配置文件必须遵循严格的语法格式,即使多余的空格都会造成Client 无法读取相应的配置参数,一旦出问题很容易被忽视。
基于Spring Cloud配置中心这种缺陷,我们使用Apollo进行了逐步的替换,使运维、开发对于不同环境之间的配置文件管理更加方便。
问题
借助Apollo可以实现
配置修改实时生效(热发布)
,即用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序。
Apollo热发布功能满足了我们在更改配置属性需求时,应用可以实时感知。但在使用过程中,如果Eureka Client 自动更新配置时,进行全量更新,则会导致Eureka Server在心跳周期内的健康检查状态如下:
-
client服务发现状态为“UNKNOWN” -
client后台仍然正常运行,无法向Eureka Server发送正常心跳
由于Eureka Server服务发现状态异常,此时是无法正常对外提供服务的。如果运维不及时检查Eureka管理界面每个client状态时,那么就会差生一起生产事故。
注意:每个client对应一个instance,下面我们统一将其称为instance。
需求
针对以上情况,虽然我们已经对instance接入了健康检查,但由于instance正常运行并没有产生告警,此时看来我们的监控还是有漏洞,因此我们需要通过Zabbix对Eureka instance状态监控来实现应用监控的全覆盖。
思路
Eureka Server注册的服务以application维度进行分组,每个application下有多个instance。因此我们借助Zabbix的自动发现,通过Eureka API 可以获取所有的分组信息,而不必每次都手动再次添加监控项。
由于Zabbix监控项是不能重复的,因此我们通过
application名/Instance ip地址
进行命名,区分不同的instance,这就要求我们的应用不能在一台服务器上部署多个应用,否则会导致监控项重复。
「注意:」
其实我们可以通过
InstanceId
作为区分更合理,但是InstanceId的使用往往不规范,如包含ip、主机名等等,由于字符过长可能导致不必要的麻烦。
Eureka API
# 获取Eureka 所有的applicationhttp://192.168.3.123:1180/eureka/apps# 获取某个application下所有的instancehttp://192.168.3.123:1180/eureka/apps/application名/
具体实现
因为需要解析Eureka API返回的数据,所以我们使用python来解析json数据。
instance自动发现
通过获取# 执行脚本自动发现application名和Instance ip地址python eureka-instance.py discovery{"data":[{"{#APP}":"TEST1","{#HOSTNAME}":"192.168.3.10"},{"{#APP}":"TEST1","{#HOSTNAME}":"192.168.3.11"}]}
{#APP}
和
{#HOSTNAME}
,我们就可以组合成对应命名规则的监控项。
# 监控项组合TEST1/192.168.3.10TEST1/192.168.3.11
获取监控项状态
经过自动发现后的数据,我们可以进一步获取监控项的状态。
# 1.获取instance 10状态python eureka-instance.py status TEST1 192.168.3.10# 执行结果UP# 2.获取instance 11状态python eureka-instance.py status TEST1 192.168.3.11# 执行结果UP
根据不同Instance的状态,只要结果非“UP”则进行告警。
最终脚本
#!/usr/local/miniconda/bin/python#-*- coding:utf-8 -*-#comment:#1.zabbix自动发现eureka instance#2.对instance的状态进行监控告警import requestsimport jsonimport sysfrom copy import deepcopy# 返回json格式数据,否则返回xml格式数据headers = {'Accept':'text/html, application/xhtml+xml, application/json;q=0.9, */*;q=0.8'}def instance_discovery():app_list = []url="http://192.168.3.123:1180/eureka/apps/"try:response=requests.get(url, headers=headers)if response.status_code == 200:instance_dic = {}#for app in response.json()["applications"]["application"][1:2]:for app in response.json()["applications"]["application"]:for instance in app['instance']:instance_dic['{#APP}'] = instance['app']instance_dic['{#HOSTNAME}'] = instance['hostName']# 深copyapp_list.append(deepcopy(instance_dic))#print(app_list)#json序列化discovery_app_info = {"data":app_list}print(json.dumps(discovery_app_info, sort_keys=True, indent=4, separators=(',', ':')))except Exception as e:print(e)def instance_status():if len(sys.argv) == 4:try:url="http://192.168.3.123:1180/eureka/apps/%s/" % (sys.argv[2])response=requests.get(url, headers=headers)if response.status_code == 200:instance_dic = {}for instance in response.json()["application"]["instance"]:if sys.argv[3] == instance["hostName"]:print(instance["status"])except Exception as e:print(e)else:print("Usage: python eureka-instance.py status app hostName")if __name__ == '__main__':if sys.argv[1] == 'discovery':instance_discovery()elif sys.argv[1] == 'status':instance_status()else:print("Usage: python eureka-instance.py [discovery]|[status app hostName]")
接入Zabbix
1.配置文件
vim eureka.confUserParameter=instance_discovery,/usr/local/miniconda/bin/python /etc/zabbix/monitor_scripts/eureka-instance.py discoveryUserParameter=instance_status[*],/usr/local/miniconda/bin/python /etc/zabbix/monitor_scripts/eureka-instance.py status "$1" "$2"
2.自动发现
注意:自动发现instance的检查时间我们设置为半小时,避免过于频繁的调用Eureka API。
3.监控项配置
注意: instance状态的检查 时间我们设 置为15分钟, 避免过于频繁 的调用Eureka API 。
4.告警信息
# 1.状态为DOWN,发生告警告警主机:中间件_eureka_192.168.3.123主机IP:192.168.3.123主机组:中间件_eureka告警时间:2022.06.01 14:58:23恢复时间:2022.06.01 15:13:24告警等级:High告警信息:Eureka/TEST1/192.168.3.10:状态为DOWN告警项目:instance_status[TEST1,192.168.3.10]问题详情:TEST1/192.168.3.10: DOWN当前状态:发生告警# 2.状态为UP,恢复告警告警主机:中间件_eureka_192.168.3.123主机IP:192.168.3.123主机组:中间件_eureka告警时间:2022.06.01 14:58:23恢复时间:2022.06.01 15:13:24告警等级:High告警信息:Eureka/TEST1/192.168.3.10:状态为DOWN告警项目:instance_status[TEST1,192.168.3.10]问题详情:TEST1/192.168.3.10: UP当前状态:告警恢复: UP
1.Bug:Zabbix对Kafka topic积压数据监控
2. 运维:CMDB好用和用好,差别还是挺大的!
3.基于等级保护梳理服务器安全合规基线
4.Linux高危命令,运维人手一份
5.后话:PipeLine支撑运维自动化
6.Kwok:开源的 IT 管理系统
7.蓝鲸实现多环境vsphere虚拟机交付
札记:弱小和无知,不是生存的障碍,傲慢才是。 --《三体》 喜欢这篇文章,记得 点赞+在看 哦~