open-falcon 自定义上报主机名

后记

本文的主要逻辑代码已提交PR并合并到官方代码中,不过获取变量改为FALCON_ENDPOINT。因此我们在线上环境中,仍然自行维护了下文中的补丁,以适应自身的业务需求。

背景

open-falcon 监控系统里面有一个重要的概念为 endpoint,可以理解为监控项目在主机标识。
默认将操作系统的主机名上报为 endpoint ,同时可以修改 agent 的 cfg.json 的 hostname 属性来自定义主机标识。
服务器规模大的时候,主机名命名趋向与业务无关、IP地址无关,常见以各种随机算法命名,也就是从主机名中很难看出来这台服务器是什么业务,也不一定能主机名中看出其IP地址的特征。

自定义主机名

我们的做法是,主机名随机命名,监控上报时以自定义数据来代替主机名,自定义数据中,有业务类型、业务属性、IP 地址等信息,仅仅通过自定义主机名即可判断告警的影响范围。
自定义属性举例: basic_nginx_1.2.3.4, cache_redis_web_5.6.7.8, java_pay_11.22.33.44.
我们将自定义主机名命名为 ENDPOINT 环境变量。

自定义主机名的实现

在每个主机增加 /etc/endpoint.env 文件,示例内容为:
ENDPOINT=basic_nginx_1.2.3.4

创建 /etc/profile.d/91-env.sh 文件,解析 /etc/endpoint.env 文件,输出环境变量 ENDPOINT,并覆盖 shell 的 PS1,文件内容为:

#!/bin/bash
# /etc/profile.d/91-env.sh
export ENDPOINT=$(test -f /etc/endpoint.env && cat /etc/endpoint.env | cut -d'=' -f 2 || hostname -s)
export PS1='[\u@${ENDPOINT} \W]\$'

同时,监控系统 zabbix、open-falcon 上报的主机名也不是默认的操作系统的主机名,而是自定义的ENDPOINT 环境变量的值 。

1.0 时代:修改 open-falcon 客户端配置

在初始化每台主机时,自动将自定义主机名填入到 falcon-agent 的配置文件 cfg.json 中的 hostname 属性。 这样操作以后,每台主机的 falcon-agent 的 cfg.json 配置文件的 hostname 属性都不一样,其他配置均相同。
PS: zabbix 修改 /etc/zabbix/zabbix_agentd.conf 的 Hostname 的属性。

思考改进

以上修改配置文件的方式,将每个 agent 的配置文件变成了“有状态”的方式,始终觉得不够优雅,增加了维护成本。
改进思路:

  • 修改启动脚本,启动时获取环境变量 ENDPOINT,通过 jq 命令行修改 cfg.json 。
  • 修改 agent 代码,获取环境变量 ENDPOINT 来代替获取系统主机名。

分析 falcon-agent 关于主机名获取的逻辑代码,修改代码相对容易,后期维护成本也比较低,我们采用了第二种方式。(在此YY一下,如果这种方式的处理能被官方接受,代码合并到官方就更没有维护成本了。)

处理代码

主机名获取的优先级为:

  1. cfg.json 中的 hostname 属性
  2. 环境变量 ENDPOINT
  3. 文件 /etc/endpoint.env 中的 ENDPOINT 的值 (作为取不到环境变量的 fallback 方法)
  4. 操作系统的主机名
diff --git a/modules/agent/g/cfg.go b/modules/agent/g/cfg.go
index c3e0181..6e4765a 100644
--- a/modules/agent/g/cfg.go
+++ b/modules/agent/g/cfg.go
@@ -2,8 +2,10 @@ package g

 import (
        "encoding/json"
+       "io/ioutil"
        "log"
        "os"
+       "strings"
        "sync"

        "github.com/toolkits/file"
@@ -72,6 +74,29 @@ func Hostname() (string, error) {
                return hostname, nil
        }

+       if os.Getenv("ENDPOINT") != "" {
+               hostname = os.Getenv("ENDPOINT")
+               return hostname, nil
+       }
+
+       // parse /etc/endpoint.env ( ENDPOINT=xxx_xxx_1.2.3.4 )
+       filePath := "/etc/endpoint.env"
+       if _, err := os.Stat(filePath); err == nil {
+               data, _ := ioutil.ReadFile(filePath)
+               str := string(data)
+               if !strings.ContainsAny(str, "ENDPOINT") {
+                       log.Panic("ERROR: /etc/endpoint.env missing ENDPOINT")
+               }
+               if !strings.ContainsAny(str, "=") {
+                       log.Panic("ERROR: /etc/endpoint.env missing =")
+               }
+               str = strings.Trim((strings.SplitAfter(str, "ENDPOINT"))[1], " ")
+               hostname = strings.Trim((strings.SplitAfter(str, "="))[1], " ")
+               if len(hostname) > 1 {
+                       return hostname, nil
+               }
+       }
+
        if os.Getenv("FALCON_ENDPOINT") != "" {
                hostname = os.Getenv("FALCON_ENDPOINT")
                return hostname, nil

falcon-agent 的 Systemd 启动脚本

启动脚本会将 ENDPOINT 环境变量传递给 falcon-agent 程序
/etc/systemd/system/falcon-agent.service

[Unit]
Description=The falcon agent
After=network.target

[Service]
LimitNOFILE=1048576
Restart=always
RestartSec=30
Type=simple
EnvironmentFile=-/etc/endpoint.env
Workdir=/app/monitor/falcon
ExecStartPre=/app/monitor/falcon/falcon-agent -c /app/monitor/falcon/cfg.json -check
ExecStart=/app/monitor/falcon/falcon-agent -c /app/monitor/falcon/cfg.json
TimeoutStopSec=5
PrivateTmp=true
User=nobody

[Install]
WantedBy=multi-user.target

说明: master 分支的代码已经修复了 agent check 启动失败的问题。

falcon-agent 的 init 启动脚本

启动脚本会将 ENDPOINT 环境变量传递给 falcon-agent 程序

#!/bin/bash
# chkconfig: 2345 90 10
# description: falcon-agent
export PATH=/usr/java/latest/bin:/sbin:/bin:/usr/sbin:/usr/bin
WORKDIR="/app/monitor/falcon"
EXEC_CMD='/app/monitor/falcon/control'

if [[ ! -f ${EXEC_CMD} ]];then
   echo "$EXEC_CMD not found"
   exit 1
fi

RETVAL=$?

start_pre(){
    source /etc/profile
    test -f /etc/endpoint.env && export $( cat /etc/endpoint.env )
    cd $WORKDIR
}

case "$1" in
    start|stop|restart|status)
        start_pre
        su - nobody -s /bin/bash -c "$EXEC_CMD $1"
        ;;
    *)
        echo $"Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

exit $RETVAL

愉快的玩耍

修改后的 falcon-agent 程序和配置文件,在我们几百台服务器上都是一样,通过灰度上线部分节点运行无异常后,已通过自动化发布程序全部更新上线。

你可能感兴趣的:(open-falcon 自定义上报主机名)