fluentd+elasticsearch+grafana搭建指北

通常大家都用ELK,但是这个世界就永远不会被一样事物统一的,主要是grafana也支持从ES中进行查询了,那就用下,毕竟grafana的界面比kinbana好看很多,虽然都是现成的,也没有二次开发的内容,但是还是会碰到一些问题,这个用ELK其实也会碰到的。 首先,默认fluentd是没有type标志的,这样导致默认到es中的都是string类型,这样只能做count了。所以我们要在所有client上安装fluent-plugin-typecast这个插件。 然后在服务端需要安装2个插件,其实一个就可以了fluent-plugin-elasticsearch, fluent-plugin-secure-forward。 用来支持传输到es中。 好了下面就是fluentd的具体配置了。首先是client端就是靠tail来收集, 但是重点是format的部分如何去匹配,还得考虑日志中的多种不同格式。 同时在打tag的时候把机器名也打进去,这样汇总的时候方便找从哪个nginx过来的日志。 还有type的部分可以把非string的给单独拉出来进行处理,string的就不用处理了。 下面这个是fluentd客户端上的配置: ```c
type tail path /opt/server/log/nginx/nginx-access.log format /^(?[^ ])\s+(?[^ ]) (?[^ ]) \[(?)\] “(?\S+)(?: +(?[^\“]) +\S)?” (?[^ ]) (?[^ ])(?: “(?[^\“])” “(?[^\“])” “(?[^\“])” (?[^ ])\s+(?[^ ])\s+(?[^ ])\s+(?[^ ])\s+(?[^ ]))?$/ time_format %Y-%m-%dT%H:%M:%S%z types status:integer,size:integer,response_time:float,upstream_time:float,cache_status:integer,upstream_status:integer tag “#{Socket.gethostname}.nginx.access.log” pos_file /var/log/td-agent/tmp/nginx.access.log.pos <match .nginx.access.log> type forward flush_interval 60s buffer_type file buffer_path /opt/server/buffer/ host agg1.hk.op.xxx.com port 24224

这里主要就是填写es的地址,然后在time_slice_format稍微耍了小花样,这样可以按年月日的分目录进行存放。不然都放同一个目录也不好查找。 ```c
1
2
3
 <match *.nginx.access.log> type copy <store> type file path /opt/server/logs/nginx-access/ time_slice_format ./nginx-access/%Y/%m/%d/%Y%m%d%H.nginx.access compress gzip flush_interval 10m time_format %Y-%m-%dT%H:%M:%S%z buffer_path /opt/server/buffer/nginx_access_buffer buffer_type file buffer_chunk_limit 50m </store> <store> type elasticsearch host hk1.es.op.xxx.com port 9200 include_tag_key true tag_key @log_name logstash_format true flush_interval 10s </store> </match> 
```   es的安装的部分就不在这里展开了,也许会在其他地方说下。不过要推荐一个工具kopf, zou哥去es大会上听来后马上给装上了,还不错,可以看到index,  node, share 这些信息,而且随着cluster的健康状态会以不同的颜色来显示出来,这样还是很贴心的。 下面这个就是一个运行的截图 [![kopf](https://images.timoq.com/2015/12/kopf.png)](https://images.timoq.com/2015/12/kopf.png) grafana的安装也不说了,我用的是2.5 stable版本,支持了es做为datasource, 也支持用户验证等等。 默认grafana是用query_string来进行全文匹配,而且不支持正则,不过grafana也支持自定义书写es查询 [https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html) https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html 根据上面的语法我们就可以自定义自己的查询语句。不过我更喜欢正则匹配。 [![grafana-regex](https://images.timoq.com/2015/12/grafana-regex.png)](https://images.timoq.com/2015/12/grafana-regex.png) 第一天用正则匹配发现了问题,怎么都匹配不上URL,后来group by 一下,居然发现png,jpg这些排在最前面,于是查了下原因, 正则不匹配的原因是因为es默认通过/ . 这些符号来进行默认分词。 那就只好更改es的index template,  把某些字段不让它进行分词,下面是我自己建立的一个template, 只用在某些index中。也可以在kopf中进行定义。 ```c
curl -XPUT http://hk1.es.op.xxx.com:9200/_template/template_1 -d ' { "mappings": { "_default_": { "_all": { "enabled": false }, "_source": { "compress": true }, "properties" : { "path": { "type": "string", "index": "not_analyzed" }, "referer": { "type": "string", "index": "not_analyzed" }, "agent": { "type": "string", "index": "not_analyzed" } } } }, "settings": { "index.cache.field.type" : "soft", "index.refresh_interval": "5s", "index.store.compress.stored": true, "index.number_of_shards": "3", "index.query.default_field": "querystring", "index.routing.allocation.total_shards_per_node": "2" }, "template": "logstash-*" }'