最近在做一个云服务的监控需求。
总的架构是基于prometheus实现的:在每个虚拟机上安装prometheus-exporter;prometheus-server从每个exporter拉取监控指标。
其中一个关键点是,虚拟机的规模是弹性的,也就是exporter的数量也是变化的。prometheus-server需要能感知到exporter的变化,prometheus官方推荐使用注册中心维护exporter的ip等信息。我们第一版方案采用了consul作为注册中心。
使用consul注册中心,在实际使用中遇到了几个坑。
为了保证consul注册中心的高可用,我们想部署一套集群,我们部署了3个server模式的consul,外面套上2个nginx,nginx外面再做keepalived-vip。虚拟机和prometheus都通过vip访问consul服务。
然后问题来了:
- 向consul注册service,同一个service最多会注册出3个instance。3个instance的ip是相同的,但是每个instance都带了一个consul-server-id的标记。
- 注销service,报404,找不到serviceId。我用A、B、C标识3个consul,假如service注册时请求到了A,那么注销的时候也只能找A注销,找B、C就不行。虽然A、B、C已经组成了集群,注销也只能找注册时的那个consul-node。
- 查询service,如果A、B、C3个consul-node都是活着的,访问任意一个,都能查询到全部的service。但是假如B挂了,A、C或者,访问A、C就只能查到A、C上注册的服务。
综上,可以认为consul集群的数据是伪一致性的。consul集群的中node是带状态的,每个node都保存了自己上面注册service信息。
- 同一个service找集群中不同的node注册,会给service下面创建多个instance。instance中包含了注册时node的信息,除了这个node信息,instance的其他信息是一样的。
- service找哪个node注册,就要找那个node注销。如果不知道注册时的node,注销时就要遍历所有的node。
- 如果所有的node都是活的,访问任意node能获取到所有的service信息。有node挂了,这个node上的注册信息就查不到了。