ELKtrack日志收集分析的实验

实验结构
filebeat –> logstash –> elasticsearch –> kibana
说明:
ELK是实时日志处理领域的第一开源选择,基于实时全文索引,统一的配置语言,支持集群线性扩展,这次实验设计的各种软件均属于ELK的套件工具。
filebeat 是一个轻量的日志采集器,安装在各应用服务器,其实logstash也可以实现此功能不过过于笨重,其监控所定义的日志文件,然后根据配置统一输出到logstash,当然也可直接输出到elasticsearch或redis,但是filebeat只支持多行合并和简单过滤控制,我们需要logstash更高级的日志处理功能;
logstash 是一个丰富的日志收集和处理工具,这里我们主要用来监听日志管道,并对日志进行清洗处理成我们想要的json数据,输出保存到elasticsearch 索引库;
elasticsearch 是一个强大的java分布式开源搜索引擎,它基于lucene实现索引和搜索的功能,使用RESTful API处理所有请求,这里我们主要用于日志数据存储和检索查询;
kibana 是一个针对elasticsearch的web工具,基于nodejs开发,这里我们用于web查询和统计界面定制;

一、系统环境

服务器系统统一都是 CentOS6.6,日志采集的 应用服务器 如下,安装 filebeat-5.2.1 并分别定义不同的采集策略。
PHP server 192.168.100.191
:采集PHP-fpm的异常日志
:采集PHP-slow的慢速日志
mysql server 192.168.100.195
:采集mysql-slow的慢速日志
日志服务器 只部署了一台,安装 logstash/elasticsearch/kibana在一起,不过都是可分开,且前两者可集群部署。
logs server 192.168.100.120
:logstash-5.2.1 监听TCP-5044端口,用于收集filebeat发送过来的日志
:elasticsearch-5.2.1 监听TCP-9200端口,用于存储 logstash 输出的日志数据
:kibana-5.2.1 监听TCP-5601端口,用于日志web数据查询

二、安装

在应用服务器上安装 filebeat 采集器

使用rpm安装包
# rpm -ivh filebeat-5.2.1-x86_64.rpm
基本配置文件路径
# vim /etc/filebeat/filebeat.yml
启动和停止filebeat的方法
# /etc/init.d/filebeat start
最后一次日志采集的定位,这个文件别修改了
# ls -l /var/lib/filebeat/registry
采集操作日志
# ls -l /log/log/filebeat/filebeat

在日志服务器上安装 elasticsearch

elasticsearch需要java运行环境支持
# yum install java-1.8.0-openjdk
# rpm -ivh elasticsearch-5.2.1.rpm
默认的安装路径
# ls -l /usr/share/elasticsearch
默认配置目录和文件
# ls -l /etc/elasticsearch/elasticsearch.yml
在配置文件中指定的数据目录和日志目录
# ls -l /data/elasticsearch
默认启动和停止elasticsearch的方法
# /etc/init.d/elasticsearch start

在安装中遇到的一个问题,其他的 sysctl 参数问题可以 google下

报错:
ERROR: bootstrap checks failed
system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk
原因:
这是在因为Centos6不支持SecComp,而ES5.2.0默认bootstrap.system_call_filter为true进行检测,所以导致检测失败,失败后直接导致ES不能启动。
解决:
在elasticsearch.yml中配置bootstrap.system_call_filter为false,注意要在Memory下面:
bootstrap.memory_lock: false
bootstrap.system_call_filter: false

在日志服务器上安装 logstash

logstash需要 java的运行环境
# rpm -ivh logstash-5.2.1.rpm
默认的安装路径
# ls -l /usr/share/logstash
默认的配置路径,指定配置文件目录、日志目录
# more /etc/logstash/logstash.yml
path.data: /var/lib/logstash
path.config: /etc/logstash/conf.d
path.logs: /var/log/logstash
作为filebeat接收器的配置文件,实验中很重的一个规则配置文件
# ls -l /etc/logstash/conf.d/filebeat.conf
默认启动和停止logstash的方法
# initctl start logstash

在日志服务器上安装 kibana

通过源码方式下载和安装kibana5
# tar zxvf kibana-5.2.1-linux-x86_64.tar.gz
# mv kibana-5.2.1-linux-x86_64 /usr/local/
# ln -s /usr/local/kibana-5.2.1-linux-x86_64 /usr/local/kibana
基本配置文件,主要是设定端口和elasticsearch的连接参数
# more /usr/local/kibana/config/kibana.yml
server.port: 5601
server.host: “192.168.100.120”
elasticsearch.url: “http://192.168.100.120:9200”
这里通过nohup启动kibana后台运行,源码包里自带nodejs运行环境,可以通过nohup.out观察输出
# nohup /usr/local/kibana/bin/kibana &

web浏览:http://192.168.100.120:5601

三、配置

1、在应用服务器上的 filebeat 配置

采集 mysql-slow 日志:/etc/filebeat/filebeat.yml

filebeat:
  prospectors:
    –
      #设置输入的类型为日志文件,以及日志路径
      input_type: log
      document_type: “mysql-slow”
      paths:
        –  /data/app/mysql/data/test08-slow.log
      #设置多行合并匹配规则,反向匹配,匹配行首不是# User@host 或者# Time:的行合并,根据slow日志的格式来调整吧
      multiline.pattern: ‘^[#][ ][User@Host:]i|[#][ ][Time:]’
      #multiline.pattern: ‘[#][ ][Time:]’
      multiline.negate: true
      multiline.match: after
      #过滤设置,黑名单。包含“Time:”的行,这个过滤是为了把不符合规则的日志清洗,但它只能对合并之后的数据进行
      exclude_lines: [“Time:”]
output:
  # 输出到 logstash,指定后端的连接参数,和logstash的设置匹配
  logstash:
    hosts: [“192.168.100.120:5044”]
logging:
  level: debug

采集 php的php-fpm和slow日志:/etc/filebeat/filebeat.ym

filebeat:
  prospectors:
    #定义第一个输入,针对php-fpm日志
    –
      input_type: log
      document_type: “php-fpm”
      paths:
        –  /data/app/php5.5.20/var/log/php-fpm.log
      #定义多行匹配规则,这里有3个正向条件(包含Stack strace:的行、包含空格+数字+.的行、包含空格+thrown in的行)
      multiline.pattern: ‘(Stack\strace:)|(\s[0-9]\.)|(#[0-9]{2}\s)|(\”\”)|(\s\sthrown\sin)’
      multiline.negate: false
      multiline.match: after
      #过滤设置,白名单。包含WARNING的汗
      include_lines: [“WARNING”]
    #定义第二个输入,针对slow日志,因为每个pool是单独的slow日志,所以通配符多个日志
    –
      input_type: log
      document_type: “php-slow”
      paths:
        –  /data/app/php5.5.20/var/log/*.log.slow
      #定义多行匹配规则,反向匹配,把[数字]的行向上合并
      multiline.pattern: ‘[\[][0-9]{2}’
      multiline.negate: true
      multiline.match: after
output:
  logstash:
    hosts: [“192.168.100.120:5044”]
logging:
  level: debug

2、在日志服务器上 elasticsearch 的配置

单节点基础配置,如果配置集群请参考其他文档

root# more /etc/elasticsearch/elasticsearch.yml
#定义es集群名称
cluster.name: bosheng_logs
#定义该节点的名称,各个节点不能重复
node.name: node1
#配置数据目录,注意elasticsearch会有自己的运行用户,要赋予目录此用户的权限
path.data: /data/elasticsearch/data
#配置日志目录
path.logs: /data/elasticsearch/logs
#关闭锁定内存
bootstrap.memory_lock: false
bootstrap.system_call_filter: false
#指定本机IP地址
network.host: 192.168.100.120
#指定http访问端口
http.port: 9200

3、在日志服务器上配置 logstach

主要是filebeat.conf 的配置,因为涉及到日志的收集和清洗,这是最主要的配置,包括对各种应用日志的规则匹配后输出指定变量的json数据给elasticsearch
值得注意的是,logstash的启动很慢(相当的慢,几分钟你不要吃惊),在调试grok规则语法的时候不是很方便,可以使用在线调试器先测试通过
https://grokdebug.herokuapp.com/

#定义logstash的一个输入源,这里定义的是beats,以及监听的端口,用来接收filebeat传输过来的数据
input {
    beats {
        port => “5044”
    }
}
filter {
    #对于type是php-fpm(和filebeat的document_type设置匹配)的日志用此规则处理
    if[type] == “php-fpm” {
        grok {
            match => [
                #和下面的比对,会发现这个正则匹配规则的写法有点特殊,这是一种多条件匹配的格式,如果日志存在多种格式的话
                “message”, “(?m)^\[%{MONTHDAY}-%{MONTH}-%{YEAR}\s%{TIME}\]\s(%{WORD:level})\:\s\[(%{WORD})\s(%{WORD:poolname})\]\s(child)\s%{NONNEGINT}\s(said\sinto\sstderr:\s)%{DATA:info}(?:\n%{GREEDYDATA})?$”,
                “message”, “^\[%{MONTHDAY}-%{MONTH}-%{YEAR}\s%{TIME}\]\s(%{WORD:level})\:\s\[(%{WORD})\s(%{DATA:poolname})\]\s(child)\s%{NONNEGINT},\s%{DATA:info}(\s\(%{NONNEGINT}%{DATA})$”,
                “message”, “^\[%{MONTHDAY}-%{MONTH}-%{YEAR}\s%{TIME}\]\s(%{WORD:level})\:\s\[(%{WORD})\s(%{DATA:poolname})\]\s(child)\s%{NONNEGINT}\s%{DATA:info}$”
            ]
        }
    }
    #对于type是php-slow(和filebeat的document_type设置匹配)的日志用此规则处理
    if[type] == “php-slow” {
        grok {
            match => [“message”, “(?m)^\[%{MONTHDAY}-%{MONTH}-%{YEAR}\s%{TIME}\]\s\s\[(pool)\s(%{DATA:poolname})\]\s(pid\s%{NONNEGINT})\n%{DATA:filename}\n%{GREEDYDATA}$”]
        }
    }
    #对于type是mysql-slow(和filebeat的document_type设置匹配)的日志用此规则处理
    if[type] == “mysql-slow” {
        grok {
            match => [“message”, “(?m)^#\s+User@Host:\s+%{USER:user}\[[^\]]+\]\s+@\s+\[(?:%{IP:clientip})?\]\n#\s+Query_time:\s+%{NUMBER:query_time:float}\s+Lock_time:\s+%{NUMBER:lock_time:float}\s+Rows_sent:\s+%{NUMBER:rows_sent:int}\s
+Rows_examined:\s+%{NUMBER:rows_examined:int}(?:\n+use\s+%{USER};)?\nSET\s+timestamp=%{NUMBER:timestamp};\n\s*(?<query>(?<action>\w+)\b.*)\s*(?:\n#\s+Time)?.*$”]
        }
    }
}
#为每一种不同type设置的日志配置不同的索引集,并传递document_type
output {
    if[type] == “php-fpm” {
        elasticsearch {
            hosts => [“192.168.100.120:9200”]
            index => “php-%{+YYYY.MM.dd}”
            document_type => “%{[@metadata][type]}”
        }
    }
    if[type] == “php-slow” {
        elasticsearch {
            hosts => [“192.168.100.120:9200”]
            index => “phpslow-%{+YYYY.MM.dd}”
            document_type => “%{[@metadata][type]}”
        }
    }
    if[type] == “mysql-slow” {
        elasticsearch {
            hosts => [“192.168.100.120:9200”]
            index => “mysql-%{+YYYY.MM.dd}”
            document_type => “%{[@metadata][type]}”
        }
    }
}

logstash提供了一个默认正则变量定义文件,包括%{USER}、%{IP}、%{NUMBER} 、%{DATA}等,路径如下,同目录下也可以看到其他的一些默认规则定义
/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.0.2/patterns/grok-patterns
在上面我们所用到的logstash配置中,涉及到的一些正则匹配规则如下,可以作为参考,毕竟要更具自己的日志格式进行调整

(?m)
打开多行模式的开关
^#
以 # 字符顶头
\s+
匹配一个或多个空字符
\s*
0个或多个空字符
%{USER:user}
以 USER 模式进行正则匹配,结果放在user中
\[[^\]]+\]
以 [ 开头 以]结尾,内容是由一个或多个不是 ] 的字符填充而成
\[(?:%{IP:clientip})?\]
以 [ 开头 以]结尾,内容可能有,也可能无,如果有并且匹配 IP 的正则模式,结果放在clientip中
%{NUMBER:id:int}
以 NUMBER 模式进行正则匹配,为整数型,结果放在id中
\n
配换行符
%{NUMBER:query_time:float}
以 NUMBER 模式进行正则匹配,为浮点型,结果放在query_time中
(?:use\s+%{USER:usedatabase};\s*\n)?
这个匹配可能有,也可能无,如果有,就是以use开头,若干空字符,以 USER 模式进行正则匹配,结果放在usedatabase中,然后紧接着 ; ,后面是0个或多个空字符,然后是换行,注意:如果有是整体有,如果无,是整体无
\b
代表字单词边界不占位置,只用来指示位置
.*
尽可能多的任意匹配
(?<query>(?<action>\w+)\b.*)
整体匹配,存到query中,以一个或多个字符开头组成的单词,结果存到action中
(?:\n#\s+Time)?
内容可能有,也可能无,如果有,是接在一个换行之后,以 # 开头,隔着一个或多个空字符,然后是Time
.*$
任意匹配直到结尾

四、一些基本的调试方法

查看目前的索引库
http://192.168.100.120:9200/_cat/indices?v
通过 RESTful 查询索引库
http://192.168.100.120:9200/mysql-*/_search
通过RESTful删除一个elasticsearch的索引库
curl -XDELETE http://127.0.0.1:9200/phpslow-2015.06.0*
使用kibana查询,通过浏览器访问
http://192.168.100.120:5601

发表评论