关于 判断网络连通性 一次有趣的实验

319 阅读1分钟

1. 前言介绍

最近做prometheus相关监控,为减少运维工作量,做了node_exporter 自动注册到ZK, 然后prometheus 从ZK中拿到监控target列表即可。在node_exporter 遇到 服务器网卡多,ip地址多时,会发生 注册到ZK中的IP 不正确,prometheus server端联node_exporter不通的情况。

2. 解决方案

如果仅仅通过规则判断IP地址规则,如:去掉回环地址等,还是比较复杂。换个思路,给node_exporter 新增一个参数,传入 promtheus server端真实IP地址,然后node_exporter在轮询服务器网卡及网卡上IP地址时,测试该IP是否能ping通prometheus server端IP来判断该IP地址是否可用。

详情如:

./node_exporter  --sd.zookeeper-address="XXX:2181"    --cf.prometheus-server-ip="XXXX"

1. 在启动node_exporter 的时候给定prometheus server 的真实IP.
2. 在node_exporter 注册ZK的时候,轮训服务器上的网卡以及网卡上的ip,设置为 srcIp.
3. 在程序中,设置 pinger.Source=${srcIp} 类似于 linux Ping命令中,指定 -I  ,参考 man ping.

-I interface
            interface  is  either  an  address,  or an interface name.  If interface is an address, it sets source address to specified interface address.  If interface in an interface name, it sets source interface to specified
            interface.  For IPv6, when doing ping to a link-local scope address, link specification (by the '%'-notation in destination, or by this option) is required.

代码示意如下:

import (
   "errors"
   "github.com/go-ping/ping"
   "net"
   "strings"
   "time"
)
/**
 ping prometheus server ip  from  given src ip , and other detail config refer the function code.
*/
func PingPrometheusServerFromSrcIp(srcIp string,prometheusIp string)(reachable bool,err error){
   reachable=false
   pingUtil, err := ping.NewPinger(prometheusIp)
   if err != nil {
      return
   }
   pingUtil.SetPrivileged(true)
   pingUtil.Count = 2
   pingUtil.Source=srcIp
   pingUtil.Timeout=time.Duration(pingUtil.Count)*time.Second

   err = pingUtil.Run()
   if err != nil {
      return
   }
   //不是全部丢包
   if stats := pingUtil.Statistics(); stats.PacketLoss < 100{
      reachable=true
   }
   return
}

3. 方案总结

这样做的优点: 方便运维同学 用相同命令 批量刷服务,代码实现也相对简单。