posts - 252,comments - 20,views - 25万

第1章 Kibana

kibana是一款开源的数据分析和可视化平台,它是Elastic Stack成员之一,设计用于和elasticsearch协作。您可以使用 kibana对elasticsearch索引中的数据进行搜索、查看、交互操作。您可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。

kibana官方展示页面地址:https://demo.elastic.co/app/kibana#/dashboard/welcome_dashboard

kibana官网链接:https://www.elastic.co/cn/products/kibana

安装kibana,可以和es装在一台机器上,至少得2G内存。

1.1 配置安装

几台服务器需要的内存以及服务划分如下:

elk1:2G-4G
es
kibana
nginx
filebeat
 ... 

elk2:512M-2G
nginx
filebeat
 ...

# 解压安装包
tar -xvf kibana-6.5.4-linux-x86_64.tar.gz

# 修改配置文件
grep ^[a-Z] kibana.yml 
server.port: 5601
server.host: "192.168.172.101" # 对外暴露服务的地址
server.name: "elk1"
elasticsearch.url: "http://192.168.172.101:9200" # 配置Elasticsearch
kibana.index: ".kibana"

# 启动
./bin/kibana

# 通过浏览器进行访问
http://192.168.172.101:5601/app/kibana

可以看到kibana页面,并且可以看到提示,导入数据到Kibana。

1.2 功能说明

1.3 数据探索

添加索引信息

即可查看索引数据

1.4 Metricbeat仪表盘

可以将Metricbeat的数据在Kibana中展示。

# 修改metricbeat配置
setup.kibana:
host: "192.168.172.101:5601"

# 安装仪表盘到Kibana
./metricbeat setup --dashboards

即可在kibana中看到仪表盘数据:

查看系统信息:

1.5 Nginx指标仪表盘

1.6 Nginx日志仪表盘

# 修改配置文件 itcast-nginx.yml 
filebeat.inputs:
#- type: log
#  enabled: true
#  paths:
#    - /var/log/nginx/*.log
#  tags: ["nginx"]

setup.kibana:
  host: "192.168.172.101:5601"

setup.template.settings:
  index.number_of_shards: 3

filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]

# 安装仪表盘到kibana
./filebeat -c itcast-nginx.yml setup

可以看到nginx的FileBeat的仪表盘了:

1.7 kibana自定义图表

在Kibana中,也可以进行自定义图表,如制作柱形图:

默认如果使用filebeat模板导入视图会把所有的服务都导入进去,而我们实际上并不需要这么多视图,而且默认的视图模板只能匹配 filebeat-*开头的索引,所以这里我们有2个需求需要解决:

  • 1.通过一定处理只导入我们需要的模板
  • 2.导入的视图模板索引名称为我们需要的索引名称

解决方法:

  • 1.备份一份filebeat的kibana视图,删除不需要的视图模板文件
  • 2.修改视图文件里默认的索引名称为我们需要的索引名称

filebeat安装路径下也有kibana目录,里面有 kibana5kibana6的图表。

/usr/local/filebeat/kibana/5的内容可以删掉,将 /usr/local/filebeat/kibana/6/dashboard和/usr/local/filebeat/kibana/6/index-pattern两个目录可以备份到root目录下。

cd /usr/local/filebeat/kibana/6/dashboard
sed -n 's#filebeat\-\*#nginx\-\*#g' Filebeat-nginx-logs.json 
sed -n 's#filebeat\-\*#nginx\-\*#gp' Filebeat-nginx-logs.json 
# 更改文件内容,替换索引名称
sed -i 's#filebeat\-\*#nginx\-\*#gp' Filebeat-nginx-logs.json  
sed -i 's#filebeat\-\*#nginx\-\*#gp' Filebeat-nginx-overview.json 

cd /usr/local/filebeat/kibana/6/index-pattern
sed -i 's#filebeat\-\*#nginx\-\*#gp' filebeat.json 

# 导入
./filebeat setup --dashboards -E setup.dashboards.directory=/usr/local/filebeat/kibana

常用的图表类型:

1.柱状图

2.折线图

3.饼图

4.仪表图

5.拼接大屏展示

可以实现的功能:

1.访问最多的IP地址前10

2.访问最多的url前10

3.访问最多的agent前10

4.访问http状态码比例

将图表添加到自定义Dashboard中:

1.8 开发者工具

在Kibana中,为开发者的测试提供了便捷的工具使用,比如我们用postman对es索引做的一些操作,其实也可以在kibana中完成,如下:

1.9 kibana监控es集群

elk版本统一,一个系列的组件必须都是一个版本,要升级也是同时升级到一个版本。而且只能升级,很难降级,因为数据很难还原成老版本的,所以生产环境中的软件升级版本操作都需要谨慎。

x-pack收费,后来大家破解,所以逐步开放功能,后续6.6版本后 x-pack的监控功能也开放了,变免费了。

点击kibana界面的monitoring项就可以了。

第2章 Nginx日志分析系统

2.1 项目需求

Nginx是一款非常优秀的web服务器,往往nginx服务会作为项目的访问入口,那么,nginx的性能保障就变得非常重
要了,如果nginx的运行出现了问题就会对项目有较大的影响。所以,我们需要对nginx的运行有监控措施,实时掌握
nginx的运行情况,那就需要收集nginx的运行指标和分析nginx的运行日志了。

2.2 业务流程

说明:

  • 通过Beats采集Nginx的指标数据和日志数据
  • Beats采集到数据后发送到Elasticsearch中
  • kibana读取数据进行分析
  • 用户通过kibana进行查看分析报表

2.3 部署安装nginx

# 安装nginx和压测工具
yum install epel-release.noarch -y
yum install nginx httpd-tools -y

# 启动nginx后可以ab压测,ip后面不加反斜杠会失败
ab -n 100 -c 100 http://192.168.172.101/

# 查看默认格式的访问日志
tail -n 10 /var/log/nginx/access.log 
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"
192.168.172.101 - - [09/May/2022:10:59:00 +0800] "GET / HTTP/1.0" 200 4833 "-" "ApacheBench/2.3" "-"

第3章 Beats简介

官网:https://www.elastic.co/cn/products/beats

Beats系列产品:

3.2 filebeat

3.2.1 架构

用于监控、收集服务器日志文件

3.2.2 部署与运行

下载(或使用资料中提供的安装包,版本为:filebeat-6.5.4):https://www.elastic.co/downloads/beats

# 安装filebeat
tar zxf filebeat-6.5.4-linux-x86_64.tar.gz -C /usr/local/

# 配置文件包括:
filebeat.yml以及modules.d目录下的,编辑filebeat.yml之前可以先备份。

# 创建配置文件itcast.yml:
filebeat.inputs:
- type: stdin
  enabled: true

setup.template.settings:
  index.number_of_shards: 3

output.console:
  pretty: true
  enable: true

# 启动filebeat:
./filebeat -e -c itcast.yml

