使用filebeat采集nginx-access日志

说在前面

nginx由于优异的性能表现,被很多系统拿来做前端部署、负载均衡等功能。其中nginx自带的access日志记录的访问日志也是相当值得拿来分析的,本篇文章将对如何使用filebeat采集nginx日志进行介绍,并针对标准日志接入和非标准日志格式接入展开说明,希望对各位读者有所帮助。

常见采集access.log 日志的工具有2个:logstash和filebeat,后者相对来说更加轻量级,对内存更为友好,因此我们此处选择用filebeat来进行演示。access.log作为常规且常用的访问日志文件,filebeat推出后ES官方就专门为nginx做了十分轻便的标准化解决方案,以便开发人员可以用很小的代价来实现日志接入ES。

方案一、filebeat最简化采集nginx

filebeat默认自带nginx module(支持nginx应用access.log日志格式化),但是这个模块默认为非启用状态,需要我们手动启用,下面我们来介绍如何使用

(一)启用nginx mudule
# 启用
./filebeat modules enable nginx

# 如果需要恢复禁用,则执行
./filebeat modules disable nginx

启动nginx模块后,会在$filebeat_home/modules.d 目录下看到原先nginx.yml.disable文件变成了nginx.yml,说明激活成功了

(二)配置filebeat
  • $filebeat_home/modules.d/nginx.yml 核心配置
    主要配置项有2个:access.enabled开关打开,var.paths路径指定nginx日志文件的路径
- module: nginx
  # Access logs
  access:
    enabled: true
    var.paths:
      - /usr/local/nginx/logs/access_log.log

  # Error logs
  error:
    enabled: false
    #var.paths:

  ingress_controller:
    enabled: false

$filebeat_home/nginx.yml文件中已经默认有了如下配置,这样只要我们配置了nginx.yml文件,就可以自动导入到filebeat.yml配置文件中了

