Grafana和Kibana绘制Nginx请求分布地图

最近一时兴起,想用地图展示我们服务(nginx)的请求分布情况,于是就有了这篇记录。

思路:

第一步:将nginx日志通过GeoLite2-City.mmdb地图库把IP转换成经纬度,传到ELK中;

第二步:通过kibana或grafana读取经纬度信息并绘制成地图。

其中:kibana使用Coordinate Map插件,高版本自带的有我这里用的是6.5版本;grafana使用Worldmap Panel插件,按grafana的 Worldmap Panel 步骤安装。

1、采集 nginx 日志到 ELK

1.1 nginx 配置 log_format

1
2
3
log_format  access  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

别忘了重启nginx使配置生效

1
./nginx/sbin/nginx -s reload

1.2 filebeat 采集 nginx 日志

这里将采集的nginx日志转发到logstash,主要是为了聚合日志,然后通过logstash统一传到kafka进行过度后,再通过logstash写入到ES;这样当日志突增的时候不会因为logstash消费不过来而丢失日志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat filebeat/filebeat.yml

filebeat.prospectors:

- input_type: log
paths:
- /work/admin/nginx/logs/39.97.130.241.log
- /work/admin/nginx/logs/access.log
- /work/admin/nginx/logs/*.com.log
- /work/admin/nginx/logs/*.cn.log
document_type: nginx-logs

output.logstash:
hosts: ["logstash.feiersmart.local:5044"]
output.console:
pretty: true

这里使用的还是filebeat-5.5.3的filebeat,如果是6X版本的配置可能稍有变化

启动filebeat,我这里使用supervisor管理服务

1
2
3
4
5
[program:filebeat]
command=/work/admin/filebeat/filebeat -e -c /work/admin/filebeat/filebeat.yml
directory=/work/admin/filebeat
redirect_stderr=true
autorestart=true

1.3 logstash 传到 kafka

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat logstash-nginx-logs.conf 

output {

if [type] == "nginx-logs" {

kafka {
bootstrap_servers => "kafka1.feiersmart.local:9092,kafka2.feiersmart.local:9092,kafka3.feiersmart.local:9092"
topic_id => "logstash-nginx-logs"
codec => "json"
compression_type => "gzip"
max_request_size => 10000120
}
}
}

配置好后,重启logstash服务

1.4 logstash 写到 ES

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
36
37
38
39
40
41
42
cat logstash-6.5.3-es/conf.d/logstash-nginx-logs.conf 

input {
kafka {
bootstrap_servers => "kafka1.feiersmart.local:9092,kafka2.feiersmart.local:9092,kafka3.feiersmart.local:9092"
topics => ["logstash-nginx-logs"]
codec => "json"
}
}

filter {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
geoip {
source => "clientip"
target => "geoip"
add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ]
add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ]
}
mutate {
convert => [ "[geoip][coordinates]", "float"]
}
}

output {

if [type] == "nginx-logs" {

stdout {
codec=>rubydebug
}

elasticsearch {
hosts => ["bj-es1.feiersmart.local:9200","bj-es2.feiersmart.local:9200","bj-es3.feiersmart.local:9200"]
index => "logstash-nginx-logs-%{+YYYY.MM.dd}"
document_id => "%{type}-%{+YYYY.MM.dd}-%{host}-%{offset}"
}
}
}

grok:日格式匹配
geoip:
source:通过geoip处理的信息,这里我们为了通过ip获取经纬,所以选择clientip作为处理的对象
target:通过geoip解析出来的地址信息存储在什么字段里,这里指定为geoip
add_field:将解析出来的经纬存放在geoip.latitude和geoip.longitude中,并且有一个geoip.coordinates是生成的经纬点
mutate:定义格式为float
output:
输出到elasticsearch,host是elk的elasticsearch的IP,默认端口9200
设置index为logstash-nginx-logs-,这在Kibana中创建index的时候会用到

配置好后,重启logstash服务

1.5 kibana 创建索引

6.5版本在 Management –> Index Patterns –> Create index pattern ,然后搜索上面的索引 logstash-nginx-logs-*,最后点击 Next step 成功创建索引。

2、kibana 绘制请求分布地图

在kibana首页选择 Visualize 点上方的+号,然后选择 Coordinate Map

kibana绘图非常简单,对中文城市名称的支持也非常好

3、grafana 绘制请求分布地图

3.1 grafana 安装 Worldmap Panel 插件

1
grafana-cli plugins install grafana-worldmap-panel

多种安装方法可参考:Worldmap Panel

安装完后重启grafana服务

3.2 添加 ES 数据源

image-20200107145429228

3.3 绘制请求分布地图

如果需要查询特定域名,可以在Query中写ES查询条件

图形选择刚刚安装的 Worldmap Panel,地图数据(Map Data Options)选择 geohash,geo_point/geohash Field填写geoip.location,在ES中geoip.location存储着经纬度信息

遗憾的是,我这里 Worldmap Panel 不能显示中文城市信息,也可能是我配置的有问题,后续有进展了再更新。

-------------本文结束感谢您的阅读-------------