This is an example configuration to have nginx output JSON logs to make it easier for Logstash processing. I was trying to get nginx > Filebeat > Logstash > ES working and it wasn't until I connected Filebeat directly to Elasticsearch that I saw the expected data. Google led me to ingest-convert.sh
and I realized filebeat setup
works for Filebeat > ES but not Filebeat > Logstash > ES. This is because Logstash does not use ingest pipelines by default. You have to enable them in the elasticsearch
output block.
Having nginx log JSON in the format required for Elasticsearch means there's very little processing (i.e. grok
) to be done in Logstash. nginx can only output JSON for access logs; the error_log
format cannot be changed.
Extra fields are output and not used by the Kibana dashboards. I included them in case they might be useful. Since they are not declared in the filebeat setup
, their default is "string" when you refresh the field list. This might limit their usefulness for aggregations.
- Don't use Logstash? Point your beats to ES and be done with it.
- On the fence about Logstash? Don't. Point your beats to ES and be done with it.
- Do you have to use Logstash? Then this might be useful.
- Do you have a specific need to use Logstash? Then this might be useful.
This article has some good information about why you would choose Logstash over ingest nodes. While there are some benefits to using Logstash, it adds complexity because you have to maintain the pipeline processors outside ES OR use conditionals in the output
block to specify the ingest node to use for each type of document. I'm still learning the internals but here are some things I found when trying to use multiple ingest nodes in ES.
- Only 1 pipeline can be specified inside an
elasticsearch
block. Multiple pipelines are supported by files, which means you'll need to pull them from the *beat install or extract them from ES. - Conditionals need to be outside the
elasticsearch
block, not inside. This means multipleelasticsearch
outputs, one for each beat. - Variables can be used for the pipeline name but I don't know of a way to check if the pipeline exists before expanding the variables. If the pipeline doesn't exist, tons of warnings are logged.
- Simplifies the processing for nginx access logs.
- Provides millisecond resolution.
- Provides other fields if you're interested in them.
- Logstash does not process nginx error logs by default. You need to set pipeline in the output block.
- Maintaining pipelines in Logstash instead of using the already managed ingest processors provided by
filebeat setup
. Although once you understand that you need to convert the ingest pipeline to Logstash.conf
format, this could be a benefit.
- ES uses
remote_ip
while nginx uses$http_x_real_ip
for servers behind proxies. I believe this is best fixed withproxy_set_header
in the nginx config but haven't had time to hash it out.
- A working ELK stack.
- *.example.com is used to demonstrate different servers.
- Tested with 6.1.2 on openSUSE. YMMV
- nginx 1.11.8 or higher.
- Half a brain. You're expected to know administration. Well, maybe three quarters of a brain.
This will load the templates and fields into Elasticsearch and the dashboards into Kibana. The ingest pipelines are loaded with filebeat --setup
which proceeds to run filebeat after the setup. filebeat setup
does not load the pipelines. I assume this is because the pipelines are relevent only when filebeat is connected directly to Elasticsearch.
filebeat setup -e \
-E 'setup.template.overwrite=true' \
-E 'setup.kibana.host="kibana.example.com:5601"' \
-E 'output.logstash.enabled=false' \
-E 'output.elasticsearch.hosts=["elasticsearch.example.com:9200"]'
Everything is wrapped in a single "nginx" element/object to match ES's "nginx" mapping. Put log-json.conf
in the nginx directory.
include log-json.conf
access_log /var/log/nginx/access.json json;
keys_under_root=true
will output fields nginx.*
which is what we want, while keys_under_root=false
will output json.nginx.*
.
filebeat.prospectors:
- type: log
paths:
- /var/log/nginx/*.json
tags: ["nginx", "json"]
json:
keys_under_root: true
add_error_key: true
You have input
and output
defined in another file in /etc/logstash/conf.d/
. Right? Add filter-nginx.conf
to the mix. This processes error_log
files as well.