filebeat.config.modules:
  # Glob pattern for configuration loading
  path: ${path.config}/modules.d/*.yml

  # Set to true to enable config reloading
  reload.enabled: true

  # Period on which files under path should be checked for changes
  reload.period: 10s

因此,当我们完成nginx.yml文件的配置后,只需要启动filebeat,就可以依赖filebeat自带的nginx模块来实现nginx日志json格式化的解析。
需要注意,这种情况下默认还是用的filebeat-xxx的索引名,虽然开箱即用,但是并不好用,后期维护起来比较麻烦。

方案二、filebeat格式化采集nginx(推荐)

方案二不直接依赖filebeat封装好的nginx模块,而是自己利用filebeat的内置函数,来实现

# 正常配置日志数据源
- type: log
  id: demo-nginx
  enabled: true
  paths:
    - /usr/local/nginx/logs/access.log
  # 引入标签,方便和其他应用日志源做区分
  tags: ["demo-nginx-access"]

定义ES源,并根据tag来创建索引


output.elasticsearch:
  # Array of hosts to connect to.
  hosts: ["10.10.10.10:9200"]
  protocol: "http"
  username: "xxxx"
  password: "xxxx"

  indices:
    - index: "demo_nginx_%{+yyyy.MM.dd}"
      when.contains:
        tags: "demo-nginx-access"

核心逻辑,定义处理器,用来做nginx access日志文本转json的逻辑
这里简单做一下介绍,首先是判断是否包含指定的标签,有的话才走处理器的逻辑,否则就正常输出到ES。
接着我们选择dissect处理器,定义好分词的规则,这里的tokenizer看着复杂,其实就是把nginx目前已有的日志格式放上去而已,nginx会自动根据你定义的占位符去做解析和赋值给占位符的变量。
默认情况下,解析出来的文本可能是text类型,如果我们希望转成数值类型的话,可以在convert属性下单独定义字段类型的转换,其实也不难。剩下的就是一些可选的配置项了

processors:
  - if:
      has_fields: ["tags"]
      and:
        - contains:
            tags: "demo-nginx-access"
    then:
      - dissect:
          tokenizer: "%{remote_addr} - %{remote_user} [%{time_local}] \"%{request_method} %{request_url} %{request_proto}\" %{status} %{request_length} %{body_bytes_sent} \"%{http_cookie}\" \"%{http_user_agent}\" %{request_time} %{upstream_addr} %{nginx_host} \"%{http_x_forwarded_for}\""
          field: "message"
          target_prefix: ""
      - convert:
          fields:
            - {from: "status", to: "status", type: "integer"}
            - {from: "request_length", to: "request_length", type: "integer"} 
            - {from: "body_bytes_sent", to: "body_bytes_sent", type: "integer"} 
            - {from: "request_time", to: "request_time", type: "float"} 
          ignore_missing: true
          ignore_failure: true
      - drop_fields:
          fields: ["message", "ecs"]  
          ignore_missing: true 

配置完成后,filebeat就会在采集日志后按照要求顺便做处理,我们就可以直接在es上面做采集到的信息做查询了

方案三、nginx日志层面转json再采集

(一)nginx配置json格式日志

从前两种方案我们可以发现,这两种方案核心思想就是把access的文本数据转json后,格式化存储到es中,这样es那边才能实现根据不同的字段来进行筛选等其他处理。还有另外一种方式就是直接将nginx日志输出为json文本,filebeat直接解析json文本,这样filebeat层面就不需要再承接格式转换的工作了。

http {
    log_format nginx_json '{"@timestamp":"$time_iso8601",'
                                  '"host":"$server_addr",'
                                  '"clientip":"$remote_addr",'
                                  '"request_length":$request_length,'
                                  '"body_bytes_sent":$body_bytes_sent,'
                                  '"responsetime":$request_time,'
                                  '"status":"$status",'
                                  '"request_method":"$request_method",'
                                  '"uri":"$uri",'
                                  '"http_referer":"$http_referer",'
                                  '"http_user_agent":"$http_user_agent",'
                                  '"http_x_forwarded_for":"$http_x_forwarded_for"}';
 
    access_log /var/log/nginx/access.log nginx_json;
}

修改完成后,nginx的输出就已经是json字符串了,我们现在需要做的就是让filebeat采集并按照json格式去解析,不然filebeat默认还是会按照普通文本去处理,最后整串文本都含在message字段里面。

(二)filebeat配置采集
  • /etc/filebeat/filebeat.yml 核心配置
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
    - /var/log/nginx/error.log
  fields:                     #类似于标签
    index: nginx
  json.keys_under_root: true
  json.overwrite_keys: true

output.elasticsearch:
  hosts: ["10.10.10.10:9200"]
  indices:                          #定义索引名
    - index: "elk-nginx-%{+yyyy.MM.dd}"
      when.equals:                  #与那个标签关联
        fields:
          index: "nginx"  
 

修改完成后,重启/启动filebeat即可完成采集

这种方案确实可行的方案,不过如果依然想要保留原先的日志格式的话,相当于是同时维护两套格式不同的日志文件,对磁盘的压力会有点大,需要按照每个项目的实际情况来考虑。由于笔者不希望直接变更现有运行的日志格式,所以没有直接采用这种方案,但不可否认这个方案落地的可行性挺不错的。

说在最后

按照ES官方的推荐,filebeat主要做采集,logstash主要做数据转换,还有一种模式是filebeat采集日志后,再由logstash处理,最后在存储到ES中,不过就nginx日志采集这件事情来说,个人会觉得链路太长了,成本有点高。
从实际应用出发,笔者个人更加推荐方案二,其次是方案三,因为方案一虽然轻便,但是要求nginx格式不做变更,同一个filebeat实例不支持采集多个不同的数据源,不太适用于实际业务场景,如果只针对大规模的流量统一初略采集,那么为了追求方便方案一还是有可取之处的。

参考文章:
官方文档:https://www.elastic.co/docs/reference/beats/filebeat/filebeat-module-nginx

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容