# 输入hello运行结果如下:
hello
{
  "@timestamp": "2022-05-13T03:14:19.320Z",
  "@metadata": {   # 元数据信息
    "beat": "filebeat",
    "type": "doc",
    "version": "6.5.4"
  },
  "prospector": {   # 标准输入勘探器
    "type": "stdin"
  },
  "beat": {  # beat版本以及主机信息
    "name": "elk1",
    "hostname": "elk1",  
    "version": "6.5.4"
  },
  "host": {
    "name": "elk1"
  },
  "source": "",
  "offset": 0,
  "message": "hello",    # 输入的内容
  "input": {   
    "type": "stdin"    # 控制台标准输入
  }
}

3.2.3 读取文件

# 配置读取文件项 itcast-log.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/*.log

setup.template.settings:
  index.number_of_shards: 3

output.console:
  pretty: true
  enable: true

# 启动filebeat
./filebeat -e -c itcast-log.yml 

# /itcast/beats/logs/下创建a.log文件,并输入如下内容
hello
world

# 观察filebeat输出
{
  "@timestamp": "2022-05-13T03:27:13.285Z",
  "@metadata": {
    "beat": "filebeat",
    "type": "doc",
    "version": "6.5.4"
  },
  "prospector": {
    "type": "log"
  },
  "input": {
    "type": "log"
  },
  "beat": {
    "name": "elk1",
    "hostname": "elk1",
    "version": "6.5.4"
  },
  "host": {
    "name": "elk1"
  },
  "message": "hello",
  "source": "/itcast/beats/logs/a.log",
  "offset": 0
}
{
  "@timestamp": "2022-05-13T03:27:13.285Z",
  "@metadata": {
    "beat": "filebeat",
    "type": "doc",
    "version": "6.5.4"
  },
  "prospector": {
    "type": "log"
  },
  "beat": {
    "name": "elk1",
    "hostname": "elk1",
    "version": "6.5.4"
  },
  "host": {
    "name": "elk1"
  },
  "source": "/itcast/beats/logs/a.log",
  "offset": 6,
  "message": "world",
  "input": {
    "type": "log"
  }
}

可以看到,已经检测到日志文件有更新,立刻就会读取到更新的内容,并且输出到控制台。

3.2.4 自定义字段

# 配置读取文件itcast-log.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /itcast/beats/logs/*.log
  # 添加自定义tag,便于后续的处理
  tags: ["web"]
  # 添加自定义字段
  fields:
    from: itcast-im
  # true为添加到根节点,false为添加到子节点中
  fields_under_root: true

setup.template.settings:
  index.number_of_shards: 3

output.console:
  pretty: true
  enable: true

# 启动filebeat
./filebeat -e -c itcast-log.yml 

# 在/itcast/beats/logs下创建b.log,并输入如下内容:
123

# 执行结果:
{
  "@timestamp": "2022-05-13T03:41:16.813Z",
  "@metadata": {
    "beat": "filebeat",
    "type": "doc",
    "version": "6.5.4"
  },
  "tags": [
    "web"
  ],
  "prospector": {
    "type": "log"
  },
  "input": {
    "type": "log"
  },
  "beat": {
    "name": "elk1",
    "hostname": "elk1",
    "version": "6.5.4"
  },
  "host": {
    "name": "elk1"
  },
  "source": "/itcast/beats/logs/b.log",
  "offset": 0,
  "message": "123",
  "from": "itcast-im"
}

3.2.5 输出到Elasticsearch

# filebeat.yml文件内容 egrep -v "#|^$" filebeat.yml  
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false
setup.template.settings:
  index.number_of_shards: 3  # 指定索引的分区数
setup.kibana:
output.elasticsearch:    # 指定ES的配置
  hosts: ["192.168.172.101:9200"]
processors:
  - add_host_metadata: ~
  - add_cloud_metadata: ~

# 最精简的版本是:
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
output.elasticsearch:
  hosts: ["192.168.172.101:9200"]

# 启动filebeat
./filebeat -e -c filebeat.yml 

这种方式收集nginx日志有一个缺点是,内容没有经过处理,所有的字段都放在一个message字段里了,只是读取到原数据,这对于我们后期操作时不利的,也不利于在kibana界面添加关键词。

3.2.6 Filebeat工作原理

Filebeat由两个主要组件组成:prospectorharvester,这两个组件协同工作将文件变动发送到指定的输出中。

  • Harvester(收割机):
    负责读取单个文件内容。每个文件会启动一个Harvester,每个Harvester会逐行读取各个文件,并将文件内容发送到指定输出中。Harvester负责打开和关闭文件,意味在Harvester运行的时候,文件描述符处于打开状态,如果文件在收集中被重命名或者被删除,Filebeat会继续读取此文件。所以在Harvester关闭之前,磁盘不会被释放。默认情况filebeat会保持文件打开的状态,直到达到close_inactive(如果此选项开启,filebeat会在指定时间内将不再更新的文件句柄关闭,时间从harvester读取最后一行的时间开始计时。若文件句柄被关闭后,文件发生变化,则会启动一个新的harvester。关闭文件句柄的时间不取决于文件的修改时间,若此参数配置不当,则可能发生日志不实时的情况,由 scan_frequency参数决定,默认10s。Harvester使用内部时间戳来记录文件最后被收集的时间。例如:设置5m,则在Harvester读取文件的最后一行之后,开始倒计时5分钟,若5分钟内文件无变化,则关闭文件句柄。默认5m)。
  • prospector(勘探者):管理Harvester并找到所有要读取的文件来源。Filebeat目前支持两种prospector类型:log和stdin。
