{{tag>logstash elasticsearch elk opensearch logging}}
====== Logstash setup ======
===== Download and install =====
wget https://artifacts.opensearch.org/logstash/logstash-oss-with-opensearch-output-plugin-8.9.0-linux-x64.tar.gz
tar xf logstash-oss-with-opensearch-output-plugin-8.9.0-linux-x64.tar.gz
cd logstash-8.9.0/ && bin/logstash-plugin install logstash-output-opensearch
===== Examples =====
==== nginx logs using regular indices ====
input {
file {
path => "/var/log/nginx/nginx_logs*_access.log"
}
}
filter {
grok {
patterns_dir => "/etc/logstash.d/patterns"
match => { "message" => "%{NGINX_ACCESS}" }
remove_field => ["message"]
}
useragent {
source => "user_agent"
target => "useragent"
remove_field => "user_agent"
}
}
output {
opensearch {
hosts => "https://{{ opensearch_host }}:9200"
user => "logstash"
password => "mypassword"
index => "logstash-nginx-access-logs-${HOSTNAME}"
manage_template => true
template_overwrite => true
template => "/etc/logstash.d/nginx_access_index_map.json"
ssl_certificate_verification => false
}
}
You can also use multiple file inputs like so:
input {
file { path => [
"/var/log/nginx/nginx_logs*_access.log",
"/var/log/nginx/some_other_web*_access.log"
]
}
}
...
Above we're using a grok pattern named **NGINX_ACCESS** stored in patterns directory. Example of pattern:
METHOD (OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT)
CACHED (HIT|MISS|BYPASS|EXPIRED|STALE|UPDATING|REVALIDATED)
NGINX_ACCESS "%{HTTPDATE:time_local}" client=%{IP:client} country=%{GREEDYDATA:country} method=%{METHOD:method} request="%{METHOD} %{URIPATHPARAM:request} HTTP/%{BASE16FLOAT:http_version}" request_length=%{INT:request_length} status=%{INT:status} bytes_sent=%{INT:bytes_sent} body_bytes_sent=%{INT:body_bytes_sent} referer=(%{URI:referer}|-) user_agent=%{GREEDYDATA:user_agent} upstream_addr=(%{HOSTPORT:upstream_addr}|-) upstream_status=(%{INT:upstream_status}|-) request_time=(%{ISO8601_SECOND:request_time}|-) upstream_response_time=(%{ISO8601_SECOND:upstream_response_time}|-) upstream_connect_time=(%{ISO8601_SECOND:upstream_connect_time}|-) upstream_header_time=(%{ISO8601_SECOND:upstream_header_time}|-) upstream_cache_status=(%{CACHED:upstream_cache_status}|-) is_bot=%{INT:is_bot} cookie_mbbauth_present=(%{GREEDYDATA:cookie_mbbauth_present}|-)
For testing the pattern use http://grokconstructor.appspot.com. Copy a few log lines there and adjust above pattern until you get a match.
''manage_template => true'' creates the pattern in opensearch (elasticsearch) DB automatically, just make sure the logstash user has the permissions to create the indices with specified names. Index pattern is described in ''template => "/etc/logstash.d/nginx_access_index_map.json"''. This must match the grok pattern above i.e.
{
"version" : 50001,
"template" : "logstash-nginx-access*",
"settings" : {
"index" : {
"refresh_interval" : "5s"
}
},
"mappings" : {
"properties" : {
"@timestamp" : {
"type" : "date"
},
"client": {
"type" : "ip"
},
"country" : {
"type" : "keyword"
},
"method" : {
"type" : "keyword"
},
"request" : {
"type" : "keyword"
},
"request_length" : {
"type" : "integer"
},
"status" : {
"type" : "integer"
},
"bytes_sent": {
"type" : "integer"
},
"body_bytes_sent": {
"type" : "integer"
},
"referer" : {
"type" : "keyword"
},
"useragent" : {
"dynamic" : true,
"properties" : {
"device" : {
"properties" : {
"name" : {
"type" : "keyword"
}
}
},
"name" : {
"type" : "keyword"
},
"os" : {
"properties" : {
"name" : {
"type" : "keyword"
},
"version" : {
"type" : "keyword"
},
"full" : {
"type" : "keyword"
}
}
},
"version" : {
"type" : "keyword"
}
}
},
"upstream_addr" : {
"type" : "keyword"
},
"upstream_status" : {
"type" : "keyword"
},
"request_time" : {
"type" : "float"
}
}
},
"aliases" : {}
}
${HOSTNAME} is an environment variable which must be defined (via .bashrc or with systemd unit which starts logstash service etc.)
# /etc/systemd/system/logstash.service
[Unit]
Description=Massage various logs and forward them to opensearch/elasticsearch
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/logstash -f /etc/logstash.d/nginx_logs.conf
Environment="HOSTNAME={{ hostname }}"
Restart=on-failure
[Install]
WantedBy=multi-user.target
''referer=(%{URI:referer}|-)'' construct means the referer in this case might be empty (''-'').
==== nginx logs using datastreams ====
This is perhaps a better approach, using [[https://opensearch.org/docs/2.15/im-plugin/data-streams/|datastreams]] as this will do some automatic rollover to new index.
Change the logstash ''output'' part to this
...
output {
opensearch {
hosts => "https://{{ opensearch_host }}:9200"
user => "logstash"
password => "mypassword"
ssl_certificate_verification => false
action => "create"
index => "whatever-pattern-abc"
}
}...
''index'' needs to be set to the name of the datastream you defined in Opensearch and add ''action'' directive.
In Opensearch you need to create a datastream, but first you need to create a template.
**1.** Go to Index Management > Templates > Create template
{{ :wiki:screenshots:opensearch_create_template1.png?800 |}}
**2.** Add template name, select type "Data streams" and put in the Time field (@timestamp in this example). Index pattern should match the pattern name for which logstash user has rights to write to and this will be the name of datastream used later.
{{ :wiki:screenshots:opensearch_create_template2.png?800 |}}
**3.** You can add an alias if you want, replicas are set to 0 here to save some space.
{{ :wiki:screenshots:opensearch_create_template3.png?800 |}}
**4.** In field mappings you need to map the fields sent by logstash. Easiest is to c/p the json into json editor from existing index, like the one that would be created by logstash using the regular index (see above).
{{ :wiki:screenshots:opensearch_create_template4.png?800 |}}
**5.** When creating datastream the name must match the pattern from step 2 above, but it doesn't have to be exactly the same (so here it should be "whatever-pattern-abc" to match logstash config). The rest should be autofilled.
{{ :wiki:screenshots:opensearch_create_datastream1.png?800 |}}
====== Tested on ======
* logstash-8.14.3
* Opensearch 2.15
====== See also ======
* [[wiki:rollover_opensearch_elasticsearch_indexes|Rollover opensearch/elasticsearch indexes]]
* [[wiki:opensearch_installation|Opensearch installation]]
====== References ======
* https://rzetterberg.github.io/nginx-elk-logging.html
* https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html
* https://github.com/logstash-plugins/logstash-patterns-core/blob/f01f3f34cfab13a28b0822bdba33db41823cb1d8/patterns/legacy/grok-patterns