使用 Logstash 的多管道功能时,你可能需要在同一 Logstash 实例中连接多个管道(Pipeline)。 此配置对于隔离这些管道的执行以及有助于打破复杂管道的逻辑很有用。 管道 input/output 启用了本文档后面讨论的许多高级体系结构模式。
如果需要在 Logstash 实例之间设置通信,请使用 Logstash 到 Logstash 的通信,或使用中间队列,例如 Kafka 或 Redis。
配置总揽
使用 pipeline input 和 pipeline output 来连接在同一 Logstash 实例中运行的两个管道。 这些输入使用 client/server 方法,其中管道输入注册一个虚拟地址,从而管道输出可以连接到这个地址。
- 创建一个 downstream 管道,以侦听虚拟地址上的事件。
- 创建一个产生事件的 upstream 管道,然后通过管道输出将它们发送到一个或多个虚拟地址。
这是此配置的一个简单示例。我们在 Logstash 安装的根目录下,寻找 config/pipelines.yml 文件,并做如下的配置:
config/pipelines.yml
# config/pipelines.yml
- pipeline.id: upstream
config.string: input { stdin {} } output { pipeline { send_to => [myVirtualAddress] } }
- pipeline.id: downstream
config.string: input { pipeline { address => myVirtualAddress } }
我们使用如下的方法来运行 Logstash:
sudo ./bin/logstash
当我们从 stdin 输入任何一些字符,我们可以看到如下的输出:
从上面可以看出来:我们把从 stdin 中输入的任意字符从从一个 pipeline 发送到另外一个 pipeline。在上面,输出的地址为 myVirtualAddress。当然我们可以同时输出到多个地址中。在 downstream 中,我们可以看到在 input 中定义了一个 地址为 myVirtualAddress 的 pipeline。
在接下来的例子中,我将来展示一个比较复杂一点的带有应用场景的例子。在下面的例子中,我们将使用同样一个 Logstash 的实例同时来处理两种日志:syslog 及 apache。
准备数据
我们今天的数据非常简单。我们在 Filebeat 的安装根目录中创建如下的两个文件:
system.log
May 11 10:40:48 scrooge disk-health-nurse[26783]: [ID 702911 user.error] m:SY-mon-full-500 c:H : partition health measures for /var did not suffice - still using 96% of partition space
May 11 10:00:39 scrooge SG_child[808]: [ID 748625 user.info] m:WR-SG-SUMMARY c:X vhost:iscrooge61.seclutions.com:80 (http) GET / => http://bali/ , status:200 , redirection URL:<n/a> , referer:<n/a> , mapping:bali , request size: 421 , backend response size: 12960 , audit token:- , time statistics (microseconds): [request total 16617 , allow/deny filters 1290 , backend responsiveness 11845 , response processing 1643 , ICAP reqmod <n/a> , ICAP respmod <n/a> ] timestamp: [2012-05-11 10:00:39] [ rid:T6zHJ38AAAEAAAo2BCwAAAMk sid:910e5dd02df49434d0db9b445ebba975 ip:172.18.61.2 ]
这是含有两个文档的 system 日志。关于日志的详细介绍,可以参阅文档。
apache.log
83.149.9.216 - - [17/May/2015:10:05:03 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-search.png HTTP/1.1" 200 203023 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
83.149.9.216 - - [17/May/2015:10:05:43 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png HTTP/1.1" 200 171717 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
同样,这也是含有两个文档的 apache.log 日志文件。
创建 Logstash 配置文件
在 Logstash 的安装目录下,我们会发现一个叫做 config/pipelines.yml 的文件:
我们修改改文件为如下的内容:
config/pipelines.yml
# config/pipelines.yml
- pipeline.id: beats-server
config.string: |
input { beats { port => 5044 } }
filter {
mutate {
remove_field => [ "log", "host", "tags", "@version", "agent" ]
}
}
output {
if [type] == "apache" {
pipeline { send_to => weblogs }
} else if [type] == "system" {
pipeline { send_to => syslog }
}
}
- pipeline.id: upstream
config.string: input { stdin {} } output { pipeline { send_to => [myVirtualAddress] } }
- pipeline.id: weblogs_downstream
config.string: |
input { pipeline { address => weblogs } }
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
date {
match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch { hosts => [ "localhost:9200" ] }
}
- pipeline.id: syslog_downstream
config.string: |
input { pipeline { address => syslog } }
filter {
grok {
match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?:%{GREEDYDATA:syslog_message}" }
add_field => [ "read_es", "%{@timestamp}" ]
}
date {
match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
}
mutate {
remove_field => [ "message" ]
remove_field => [ "syslog_timestamp" ]
convert => ["bool","boolean"]
rename => { "ip" => "[geoPoint][ip]" }
rename => { "latitude" => "[geoPoint][latitude]" }
rename => { "longitude" => "[geoPoint][longitude]" }
rename => { "location" => "[geoPoint][location]" }
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch { hosts => [ "localhost:9200" ] }
}
在上面,其实非常简单。我首先看如下的部分:
- pipeline.id: beats-server
config.string: |
input { beats { port => 5044 } }
filter {
mutate {
remove_field => [ "log", "host", "tags", "@version", "agent" ]
}
}
output {
if [type] == "apache" {
pipeline { send_to => weblogs }
} else if [type] == "system" {
pipeline { send_to => syslog }
}
}
在上面它接受从 port 为 5044 端口的数据。我们首先使用 filter 来把一些不需要的字段删除掉,这样我们的显示更加好看一些。在输出的部分,我们来依据文档的类型从而发送到不同的 pipeline 去做处理。如果是 apache 日志,我们发送到地址为 weblogs 的 pipeline 中去。如果类型是 system,那么我们发送至地址为 syslog 的 pipeline 中。在接下来的两个 pipeline:
- pipeline.id: upstream
- pipeline.id: syslog_downstream
它们分别针对不同的日志进行不同的数据清洗。因为不同的日志有不同的清洗方法,所以在我们使用不同的 pipeline 来分别进行处理。
我们可以使用如下的方法来启动 Logstash:
sudo ./bin/logstash -r
启动 Filebeat 导入数据
我们接下来使用 Filebeat 来把数据导入到 Logstash 中。安装好我们的 Filebeat,并修改 Fillebeat 的配值文件。请在文件的前面添加如下的部分:
filebeat.yml
filebeat.inputs:
# Each - is an input. Most options can be set at the input level, so
# you can use different inputs for various configurations.
# Below are the input specific configurations.
- type: log
# Change to true to enable this input configuration.
enabled: true
fields_under_root: true
fields:
type: "apache"
# Paths that should be crawled and fetched. Glob based paths.
paths:
- ./apache.log
- type: log
# Change to true to enable this input configuration.
enabled: true
fields_under_root: true
fields:
type: "system"
# Paths that should be crawled and fetched. Glob based paths.
paths:
- ./system.log
在上面,我们添加了对 Filebeat 安装目录下的 system.log 及 apache.log 的数据采集。同时为了能够把数据导入到 Logstash 中的 5044 端口地址,我们需要针对 filebeat.yml 做更进一步的修改:
filebeat.yml
#output.elasticsearch:
# Array of hosts to connect to.
#hosts: ["localhost:9200"]
# Protocol - either `http` (default) or `https`.
#protocol: "https"
# Authentication credentials - either API key or username/password.
#api_key: "id:api_key"
#username: "elastic"
#password: "changeme"
# ------------------------------ Logstash Output -------------------------------
output.logstash:
# The Logstash hosts
hosts: ["localhost:5044"]
在上面,我们禁止直接导入到 Elasticsearch。我们启动 Logstash 的输出。我们使用如下的方法来启动 Filebeat:
./filebeat -e
从输出中,我们可以看到有两个 havester 已经被创建。
在 Logstash 以及 Kibana 中检查数据
我们查看 Logstash 的输出 terminal:
从上面,我们可以看到有数据输出。
我们同时查看 Kibana:
GET logstash/_search
我们可以看到有四个文档被导入:
针对 Linux 的 Logstash 配置
在上面的 pipelines.yml 中,把各个 pipeline 放入一个文件中显得非常凌乱。对于使用 RPM 或者 DEB 安装包的 Logstash 用户来说,我们可以使用如下的方式来进行简化明了。
/etc/logstash/pipelines.yml
# config/pipelines.yml
- pipeline.id: beats-server
config.string: |
input { beats { port => 5044 } }
filter {
mutate {
remove_field => [ "log", "host", "tags", "@version", "agent" ]
}
}
output {
if [type] == "apache" {
pipeline { send_to => weblogs }
} else if [type] == "system" {
pipeline { send_to => syslog }
}
}
- pipeline.id: weblogs_downstream
path.config: "/etc/logstash/conf.d/weblogs.conf"
- pipeline.id: syslog_downstream
path.config: "/etc/logstash/conf.d/syslog.conf"
我们接着在位置 /etc/logstash/conf.d 创建如下的两个文件:
weblogs.conf
input { pipeline { address => weblogs } }
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
date {
match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch { hosts => [ "localhost:9200" ] }
}
syslog.conf
input { pipeline { address => syslog } }
filter {
grok {
match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} \[%{DATA}\] %{DATA} %{WORD:type} \"userText\":\"%{DATA:userText}\",\"prduction\":%{NUMBER:prduction:int},\"version\":%{NUMBER:version:int},\"bool\":%{DATA:bool},\{\"geoPoint\":\{\"location\":\"%{DATA:location}\",\"ip\":\"%{IP:ip}\",\"latitude\":%{BASE10NUM:latitude},\"longitude\":%{BASE10NUM:longitude},(\"optionalField\":%{BASE10NUM:optionalField},)?\}\}" }
add_field => [ "read_es", "%{@timestamp}" ]
}
date {
match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
}
mutate {
remove_field => [ "message" ]
remove_field => [ "syslog_timestamp" ]
convert => ["bool","boolean"]
rename => { "ip" => "[geoPoint][ip]" }
rename => { "latitude" => "[geoPoint][latitude]" }
rename => { "longitude" => "[geoPoint][longitude]" }
rename => { "location" => "[geoPoint][location]" }
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch { hosts => [ "localhost:9200" ] }
}
在配置完上面的文件后,你需要对 Logstash 进行重启:
service logstash restart