书接上回:《ELK中Logstash的基本配置和用法》
引入logstash
Nginx日志格式修改
默认情况下,Nginx的日志记录的是下面的格式:
127.0.0.1 - - [21/Aug/2023:10:55:30 +0800] "POST /url/index HTTP/1.1" 200 39801 "http://test.cc/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
在 nginx.conf
中也可以看到相关配置信息:
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
现在为了方便收集日志,我们把这里的格式改为 json格式,在 nginx.conf
中加入下面的内容:
log_format json '{"@timestamp": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"remote_user": "$remote_user", '
'"body_bytes_sent": "$body_bytes_sent", '
'"request_time": "$request_time", '
'"status": "$status", '
'"request_uri": "$request_uri", '
'"request_method": "$request_method", '
'"http_referrer": "$http_referer", '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"http_user_agent": "$http_user_agent"}';
access_log logs/access.log json;
以上配置是手动组装了一个json格式的配置信息。相关字段说明如下:
- $time_iso8601:格式化时间格式
- $remote_addr #记录访问网站的客户端ip地址
- $remote_port # 客户端的port
- $remote_user # 如果nginx有配置认证,该变量代表客户端认证的用户名
- $time_local #记录访问时间与时区
- $request #用户的http请求起始行信息,包括方法名、请求地址、http版本
- $status #http状态码,记录请求返回的状态码,例如:200、301、404等
- $body_bytes_sent #服务器发送给客户端的响应body字节数
- $http_referer #记录此次请求是从哪个连接访问过来的,可以根据该参数进行防盗链设置。
- $http_user_agent #记录客户端访问信息,例如:浏览器、手机客户端等
- $http_x_forwarded_for #当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置
- $request_body # post上传的数据
- $request_time # 整个请求的总时间
- $upstream_response_time # 请求过程中,和php-fpm的交互时间
- $args # 请求中的参数,如www.123.com/1.php?a=1&b=2的 $args就是a=1&b=2
- $content_length # HTTP请求信息里的”Content-Length”
- $conten_type # HTTP请求信息里的”Content-Type”
- $document_root # nginx虚拟主机配置文件中的root参数对应的值
- $document_uri 或 $uri # 当前请求中不包含指令的URI,如www.123.com/1.php?a=1&b=2的
- $document_uri就是1.php,不包含后面的参数
- $request_uri # 请求的链接,包括和args
- $host # 主机头,也就是域名
- $http_cookie # 客户端的cookie信息
- $request_body_file # 做反向代理时发给后端服务器的本地资源的名称
- $request_method # 请求资源的方式,GET/PUT/DELETE等
- $request_filename # 当前请求的资源文件的路径名称,相当于是document_uri的组合
- $scheme # 请求的协议,如ftp,http,https
- $server_protocol # 客户端请求资源使用的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等
- $server_addr # 服务器IP地址
- $server_name # 服务器的主机名
- $server_port # 服务器的端口号
记得把 相关log 的后面的main改成json,还有需要修改的虚拟主机的log。
修改后记录的log格式如下:
{"@timestamp": "2023-08-21T11:24:00+08:00", "remote_addr": "127.0.0.1", "remote_user": "-", "body_bytes_sent": "11277", "request_time": "5.926", "status": "200", "request_uri": "/url/index", "request_method": "POST", "http_referrer": "http://test.cc/", "http_x_forwarded_for": "-", "http_user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"}
配置logstash收集nginx日志
写入文件 logstash/config/logstash-to-es.conf
:
input {
file {
path => ["/home/rx/mywebsite.log"]
type => "mywebsite"
tags => ["mywebsite","prod"]
start_position => "beginning"
}
}
filter {
json {
source => "message"
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "mywebsite-prod-log-%{+YYYY.MM.dd}"
user => "elastic"
password => "mypassword"
}
}
然后启动logstash即可开始收集:
./bin/logstash -r -f ./config/logstash-to-es.conf
引入Redis
如果服务器比较多,写入的日志落在不同的机器上,那么可以使用redis或者kafka作为中间件,收集多台机器的日志进行汇总处理。处理顺序:logstash收集日志 -> redis/kafka -> logstash过滤日志 -> ES ->kibana
。流程图如下:
由于我在测试的过程中没有设置redis的密码,导致运行logstash失败
因此这里给redis设置一个密码:
redis-cli
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass 123456
OK
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "123456"
收集日志写入redis
添加配置文件vim logstash-7.1.0/config/my_config/logstash-to-redis.conf
,内容如下:
input {
file {
path => ["/var/log/syslog"]
type => "system"
tags => ["syslog","test"]
start_position => "beginning"
}
file {
path => ["/var/log/auth.log"]
type => "system"
tags => ["auth","test"]
start_position => "beginning"
}
}
filter {
}
output {
redis {
host => ["127.0.0.1:6379"]
password => "123456"
db => "5"
data_type => "list"
key => "logstash"
}
}
上面redis部分的配置,host是个数组,可以配置多个redis服务;db表示redis的第几个数据库;data_type这里用list类型模拟消息队列;key表示将来存储的redis数据的key的名称。
然后启动logstash,指定上面的配置信息:./bin/logstash -f ./config/my_config/logstash-to-redis.conf
然后打开redis客户端看看是否有数据:
可以看到redis中的消息队列已经存储了很多数据,接下来消费它。
从redis中读取日志
在logstash的配置文件中添加配置文件 vim logstash-7.1.0/config/my_config/logstash-from-redis.conf
,内容如下:
input {
redis {
host => "127.0.0.1"
port => 6379
password => "123456"
db => "5"
data_type => "list"
key => "logstash"
}
}
filter {
}
output {
if [type] == "system" {
if [tags][0] == "syslog" {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "logstash-system-syslog-%{+YYYY.MM.dd}"
}
stdout { codec=> rubydebug }
}
else if [tags][0] == "auth" {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "logstash-system-auth-%{+YYYY.MM.dd}"
}
stdout { codec=> rubydebug }
}
}
}
然后启动logstash,指定上面的配置信息:./bin/logstash -f ./config/my_config/logstash-from-redis.conf
启动后就开始消费redis里面的数据并写入ES中。
logstash解析自定义日志格式
如果收集的日志不是json格式的,比如默认的nginx日志是以空格分隔的:
针对这样的日志格式,怎么配置logstash来解析呢?
下面记录一下配置信息备用。
# vim logstash-7.17.12/config/logstash.conf
input {
redis {
host => "192.168.0.1"
port => 6379
password => "123456"
db => "0"
data_type => "list"
key => "filebeat"
}
}
filter {
if [app] == "www" {
if [type] == "nginx-access" {
grok {
match => {
"message" => "%{IPV4:remote_addr} - (%{USERNAME:remote_user}|-) \[%{HTTPDATE:time_local}\] \"%{WORD:request_method} %{URIPATHPARAM:request_uri} HTTP/%{NUMBER:http_protocol}\" %{NUMBER:http_status} %{NUMBER:body_bytes_sent} \"%{GREEDYDATA:http_referer}\" \"%{GREEDYDATA:http_user_agent}\" \"(%{IPV4:http_x_forwarded_for}|-)\""
}
overwrite => ["message"]
}
geoip {
source => "remote_addr"
target => "geoip"
database => "/opt/GeoLite2-City.mmdb"
add_field => ["[geoip][coordinates]", "%{[geoip][longitude]}"]
add_field => ["[geoip][coordinates]", "%{[geoip][latitude]}"]
}
date {
locale => "en"
match => ["time_local", "dd/MMM/yyyy:HH:mm:ss Z"]
}
mutate {
convert => ["[geoip][coordinates]", "float"]
}
}
}
}
output {
elasticsearch {
hosts => ["http://192.168.0.212:9200","http://192.168.0.213:9200","http://192.168.0.214:9200"]
index => "logstash-%{type}-%{+YYYY.MM.dd}"
}
stdout{codec => rubydebug }
}
引入Filebeat
Filebeat简介
- Filebeat 是使用 Golang 实现的轻量型日志采集器,也是 Elasticsearch stack 里面的一员。Filebeat是用于转发和集中日志数据的轻量级传送工具。Filebeat监视您指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或 Logstash进行索引。
- Logstash功能虽然强大,但是它依赖java、在数据量大的时候,Logstash进程会消耗过多的系统资源,这将严重影响业务系统的性能,而filebeat就是一个完美的替代者,filebeat是Beat成员之一,基于Go语言,没有任何依赖,配置文件简单,格式明了,同时,filebeat比logstash更加轻量级,所以占用系统资源极少,非常适合安装在生产机器上。
- Filebeat的工作方式如下:启动Filebeat时,它将启动一个或多个输入,这些输入将在为日志数据指定的位置中查找。对于Filebeat所找到的每个日志,Filebeat都会启动收集器。每个收集器都读取单个日志以获取新内容,并将新日志数据发送到libbeat,libbeat将聚集事件,并将聚集的数据发送到为Filebeat配置的输出。
- logstash如果收集大量日志的时候,会占用很大的内存,使用Filebeat可以缓解这种情况。
Filebeat支持输出到多种存储介质:
引入Filebeat后的流程图如下:
Filebeat安装和配置
在 这里 下载(我这里下载的5.6.9版本的,不同版本的配置文件不同),然后解压,可以根据需要修改配置文件filebeat.yml
。更多内容参考:这里。
启动filebeat并且输出内容nohup ./filebeat -e -c filebeat.yml &
启动后,在当前目录下会生成一个nohup.out文件,可以查看filebeat启动日志和运行状态。以操作系统中/var/log/secure文件的日志格式为例,消费输出日志内容示例如下:
{"@timestamp":"2023-08-30T11:27:48.755Z",
"@metadata":{"beat":"filebeat","type":"doc","version":"6.3.2","topic":"osmessages"},
"beat":{"name":"filebeatserver","hostname":"filebeatserver","version":"6.3.2"},
"host":{"name":"filebeatserver"},
"source":"/var/log/secure",
"offset":11326,
"message":"Jan 31 17:41:56 localhost sshd[13053]: Failed password for root from 172.16.213.37 port 49560 ssh2",
"prospector":{"type":"log"},
"input":{"type":"log"},
"fields":{"log_topic":"osmessages"}
}
输出信息格式解读
从这个输出可以看到,输出日志被修改成了JSON格式,日志总共分为10个字段,分别是"@timestamp"、"@metadata"、"beat"、"host"、"source"、"offset"、"message"、"prospector"、"input"和"fields"
字段,每个字段含义如下:
- @timestamp:时间字段,表示读取到该行内容的时间。
- @metadata:元数据字段,此字段只有是跟Logstash进行交互使用。
- beat:beat属性信息,包含beat所在的主机名、beat版本等信息。
- host: 主机名字段,输出主机名,如果没主机名,输出主机对应的IP。
- source: 表示监控的日志文件的全路径。
- offset: 表示该行日志的偏移量。
- message: 表示真正的日志内容。
- prospector:filebeat对应的消息类型。
- input:日志输入的类型,可以有多种输入类型,例如Log、Stdin、redis、Docker、TCP/UDP等
- fields:topic对应的消息字段或自定义增加的字段。
通过filebeat接收到的内容,默认增加了不少字段,但是有些字段对数据分析来说没有太大用处,所以有时候需要删除这些没用的字段,在filebeat配置文件中添加如下配置,即可删除不需要的字段:
processors:
- drop_fields:
fields: ["beat", "input", "source", "offset"]
这个设置表示删除"beat"、"input"、"source"、"offset"
四个字段,其中, @timestamp
和@metadata
字段是不能删除的。做完这个设置后,再次查看输出日志,已经不再输出这四个字段信息了。
从nginx日志文件中读取内容
修改 filebeat 的配置文件,从nginx日志文件中读取内容,然后输出到redis:vim filebeat-5.6.9/filebeat.yml
,内容如下:
filebeat.inputs:
- type: log
paths:
- /usr/local/nginx/logs/access.log
# tags: ["access"]
fields:
app: www
type: nginx-access
fields_under_root: true
- type: log
paths:
- /usr/local/nginx/logs/error.log
# ags: ["error"]
fields:
app: www
type: nginx-error
fields_under_root: true
output.redis:
hosts: ["192.168.0.1"]
port: 6379
password: "123456"
key: "filebeat"
db: 5
datatype: list
启动filebeat:nohup ./filebeat -e -c filebeat.yml -d "publish" &
然后查看redis里面已经有了nginx的日志数据。文章来源:https://www.toymoban.com/news/detail-670791.html
然后再消费者机器上配置logstash消费redis中的数据,vim logstash-7.17.12/config/logstash-from-redis.conf
,配置内容如下:文章来源地址https://www.toymoban.com/news/detail-670791.html
input {
redis {
host => "192.168.0.1"
port => 6379
password => "123456"
db => "5"
data_type => "list"
key => "filebeat"
}
}
filter {
json {
source => "message"
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "mywebsite-prod-log-%{+YYYY.MM.dd}"
user => "elastic"
password => "mypassword"
}
}
到了这里,关于使用ELK(ES+Logstash+Filebeat+Kibana)收集nginx的日志的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!