filebeat.prospectors:
- input_type: log
  paths:
    - /apps/logs/*/info.log

Prospector会找到 /apps/logs/*目录下的所有 info.log文件,并为每个文件启动一个Harvester。Prospector会检查每个文件,看Harvester是否已经启动,是否需要启动,或者文件是否可以忽略。若Harvester关闭,只有在文件大小发生变化的时候Prospector才会执行检查。只能检测本地的文件。

Filebeat如何记录文件状态:

将文件状态记录在文件中(默认在 /var/lib/filebeat/registry)。此状态可以记住Harvester收集文件的偏移量。若连接不上输出设备,如ES等,filebeat会记录发送前的最后一行,并再可以连接的时候继续发送。Filebeat在运行的时候,Prospector状态会被记录在内存中。Filebeat重启的时候,利用registry记录的状态来进行重建,用来还原到重启之前的状态。每个Prospector会为每个找到的文件记录一个状态,对于每个文件,Filebeat存储唯一标识符以检测文件是否先前被收集。

cat /usr/local/filebeat/data/registry 
[{"source":"/var/log/nginx/access.log","offset":0,"timestamp":"2022-05-13T11:24:47.383885505+08:00","ttl":-2,"type":"log","meta":null,"FileStateOS":{"inode":1952430,"device":64768}},{"source":"/var/log/nginx/error.log","offset":0,"timestamp":"2022-05-13T11:24:47.38635557+08:00","ttl":-2,"type":"log","meta":null,"FileStateOS":{"inode":1952431,"device":64768}},{"source":"/var/log/tomcat/localhost_access_log.2022-05-10.txt","offset":1538,"timestamp":"2022-05-10T14:07:09.20403083+08:00","ttl":-2,"type":"log","meta":null,"FileStateOS":{"inode":1607199,"device":64768}},{"source":"/var/log/elasticsearch/elasticsearch.log","offset":5426,"timestamp":"2022-05-10T14:07:09.206505213+08:00","ttl":-2,"type":"log","meta":null,"FileStateOS":{"inode":201340004,"device":64768}},{"source":"/itcast/beats/logs/a.log","offset":12,"timestamp":"2022-05-13T13:40:29.577318337+08:00","ttl":-2,"type":"log","meta":null,"FileStateOS":{"inode":136020015,"device":64768}},{"source":"/itcast/beats/logs/b.log","offset":4,"timestamp":"2022-05-13T13:40:29.577817554+08:00","ttl":-2,"type":"log","meta":null,"FileStateOS":{"inode":136020014,"device":64768}},{"source":"/itcast/beats/logs/q.log","offset":4,"timestamp":"2022-05-13T13:46:54.62428932+08:00","ttl":-2,"type":"log","meta":null,"FileStateOS":{"inode":136020018,"device":64768}},{"source":"/itcast/logs/app.log","offset":8482,"timestamp":"2022-05-14T14:16:25.01718088+08:00","ttl":-1,"type":"log","meta":null,"FileStateOS":{"inode":205062805,"device":64768}}]

Filebeat如何保证事件至少被输出一次:

Filebeat之所以能保证事件至少被传递到配置的输出一次,没有数据丢失,是因为filebeat将每个事件的传递状态保存在文件中。在未得到输出方确认时,filebeat会尝试一直发送,直到得到回应。若filebeat在传输过程中被关闭,则不会再关闭之前确认所有时事件。任何在filebeat关闭之前为确认的时间,都会在filebeat重启之后重新发送。这可确保至少发送一次,但有可能会重复。可通过设置shutdown_timeout 参数来设置关闭之前的等待事件回应的时间(默认禁用)。

Filebeat如何保持文件的状态:

  • Filebeat 保存每个文件的状态并经常将状态刷新到磁盘上的注册文件中。该状态用于记住harvester正在读取的最后偏移量,并确保发送所有日志行。如果输出(例如Elasticsearch或Logstash)无法访问,Filebeat会跟踪最后发送的行,并在输出再次可用时继续读取文件。在Filebeat运行时,每个prospector内存中也会保存的文件状态信息,当重新启动Filebeat时,将使用注册
    文件的数据来重建文件状态,Filebeat将每个harvester在从保存的最后偏移量继续读取。

启动命令:

./filebeat -e -c itcast.yml 
./filebeat -e -c itcast.yml -d "publish"

# 参数说明
-e: 输出到标准输出,默认输出到syslog和logs下
-c: 指定配置文件
-d: 输出debug信息

# 测试
DEBUG   [publish]       pipeline/processor.go:308       Publish event: {
  "@timestamp": "2022-05-13T05:41:49.586Z",
  "@metadata": {
    "beat": "filebeat",
    "type": "doc",
    "version": "6.5.4"
  },
  "source": "/itcast/beats/logs/q.log",
  "tags": [
    "haoke-im"
  ],
  "beat": {
    "hostname": "elk1",
    "version": "6.5.4",
    "name": "elk1"
  },
  "host": {
    "name": "elk1"
  },
  "fields": {
    "from": "haoke-im"
  },
  "offset": 0,
  "message": "456",
  "prospector": {
    "type": "log"
  },
  "input": {
    "type": "log"
  }
}

3.2.7 读取Nginx日志文件

将nginx日志的每行转换为json格式,便于在kibana中根据关键字段查看。

# 原来的默认格式
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日志
log_format main '{ "time_local": "$time_local", '
                 '"remote_addr": "$remote_addr", '
                 '"referer": "$http_referer", '
                 '"request": "$request", '
                 '"status":  "$status", '
                 '"bytes": "$body_bytes_sent", '
                 '"agent": "$http_user_agent",'
                 '"x_forwarded": "$http_x_forwarded_for", '
                 '"up_addr": "$upstream_addr", '
                 '"up_host": "$upstream_http_host", '
                 '"upstream_time": "$upstream_response_time", '
                 '"request_time": "$request_time"'
' } ';

# 修改nginx配置文件,添加json格式的日志,并将默认的日志格式改为json
    log_format json '{ "time_local": "$time_local", '
                    '"remote_addr": "$remote_addr", '
                    '"referer": "$http_referer", '
                    '"request": "$request", '
                    '"status":  "$status", '
                    '"bytes": "$body_bytes_sent", '
                    '"agent": "$http_user_agent", '
                    '"x_forwarded": "$http_x_forwarded_for", '
                    '"up_addr": "$upstream_addr", '
                    '"up_host": "$upstream_http_host", '
                    '"upstream_time": "$upstream_response_time", '
                    '"request_time": "$request_time"'
' } ';

    access_log  /var/log/nginx/access.log  json;

# 检查有无语法错误
nginx -t

# 清空原有日志
> /var/log/nginx/access.log 

# 重载nginx
systemctl reload nginx

# 重新压测
ab -n 100 -c 100 http://192.168.172.101/  

# 查看新生成的nginx日志格式
tail -f 10 /var/log/nginx/access.log 
{
    "time_local":"09/May/2022:15:47:35 +0800",
    "remote_addr":"192.168.172.101",
    "referer":"-",
    "request":"GET / HTTP/1.0",
    "status":"200",
    "bytes":"4833",
    "agent":"ApacheBench/2.3",
    "x_forwarded":"-",
    "up_addr":"-",
    "up_host":"-",
    "upstream_time":"-",
    "request_time":"0.000"
}
是json格式,此时因为数据格式已经发生变化,需要在es-head界面删掉filebeat索引,重新生成新的filebeat索引

# 重启filebeat
./filebeat -e -c filebeat.yml 

# 压测
ab -n 100 -c 100 http://192.168.172.101/

filebeat会记录一下上一次读到什么位置了,重新启动后会从上一次记录的位置开始读取数据(类似于tail -f)
此时kibana中的日志还是没有变成k-v格式,仍然是都在message字段里。
需要给filebeat配置文件input的位置添加以下两行内容,和path对齐:
json.keys_under_root: true    # 传输给es之前已经解析成json格式完毕
json.overwrite_keys: true
然后再在es-head上和kibana上删除一次filebeat索引,再重启filebeat。

# 压测
ab -n 100 -c 100 http://192.168.172.101/

自定义索引名称,修改filebeat配置文件output部分的内容,和hosts对齐
  index: "nginx-%{[beat.version]}-%{+yyyy.MM}"
重启filebeat会报错,需要在output部分加上下面4行,顶格写:
setup.template.name: "nginx"
setup.template.pattern: "nginx-*"
setup.template.enabled: false
setup.template.overwrite: true

# 综上所述,filebeat_nginx_tags.yml的最终版为:
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["access"]

- type: log
  enabled: true
  paths:
    - /var/log/nginx/error.log
  tags: ["error"]

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  # index: "nginx-%{[beat.version]}-%{+yyyy.MM}"
  indices:
  - index: "nginx-access-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "access"
  - index: "nginx-error-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "error"
setup.template.name: "nginx"
setup.template.pattern: "nginx-*"
setup.template.enabled: false
setup.template.overwrite: true


# 上述配置如果是在7.x中,则为  
index: "nginx-%{[agent.version]}-%{+yyyy.MM}"
# 压测
ab -n 100 -c 100 http://192.168.172.101/

总结

上述做了收集nginx日志的以下几条:

1.收集普通格式的日志

不能拆分显示,所有的日志记录成了一条

2.收集json格式的nginx日志

修改nginx日志格式为json

filebeat添加json解析的参数

3.自定义索引名称

修改filebeat添加4条配置

给elk2和elk3也安装filebeat和nginx,直接使用elk1的filebeat配置文件和nginx配置文件

用ab压测产生日志

4.把 access.logerror.log存在不同的index索引中,所以需要修改filebeat的output内容。

打标签(设置k值)然后判断标签,error.log也通过filebeat过滤,配置文件也改为下面这样,error.log不需要json两行的原因是它不是json格式,根据es-head里显示的任意一个key值都可以作为判断条件,这里选择的判断条件是tags。

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tag: ["access"]

- type: log
  enabled: true
  paths:
    - /var/log/nginx/error.log
  tag: ["error"]

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  # index: "nginx-%{[beat.version]}-%{+yyyy.MM}"
  indices:
  - index: "nginx-access-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "access"
  - index: "nginx-error-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "error"
setup.template.name: "nginx"
setup.template.pattern: "nginx-*"
setup.template.enabled: false
setup.template.overwrite: true

将修改好的nginx文件备份一份,方便以后相同情况可以直接使用(以后使用时还是需要将名字改回filebeat.yml的)。

cp filebeat.yml  /root/filebeat_nginx_tags.yml

3.2.8 收集tomcat日志

# 安装tomcat
yum install tomcat tomcat-webapps tomcat-admin-webapps tomcat-docs-webapp tomcat-javadoc -y

# 启动tomcat
systemctl start tomcat

# tomcat日志文件
/var/log/tomcat/localhost_access_log.2022-05-10.txt 

# 修改/etc/tomcat/server.xml第139行,删掉后添加下面内容:
# 清空tomcat日志
> /var/log/tomcat/localhost_access_log.2022-05-10.txt
 
# 重启tomcat
systemctl restart tomcat

# 此时访问192.168.172.101:8080后产生的日志
{"clientip":"192.168.172.1","ClientUser":"-","authenticated":" -","AccessTime":"[10/May/2022:10:51:48 +0800]","method":"GET / HTTP/1.1","status":"200","SendBytes":"11217","Query?string":"","partner":"-","AgentVersion":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39"}
去浏览器的json格式检验,发现上述日志确实是json格式。

# 编辑filebeat.yml,可以借鉴nginx的access.log
- type: log
  enabled: true
  paths:
    - /var/log/tomcat/localhost_access_log.*.txt
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ['tomcat']

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  # index: "nginx-%{[beat.version]}-%{+yyyy.MM}"
  indices:
  - index: "nginx-access-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "access"
  - index: "nginx-error-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "error"
  - index: "tomcat-access-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "tomcat"

# 只需要提前运行过这部分就行,叫什么名字不重要
setup.template.name: "nginx"
setup.template.pattern: "nginx-*"
setup.template.enabled: false
setup.template.overwrite: true

3.2.9 收集java日志

官方文档说明:https://www.elastic.co/guide/en/beats/filebeat/6.6/multiline-examples.html

这里以收集elasticsearch的日志为例,因为elasticsearch就是java语言开发的。修改filebeat配置文件:
filebeat.inputs:
###########es-java###############
- type: log
  enabled: true
  paths:
    -  /var/log/elasticsearch/elasticsearch.log
  tags: ["es-java"]
  multiline.pattern: '^\['
  multiline.negate: true
  multiline.match: after

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  # index: "nginx-%{[beat.version]}-%{+yyyy.MM}"
  indices:
  - index: "es-java-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      tags: "es-java"
setup.template.name: "nginx"
setup.template.pattern: "nginx-*"
setup.template.enabled: false
setup.template.overwrite: true

multi三行的含义是到下一个[中括号出现时,才停止匹配,否则将认为到下一个[前的内容都是一条日志的内容,当然这里的匹配模式可以具体的正则表达式修改

3.2.10 收集docker日志

  • 第一种方式,编辑filebeat配置文件,这个很少使用。
# 启动一个nginx容器
docker pull nginx
docker run --name nginx -p 80:80 -d nginx
docker exec -it 661a1d2fcc52 /bin/bash   # 容器id,是debian操作系统,内核新,比centos精简
此时可以在浏览器中通过http://192.168.172.102:80访问了(80端口可省略)

# 查看容器日志
docker logs -f nginx

# 编辑filebeat配置文件:
filebeat.inputs:
- type: docker
  containers.ids:
    - '661a1d2fcc5294500ab0fb7b08fcaf7271f1741cfce682035a21462acde60a4a'

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  index: "docker-%{[beat.version]}-%{+yyyy.MM}"
setup.template.name: "docker"
setup.template.pattern: "docker-*"
setup.template.enabled: false
setup.template.overwrite: true

# 重启filebeat,这种方式的缺点是access.log和error.log日志没有分开
  • 第二种方式,以stream作为key,stdout代表 access.log,stderr代表 error.log

filebeat.yml改成下面这样:

filebeat.inputs:
- type: docker
  containers.ids:
  - '661a1d2fcc5294500ab0fb7b08fcaf7271f1741cfce682035a21462acde60a4a'

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  index: "docker-access-%{[beat.version]}-%{+yyyy.MM}"

setup.template.name: "docker"
setup.template.pattern: "docker-*"
setup.template.enabled: false
setup.template.overwrite: true

# 再启动一个nginx容器,产生日志
docker run --name nginx-v2 -p 8080:80 -d nginx

# 有多个容器时,filebeat配置可以这样写:
filebeat.inputs:
- type: docker
  containers.ids:
  - '*'

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  index: "docker-access-%{[beat.version]}-%{+yyyy.MM}"

setup.template.name: "docker"
setup.template.pattern: "docker-*"
setup.template.enabled: false
setup.template.overwrite: true

# 修改完后重启filebeat

这种方式的缺点是,在kibana或es-head界面没有办法把不同容器区分开来

  • 第三种方式,根据服务类型收集多个容器日志:
yum install python2-pip -y

# 升级pip
/usr/bin/python -m pip install --upgrade pip

# 临时使用清华源
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package --trusted-host pypi.tuna.tsinghua.edu.cn
yum install docker-compose -y
docker-compose version 

# 编写docker-compose.yml,内容如下:
version: '3'
services:
  nginx:
    image: nginx
    # 设置labels
    labels:
      service: nginx
    # logging设置增加labels.service,日志中会增加打标签的内容
    logging:
      options:
        labels: "service"
    ports:
      - "8080:80"
  db:
    image: nginx:latest
    # 设罝labels
    labels:
      service: db
    # 1ogging设置增加labels.service
    logging:
      options:
        labels: "service"
    ports:
      - "80:80"

# 前台启动
docker-compose up

# 此时要收集filebeat日志,filebeat.yml可以这样写:
filebeat.inputs:
- type: log
  paths:
    - /var/lib/docker/containers/*/*-json.log
  json.keys_under_root: true
  json.overwrite_keys: true

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  # index: "docker-access-%{[beat.version]}-%{+yyyy.MM}"
  indices:
  - index: "docker-nginx-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      attrs.service: "nginx"
  - index: "docker-db-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      attrs.service: "db"

