ELK · Logstash的使用

四、Logstash

1、简介

在这里插入图片描述

2、功能

简单来说就是输入-过滤-输出。

3、部署安装

#检查jdk环境,要求jdk1.8+ 
java -version 

#解压安装包 
tar -xvf logstash-6.2.2.tar.gz 

#第一个logstash示例 
bin/logstash -e 'input { stdin { } } output { stdout {} }'

在这里插入图片描述

4、接收filebeat输入的日志

接下来,我们将Filebeat和Logstash整合起来,读取nginx的日志。

通过filebeat采集日志输送到logstash经过过滤存储到Elasticsearch

a.安装Nginx

apt install nginx -y 
#/usr/sbin/nginx:主程序 
#/etc/nginx:存放配置文件 
#/usr/share/nginx:存放静态文件 
#/var/log/nginx:存放日志 

#nginx服务命令 
service nginx {start|stop|restart|reload|force-reload|status|configtest|rotate|upgrade} 

#通过浏览器访问页面并且查看日志 
#访问地址:http://192.168.1.7/ 
tail -f /var/log/nginx/access.log

在这里插入图片描述

b.配置Filebeat

#vim test-nginx.yml 
filebeat.inputs: 
- type: log 
  enabled: true 
  paths: 
    - /var/log/nginx/access.log 
  tags: ["log"] 
  fields: 
    from: nginx 
  fields_under_root: false 
output.logstash: 
  hosts: ["192.168.1.7:5044"] 
  
#启动 
./filebeat -e -c test-nginx.yml 
#说明:现在启动会报错,因为Logstash还没有启动

c.配置Logstash

vim test-pipeline.conf 
#输入如下内容: 
input { 
	beats { 
		port => "5044" 
	} 
}
# 这里先不启用filter
# filter { 
#
# } 
output { 
	stdout { codec => rubydebug } 
}

#启动 --config.test_and_exit 用于测试配置文件是否正确 
bin/logstash -f test-pipeline.conf --config.test_and_exit
#正式启动 --config.reload.automatic 热加载配置文件,修改配置文件后无需重新启动 
bin/logstash -f test-pipeline.conf --config.reload.automatic

测试分别启动Filebeat和Logstash,刷新nginx页面查看输出。

{ 
    "@timestamp" => 2019-01-14T12:23:37.604Z, 
    "fields" => { 
        "from" => "nginx" 
    }, 
    "source" => "/var/log/nginx/access.log", 
    "tags" => [ 
        [0] "log", 
        [1] "beats_input_codec_plain_applied" 
    ], 
    "host" => { 
        "name" => "itcast01" 
    }, 
    "beat" => { 
        "name" => "itcast01", 
        "version" => "6.2.2", 
        "hostname" => "itcast01" 
    },
    "@version" => "1", 
    "offset" => 600, 
    "message" => "192.168.1.20 - - [14/Jan/2019:20:23:35 +0800] \"GET / HTTP/1.1\" 
    304 0 \"-\" \"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, 
    like Gecko) Chrome/70.0.3538.67 Safari/537.36\"", 
    "input" => { 
        "type" => "log" 
    },
    "prospector" => { 
        "type" => "log" 
    } 
} 
#可以看到,已经在控制台输出了nginx的访问日志。

d.配置filter

在前面的输出中,可以看出,虽然可以拿到日志信息,但是信息格式并不友好,比如说,不能直接拿到日志中的ip地址。

# 1、自定义nginx日志格式
vim /etc/nginx/nginx.conf 
log_format  main   '$remote_addr|$time_local|$request|'
                   '$status|$body_bytes_sent|$http_referer|'
                   '$http_user_agent|$http_x_forwarded_for|'
                   '$upstream_addr|$upstream_status|$request_time|$upstream_response_time';
access_log /usr/local/nginx/logs/access.log main;

nginx -s reload 

