自从使用EFK(Elasticsearch/Fluentd/Kibana)日志系统对各项目的日志进行采集、分析及可视化展示后,逐渐发现添加配置是件繁琐的事情。于是构想对从添加配置到可视化过程中可自动化的部分,初步针对以下方面进行自动化减轻工作负担,让日志的采集、分析和可视化更轻松方便:
- 自动添加Fluentd配置
 日志需要采集则需要在日志生成端对Fluentd进行配置,并且汇聚端同样需要添加相关的Fluentd配置。手动添加既繁琐又容易出错,所以这部分需要交由程序完成。
- 自动添加Kibana图表
 Fluentd采集日志存入Elasticsearch后,要在Kibana上可视化则需要添加各种图表,添加完图表后还需要添加Dashboard将图表统一添加进Dashboard方便查看。这个过程只是添加一个项目就已经比较繁琐,若需要同时添加多个项目则需要浪费很多时间进行添加图表及Dashboard。这部分是必须自动完成的,手动操作过于耗时耗力。
 针对以上两点,主要通过Shell及Python程序完成自动添加Fluentd配置和Kibana图表的工作,简要流程如下:
- 在Fluentd汇聚端使用FlaskPython框架写接口,负责接收传递过来的参数并调用Shell脚本添加Fluentd汇聚端配置及添加Kibana图表。
- 在日志生成端利用Shell脚本获取输入参数,将参数组合成JSON格式并POST提交给Flask接口。
自动添加Fluentd配置
- 日志生成端获取配置Fluentd的tag,组合成JSON格式后POST提交到Python接口
- Python接口接收- tag,调用本地脚本添加汇聚端Fluentd配置。检查Fluentd配置是否正确、重新加载配置文件、返回结果- code给客户端脚本
- 判断服务端返回结果code,成功则添加客户端Fluentd配置
客户端脚本部分代码:
 因为Elasticsearch的Indices名不能存在大写字母,所以统一所有tag的字母均为小写字母1
2
3
4read -p "请输入tag(字母必须小写且不包含空格): " FLUENTD_TAG_TMP
read -p "请输入日志路径: " LOG_PATH
FLUENTD_TAG="`echo $FLUENTD_TAG_TMP|awk '{gsub(/ +/,"_",$0);print tolower($0)}'`"
 调用Python接口,POST请求接口将数据以JSON格式提交,添加服务端Fluentd配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36echo -e "调用服务端接口添加配置文件......"
FLUENTD_RESULT="`curl -s -X POST -H "Content-Type: application/json" -d '{"auth_key":"'$AUTH_KEY'", "fluentd_tag":"'$FLUENTD_TAG'", "action_type":0}' $POST_URL`"
case "$FLUENTD_RESULT" in
	0)
		echo -e "\033[0;40;31m服务端添加配置成功\033[0m"
		AddFluentdConfig
		ReloadFluentd
		CallKibanaAPI
		;;
	1)
		echo -e "\033[0;40;31m认证失败\033[0m"
		exit 6
		;;
	2)
		echo -e "\033[0;40;31m服务端配置文件已存在\033[0m"
		read -p "是否继续添加客户端配置(y/n): " FLAG
		if [[ $FLAG == 'y' ]]; then
			AddFluentdConfig
			ReloadFluentd
		else
			exit 7
		fi
		;;
	3)
		echo -e "\033[0;40;31m服务端配置文件发现错误,请手动检查服务端配置\033[0m"
		exit 8
		;;
	4)
		echo -e "\033[0;40;31mPOST参数错误\033[0m"
		exit 9
		;;
	*)
		echo -e "\033[0;40;31mError: $FLUENTD_RESULT.\033[0m"
		exit 10
		;;