setup.template.name: "docker"
setup.template.pattern: "docker-*"
setup.template.enabled: false
setup.template.overwrite: true

# 根据服务类型和日志类型(access/error)来判断。filebeat.yml文件的output部分需要修改,两个条件写一起就变成and关系。
output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  # index: "docker-access-%{[beat.version]}-%{+yyyy.MM}"
  indices:
  - index: "docker-nginx-access-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      attrs.service: "nginx"
      stream: "stdout"

  - index: "docker-nginx-error-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      attrs.service: "nginx"
      stream: "stderr"

  - index: "docker-db-access-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      attrs.service: "db"
      stream: "stdout"

  - index: "docker-db-error-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      attrs.service: "db"
      stream: "stderr"

setup.template.name: "docker"
setup.template.pattern: "docker-*"
setup.template.enabled: false
setup.template.overwrite: true

修改完后重启filebeat。

3.2.10.1 总结

做了哪些工作:

nginx日志:

1.默认配置收集

  • 索引名固定
  • 所有类型放在一个message字段

2.自定义模板

  • 自定义了索引名称
  • 根据日志类型打tag标签拆分

3.把nginx日志转换为json格式

  • 可以按照需要的字段过滤分析

tomcat日志:

  • 转换为json格式

docker日志:

1.默认配置不能按照容器类型拆分