# 2、写nginx-patterns文件
REMOTE_ADDR              ^([\d\.]+)
TIME_LOCAL               [^\s]+\s\+\d{4}
REQUEST                  [A-Z]+\s.*\sHTTP/\d\.\d
STATUS                   \d{3}
BODY_BYTES_SENT          \d+
HTTP_REFERER             [^\|]*
HTTP_USER_AGENT          [^\|]*
HTTP_X_FORWARDED_FOR     [\d.]+|-
UPSTREAM_ADDR            [^\|]*
UPSTREAM_STATUS          [\d]{3}|-
REQUEST_TIME             [0-9]*\.[0-9]+
UPSTREAM_RESPONSE_TIME   ([0-9]*\.[0-9]+|-)$

NGINX_LOGS %{REMOTE_ADDR:remote_addr}\|%{TIME_LOCAL:time_local}\|%{REQUEST:request}\|%{STATUS:status}\|%{BODY_BYTES_SENT:body_bytes_sent}\|%{HTTP_REFERER:http_referer}\|%{HTTP_USER_AGENT:http_user_agent}\|%{HTTP_X_FORWARDED_FOR:http_x_forwarded_for}\|%{UPSTREAM_ADDR:upstream_addr}\|%{UPSTREAM_STATUS:upstream_status}\|%{REQUEST_TIME:request_time}\|%{UPSTREAM_RESPONSE_TIME:upstream_response_time}

USERHOST [\d\.]+
USERNAME [a-zA-Z]+


#3、修改test-pipeline.conf文件
input {
	beats {
		port => "5044"
	}
}
filter{
	grok{
		patterns_dir => "/opt/software/elk6.2.2/logstash-6.2.2/nginx-patterns_02"
		match => {
			"message" => "%{NGINX_LOGS}"
		}
		add_tag =>["nginx_logs"]
	}
}
output {
    stdout { codec => rubydebug }
}


#4、测试
{ 
    "input" => { 
   	 "type" => "log" 
	}, 
    "http_referer" => "-", 
    "remote_addr" => "192.168.1.20", 
    "fields" => { 
    	"from" => "nginx" 
    }, 
    "host" => { 
   	 "name" => "itcast01" 
    }, 
    "offset" => 664, 
    "request" => "GET / HTTP/1.1", 
    "message" => "192.168.1.20 - - [14/Jan/2019:22:52:49 +0800] \"GET / 
    HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 
    (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36\"", 
    "bytes_sent" => "0", 
    "status" => "304", 
    "time_local" => "14/Jan/2019:22:52:49 +0800", 
    "http_user_agent" => "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 
    (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36", 
    "prospector" => { 
         "type" => "log" 
    }, 
    "@version" => "1", 
    "remote_user" => "-", 
    "@timestamp" => 2019-01-14T14:52:58.948Z, 
    "source" => "/var/log/nginx/access.log", 
    "beat" => { 
        "name" => "itcast01", 
        "hostname" => "itcast01", 
        "version" => "6.2.2" 
    }, 
    "tags" => [ 
        [0] "log", 
        [1] "beats_input_codec_plain_applied", 
        [2] "nginx_access" 
    ] 
}

e.logstash grok内置正则过滤规则

USERNAME [a-zA-Z0-9._-]+
USER %{USERNAME}
INT (?:[+-]?(?:[0-9]+))
BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
NUMBER (?:%{BASE10NUM})
BASE16NUM (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
BASE16FLOAT \b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa-f]+)))\b

POSINT \b(?:[1-9][0-9]*)\b
NONNEGINT \b(?:[0-9]+)\b
WORD \b\w+\b
NOTSPACE \S+
SPACE \s*
DATA .*?
GREEDYDATA .*
QUOTEDSTRING (?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``))
UUID [A-Fa-f0-9]{8}-(?:[A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12}

# Networking
MAC (?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})
CISCOMAC (?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})
WINDOWSMAC (?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})
COMMONMAC (?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})
IPV6 ((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?
IPV4 (?<![0-9])(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))(?![0-9])
IP (?:%{IPV6}|%{IPV4})
HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b)
HOST %{HOSTNAME}
IPORHOST (?:%{HOSTNAME}|%{IP})
HOSTPORT %{IPORHOST}:%{POSINT}

# paths
PATH (?:%{UNIXPATH}|%{WINPATH})
UNIXPATH (?>/(?>[\w_%!$@:.,-]+|\\.)*)+
TTY (?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+))
WINPATH (?>[A-Za-z]+:|\\)(?:\\[^\\?*]*)+
URIPROTO [A-Za-z]+(\+[A-Za-z+]+)?
URIHOST %{IPORHOST}(?::%{POSINT:port})?
# uripath comes loosely from RFC1738, but mostly from what Firefox
# doesn't turn into %XX
URIPATH (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%_\-]*)+
#URIPARAM \?(?:[A-Za-z0-9]+(?:=(?:[^&]*))?(?:&(?:[A-Za-z0-9]+(?:=(?:[^&]*))?)?)*)?
URIPARAM \?[A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]]*
URIPATHPARAM %{URIPATH}(?:%{URIPARAM})?
URI %{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})?

# Months: January, Feb, 3, 03, 12, December
MONTH \b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b
MONTHNUM (?:0?[1-9]|1[0-2])
MONTHNUM2 (?:0[1-9]|1[0-2])
MONTHDAY (?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9])

# Days: Monday, Tue, Thu, etc...
DAY (?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)

# Years?
YEAR (?>\d\d){1,2}
HOUR (?:2[0123]|[01]?[0-9])
MINUTE (?:[0-5][0-9])
# '60' is a leap second in most time standards and thus is valid.
SECOND (?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?)
TIME (?!<[0-9])%{HOUR}:%{MINUTE}(?::%{SECOND})(?![0-9])
# datestamp is YYYY/MM/DD-HH:MM:SS.UUUU (or something like it)
DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR}
DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}
ISO8601_TIMEZONE (?:Z|[+-]%{HOUR}(?::?%{MINUTE}))
ISO8601_SECOND (?:%{SECOND}|60)
TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?
DATE %{DATE_US}|%{DATE_EU}
DATESTAMP %{DATE}[- ]%{TIME}
TZ (?:[PMCE][SD]T|UTC)
DATESTAMP_RFC822 %{DAY} %{MONTH} %{MONTHDAY} %{YEAR} %{TIME} %{TZ}
DATESTAMP_RFC2822 %{DAY}, %{MONTHDAY} %{MONTH} %{YEAR} %{TIME} %{ISO8601_TIMEZONE}
DATESTAMP_OTHER %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{TZ} %{YEAR}
DATESTAMP_EVENTLOG %{YEAR}%{MONTHNUM2}%{MONTHDAY}%{HOUR}%{MINUTE}%{SECOND}

# Syslog Dates: Month Day HH:MM:SS
SYSLOGTIMESTAMP %{MONTH} +%{MONTHDAY} %{TIME}
PROG (?:[\w._/%-]+)
SYSLOGPROG %{PROG:program}(?:\[%{POSINT:pid}\])?
SYSLOGHOST %{IPORHOST}
SYSLOGFACILITY <%{NONNEGINT:facility}.%{NONNEGINT:priority}>
HTTPDATE %{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT}

# Shortcuts
QS %{QUOTEDSTRING}

# Log formats
SYSLOGBASE %{SYSLOGTIMESTAMP:timestamp} (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:logsource} %{SYSLOGPROG}:
COMMONAPACHELOG %{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-)
COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:referrer} %{QS:agent}

