背景
- devops中日志服务的搭建
- 收集各个节点(agent)的日志文件进ES集群,并提供分析和查询的服务
- 各个agent的filebeat收集服务不能终断,也就是需要动态reload配置文件
- 支持用户设置分隔符划分和正则匹配两种方式添加field字段
技术方案
- 将filebeat部署在agent节点,master节点控制agent节点的配置文件,filebeat很轻量
- 因为filebeat的配置文件支持reload的只有input和moudel两个模块,但是需要对用户提供的分隔符和正则表达式进行处理,可以完成这个操作的processors模块不支持动态reload,所以filebeat只收集日志,处理日志的任务交给logstach,logstach支持整个配置文件的动态reload
Filebeat安装以及使用
-
Filebeat是一个轻量化的日志收集工具,对标Logstach,filebeat只有30M,而logstach有300M
-
调试启动命令:
./filebeat -e -c filebeat.yml
,-c指明配置文件路径,-e表示记录到stderr,并禁用syslog文件输出 -
启动命令相关:https://johng.cn/filebeat-command-configuration/
-
后台启动方式:
nohup ./filebeat -e -c filebeat.yml > filebeat.log &
-
filebeat启动可以使用root用户,但是ES启动不能使用root用户
-
reload相关写法参考:https://blog.csdn.net/junxuezheng/article/details/108349689
-
filebeat.yml配置文件
filebeat.config.inputs: enable: true path: /usr/local/xxx/input.yml reload.enable: true reload.period: 5s output.console: pretty: true #output.elasticsearch: # hosts: ["10.243.65.186:9200"] output.logstash: hosts: ["1.1.1.186:5044"] processors: - rename: fields: - from: host to: _host - from: message to: _message ignore_missing: false fail_on_error: true - drop_fields: fields: - ecs - log - input
-
input.yml文件
- type: log # Change to true to enable this input configuration. enabled: true # Paths that should be crawled and fetched. Glob based paths. paths: - /usr/local/xxx tags: c7f1771f-0c8f-4c75-9d71-3b8c4b6bd191 fields: source: wang_test fields_under_root: true
-
filebeat只能输出到一个地方,logstach可以输出到多个地方
-
fields_under_root,这个字段如果设置为true,则新增的字段成为顶级目录,和message平级,如果为false,则会多出一个fields字段,这个fields字段和message字段平级,我们自定义的字段都存放在fields字段下
-
注意,filebeat文件夹下有一个data的文件夹,可以记录哪些行传输过,所以如果ctrl+c之后再重开,不会把之前传过的内容再传一遍,除非删除这个data文件夹
Logstach安装以及使用
-
二进制安装,解压即用
-
可以用root用户启动
-
部署命令:`bin/logstash -f config/xxx.conf
-
测试config文件是否写的正确
bin/logstash -t -f config/xxx.conf
-
配置logstash自动刷新配置文件:
bin/logstash -f config/xxx.conf --config.reload.automatic
-
配置文件如下:
input { beats { port => 5044 } } filter { mutate{ rename => {"host" => "_host"} rename => {"message" => "_message"} rename => {"tags" => "_tags"} remove_field => ["@version", "ecs"] } if [log][file][path] == "/usr/local/dashuaibi/log/wang.log"{ dissect { mapping => { "message" => "%{wang_time} %{wang_pid} %{wang_level} %{comtent}" } } } } output { if [log][file][path] == "/usr/local/dashuaibi/log/wang.log"{ elasticsearch { hosts => "10.1.1.186:9200" index => "wang_test_666" } } }
- 注意:mapping里的分隔符表达式,最后一个字段默认会把后面所有的内容都接收下来
- field字段的增删改在filebeat和logstash中都可以做,看业务需求。
Elasticsearch安装以及使用
-
二进制安装,解压即用
tar -zxf xxx.tar.gz
-
先在root用户下修改权限
chown -R elastic:elastic elastic
- 最后一个elastic是文件夹的名字
- -R表示处理指定目录以及其子目录下的所有文件
-
vim config/elasticsearch.yml
,将network.host: 0.0.0.0
,让外部可以访问到 -
node.name: node-1
这行的注释也打开,下面这个操作要用 -
vim config/elasticsearch.yml
,将cluster.initial_master_nodes: ["node-1"]
这行的注释打开,有几个节点就在list里写几个值,否则master节点会一直搜索另一个节点,"node-1"是本台机器的hostname,需要提前在/etc/hosts里定义(如果默认没有添加的话),文件里写的是ip + hostname -
启动命令:
bin/elasticsearch
-
ES不能使用root用户启动
-
可以在创建ES索引的时候指定分片的参数,wangtest是要创建的索引名
PUT wangtest { "settings": { "index": { "number_of_shards": 3, "number_of_replicas": 1 } } }
Kibana安装以及使用
- 二进制安装,解压即用
vim config/kibana.yml
,将server.host:"0.0.0.0"
,让外部可以访问到- 启动命令:
./bin/kibana
,注意这个.必须带 - Kibana也不能使用root用户启动,但是根据提示,好像有开关可以控制使用root启动
监控软件cerebro的安装和使用
-
下载压缩包,解压
-
bin/cerebro
-
非必须:如果经常使用的话,可以先在
conf/application.conf
中配置好ElasticSearch服务器地址hosts = [ { host = "http://localhost:9200" name = "Some Cluster" } ]
-
参考:https://www.jianshu.com/p/433d821f9667
如何在脚本里启动filebeat
-
前提背景:有一些场景是需要在脚本里自动启动的 ,且希望在后台运行,所以我想到了nohup
nohup ./filebeat -e -c /usr/local/sahoc/filebeat.yml &
这个做法可以后台起一个进程运行filebeat,但是主进程不会退出,因为启动的filebeat在另一个进程里有终端输出
-
解决方案:
nohup ./filebeat -e -c /usr/local/sahoc/filebeat.yml >> $FILEBEAT_LOG 2>&1 &
这样把终端的输出重定向到一个文件,主进程就不会持续监听了,注意2>&1必须加,必须把所有的输出都追加到文件,文件地址可以是/dev/null
关于ES查询的分页问题
这里的查询分为两种,一种是基于ES的DQL,就是用restfulAPI的调用方式,另一种是说使用SQL语言进行查询。众所周知在MYSQL里分页可以使用limit 10,5来解决,第一个10是偏移量(offset),从第十个数据开始读取,第二个参数5说明是一次取5个值,通过这种方式可以实现分页。但是使用
POST /_sql?format=txt{
"query": "SELECT CONTENT FROM XXX LIMIT 10,5"
}
ES报错,不能识别逗号,所以说这个接口里的limit后面只支持一个参数。下面说分别对应这两种方法的解决方案
-
DQL查询方式
- from+size方式
- scroll方式
- search_after方式
- 参考:https://chunsoft.blog.csdn.net/article/details/91406928
-
SQL的查询方式
- cursor(游标)方式
- 参考:https://blog.csdn.net/qq_42569136/article/details/115465322
- 参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-pagination.html
- 感觉这种方式和上面的search_after是一样的,多用于数据导出,并不适用这种场景,且不能跳转,只能一页一页的读
- fetch_size方案
- 参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-search-api.html#sql-search-api-request-body
- 可以看到这里有一个fetch_size的参数,讲道理应该和上面一样还有一个fetch_from就完美了,可惜是官方并没有提供这个参数,想不明白是为什么
-
最终的方案,使用先用/_sql/translate把SQL查询变成DQL之后,再在DQL里面补充from和size字段,默认情况下使用translate会自动有一个size:1000的对象,如果SQL语句里有limit 100,这个1000就变成100了,但是不会自动添加from
如果一行数据,用指定的分割方式没有分割出来怎么办
直接把这个数据添加到message里,并不会丢弃
如果之前我们的filebeat的input.yml文件有一段时间为空,后面再加上还能正常工作吗?
可以
采用上面的方案会导致,每次有新的数据加入log文件,都会把之前的所有内容再重新传一遍,导致重复采集
- 问题出在vim编辑器,用echo添加就不会有问题,估计是vim保存的时候创建了一个新的文件或者链接
- 参考:https://elasticsearch.cn/question/2533
vi指令保存后,会重复发送,用echo写东西测试没问题,类似vi估计都会有问题。官方论坛翻译内容如下:
你怎么修改文件。你试过了$ echo ‘new line’ >> /usr/src/app/log.log吗?filebeat试图根据元数据来检测文件是否是新的。一些工具/编辑器创建一个全新的文件保存并取消旧链接。这被filebeat检测为新文件,迫使它重新发送所有内容。
上面使用[log][file][path]
不太严谨
-
如果不同机器上有不同的业务,但是log文件名都一样,这样就会把这些日志放在一个索引,其实不应该放在一起
-
采用打tags的方式解决
-
filebeat_input.yml文件里加入tag
- type: log # Change to true to enable this input configuration. enabled: true # Paths that should be crawled and fetched. Glob based paths. paths: - /usr/local/xxx tags: wang1 fields: source: wang_test - type: log # Change to true to enable this input configuration. enabled: true # Paths that should be crawled and fetched. Glob based paths. paths: - /usr/local/xxx tags: wang2 fields: source: wang_test
tags后面的值可以不带引号
-
logstash配置文件根据这个tag去做相应的处理
inputs { beats { port => 5044 } } filter { if "wang1" in [tags]{ dissect { mapping => { "message" => "%{wang_time} %{wang_pid} %{wang_level} %{comtent}" } } } } output { if "wang1" in [tags]{ elasticsearch { hosts => "10.1.1.186:9200" index => "wang_test_666" } } }