2.使用docker-compose添加了一个字段service

3.根据服务类型和日志类型生成不同的容器类型的索引

java日志:

1.多行匹配模式

3.2.11 filebeat自带的模块modules收集日志

前面要想实现日志数据的读取以及处理都是自己手动配置的,其实,在Filebeat中,有大量的Module,可以简化我们的配置,直接就可以使用,如下:

1.nginx

2.mongo

3.redis

4.mysql

以nginx module的设置为例,操作步骤如下:
0.filebeat配置文件配置模块路径
1.激活模块
2.修改模块配置文件
3.修改nginx日志为普通格式,清空nginx日志
4.安装es2个插件
5.重启es
6.重启filebeat

# 0.在filebeat.yml中修改这几行:
filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: true
  reload.period: 10s

setup.kibana:
  host: "192.168.172.101:5601"

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
  # index: "nginx-%{[beat.version]}-%{+yyyy.MM}"
  indices:
  - index: "nginx-access-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      fileset.name: "access"
  - index: "nginx-error-%{[beat.version]}-%{+yyyy.MM}"
    when.contains:
      fileset.name: "error"
setup.template.name: "nginx"
setup.template.pattern: "nginx-*"
setup.template.enabled: false
setup.template.overwrite: true

# 1.查看所有disabled的模块
./filebeat modules list
Enabled:

Disabled:
apache2
auditd
elasticsearch
haproxy
icinga
iis
kafka
kibana
logstash
mongodb
mysql
nginx
osquery
postgresql
redis
suricata
system
traefik

# 激活nginx模块,直接修改后缀名效果一样。
./filebeat modules enable nginx

修改filebeat的nginx模板配置文件,只用添加路径就可以了
- module: nginx
  access:
    enabled: true
    var.paths: ["/var/log/nginx/access.log"]

  error:
    enabled: true
    var.paths: ["/var/log/nginx/error.log"]

# 3.恢复nginx日志格式,修改main后重启

# 4.filebeat启动失败,需要在elasticsearch中安装ingest-user-agent和ingest-geoip两个插件:
./bin/elasticsearch-plugin install ingest-user-agent
./bin/elasticsearch-plugin install ingest-geoip

当然了,其他的module的用法参加官方文档:https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules.html

3.3 Metricbeat

  • 定期收集操作系统或应用服务的指标数据
  • 存储到elasticsearch中,进行实时分析

3.3.1 Metricbeat组成

Metricbeat有2部分组成,一部分是Module,另一部分为Metricset。

  • Module
    • 收集的对象,如:mysql、redis、nginx、操作系统等;
  • Metricset
    • 收集指标的集合,如:cpu、memory、network等;

以Redis Module为例:

3.3.2 部署与收集系统指标

# 部署过程:
tar zxf metricbeat-6.5.4-linux-x86_64.tar.gz -C /usr/local/

# 编辑配置文件
egrep -v "#|^$" metricbeat.yml 
metricbeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false
setup.template.settings:
  index.number_of_shards: 1
  index.codec: best_compression
setup.kibana:
  host: "192.168.172.101:5601"
output.elasticsearch:
  hosts: ["192.168.172.101:9200"]
processors:
  - add_host_metadata: ~
  - add_cloud_metadata: ~

# 启动
./metricbeat -e

在elasticsearch中可以看到,系统的一些指标数据已经写进去了。

system module配置:

[root@elk1 /usr/local/metricbeat/modules.d]# cat system.yml 
# Module: system
# Docs: https://www.elastic.co/guide/en/beats/metricbeat/6.5/metricbeat-module-system.html

- module: system
  period: 10s
  metricsets:
    - cpu
    - load
    - memory
    - network
    - process
    - process_summary
    #- core
    #- diskio
    #- socket
  process.include_top_n:
    by_cpu: 5      # include top 5 processes by CPU
    by_memory: 5   # include top 5 processes by memory

- module: system
  period: 1m
  metricsets:
    - filesystem
    - fsstat
  processors:
  - drop_event.when.regexp:
      system.filesystem.mount_point: '^/(sys|cgroup|proc|dev|etc|host|lib)($|/)'

- module: system
  period: 15m
  metricsets:
    - uptime

#- module: system
#  period: 5m
#  metricsets:
#    - raid
#  raid.mount_point: '/'

3.3.3 Module

# 查看列表
./metricbeat modules list

# 默认启用
Enabled:
system

Disabled:
aerospike
apache
ceph
couchbase
docker
dropwizard
elasticsearch
envoyproxy
etcd
golang
graphite
haproxy
http
jolokia
kafka
kibana
kubernetes
kvm
logstash
memcached
mongodb
munin
mysql
nginx
php_fpm
postgresql
prometheus
rabbitmq
redis
traefik
uwsgi
vsphere
windows
zookeeper

3.3.4 Nginx Module

3.3.4.1 开启nginx的状态查询

在nginx中,需要开启状态查询,才能查询到指标数据。

# 重新编译nginx,需要加入--with-http_stub_status_module模块
参考链接:https://www.cnblogs.com/even160941/p/15064925.html

# 查询版本信息
nginx -V
nginx version: nginx/1.20.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_auth_request_module --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug --with-stream

