(ELK/EFK)之Fluentd日志过滤解析与客户端IP地址地理位置处理

  • A+
所属分类:elk

1 背景与说明

日志收集我们主要采用ELK/EFK方案,具体为什么采用这种方案本篇不进行更多阐述;本篇主要针对把业务日志进行解析并相关处理后推送到ElasticSearch中更方便进行检索与数据统计查看,本篇日志推送源来自于Docker的Fluentd Log Driver,非Docker环境操作的仅作为参考。

2 目的效果图

统计图

3 主要三样插件

3.1 内置Parser插件

这个插件在最新的Fluentd中已经内置了,直接使用即可。参考地址

3.2 ElasticSearch插件

把Fluentd收集到的日志信息推到ES进行存储,参考地址

3.3 地理位置插件

根据客户端IP地址获取到更多地理相关的信息,这样可以在kibana上使用地图与位置的统计图方式更直观查看信息,参考地址

4 开始

4.1 解析日志数据到对应属性

4.1.1 日志原始数据

以下是Docker的输出标准日志数据格式内容。

2017-03-03T10:46:21+08:00   1806d6c91569    {"log":"2017-03-03 10:46:21 HKT  INFO AccessInterceptor:80 - {time=1488509181152, method=POST, action=/nakedhub/adminx/auth/welcome, locale=zh_CN, cost=4, userId=185713, user-agent=null, header-security-token=null, clientIp=139.196.12.22, clientType=null, params={password=111111, username=maomao}, status=200, paramsOfJson=null}","container_id":"1806d6c91569612cdd746651eeb808591e0176befe565820a339294fc2a9ea0d","container_name":"/nhbackend-st.1.d7r1qsa35zwfxtsmyh5np61ft","source":"stdout"}

4.1.2 核心解析格式配置

<filter **>
    @type parser
    time_format %Y-%m-%d %H:%M:%S %Z
    key_name log
    suppress_parse_error_log true
    reserve_data true
    format /.*(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \w+?).+AccessInterceptor(.+time=(?<requesttime>.+?),)(.+method=(?<method>.+?),)(.+action=(?<action>.+?),)(.*locale=(?<locale>.+?),)(.+cost=(?<cost>.+?),)(.*userId=(?<userId>.*?),)(.*agent=(?<user-agent>.*?),)(.+token=(?<token>.*?),)(.+clientIp=(?<clientIp>.+?),)(.+clientType=(?<clientType>.+?),)(.*params={(?<params>.*?)})(.+status=(?<status>.*?),)(.*Json=(?<paramsOfJson>.*?)})/
    types cost:integer,status:integer
  </filter>

这里我采用Fluentd中的”filter”对数据进行过滤处理,主要的格式化配置都在”format”这段配置中,主要采用正则表达式拆分数据到自定义的以”<>”包围起来的属性中,测试表达式格式可以点开在线格式解析表达式,测试完毕后再把表达式配置就好了;另外值得注意的是”time”这个属性值,这个值解析器会自动识别为时间类型,会按照”time_format”配置定义的格式转换至时间类型;”key_name”配置在官方文档中并没有提及(但这个配置是必须的),我得出来的结论是这个配置会把外层JSON的”log”内容拿出来后再去做解析;”types”则是把自定义的属性进行类型指定,推送到Elasticsearch中也是相应类型(否则通过kibana做统计计算的时候由于不是Number类型会有问题);”reserve_data”配置则表示原始”log”的内容是否保留到输出项中。

4.1.3 最后日志输出项

2017-03-03T10:46:21+08:00   1806d6c91569    {"log":"2017-03-03 10:46:21 HKT  INFO AccessInterceptor:80 - {time=1488509181152, method=POST, action=/nakedhub/adminx/auth/welcome, locale=zh_CN, cost=4, userId=185713, user-agent=null, header-security-token=null, clientIp=139.196.12.22, clientType=null, params={password=111111, username=maomao}, status=200, paramsOfJson=null}","container_id":"1806d6c91569612cdd746651eeb808591e0176befe565820a339294fc2a9ea0d","container_name":"/nhbackend-st.1.d7r1qsa35zwfxtsmyh5np61ft","source":"stdout","requesttime":"1488509181152","method":"POST","action":"/nakedhub/adminx/auth/welcome","locale":"zh_CN","cost":4,"userId":"185713","user-agent":"null","token":"null","clientIp":"139.196.12.22","clientType":"null","params":"password=111111, username=maomao","status":200,"paramsOfJson":"null"}

4.2 推送到ElasticSearch核心配置

<match>
      @type elasticsearch
      host 10.47.121.12
      port 9200
      user elastic
      password 123456
      scheme http
      index_name fluentd
      type_name fluentd
      logstash_format true
      logstash_prefix docker
      reload_connections false
</match>

由于我的ES安装了XPACK所以我使用了账号与密码项配置内容,另外注意”password”这里不用使用特殊字符,否则会出现Fluentd连接ElasticSearch的时候字符编码不对导致认为账户与密码不对的错误问题。

4.3 客户端IP地理位置处理

4.3.1 注意

这个”filter”的配置项必须要在以上日志解析的配置项下面,要先解析到了”clientIp”属性,我们才能方便配置从而让插件获取客户端IP地址处理地理位置属性。

4.3.2 核心配置

<filter **>
    type geoip
    geoip_lookup_key clientIp
    geoip_database /home/fluent/GeoLiteCity.dat
    <record>
      latitude        ${latitude["clientIp"]}
      longitude       ${longitude["clientIp"]}
      country_code3   ${country_code3["clientIp"]}
      country         ${country_code["clientIp"]}
      country_name    ${country_name["clientIp"]}
      dma             ${dma_code["clientIp"]}
      area            ${area_code["clientIp"]}
      region          ${region["clientIp"]}
      city            ${city["clientIp"]}
      location        '[${longitude["clientIp"]},${latitude["clientIp"]}]'
    </record>
    skip_adding_null_record  true
    log_level         info
    flush_interval    1s
</filter>

“GeoLiteCity.dat”参考GITHUB项目地址去下载,”location”会自动转换为”geo_point”类型。

4.3.3 Kibana类型”geo_point”问题

No Compatible Fields: The "xxx" index pattern does not contain any of the following field types: geo_point
  • 1

当”location”属性值已经存在ES中了就算配置后依然无法自动转成”geo_point”类型,我们需要手动进行处理了,先删除相关的所以索引,然后手动创建类型模板定义”location”的类型,然后创建测试索引查看。

4.3.3.1 创建模板类型

打开Shell控制台创建文件”json”,文件内容为以下。

{
  "template": "docker-*",
  "mappings": {
    "_default_": {
      "properties" : {
        "location": { "type": "geo_point"}
      }
    }
  }
}
curl -u elastic:123456 -XPUT 'http://10.47.121.12:9200/_template/docker' -d @json

4.3.3.2 创建测试索引

curl -u elastic:123456 -XPUT 'http://10.47.121.12:9200/docker-test/fluentd/2' -d '{"host":"8.8.8.8","location":[1.23,4.56]}'

4.3.3.3 查看索引属性类型

curl -u elastic:123456 -XGET http://10.47.121.12:9200/docker-test/fluentd/_mapping?pretty

4.3.3.4 原始问题参考地址

https://github.com/y-ken/fluent-plugin-geoip/issues/16

4.3.4 最后日志输出内容

2017-03-03T10:46:21+08:00   1806d6c91569    {"log":"2017-03-03 10:46:21 HKT  INFO AccessInterceptor:80 - {time=1488509181152, met
  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin
ssh

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: