Elastic Stack--ELFK架构

 前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除

 学习B站博主教程笔记: 

最新版适合自学的ElasticStack全套视频(Elk零基础入门到精通教程)Linux运维必备—ElasticSearch+Logstash+Kibana精讲_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1VMW3e6Ezk/?spm_id_from=333.1007.tianma.1-1-1.click&vd_source=e539f90574cdb0bc2bc30a8b5cb3fc00

一、部署logstash环境

 # 官方下载搜索地址
 https://www.elastic.co/cn/downloads/past-releases#elasticsearch
 ​
 # 使用wget在master节点进行下载安装
 wget https://artifacts.elastic.co/downloads/logstash/logstash-7.17.3-x86_64.rpm
 yum -y localinstall logstash-7.17.3-x86_64.rpm

创建软链接:

 [root@k8s-master ~]# systemctl cat logstash
 ...
 ExecStart=/usr/share/logstash/bin/logstash "--path.settings" "/etc/logstash"
 ...
 ​
 # 创建一个软链接方便操作
 ln -sv /usr/share/logstash/bin/logstash /usr/local/bin
 logstash -h     # 检查
 ​
 # 创建一个用于存放配置文件的目录
 [root@k8s-master ~]# mkdir config-logstash

二、input插件

1、收集标准输入

 #(1)编写配置文件
 # vim config-logstash/01--sdtin-to-stdout.yml
 input { stdin {} }
 output { stdout {} }
 ​
 #(2)检查配置文件语法
 logstash -tf config-logstash/01-stdin-to-stdout.conf
 ​
 #(3)启动logstash实例
 logstash -f config-logstash/01-stdin-to-stdout.conf

2、文件输入插件

 input {
   file {
      #指定文件路径
      path => ["/tmp/test/*.txt"]
      #指定文件的读取位置,仅在".sincedb*"文件中没有记录的情况下生效
      #默认从末尾开始读取
      start_position => "beginning"      # /"end"
   }
 }
 ​
 output { stdout {} }

选择 Logstash 开始初始读取文件的位置:在开始时或在最后。默认行为将文件视为实时流,因此从最后开始

3、tcp输入插件,实现日志聚合

 input { tcp { port => 8888 }}
 output { stdout {} }

4、基于http案例

 input {
   http { port => 8888 }
   http { port => 9999 }
 }
 ​
 output { stdout {} }

5、input插件基于redis案例

 input {
   redis {
     data_type => "list"         # 指定的redis的键的类型
     db => 5                     # 指定数据库的编号,默认值是0号数据库
     host => "192.168.1.10"      # 指定数据库的IP地址,默认值是localhost
     port => 6379                # 指定数据库的端口号,默认值为6379
     password => "cluster"       # 指定redis的认证密码
     key => "xxxx"               # 指定从redis的哪个key取数据
   }
   http { port => 8888 }}
 ​
 output { stdout {} }

6、input插件基于beats案例

 # filebeat配置:
 filebeat.inputs:
 - type: tcp
   host: "0.0.0.0:9000"
 ​
 output.logstash:
   hosts: ["192.168.1.10:5044"]
 ​
 # logstash配置:
 input { beats { port => 5044 } }
 output { stdout {} }

三、output插件

1、logstash发送数据到redis环境

(1)编写配置文件

 input { tcp { port => 9999 } }
 ​
 ouput {
   stdout {}
   redis {
     host => "192.168.1.10"      # 指定redis的主机地址
     port => "6379"              # 指定redis的端口号
     db => 10                    # 指定redis的数据库编号
     password => "cluster"       # 指定redis的密码
     data_type => "list"         # 指定写入数据的key类型
     key => "cluster-linux-logstash" # 指定写入的key名称
   }
 }

(2)启动测试

 logstash -f config/tcp-to-redis.conf
 # 发送测试数据
 echo 111111 | nc 192.168.1.10 9999
 # 在redis中查看数据
 192.168.1.10:6379[10]>KEYS *
 1) "cluster-linux-logstash"
 192.168.1.10:6379[10]>type cluster-linux-logstash
 list

2、logstash输出插件file案例

(1)编写配置文件

 input { tcp { port => 9999 } }
 ​
 output {
   stdout{}
   file { 
     path => "/tmp/cluster-linux-logstash.log"       # 指定磁盘的落地位置
   }
 }

(2)测试运行

 logstash -f /config-logstash/tcp-to-file.conf
 ​
 # 同样的对9999端口发送测试数据
 echo 老男孩教育 | nc 192.168.1.10 9999
 cat /tmp/cluster-linux-logstash.log
 ...

3、logstash的输出插件到ES案例

(1)配置文件编写

 input { tcp { port => 9999 } }
 ​
 output {
   stdout{}
   elasticsearch {
     hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
     index => "cluster-linux-logstash-%{+yyyy.MM.dd}"
   }
 }

(2)启动测试

 logstash -rf config-logstash/tcp-to-es.conf

四、logstash综合案例

1、根据架构图收集日志

 # many-to-es.conf
 input {
   tcp {
     type => "tcp"
     port => 6666
   }
   beats {
     type => "beat"
     port => 7777
   }
   redis {
     type => "redis"
     data_type => "list" 
     db => 5
     host => "192.168.1.10"  
     port => "6379"                      
     password => "cluster"   
     key => "cluster-linux-filebeat"
   }  
 }
 ​
 output {
   # stdout{}    # 生产环境注释,输出到屏幕(调试使用)
   if [type] == "tcp" {
     elasticsearch {
       hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
       index => "cluster-linux-tcp-%{+yyyy.MM.dd}"
     }
   }else if [type] == "beat" {
     elasticsearch {
       hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
       index => "cluster-linux-beat-%{+yyyy.MM.dd}"
     }
   }else if [type] == "redis" {
     elasticsearch {
       hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
       index => "cluster-linux-redis-%{+yyyy.MM.dd}"
     }
   }else {
     elasticsearch {
       hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
       index => "cluster-linux-other-%{+yyyy.MM.dd}"
     }
   }
 }
 ​
 # 收集9999端口服务的日志信息:tcp-to-logstash.yml
 filebeat.inputs:
 - type: tcp
   host: "0.0.0.0:9999"
 output.logstash:
   host: ["192.168.1.10:7777"]
   
 # 收集redis服务端口日志信息:tcp-to-redis.yml
 filebeat.inputs:
 - type: tcp
   host: "0.0.0.0:8888"
 output.redis:
   hosts: ["192.168.1.10:6379"]
   password: "cluster"
   db: 5
   key: "cluster-linux-filebeat"
   timeout: 3

启动测试:

 filebeat -e -c tcp-to-logstash.yml
 filebeat -e -c tcp-to-redis.yml --path.data /tmp/filebeat/
 logstash -rf many-to-es.conf

2、收集Nginx与Tomcat日志

(1)收集Nginx日志到redis步骤:

 #1、nginx-to-redis.yml
 filebeat.inputs:
 - type: log
   paths: 
     - /var/log/nginx/access.log*
   json.keys_under_root: true
   
 output.redis:
   hosts: ["192.168.1.10:6379"]
   password: "cluster"
   db: 8
   key: "cluster-linux-filebeat"
   timeout: 3
   
 #2、运行测试
 [root@k8s-node1 config]# rm -rf /var/lib/filebeat/*
 [root@k8s-node1 config]# filebeat -e -c /etc/filebeat/config/32-nginx-to-redis.yml 
 [root@k8s-master ~]# redis-cli -a cluster -n 8
 127.0.0.1:6379[8]> keys *
 1) "cluster-linux-filebeat"
 127.0.0.1:6379[8]> lrange cluster-linux-filebeat 0 -1
 1) "{\"@timestamp\":\"202...    # 发现数据已经送达redis

(2)logstash收集日志到ES

 # many-to-es.conf
 input {
   beats {
     port => 8888
   }
   redis {
     data_type => "list"
     db => 8
     host => "192.168.1.10"
     port => 6379
     password => "cluster"
     key => "cluster-linux-filebeat"
   }
 }
 ​
 output {
   stdout{}
   elasticsearch {
     hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
     index => "cluster-linux-logstash-%{+yyyy.MM.dd}"
   }
 }
 ​
 #运行测试
 [root@k8s-master ~]# logstash -f config-logstash/11-many-to-es.conf

(3)收集Tomcat日志到logstash:

 #1、tomcat-to-logstash.yml
 filebeat.inputs:
 - type: log
   paths:
     - /root/software/apache-tomcat-10.1.28/logs/*.txt
   json.keys_under_root: true
 ​
 output.logstash:
   hosts: ["192.168.1.10:8888"]
   
 #2、运行测试
 [root@k8s-node1 config]# filebeat -e -c /etc/filebeat/config/33-tomcat-to-logstash.yml --path.data /tmp/filebeat/

五、filter插件

1、gork

1.1、基本的gork使用

Grok将非结构化日志数据解析为结构化和可查询的好方法;非常适合syslog日志、apache和其他网络服务器日志、Mysql日志,以及通常为人类而非计算机消耗而编写的任何日志格式。内置120种匹配模式,当然也可自定义匹配模式;

(1)还原nginx日志格式,使用原生日志

 vim /etc/ngin/nginx.conf

(2)编写filebeat收集Nginx原生日志文件输出到logstash的8888端口文件:

 # nginx-to-logstash.yml文件内容如下:
 filebeat.inputs:
 - type: log
   paths:
     - /var/log/nginx/access.log
 ​
 output.logstash:
   hosts: ["192.168.1.10:8888"]

(3)编写logstash收集8888端口收到的文件并发送的ES集群中文件:

使用grok过滤器对原生日志进行拆分;

 # beat-to-es.conf文件内容如下:
 input {
   beats {
     port => 8888
   }
 }
 filter {
   grok {
     match => {
       # "message" => "%{COMBINEDAPACHELOG}"   # 官方GitHub已经废弃,建议使用下面的匹配模式
       "message" => "%{HTTPD_COMMONLOG}"
     }
   }
 }
 output {
   stdout {}
   elasticsearch {
     hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
     index => "cluster-linux-logstash-%{-yyyy.MM.dd}"
   }
 }

(4)运行测试

 filebeat -e -c /etc/config/nginx-to-logstash.yml
 logstash -rf config-logstash/beat-to-es.conf

1.2、gork自定义的正则案例(知识储备)

有时候logstash没有我们需要的模式;我们自定义方法为:

首先使用 Oniguruma syntax 进行命名捕获,可让我们匹配一段文本并将其保存为字段:

 (?<field_name>这里的模式)
 ​
 # 例如,后缀日志有queue id一个10或11个字符的十六进制值,我们可以
 (?<queue_id>[0 - 9A - F]{10,11})

或者创建自定义模式文件:

  • 创建一个目录,包含一个名为patterns的文件extra
  • 在该文件中,将需要的模式写为模式名称、一个空格,然后是该模式的正则表达式。例如上述可以写成:

 # ./patterns/posifix的内容:
 POSITION_QUEUEID [0 - 9A - F]{10,11}

然后使用patterns_dir这个插件中的设置告诉logstash你的自定义模式目录在哪。完整示例:

 Jan  1 06:25:43 mailserver14 postfix/cleanup[21403]: BEF25A72965: message-id=<20130101142543.5828399CCAF@mailserver14.example.com>
 ​
 filter {
   grok {
     patterns_dir => ["./patterns"]
     match => { "message" => "%{SYSLOGBASE} %{POSTFIX_QUEUEID:queue_id}: %{GREEDYDATA:syslog_message}" }
   }
 }

这会匹配并生成出一下字段:

 timestamp: Jan  1 06:25:43
 logsource: mailserver14
 program: postfix/cleanup
 pid: 21403
 queue_id: BEF25A72965
 syslog_message: message-id=<20130101142543.5828399CCAF@mailserver14.example.com>

1.3、remove_field与add_field子弹

如果此筛选器成功,将此事件中删除任意字段。 字段名称可以是动态的,并使用 %{field} 包含事件的一部分 例:

 filter {
   grok {
     # 移除指定的字段
     remove_field => [ "需要移除的字段1", "需要移除的字段2" ]
     # 添加指定的字段
     add_filed => { 
        "oldboyedu-clientip" => "clientip ---> %{clientip}"
        "school" => "北京大学"   
     }
   }
 }

1.4、add_tag与remove_tag字段

添加与移除tag标签:

 filter {
   grok {
     # 添加tag
     add_tag => [ "linux","zookeeper","kafka","elk" ]
     # 移除tag
     remove_tag => [ "zookeeper","kafka" ]
   }
 }

1.5、id字段

ID为插件配置添加一个唯一的。若有两个或多个相同类型的插件时建议使用。

 filter {
   grok {
     ...
     id => "nginx"
   }
 }

2、date插件修改写入ES的时间

 filter {
   grok {...}
   date {
     # 两种写法均可
     match => ["timestamp","dd/MMM/yyyy:HH:mm:ss Z"]
     match => ["timestamp","dd/MMM/yyyy:HH:mm:ss +0800"]
     # 可选项;
     timezone => "Asia/Shanghai"
     # 将匹配到的时间字段解析后存储到目标字段,若不指定,则默认字段为"@timestamp"字段
     target => "cluster-linux-access-time"
   }
 }

3、geoip分析源地址的地理位置

geoip字段对IP地址进行分析

 filter {
   grok {..}
   date {..}
   geoip {
       # 指定基于哪个IP进行分析
       source => "clientip"
       # 可设置只展示指定字段,若不设置,表示显示所有的查询字段
       fields => ["city_name","country_name","ip"]
       # 指定geoip的输出字段,对多个IP地址进行分析
       target => "cluster-linux-geoip"
   }
 }

4、useragent分析客户端的设备类型

 filter {
   date {..}
   geoip {..}
   useragent {
      source => "http_user_agent"            # 指定客户端的设备相关信息的字段
      target => "cluster-linux-useragent"    # 将分析的数据存储在一个指定的字段中,若不指定,则默认存储在target字段中
   }
 }

5、mutate组件数据准备

(1)python脚本准备数据

 cat > generate_log.py <<EOF
 #!/usr/bin/env/ python
 import datetime
 import random
 import logging
 import time
 import sys
 ​
 LOG_FORMAT = "%(levelname)s %(asctime)s [com.oldboyedu.%(module)s] - %(message)s "
 DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
 ​
 # 配置root的logging.Logger实例的基本配置
 logging.basicConfig(level=logging.INFO,format=LOG_FORMAT,detefmt=DATE_FORMAT,filename=sys.argv[1],filemode='a',)
 actions = ["浏览页面","评论商品","加入收藏","加入购物车","提交订单","使用优惠券","领取优惠券","搜索","查看订单","付款","清空购物车"]
 ​
 while True:
     time.sleep(random.randint(1,5))
     user_id = random.randint(1,10000)
     price = round(random.uniform(15000,30000),2)
     action = random.choice(actions)
     svip = random.choice([0,1])
     logging.info("DAU|{0}|{1}|{2}".format(user_id,action,svip,price))
 EOF
 # 运行、生成数据
 nohup python generate_log.py /tmp/app.log &>/dev/null &

(2)编写filebeat文件收集日志,并发送到logstash服务器的8888端口,以便接收:

 filebeat.inputs:
 - type: log
   enabled: true
   paths:
     - /tmp/app.log*
 output.logstash:
   hosts: ["192.168.1.10:8888"]

(3)在logstash服务器编写文件收集日志并发送到ES

 input {
   beats {
     port => 8888
   }
 }
 filter {
   mutate {
     add_field => { "school" => "B站大学老男孩IT教育" }
     remove_field => [ "@timestamp","agent","host","@version","ecs","tags","input","log"] }
   # 对"message"字段内容使用"|"进行切分"
   mutate { split => { "message" => "|" }}
   mutate {
     # 添加字段,其中引用到了变量
     add_field => {
        "user_id" => "%{[message][1]}"
        "action" => "%{[message][2]}"
        "svip" => "%{[message][3]}"
        "price" => "%{[message][4]}"
     }
   }
   mutate {
     # 将指定字段转换成相应的数据类型
     convert => {
        "user_id" => "integer"
        "svip" => "boolean"
        "price" => "float"
     }
   }
   mutate { strip => ["svip"] }      # 去除空格
   mutate { copy => { "price" => "cluster-linux-price" } }   #拷贝字段
   mutate { rename => { "message" => "cluster-ssvip" }}      #重命名
   mutate { replace => { "message" => "%{message}:My new message"}}  #替换
   mutate { uppercase => [ "message" ]}  # 首字母大写
 }
 ​
 output {
   stdout {}
   elasticsearch {
     hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
   }
 }

6、多if分支判断

(1)架构图如下:

(2)通过filebeat收集nginx的access.log日志:

 filebeat.inputs:
 - type: log
   paths:
     - /var/log/nginx/access.log*
   json.keys_under_root: true
 output.logstash:
   hosts: ["192.168.1.10:8888"]

(2)logstash收集端口日志文件如下:

 input {
   beats {
     type => "cluster-beats"
     port => 8888
   }
   tcp {
     type => "cluster-tcp"
     port => 9999
   }
   tcp {
     type => "cluster-tcp-new"
     port => 7777
   }
   tcp {
     type => "cluster-http"
     port => 6666
   }
   tcp {
     type => "cluster-file"
     path => "/tmp/apps.log"
   }
 }
 filter {
   mutate {
     add_field => {
       "school" => "B站大学老男孩IT"
     }
   }
   if [type] == ["cluster-beats","cluster-tcp-new","cluster-http"] {
     mutate {
       remove_field => ["agent","host","@version","ecs","tags","input","log"]
     }
     geoip {
       source => "clientip"
       target => "cluster-linux-geoip"
     }
     useragent {
       source => "http_user_agent"
       target => "cluster-linux-useragent"
     } else if [type] == "cluster-file" {
       mutate {
         add_field => {
           "class" => "cluster-linux80"
           "address" => "xxx"
           "hobby" => ["LOL","王者荣耀"]
         }
         remove_field => ["host","@version","school"]
       }
     }  
   } else {
     mutate {
       remove_field => ["port","@version","host"]
     }
     mutate { 
       split => { "message" => "|" }}
       add_field => {
         "user_id" => "%{[message][1]}"
         "action" => "%{[message][2]}"
         "svip" => "%{[message][3]}"
         "price" => "%{[message][4]}"
       }
       remove_field => ["message"]
       strip => ["svip"]
     }
     mutate {
       # 将指定字段转换成相应的数据类型
       convert => {
          "user_id" => "integer"
          "svip" => "boolean"
          "price" => "float"
       }
     }
   }
 } 
 output {
   stdout {}
   if [type] == "cluster-beats" {
     elasticsearch {
       hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
       index => "cluster-linux-logstash-beats-%{+YYYY.MM.dd}"
     }  
   } else {
     elasticsearch {
       hosts => ["192.168.1.10:9200","192.168.1.11:9200","192.168.1.12:9200"]
       index => "cluster-linux-logstash-tcp-%{+YYYY.MM.dd}"      
     }
   }
 ​
 }

(3)通过filebeat收集app.log的日志:

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /tmp/app.log*
output.logstash:
  hosts: ["192.168.1.10:9999"]

六、Kibana的样例数添加

...

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李学不完

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值