# 配置nginx
vim nginx.conf
location /nginx-status {
stub_status on;
access_log off;
}

测试:

结果说明:

  • Active connections:正在处理的活动连接数
  • server accepts handled requests
    • 第一个 server 表示Nginx启动到现在共处理了9个连接
    • 第二个 accepts 表示Nginx启动到现在共成功创建 9 次握手
    • 第三个 handled requests 表示总共处理了 21 次请求
    • 请求丢失数 = 握手数 - 连接数 ,可以看出目前为止没有丢失请求
  • Reading: 0 Writing: 1 Waiting: 1
    • Reading:Nginx 读取到客户端的 Header 信息数
    • Writing:Nginx 返回给客户端 Header 信息数
    • Waiting:Nginx 已经处理完正在等候下一次请求指令的驻留链接(开启keep-alive的情况下,这个值等于Active - (Reading+Writing))

3.3.4.2 配置Nginx Module

# 启用nginx Module
./metricbeat modules enable nginx

# 修改nginx module配置
cat modules.d/nginx.yml 
# Module: nginx
# Docs: https://www.elastic.co/guide/en/beats/metricbeat/6.5/metricbeat-module-nginx.html

- module: nginx
  #metricsets:
  #  - stubstatus
  period: 10s

  # Nginx hosts
  hosts: ["http://192.168.172.101"]

  # Path to server status. Default server-status
  server_status_path: "nginx-status"

  #username: "user"
  #password: "secret"

# 启动
./metricbeat -e

# 压测
ab -n 100 -c 100 http://192.168.172.101/nginx-status 

测试:

可以看到,nginx的指标数据已经写入到了Elasticsearch。
更多的Module使用参见官方文档:
https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html

3.3.4.3 Metricbeat仪表盘

可以把Metricbeat的数据在kibana中展示

# 修改metricbeat配置
setup.kibana:
host: "192.168.40.133:5601"

# 安装仪表盘到kibana
./metricbeat setup --dashboards
Loading dashboards (Kibana must be running and reachable)
Loaded dashboards

即可在kibana中看到仪表盘数据:

查看系统信息:

3.3.4.4 Nginx指标仪表盘

3.3.4.5 Nginx日志仪表盘

# 修改filebeat的配置文件 cat itcast-nginx.yml 
filebeat.inputs:
#- type: log
#  enabled: true
#  paths:
#    - /var/log/nginx/*.log
#  tags: ["nginx"]

setup.kibana:
  host: "192.168.172.101:5601"

setup.template.settings:
  index.number_of_shards: 3

filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false

output.elasticsearch:
  hosts: ["192.168.172.101:9200"]

# 安装仪表盘到kibana
./filebeat -c itcast-nginx.yml setup
Loaded index template
Loading dashboards (Kibana must be running and reachable)
Loaded dashboards
Loaded machine learning job configurations

可以看到nginx的FileBeat的仪表盘了:

3.3.4.6 自定义图表

在Kibana中,也可以进行自定义图表,如制作柱形图:

将图表添加到自定义Dashboard中:

3.3.4.7 开发者工具

在Kibana中,为开发者的测试提供了便捷的工具使用,如下:

第5章 Logstash

5.1 简介

用途:

5.2 部署安装

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

# 解压安装包
tar -zxf logstash-6.5.4.tar.gz

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

# 执行效果如下:
[2022-05-13T22:36:01,604][INFO ][logstash.agent           ] Successfully started Logstash API endpoint {:port=>9600}
hello
{
    "@timestamp" => 2022-05-13T14:36:09.750Z,
       "message" => "hello",
      "@version" => "1",
          "host" => "elk1"
}

5.3 配置详解

logstash的配置有三部分,如下:

input { # 输入
    stdin { ... } # 标准输入
}
filter { # 过滤,对数据进行分割、截取等处理
    ...
}
output { # 输出
    stdout { ... } # 标准输出
}

Input:输入数据到logstash。

一些常用的输入为:

  • file:从文件系统的文件中读取,类似于 tail -f命令
  • syslog: 在514端口上监听系统日志消息,并根据RFC3164标准进行解析
  • redis: 从redis service中读取
  • beats: 从filebeat中读取

Filters:数据中间处理,对数据进行操作。

一些常用的过滤器为:

  • grok:解析任意文本数据,Grok 是 Logstash 最重要的插件。它的主要作用就是将文本格式的字符串,转换成为具体的结构化的数据,配合正则表达式使用。内置120多个解析语法。

