Logstash 介绍及基本使用
一.logstash架构介绍
1.什么是logstash?
Logstash是开源的数据处理管道,能够同时可以从多个源采集数据,转换数据,然后输出数据
2.Logstash架构介绍
Logstash的基础架构类型pipeline流水线,如下图所示:
input:数据采集(常用插件:stdin、file、kafka、beat、http、redis)
Filter:数据解析/转换(常用插件:grok、date、geoip、mutate、useragent)
Output:数据输出(常用插件:Elasticsearch)
3.实时解析和转换数据
数据从源传输到存储库的过程中,Logstash 过滤器能够解析各个事件,识别已命名的字段以构建结构,并将它们转换成通用格式,以便进行更强大的分析和实现商业价值。
Logstash 能够动态地转换和解析数据,不受格式或复杂度的影响:
- 利用 Grok 从非结构化数据中派生出结构
- 从 IP 地址破译出地理坐标
- 将 PII 数据匿名化,完全排除敏感字段
- 简化整体处理,不受数据源、格式或架构的影响
二、Logstash插件
2.1Logstash input插件
input插件用于指定输入源,一个pipeline可以有多个input插件,我们主要围绕以下几个input插件进行学习
stdin
file
beat
kafka
#1.安装Logstash(准备一台机器10.0.0.151)
[root@logstash-node1 ~]# yum install java -y
[root@logstash-node1 ~]# ls
logstash-7.4.0.rpm
[root@logstash-node1 ~]# rpm -ivh logstash-7.4.0.rpm
[root@logstash-node1 ~]# ll /etc/logstash/
total 36
drwxrwxr-x 2 root root 6 Sep 27 2019 conf.d
-rw-r--r-- 1 root root 2019 Sep 27 2019 jvm.options
-rw-r--r-- 1 root root 5043 Sep 27 2019 log4j2.properties
-rw-r--r-- 1 root root 342 Sep 27 2019 logstash-sample.conf
-rw-r--r-- 1 root root 8236 Jun 27 10:17 logstash.yml
-rw-r--r-- 1 root root 285 Sep 27 2019 pipelines.yml
-rw------- 1 root root 1696 Sep 27 2019 startup.options
#修改jvm.options
[root@logstash-node1 ~]# vim /etc/logstash/jvm.options
-Xms512m
-Xmx512m
#案例1
[root@logstash-node1 conf.d]# cat input_stdin_output_console.conf
input {
stdin {
type => stdin
tags => "tags_stdin"
}
}
output {
stdout {
codec => "rubydebug"
}
}
#启动logstash
[root@logstash-node1 conf.d]# /usr/share/logstash/bin/logstash -f input_stdin_output_console.conf
#案例2 从file文件中读取数据,然后输入值标准输入
[root@logstash-node1 conf.d]# cat input_file_output_console.conf
input {
file {
path => "/var/log/test.log" #可以touch一个文件,随意弄点数据
type => syslog
exclude => "*.gz" #不想监听的文件规则,基于glob匹配语法
start_position => "beginning" #第一次从头开始读取文件 beginning or end
stat_interval => "3" #定时检查文件是否更新,默认1s
}
}
output {
stdout {
codec => rubydebug
}
}
[root@logstash-node1 conf.d]# cat /var/log/test.log
123
123456
2334r4
#启动logstash
[root@logstash-node1 conf.d]# /usr/share/logstash/bin/logstash -f input_file_output_console.conf
[root@logstash-node1 ~]# echo "11111" >/var/log/test.log
{
"message" => "11111",
"host" => "logstash-node1",
"path" => "/var/log/test.log",
"@timestamp" => 2021-06-27T02:41:23.016Z,
"@version" => "1",
"type" => "syslog"
}
2.2 Logstash Filter插件
数据从源传输到存储的过程中,Logstash的filter过滤器能够解析各个事件,识别已命名的字段结构,并将它们转换成通用的格式,以便轻松,更快速的分析和实现商业价值。
利用Grok从非结构化数据中派生出结构
利用geoip从ip地址分析出地理坐标
利用useragent从请求中分析操作系统,设备类型
2.2.1 Grok插件
grok语法生成器
用官方的grok语法生成器加载不出来,用这个在线grok语法校验
测试用例日志
[08/Nov/2020:11:40:24 +0800] tc-com.g-netlink.net - - 192.168.122.58 192.168.122.58 192.168.125.135 80 GET 200 /geelyTCAccess/tcservices/capability/L6T7944Z0JN427155 ?pageIndex=1&pageSize=2000&vehicleType=0 21067 17
测试grok表达式
[%{HTTPDATE:access_time}\] %{DATA:hostname} %{DATA:username} %{DATA:fwd_for} %{DATA:remote_hostname} %{IP:remote_ip} %{IP:local_ip} %{NUMBER:local_port} %{DATA:method} %{DATA:status} %{DATA:uri} %{DATA:query} %{NUMBER:bytes} %{NUMBER:latency_ms}
1.grok是如何出现?
#我们希望将如下非结构化的数据解析成json结构化数据格式
112.195.209.90 - - [20/Feb/2018:12:12:14 +0800] "GET / HTTP/1.1" 200 190 "-" "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36" "-"
#需要用到非常复杂的正则表达式
2.grok如何解决该问题?grok其实是带有名字的正则表达式集合,grok内置了很多pattern可以直接使用。
[grok语法生成器](http://grokdebug.herokuapp.com/)
%{IPORHOST:clientip} %{NGUSER:ident} %{NGUSER:auth} \[%{HTTPDATE:timestamp}\]
"%{WORD:verb} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response}(?:%{NUMBER:bytes}|-) (?:"(?:%{URI:referrer}|-)"|%{QS:referrer})
%{QS:agent} %{QS:xforwardedfor} %{IPORHOST:host} %{BASE10NUM:request_duration}
3.grok语法示意图
4.grok实例,使用grok pattern将nginx日志转为json格式
[root@logstash-node1 conf.d]# cat input_http_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
}
output {
stdout {
codec => rubydebug
}
}
#启动,加-r修改配置并重启
[root@logstash-node1 conf.d]# /usr/share/logstash/bin/logstash -f input_http_filter_grok_output_console.conf -r
2.2.2 Geopip插件
groip插件:根据ip地址提供的对应地域信息,比如经纬度、城市名等、方便进行地理数据分析
#1.配置文件
[root@logstash-node1 conf.d]# cat input_http_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
#提取clientip字段,获取地域信息
geoip {
source => "clientip"
}
}
output {
stdout {
codec => rubydebug
}
}
2.2.3 Date插件
date插件:将日期字符串解析为日志类型,然后替换@timestamp字段或指定的其他字段
match类型为数组,用于指定日期匹配的格式,可以以此指定多种日期格式
target类型为字符串,用于指定赋值的字段名,默认是@timestamp
timezone类型为字符串,用于指定区域
#1.date实例。将nginx请求中的timestamp日志进行解析
[root@logstash-node1 conf.d]# cat input_http_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
geoip {
source => "clientip"
}
#20/Feb/2018:12:12:14 +0800
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
target => "@timestamp"
timezone => "Asia/Shanghai"
}
}
output {
stdout {
codec => rubydebug
}
}
2.2.4 useragent插件
useragent插件:根据请求中的user-agent字段,解析出浏览器设备,操作系统等信息
#1.useragent示例
[root@logstash-node1 conf.d]# cat input_http_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
geoip {
source => "clientip"
}
#20/Feb/2018:12:12:14 +0800
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
target => "@timestamp"
timezone => "Asia/Shanghai"
}
#提取agent字段,进行解析
useragent {
source => "agent" #指定从哪个字段获取数据解析
target => "user_agent" #转换后的新字段
}
}
output {
stdout {
codec => rubydebug
}
}
找user_agent,看结果
2.2.5 mutate插件
mutate主要是对字段进行,类型转换、删除、替换、更新等操作
remove_field 删除字段
split 字符串切割
add_field 添加字段
convert 类型转换
gsub 字符串替换
rename 字段重命名
#1.mutate删除无用字段,比如:headers、message、agent
[root@logstash-node1 conf.d]# cat input_http_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
geoip {
source => "clientip"
}
#20/Feb/2018:12:12:14 +0800
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
target => "@timestamp"
timezone => "Asia/Shanghai"
}
useragent {
source => "agent"
target => "user_agent"
}
#删除不需要的字段
mutate {
remove_field => ["message", "headers", "timestamp", "agent"]
}
}
output {
stdout {
codec => rubydebug
}
}
#2.mutate中的split字符切割,指定|作为分隔符
DAU|8367|加入购物车|2020-01-15 01:08:11
[root@logstash-node1 conf.d]# cat input_java_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
mutate {
split => {"message" => "|"}
}
}
output {
stdout {
codec => rubydebug
}
}
#启动
[root@logstash-node1 conf.d]# /usr/share/logstash/bin/logstash -f input_java_filter_grok_output_console.conf -r
#3.mutate中add_field,可以将分割后的数据创建出新的字段名称,便于以后的统计和分析
[root@logstash-node1 conf.d]# cat input_java_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
mutate {
split => {"message" => "|"}
}
#将分割后的字段添加到指定的字段名称
mutate {
add_field => {
"UserID" => "%{[message][0]}"
"Action" => "%{[message][1]}"
"Date" => "%{[message][2]}"
}
remove_field => ["message","headers"]
}
}
output {
stdout {
codec => rubydebug
}
}
2.2.6 mutate中的convert类型的转换,支持转换integer、float、string和boolean
[root@logstash-node1 conf.d]# cat input_java_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
mutate {
split => {"message" => "|"}
}
#将分割后的字段添加到指定的字段名称
mutate {
add_field => {
"UserID" => "%{[message][0]}"
"Action" => "%{[message][1]}"
"Date" => "%{[message][2]}"
}
remove_field => ["message","headers"]
convert => {
"UserID" => "integer"
"Action" => "string"
"Date" => "string"
}
}
}
output {
stdout {
codec => rubydebug
}
}
三、Logstash Output插件
负责将logstash Event输出,常见的插件如下:
stdout
file
elasticsearch
3.1 输出到Linu端,便于调试
#实例配置
output {
stdout {
codec => rubydebug
}
}
输出到文件,实现将分散在多地的文件统一到移除的需求,比如将所有web机器的web日志收集到一个文件中,从而方便查阅信息
3.2 输出到elasticsearch,是最常用的插件,基于htto协议实现
#示例配置
output {
elasticsearch {
hosts => ["10.0.0.161:9200","10.0.0.162:9200","10.0.0.163:9200"]
index => "nginx-%{+yyyy.MM.dd}" #所有名称
template_overwrite => true #覆盖所有模板
}
}
#1.输入到面板和Elasticsearch
[root@logstash-node1 conf.d]# cat input_java_filter_grok_output_console.conf
input {
http {
port => 7474
}
}
filter {
mutate {
split => {"message" => "|"}
}
#将分割后的字段添加到指定的字段名称
mutate {
add_field => {
"UserID" => "%{[message][0]}"
"Action" => "%{[message][1]}"
"Date" => "%{[message][2]}"
}
remove_field => ["message","headers"]
convert => {
"UserID" => "integer"
"Action" => "string"
"Date" => "string"
}
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
hosts => ["10.0.0.161:9200","10.0.0.162:9200","10.0.0.163:9200"]
index => "app-%{+YYYY.MM.dd}"
template_overwrite => true
}
}