esac
 Python接口接收参数,调用本地脚本添加服务端Fluentd配置
 Python接口使用Flask轻量框架,以守护进程方式运行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class AutoEFKDaemon(Daemon):
    """自动添加Fluentd/Kibana配置"""
    def run(self):
        """overwrite class Daemon's function run()"""
        app = Flask(__name__)
        @app.route('/autoEFK', methods=['POST'])
        def autoAddEFKConfig():
            """添加Fluentd配置 & 调用Elasticsearch接口使Kibana画图"""
            #接收POST参数。action_type=0 添加Fluentd;action_type=1 Kibana绘图
            try:
                auth_key = request.json['auth_key']
                fluentd_tag = request.json['fluentd_tag']
                action_type = int(request.json['action_type'])
            except Exception:
                return str(4)
            fluentd_bash_script = os.path.join(sys.path[0], 'script/autoAddFluentd.sh')
            kibana_bash_script = os.path.join(sys.path[0], 'script/autoAddKibana.sh')
            #简单验证
            if auth_key != 'HVlbnRkCg==':
                return str(1)
            #调用Fluentd shell脚本
            if action_type == 0:
                shellReslulCode = subprocess.call(['bash', fluentd_bash_script, fluentd_tag])
                return str(shellReslulCode)
            elif action_type == 1:
                shellReslulCode = subprocess.call(['bash', kibana_bash_script, fluentd_tag])
                return str(shellReslulCode)
        app.run(host='0.0.0.0', port=23333)
Kibana自动绘图
 Kibana自身并不提供API,所以想要通过程序使得Kibana自动绘图则需要通过调用Elasticsearch的API。因为Kibana使用Elasticsearch的index来存储Visualizations和Dashboard等信息,在Kibana的配置文件中有相关配置。该index目录在Elasticsearch的indices目录下,默认的目录名称为.kibana。
| 1 | $> vim /usr/local/kibana/config/kibana.yml | 
 可以通过Elasticsearch的API查看及创建Kibana相关数据。有关Kibana最重要的数据有:index-pattern、visualization和dashboard。通过curl可直接查看相关数据1
2
3
4
5
6
7
8
9#查看所有不同类型的数据
curl -XGET 'http://localhost:9200/.kibana/_search?type=index-pattern&pretty'
curl -XGET 'http://localhost:9200/.kibana/_search?type=visualization&pretty'
curl -XGET 'http://localhost:9200/.kibana/_search?type=dashboard&pretty'
#查看具体类型下具体实例的数据
curl -XGET 'http://localhost:9200/.kibana/index-pattern/your_index-pattern_name?pretty'
curl -XGET 'http://localhost:9200/.kibana/visualization/your_visualization_name?pretty'
curl -XGET 'http://localhost:9200/.kibana/dashboard/your_dashboard_name?pretty'
 查看名为logstash-*的index-pattern数据1
2
3
4
5
6
7
8
9$> curl -XGET 'http://localhost:9200/.kibana/index-pattern/logstash-*?pretty'
{
  "_index" : ".kibana",
  "_type" : "index-pattern",
  "_id" : "logstash-*",
  "_version" : 15,
  "found" : true,
  "_source":{"title":"logstash-*","timeFieldName":"@timestamp","fields":"[{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},......}
}
 假如请求一个并不存在的index-pattern,则会返回如下信息"found" : false,可用于判断数据是否已存在于Kibana中。1
2
3
4
5
6
7$> curl -XGET 'http://localhost:9200/.kibana/index-pattern/test*?pretty'
{
  "_index" : ".kibana",
  "_type" : "index-pattern",
  "_id" : "test*",
  "found" : false
}
 获得数据格式后便可构造数据,通过程序创建Kibana相关数据。比如需要创建index-pattern数据结构和logstash-* 相同的新index-pattern,新index-pattern的名称为test*,只需要将_source的内容做适当修改并提交给Elasticsearch便可:1
$> curl -XPUT 'http://localhost:9200/.kibana/index-pattern/test-*?pretty' -d '{"title":"test-*","timeFieldName":"@timestamp","fields":"[{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},......}'
 创建visualization和dashboard方法相同。index-pattern、visualization和dashboard之间相互依赖,注意修改数据中相关联的部分即可。1
index-pattern————>visualization————>dashboard
改进
目前初步实现利用脚本程序完成日志的采集、分析和可视化流程,但仍有可改进的地方。
- 利用SaltStack进行统一的配置管理。若项目增多需要管理的配置文件便会增加,为方便统一管理配置文件需要使用额外的工具进行管理。
- 操作的Web界面化。目前只实现运行脚本添加配置,为更进一步方便添加、管理配置,可开发拥有Web界面操作及结合SaltStack的管理系统。