官方提供的grok表达式:[https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns](https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns)
grok在线调试:[https://grokdebug.herokuapp.com/](https://grokdebug.herokuapp.com/)

  • mutate:对字段进行转换。例如对字段进行删除、替换、修改、重命名等。
  • drop: 丢弃一部分events不进行处理。
  • clone: 拷贝 event,这个过程中也可以添加或移除字段。
  • geoip: 添加地理信息(为前台kibana图形化展示使用)

Outputs:outputs是logstash处理管道的最末端组件。一个event可以在处理过程中经过多重输出,但是一旦所有的outputs都执行结束,这个event也就完成生命周期。

一些常见的outputs为:

  • elasticsearch: 可以高效的保存数据,并且能够方便和简单的进行查询。
  • file: 将event数据保存到文件中。
  • graphite: 将event数据发送到图形化组件中,一个很流行的开源存储图形化展示的组件。

Codecs:codecs 是基于数据流的过滤器,它可以作为input,output的一部分配置

Codecs可以帮助你轻松的分割发送过来已经被序列化的数据。

一些常见的codecs:

  • json:使用json格式对数据进行编码/解码。
  • multiline:将汇多个事件中数据汇总为一个单一的行。比如:java异常信息和堆栈信息。

5.3.1 输入

  • 采集各种样式、大小和来源的数据,数据往往以各种各样的形式,或分散或集中地存在于很多系统中。
  • Logstash 支持各种输入选择 ,可以在同一时间从众多常用来源捕捉事件。能够以连续的流式传输方式,轻松地
    从您的日志、指标、Web 应用、数据存储以及各种 AWS 服务采集数据。

5.3.2 过滤

  • 实时解析和转换数据
  • 数据从源传输到存储库的过程中,Logstash 过滤器能够解析各个事件,识别已命名的字段以构建结构,并将它
    们转换成通用格式,以便更轻松、更快速地分析和实现商业价值。

5.3.3 输出

Logstash 提供众多输出选择,您可以将数据发送到您要指定的地方,并且能够灵活地解锁众多下游用例。

日志:
2022-03-31 00:00:00.007 [WARN] [pool-6-thread-12] c.s.resthelper.utils.LoggerHelper - RestInvokeAspect,prepareBeforeInvoke,Y,"no parameters found, method: getCsgoMaps."
grok:
%{GREEDYDATA:timestamp}\[%{WORD:loglevel}\]%{GREEDYDATA:message} 
%{GREEDYDATA:timestamp}%{SPACE}\[%{WORD:loglevel}\]%{SPACE}%{GREEDYDATA:message}

日志:
192.168.172.101 - - [15/May/2022:18:23:37 +0800] "GET / HTTP/1.1" 200 4833 "-" "curl/7.29.0"
grok匹配规则:
%{GREEDYDATA:remote_addr}%{SPACE}\-%{SPACE}\-%{SPACE}\[%{GREEDYDATA:timestamp}\]%{SPACE}"%{GREEDYDATA:request}"%{SPACE}%{INT:http_code}%{SPACE}%{INT:http_body_bytes_sent}%{SPACE}"%{GREEDYDATA:http_referer}"%{SPACE}"%{GREEDYDATA:http_user_agent}"

5.4 读取自定义日志

前面我们通过Filebeat读取了nginx的日志,如果是自定义结构的日志,就需要读取处理后才能使用,所以,这个时
候就需要使用Logstash了,因为Logstash有着强大的处理能力,可以应对各种各样的场景。

5.4.1 日志结构

2019-03-15 21:21:21|ERROR|读取数据出错|参数:id=1002

可以看到,日志中的内容是使用“|”进行分割的,使用,我们在处理的时候,也需要对数据做分割处理。

5.4.2 编写配置文件

vim itcast-pipeline.conf
input {
  file {
    path => "/itcast/logstash/logs/app.log"
    start_position => "beginning"
  }
}

filter {
  mutate {
    split => {"message" => "|"}
  }
}
output {
  stdout { codec => rubydebug }
}

5.4.3 启动测试

# 启动
./bin/logstash -f config/itcast-pipeline.conf 

# 写日志到文件
echo "2019-03-15 21:21:21|ERROR|读取数据出错|参数:id=1002" >> /itcast/logstash/logs/app.log

# 输出的结果
{
          "path" => "/itcast/logstash/logs/app.log",
    "@timestamp" => 2022-05-13T15:05:02.392Z,
          "host" => "elk1",
      "@version" => "1",
       "message" => [
        [0] "2019-03-15 21:21:21",
        [1] "ERROR",
        [2] "读取数据出错",
        [3] "参数:id=1002"
    ]
}

可以看到,数据已经被分割了。

5.4.4 输出到Elasticsearch

input {
  file {
    path => "/itcast/logstash/logs/app.log"
    start_position => "beginning"
  }
}

filter {
  mutate {
    split => {"message" => "|"}
  }
}
output {
  elasticsearch {
    hosts => ["192.168.172.101:9200"]
  }
}

# 启动
./bin/logstash -f config/itcast-pipeline.conf

# 写入数据
echo "2019-03-15 21:21:21|ERROR|读取数据出错|参数:id=1003" >>  /itcast/logstash/logs/app.log

测试:

第6章 综合练习

下面我们将前面所学习到的Elasticsearch + Logstash + Beats + Kibana整合起来做一个综合性的练习,目的就是让
学生们能够更加深刻的理解Elastic Stack的使用。

6.1 流程说明

  • 用APP生产日志,用来记录用户的操作
    • [INFO] 2019-03-15 22:55:20 [cn.itcast.dashboard.Main] - DAU|5206|使用优惠券|2019-03-15
      03:37:20
    • [INFO] 2019-03-15 22:55:21 [cn.itcast.dashboard.Main] - DAU|3880|浏览页面|2019-03-15 07:25:09
  • 通过Filebeat读取日志文件中的内容,并且将内容发送给Logstash,原因是需要对内容做处理
  • Logstash接收到内容后,进行处理,如分割操作,然后将内容发送到Elasticsearch中
  • Kibana会读取Elasticsearch中的数据,并且在Kibana中进行设计Dashboard,最后进行展示

说明:日志格式、图表、Dashboard都是自定义的。

6.2 APP介绍

APP在生产环境应该是真实的系统,然而,我们现在仅仅的学习,为了简化操作,所以就做数据的模拟生成即可。
业务代码如下:

运行结果:

[INFO] 2019-03-15 22:54:42 [cn.itcast.dashboard.Main] - DAU|4645|领取优惠券|2019-03-15 07:40:29
[INFO] 2019-03-15 22:54:44 [cn.itcast.dashboard.Main] - DAU|3482|领取优惠券|2019-03-15 18:34:04
[INFO] 2019-03-15 22:54:48 [cn.itcast.dashboard.Main] - DAU|5607|加入收藏|2019-03-15 22:44:09
[INFO] 2019-03-15 22:54:50 [cn.itcast.dashboard.Main] - DAU|9619|加入收藏|2019-03-15 21:39:47
[INFO] 2019-03-15 22:54:53 [cn.itcast.dashboard.Main] - DAU|7666|加入收藏|2019-03-15 17:47:18
[INFO] 2019-03-15 22:54:54 [cn.itcast.dashboard.Main] - DAU|4871|提交订单|2019-03-15 02:36:27
[INFO] 2019-03-15 22:54:55 [cn.itcast.dashboard.Main] - DAU|7126|加入收藏|2019-03-15 16:11:06
[INFO] 2019-03-15 22:55:00 [cn.itcast.dashboard.Main] - DAU|9606|评论商品|2019-03-15 02:12:00
[INFO] 2019-03-15 22:55:02 [cn.itcast.dashboard.Main] - DAU|7698|查看订单|2019-03-15 08:17:02

代码在资料中可以找到,itcast-dashboard-generate.zip。
部署:

# 打包成jar包,在linux中运行
java -jar itcast-dashboard-generate-1.0-SNAPSHOT.jar
#运行之后,就可以将日志写入到/itcast/logs/app.log文件中

6.3 Filebeat

cat itcast-dashboard.yml 
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /itcast/logs/*.log

setup.template.settings:
  index.number_of_shards: 3

output.logstash:
  hosts: ["192.168.172.101:5044"]

# 启动
./filebeat -e -c itcast-dashboard.yml

6.4 Logstash

cat config/itcast-dashboard.conf 
input {
  beats {
    port => "5044"
  }
}

filter {
  mutate {
    split => {"message" => "|"}
  }

  mutate {
    add_field => {
      "userId" => "%{message[1]}"
      "visit" => "%{message[2]}"
      "date" => "%{message[3]}"
    }
  }
  mutate {
    convert => {
      "userId" => "integer"
      "visit" => "string"
      "date" => "string"
    }
  }
}
output {
  elasticsearch {
    hosts => ["192.168.172.101:9200"]
  }
}

# 启动
./bin/logstash -f config/itcast-dashboard.conf

6.5 Kibana

# 启动
./bin/kibana

# 通过浏览器访问
http://192.168.172.101:5601/app/kibana

6.5.1 时间间隔的柱形图

说明:x轴是时间,以天为单位,y轴是count数
保存:(my-dashboard-时间间隔的柱形图)

6.5.2 各个操作的饼图分布

统计各个操作的数量,形成饼图。
保存:(my-dashboard-各个操作的饼图)

6.5.3 数据表格

在数据探索中进行保存,并且保存,将各个操作的数据以表格的形式展现出来。
保存:(my-dashboard-表格)

6.5.4 制作Dashboard

第7章 利用缓存收集日志

7.1 利用缓存的优点

当日志的数量非常多的时候,可能需要引入缓存层作为临时存储数据的地方,防止因为ES处理不过来导致日志丢失的情况。

filbeat支持将日志发送到redis或者kafka作为消息队列缓存,但是使用了缓存层,就不能使用模板来配置日志收集了,所以最好日志是json格式。

7.2 使用redis作为缓存

适用于es性能瓶颈时
nginx     ----->   redis  -----> logstash -----> es
   +
filebeat

yum安装redis后启动

即使logstash和es机器都宕机了,数据也都会先存储在redis里。后续再从redis里读取数据
有一个缺陷是只支持filebeat将数据传输到redis单节点,不支持传输到redis集群或哨兵模式。
官网地址:https://www.elastic.co/guide/en/beats/filebeat/6.5/redis-output.html

filebeat_redis_tags.yml:
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["access"]

setup.kibana:
  host: "192.168.172.101:5601"

output.redis:
  hosts: ["192.168.172.101"]
  key: "filebeat"
  db: 0
  timeout: 5

重启filebeat
./filebeat -e -c filebeat_redis_tags.yml
连接redis
redis-cli -h 192.168.172.101
输入keys *
查看有无filebeat这个键,没出现的话访问nginx,有日志增加应该会出现,filebeat键是list列表类型的
type filebeat
LLEN filebeat
LRANGE filebeat 1 10
此时日志也是json格式

安装logstash
在logstash的配置目录下,新建logstash有关redis的配置文件
vim redis.conf
input { 
  redis {
    host => '192.168.172.101'
    port => '6379'
    db => '0'
    key => 'filebeat'
    data_type => 'list'
  }
}

filter {
  mutate {
    # nginx和php解析的时间,变成浮点数后可以按照大小排序。
    convert => ["upstream_time" , "float"]
    convert => ["request_time" , "float"]
  }
}

output {
  stdout {}
  elasticsearch {
    hosts => "http://192.168.172.101:9200"
    manage_template => false
    index => "nginx-access-%{+yyyy.MM.dd}"
  }
}

# 启动logstash
./bin/logstash -f /usr/local/logstash/config/redis.conf

logstash启动后可以看到redis中未消费的数据在逐渐减少,这就说明redis可以为es分担一些读写方面的存储方面的压力。
此时只会有一个索引,nginx-access-年月生成
要对access和error日志分别生成索引。filebeat文件可以这样改:
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["access"]

- type: log
  enabled: true
  paths:
    - /var/log/nginx/error.log
  tags: ["error"]

setup.kibana:
  host: "192.168.172.101:5601"

output.redis:
  hosts: ["192.168.172.101"]
  keys: 
    - key: "nginx-access"
      when.contains:
        tags: "access"
    - key: "nginx-error"
      when.contains:
        tags: "error"
  db: 0
  timeout: 5 

# 编辑logstash的redis.conf:
input {
  redis {
    host => '192.168.172.101'
    port => '6379'
    db => '0'
    key => 'nginx-access'
    data_type => 'list'
  }
  redis {
    host => '192.168.172.101'
    port => '6379'
    db => '0'
    key => 'nginx-error'
    data_type => 'list'
  }
}

filter {
  mutate {
    convert => ["upstream_time" , "float"]
    convert => ["request_time" , "float"]
  }
}

output {
  stdout {}
    if "access" in [tags] {
    elasticsearch {
      hosts => "http://192.168.172.101:9200"
      manage_template => false
      index => "nginx-access-%{+yyyy.MM}"
      }
    }
    if "error" in [tags] {
    elasticsearch {
      hosts => "http://192.168.172.101:9200"
      manage_template => false
      index => "nginx-error-%{+yyyy.MM}"
      }
    }
} 
此时连接redis,查看所有key不一定会看到有索引出现,因为es都将数据读取并存储完了,所以redis中没有key。
logstash根据filebeat里定义的tags来判断将什么数据存到什么索引里,在redis里数据也是根据tags来区分的。
由于是通过tags来进行区分的,所以logstash的配置文件key的部分都可以做以优化,修改key的值,将input的第二部分可以删掉,减轻一下logstash的工作量。
input {
  redis {
    host => '192.168.172.101'
    port => '6379'
    db => '0'
    key => 'nginx'
    data_type => 'list'
  }
}

filter {
  mutate {
    convert => ["upstream_time" , "float"]
    convert => ["request_time" , "float"]
  }
}

output {
  stdout {}
    if "access" in [tags] {
    elasticsearch {
      hosts => "http://192.168.172.101:9200"
      manage_template => false
      index => "nginx-access-%{+yyyy.MM}"
      }
    }
    if "error" in [tags] {
    elasticsearch {
      hosts => "http://192.168.172.101:9200"
      manage_template => false
      index => "nginx-error-%{+yyyy.MM}"
      }
    }
} 
将filebeat配置文件中
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["access"]

- type: log
  enabled: true
  paths:
    - /var/log/nginx/error.log
  tags: ["error"]

setup.kibana:
  host: "192.168.172.101:5601"

output.redis:
  hosts: ["192.168.172.101"]
  key: "nginx"
  db: 0
  timeout: 5 

7.3 使用kafka作为缓存

elk结合kafka用的好处:

  • kafka使用起来比较简单,业内公司用得很多,logstash可以借助kafka解决单点问题实现高可用
  • kafka吐的数据是json格式,方便解析
  • 多个logstash并行连接kafka的topic还能提高吞吐率
  • 用不同topic分别存储不同类型的数据也方便管理

3台服务器,主机之间互相通信,hosts文件配置好。

部署zookeeper

参考链接: https://www.cnblogs.com/even160941/p/14666971.html

部署kafka

参考链接:https://www.cnblogs.com/even160941/p/14667974.html

编辑logstash的 kafka.conf配置文件:

input {
  kafka {
    bootstrap_servers => "192.168.172.101:9092"
    topics => ["elklog"]
    group_id => "logstash"
    codec => "json"
  }
}

filter {
  mutate {
    convert => ["upstream_time" , "float"]
    convert => ["request_time" , "float"]
  }
}

output {
    if "access" in [tags] {
      elasticsearch {
        hosts => "http://192.168.172.101:9200"
        manage_template => false
        index => "nginx-access-%{+yyyy.MM}"
      }
    }
    if "error" in [tags] {
      elasticsearch {
        hosts => "http://192.168.172.101:9200"
        manage_template => false
        index => "nginx-error-%{+yyyy.MM}"
      }
    }
}

编辑filebeat的 filebeat_kafka_tags.yml配置文件:

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["access"]

- type: log
  enabled: true
  paths:
    - /var/log/nginx/error.log
  tags: ["error"]

setup.kibana:
  host: "192.168.172.101:5601"

output.kafka:
  hosts: ["192.168.172.101:9092","192.168.172.102:9092","192.168.172.103:9092"]
  topic: elklog

启动filebeat:

 ./filebeat -e -c filebeat_kafka_tags.yml 

启动logstash:

./bin/logstash -f /usr/local/logstash/config/kafka.conf 

终极架构

nginx+keepalived --> redis --> logstash --> es --> kibana

posted on   jiayou111  阅读(316)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示