# Log Levels
LOGLEVEL ([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo|INFO|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?)

f.发送到Elasticsearch

#vim test-pipeline.conf 
input { 
    beats { 
          port => "5044" 
    } 
}
filter { 
    grok {
        patterns_dir => "/opt/software/logstash-6.2.2/nginx-patterns" 
        match => { "message" => "%{NGINX_ACCESS}"} 
        remove_tag => [ "_grokparsefailure" ] 
        add_tag => [ "nginx_access" ] 
    } 
}
#output {
# stdout { codec => rubydebug } 
#}
output { 
    elasticsearch { 
    	hosts => [ "192.168.1.7:9200","192.168.1.7:9201","192.168.1.7:9202" ] 
    } 
}

5、接收JSON格式的日志输出

a、修改nginx的日志格式

log_format  json  '{"@timestamp":"$time_iso8601",'
                       '"@version":"1",'
                       '"client":"$remote_addr",'
                       '"url":"$uri",'
                       '"status":"$status",'
                       '"domain":"$host",'
                       '"host":"$server_addr",'
                       '"size":"$body_bytes_sent",'
                       '"responsentime":"$request_time",'
                       '"referer":"$http_referer",'
                       '"useragent":"$http_user_agent"'
                        '}';
access_log /usr/local/nginx/logs/access_json.log json;

b、修改filtbeat配置

filebeat.prospectors:
- type: log
  enabled: true
  paths:
  - /usr/local/nginx/logs/access_json.log
  fields:
    filetype: log_nginx
  fields_under_root: true
setup.template.settings:
  index.number_of_shards: 3
output.logstash:
  hosts: ["192.168.179.128:5044"]

c、修改logstash的配置

input {
	beats {
		port => "5044"
	}
}
filter {
	json {
		source => "message"         # 将message中的键值对进行拆分
		remove_field => ["message"]
	}
}
output {
	stdout { codec => rubydebug }
}

d、启动logstash、filebeat测试访问nginx

#输出如下
{
         "filetype" => "log_nginx",
             "beat" => {
         "version" => "6.2.2",
            "name" => "localhost.localdomain",
        "hostname" => "localhost.localdomain"
    },
             "tags" => [
        [0] "beats_input_codec_plain_applied"
    ],
              "url" => "/es",
           "domain" => "192.168.179.128",
        "useragent" => "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
       "prospector" => {
        "type" => "log"
    },
           "client" => "192.168.179.1",
             "size" => "435",
           "source" => "/usr/local/nginx/logs/access_json.log",
           "status" => "200",
           "offset" => 3380,
             "host" => "192.168.179.128",
          "referer" => "-",
         "@version" => "1",
    "responsentime" => "0.006",
       "@timestamp" => 2020-11-06T07:24:32.000Z
}

6、自定义Template模板配置

{
    "template": "nginx-json*",
    "version": 50001,
    "settings": {
        "index.refresh_interval": "5s"
    },
    "mappings": {
        "_default_": {
            "_all": {
                "enabled": true,
                "norms": false
            },
            "dynamic_templates": [
                {
                    "message_field": {
                        "path_match": "message",
                        "match_mapping_type": "string",
                        "mapping": {
                            "type": "text",
                            "norms": false
                        }
                    }
                },
                {
                    "string_fields": {
                        "match": "*",
                        "match_mapping_type": "string",
                        "mapping": {
                            "type": "text",
                            "norms": false,
                            "analyzer": "ik_max_word",
                            "fields": {
                                "keyword": {
                                    "type": "keyword"
                                }
                            }
                        }
                    }
                }
            ],
            "properties": {
                "@timestamp": {
                    "type": "date",
                    "include_in_all": false
                },
                "@version": {
                    "type": "keyword",
                    "include_in_all": false
                }
            }
        }
    }
}

在logstash的配置文件中加入template配置

input {
        beats {
                port => "5044"
        }
}
filter {
  json {
    source => "message"         # 将message中的键值对进行拆分
    remove_field => ["message"]
  }
}
output {
        if [filetype] == "log_nginx"{
                elasticsearch{
                        hosts=>["192.168.179.128:9200"]
                        index => "nginx_json_%{+YYYY-MM-dd}.log"
                        template_overwrite => true
                        template => "/opt/software/elk6.2.2/logstash-6.2.2/test-nginx-dynamic-template.json"
                        template_name => "ngins-json*"
                }
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值