传统方案都是通过logstash模版解析nginx日志,现在使用filebeat自带的nginx模块就可以省去logstash。

根据nginx日志配置调整设置

首先要看nginx的配置,如果nginx使用的是默认的日志配置,则忽略这一步。 否则需要根据nginx日志配置来配置filebeat的模版。

比如我们的日志中添加了请求体的记录:

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

先修改template定义,添加request_body字段,对应文件为filebeat.template.json

1
2
3
4
"request_body": {
  "ignore_above": 1024,
  "type": "keyword"
}

再到pipeline定义中解析设置, 修改pattern,对应文件为module/nginx/access/ingest/default.json

1
 "%{IPORHOST:nginx.access.remote_ip} - %{DATA:nginx.access.user_name} \\[%{HTTPDATE:nginx.access.time}\\] \"%{WORD:nginx.access.method} %{DATA:nginx.access.url} HTTP/%{NUMBER:nginx.access.http_version}\" %{NUMBER:nginx.access.response_code} %{NUMBER:nginx.access.body_sent.bytes} %{DATA:nginx.access.request_body} \"%{DATA:nginx.access.referrer}\" \"%{DATA:nginx.access.agent}\" %{DATA:nginx.access.forwarded}"

启动

首先需要在ES添加两个插件:

1
2
bin/elasticsearch-plugin install ingest-user-agent
bin/elasticsearch-plugin install ingest-user-agent

编辑filebeat.yml

  1. 添加默认的prospector,配置log的路径
  2. 修改output.elasticsearch的地址,端口,密码等

启动客户端,加载nginx模块:

1
nohup ./filebeat -e -modules=nginx -M "nginx.access.var.paths=[/data/logs/access*]" -M "nginx.error.var.paths=[/data/logs/error.log]" >/dev/null 2>&1 &

调整nginx日志配置后的变更

Ingest

删除已经创建的pipeline

1
2
3
GET _ingest/pipeline

DELETE _ingest/pipeline/filebeat-5.4.1-nginx-access-default

Index templates

因为默认不会覆盖已有的templates,所以要删除已经创建的templates:

1
2
GET /_template/
DELETE /_template/filebeat

或者在配置文件中将overwrite设为true:

1
2
output.elasticsearch:
  template.overwrite: true

kibana查看图表

创建完成之后dashboard中会创建默认的几个面板。 Filebeat Nginx Dashboard:

追踪日志排查问题

客户端有个积压已久的问题: 应用没有看到相关日志,怀疑nginx层返回跳转指令,排查30X响应头:

 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
GET filebeat-2017.06.18/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "nginx.access.user_agent.os_name": {
            "value": "iOS"
          }
        }
        },
        {"term": {
          "nginx.access.response_code": {
            "value": "301"
          }
        }}
      ]
    }
  },
  "sort": [
    {
      "@timestamp": {
        "order": "desc"
      }
    }
  ],
  "size": 20
}

定位到是因为响应头为301却没有返回跳转地址: 通过flask模拟:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import os
from flask import Flask,redirect

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def hello():
    return redirect("", code=301)

if __name__ == '__main__':
    # Bind to PORT if defined, otherwise default to 5000.
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port)

成功在客户端复现,通过客户端逻辑调整修复了这个困扰已久的问题。