elk

转载,供日后回查

ELK6.2.2(elasticsearch+logstash+kibana)开源日志分析平台搭建(零):源起

子豪

1现状:

我司目前日志情况是,在各个IDC部署四个大业务线程序。日志统一打印到各自IDC的/logdata目录。此目录为百T级别的gluster。在其中,日志按照机器名称=》程序名称的目录结构存放。在同一目录下,分别为同一程序的运行日志(process.log),错误日志(error.log),下行日志(submit.log),上行日志(recv.log)等类别的日志,并按照日期切分。

[superuser@ft3q-app47 logs]$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-LogVol01
                      1.1T  106G  920G  11% /
/dev/sda1             190M   41M  140M  23% /boot
tmpfs                  24G     0   24G   0% /dev/shm
192.168.193.201:/logdata
                      110T   45T   65T  41% /logdata
192.168.173.201:/logdata
                       37T   11T   27T  28% /logdata-1
  • 2出现的问题:

2.1运维同事目前还是用传统的查询文件方式查看日志。cat error.log_yyyy_mm_dd|grep “keyword”。在分布式、微服务的环境下, 比较繁琐,而且还容易遗漏,最重要的是效率低。

2.2询问一条消息的消息轨迹时无从下手,分别经过的服务端、逻辑和网关模块因为分布式太多了。

  • 3痛点:

3.1从海量分散文件中,迅速、准确地找到包含某关键词的日志。

3.2完整找出某关键词在某一时间段内出现在的每个日志中,即消息轨迹。

  • 4解决方案:

构建我司自己的日志分析系统。

  • 5方案一

5.1splunk

Splunk是大数据领域第一家在纳斯达克上市公司,Splunk提供一个机器数据的引擎。使用 Splunk可收集、索引和利用所有应用程序、服务器和设备(物理、虚拟和云中)生成的快速移动型计算机数据 。从一个位置搜索并分析所有实时和历史数据。 使用 Splunk 处理计算机数据,可让您在几分钟内(而不是几个小时或几天)解决问题和调查安全事件。监视您的端对端基础结构,避免服务性能降低或中断。以较低成本满足合规性要求。关联并分析跨越多个系统的复杂事件。获取新层次的运营可见性以及 IT 和业务智能。

elk

但因为其要求每日数据量小于500M,否则收费,每月225美元,并且其可拓展性差。我司每日某一业务线日志量就可达300G。所以我们不用。(还不是因为要钱嘛)

elk

5.2ELK stack

elk

 

ELK 是elastic公司提供的一套完整的日志收集、展示解决方案,是三个产品的首字母缩写,分别是ElasticSearch、Logstash 和 Kibana
ElasticSearch简称ES,它是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。ELK 是elastic公司提供的一套完整的日志收集、展示解决方案,是三个产品的首字母缩写,分别是ElasticSearch、Logstash 和 Kibana。

Logstash是一个具有实时传输能力的数据收集引擎,用来进行数据收集(如:读取文本文件)、解析,并将数据发送给ES。

Kibana为 Elasticsearch 提供了分析和可视化的 Web 平台。它可以在Elasticsearch 的索引中查找,交互数据,并生成各种维度表格、图形。

其特点是代码开源,并且是JAVA写的,有完善的REST API,我们可以拓展程序。所以选择ELK进行日志分析。

elk

  • 6规划一:ELK读取分散文件

方案设计:

在不改动现有平台的情况下,增加一套ELK读取分散的文件。通过logstash组件读取每个文件建立索引入es,运维人员可通过kibana方便查询。架构如下:

elk

优点:现有程序完全没有改动。

缺点:

1日志还是零散分部,cluster有报出文件性能差问题。

2日志占用空间,导入ES后索引占用空间,即数据冗余。

3 Logstash Agent的维护不是很理想,Logstash是基于Ruby的,启动它就要有几十兆内存被jvm吃掉,我们想避免在每个机器上都要起一个Logstash。并且在我们使用过程中Logstash非常不稳定,莫名其妙就死掉了,还需要一个守护进程守护它。

4log标准化。现阶段各程序日志还是不标准。

  • 6规划二:增加KAFKA

日志直接写入KAFKA,logstash抽取KAFKA数据入ES,运维人员可通过kibana方便查询。架构如下:

elk

此架构避免了单个logstash读取多文件会卡的问题。使用kafak,可以让统一模块如cmpp服务端写入同一kafka话题(topic),使得负载均衡的模块可以完整地录入。Logstash通过读取一个topic赋予一个确定的索引如 logstash-server-cmpp,在以后查询中就可以批量查询同一功能的日志了。

优点:

1去除日志gluster。

2日志规范化后,可以精细查询每条日志。并且可以分词检索。

3完整,精确。消息轨迹可以查询出来。

4建立相应索引后,可以快速检索。

缺点:

1需要对现有程序进行改动,1建立标准化日志打印公共包2引入kafka包3修改log4j配置文件

2申请资源,每个IDC需要搭建至少一套kafka、ELK。

对现有平台的影响:

1、程序改动。程序必须改动,可以分批次地灰度上线。

2、容错机制。kafka使用集群部署,一般不会挂掉。如果kafka挂掉,程序可以运行。

3、性能。底层使用apach自己的kafka-clients,性能应该能保证。经测试,单个log入单个topic速度在700/s。

4、运维人员查询机制。由以往登入跳板机,grep各模块文件,转换到查询模块索引,指定某字段为某值,web页面查询。

5、报警机制改变。以往基于error日志文件。现在可以使用ES自带的查询API监控某一个TOPIC,出现关键字报警。

6、配套程序开发。定时删除kafka数据,定时删除es索引,监控程序等。

  • 7规划三:每个IDC分业务搭建多套ELK

日志量大以后,每个IDC内部根据业务进行细分,分出多套日志系统。架构如下:

elk

根据LinkedIn(领英)的使用情况来看,有20多个针对不同业务模块的ELK集群,1000+服务器,主要都是Elasticsearch。1分钟之内生产系统发生的log这边就可以搜索,所有的log保留7到14天。现在大概有500亿的索引文档,500到800T,之前测试时推到1500到2000T都是可以工作的。

  • 8目前测试情况:

ft3q IDC的tapp21-tapp23部署3台kafka集群。tapp25部署ELK。测试程序分别模拟服务端、逻辑、网关发送至3个topic,logstash消费信息并且赋予3种索引。其中submit明细我做了分词,将手机号、内容、redis队列名解析出来。

elk

ELK6.2.2(elasticsearch+logstash+kibana)开源日志分析平台搭建(一):es简单搭建

1物理环境

物理机配置

IP CPU 内存 硬盘
192.168.193.47 E5-2650v2 48G 1TB
192.168.193.147 E5-2650v2 48G 1TB
192.168.193.48 E5-2640v3 64G 1TB
192.168.193.148 E5-2640v3 64G 1TB

因为强调elk比较吃机器,所以网络部门同事给了不错的机器。应该可以运行elk。

[superuser@ft3q-app47 elk]$ top
top - 16:59:37 up 87 days, 22:55,  1 user,  load average: 27.89, 24.80, 24.19
Tasks: 622 total,   2 running, 620 sleeping,   0 stopped,   0 zombie
Cpu(s):  3.5%us,  3.0%sy,  0.0%ni, 92.7%id,  0.8%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  49397260k total, 48563720k used,   833540k free,   253412k buffers
Swap: 16777212k total,  3753420k used, 13023792k free, 15169808k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                   
30512 superuse  20   0 86.3g  20g 460m S 176.5 44.3   9889:16 java                                                                                                                                      
 1086 root      20   0     0    0    0 S  2.6  0.0 271:20.94 jbd2/dm-1-8                                                                                                                                
 2707 root      20   0     0    0    0 S  2.0  0.0  28:19.76 kondemand/2                                                                                                                                
 2713 root      20   0     0    0    0 S  2.0  0.0  37:24.09 kondemand/8

规划一下,在前3台安装ES集群。最后一台安装filebeat,packagebeat等小东西。

2安装java

因为是java写的,所以首先需要安装java。安装方法我就不写了。

[superuser@ft3q-app47 logs]$ java -version
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

3官网找到最新版下载地址,下载。目前是6.2.2

[superuser@ft3q-app47 elk]$ pwd
/home/superuser/elk
[superuser@ft3q-app47 elk]$ ll
总用量 28
drwxr-xr-x  6 superuser superuser 4096 3月  22 13:25 cerebro-0.7.2
drwxr-xr-x  9 superuser superuser 4096 3月  14 16:01 es
drwxr-xr-x  5 superuser superuser 4096 3月  20 10:11 filebeat
drwxrwxr-x 12 superuser superuser 4096 3月  14 17:22 kibana
drwxrwxr-x 11 superuser superuser 4096 3月  22 10:18 logstash
drwxrwxr-x 14 superuser superuser 4096 3月  22 17:10 logstash_bank
drwxr-xr-x  4 superuser superuser 4096 3月  19 14:26 packetbeat
[superuser@ft3q-app47 elk]$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.2.tar.gz

4解压并改名

[superuser@ft3q-app47 elk]$ tar -zxvf elasticsearch-6.2.2.tar.gz
[superuser@ft3q-app47 elk]$ mv elasticsearch-6.2.2 es

5修改config/elasticsearch.yml配置文件

[superuser@ft3q-app47 es]$ vim config/elasticsearch.yml
#集群名称
cluster.name: ft3q
#节点名称
node.name: node-47
#如果是master节点设置成true 如果是
node.master: true
#如果是data节点设置成true
node.data: true
#数据储存路径
path.data: /home/superuser/elk/es/data
#日志储存路径
path.logs: /home/superuser/elk/es/logs
#监听地址
network.host: 192.168.193.47
#交互端口
http.port: 9200
#集群的三个节点
discovery.zen.ping.unicast.hosts: ["192.168.193.47", "192.168.193.147","192.168.193.48"]
#至少要发现集群可做master的节点数
discovery.zen.minimum_master_nodes: 2
#不锁内存
bootstrap.memory_lock: false
#Centos6不支持SecComp
bootstrap.system_call_filter: false
#如果启用了 HTTP 端口,那么此属性会指定是否允许跨源 REST 请求。
http.cors.enabled: true
#如果 http.cors.enabled 的值为 true,那么该属性会指定允许 REST 请求来自何处。
http.cors.allow-origin: "*"
#增大bulk队列大小
thread_pool.bulk.queue_size: 20000
#设置恢复时的吞吐量(例如:100mb,默认为0无限制.如果机器还有其他业务在跑的话还是限制一下的好) 
indices.recovery.max_bytes_per_sec: 100mb
#可以使用值:eg:50mb 或者 30%(节点 node heap内存量),默认是:unbounded
indices.fielddata.cache.size: 50mb
#集群发现超时时间
discovery.zen.ping_timeout: 200s
#集群ping间隔
discovery.zen.fd.ping_interval: 30s
#超时
discovery.zen.fd.ping_timeout: 200s

6修改config/jvm.options配置文件

-Xms20g
-Xmx20g

主要就是这两个值,根据自己的机器来配置。

7修改系统参数

如果现在启动es,仍然会报一些错,根据错误信息,修改系统参数。切换到root。

7.1max file descriptors [65535] for elasticsearch process is too low, increase to at least [65536]

方案:vi /etc/sysctl.conf

fs.file-max=655350

保存之后sysctl -p使设置生效

vi /etc/security/limits.conf 新增

* soft nofile 655350

* hard nofile 655350

保存之后sysctl -p使设置生效

7.2max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

方案:vi /etc/sysctl.conf

vm.max_map_count=655360

保存之后sysctl -p使设置生效

可能还会遇到max number of threads [1024] for user [huang] is too low, increase to at least [4096]

需要修改用户的最大可用线程数,vim /etc/security/limits.d/90-nproc.conf

可能还会遇到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

禁用:在elasticsearch.yml中配置bootstrap.system_call_filter为false,注意要在Memory下面: 
bootstrap.memory_lock: false 
bootstrap.system_call_filter: false

8终于可以启动

以后台方式启动

[superuser@ft3q-app47 es]$ ./bin/elasticsearch -d

9验证一下

[superuser@ft3q-app47 es]$ curl 192.168.193.47:9200
{
  "name" : "node-47",
  "cluster_name" : "ft3q",
  "cluster_uuid" : "vAUZvtDIQoWGReAgGu19Vw",
  "version" : {
    "number" : "6.2.2",
    "build_hash" : "10b1edd",
    "build_date" : "2018-02-16T19:01:30.685723Z",
    "build_snapshot" : false,
    "lucene_version" : "7.2.1",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

10其他两台也照此安装,最后可以看到,这三台组成集群,5分片*2副本,显示绿色。

elk

ELK6.2.2(elasticsearch+logstash+kibana)开源日志分析平台搭建(二):kibana简单搭建

1下载,解压,重命名

[superuser@ft3q-app48 es]$ wget https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-linux-x86_64.tar.gz
[superuser@ft3q-app48 es]$ tar -zxvf kibana-6.2.2-linux-x86_64.tar.gz
[superuser@ft3q-app48 es]$ mv kibana-6.2.2-linux-x86_64 kibana

2配置

[superuser@ft3q-app47 kibana]$ vim config/kibana.yml
#端口
server.port: 5601
#监听地址 本机
server.host: "0.0.0.0"
#命名
server.name: "kibanaServer47"
#es集群地址
elasticsearch.url: "http://192.168.193.47:9200"
#kibana入es的索引
kibana.index: ".kibana"
#x-pack插件安装后的用户名,密码
elasticsearch.username: "kibana"
elasticsearch.password: "kibana"

3启动,后台运行

[superuser@ft3q-app47 kibana]$ nohup ./bin/kibana &

4查看运行情况

浏览器查看 http://192.168.193.47:5601

elk

完美!

ELK(elasticsearch+logstash+kibana)开源日志分析平台搭建(四):logstash解析日志

前文已经简单搭建好了elk,现在就入数据这一方面,我们简单分析。

1现状:我司java程序全部使用log4j2经行日志写文件。其基本例子如下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- status:log4j自身日志,monitorInterval:自动检测配置文件是否改变,单位:s -->
<configuration status="info" monitorInterval="5" shutdownHook="disable">
    <Properties>
        <!-- 配置日志文件输出目录 -->
        <Property name="LOG_HOME">/logdata-local/path/to/log/</Property>
    </Properties>
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n"/>
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
        </Console>

        <!-- 服务端主日志 -->
        <RollingFile name="asyncservice" fileName="${LOG_HOME}/service.log"
                     filePattern="${LOG_HOME}/service_%d{yyyy-MM-dd}_%i.log">
            <Filters>
                <!-- 打印除error日志所有日志 -->
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout charset="UTF-8"
                           pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} [%L]  - %msg%n"/>
            <Policies>
                <!-- 更新时间 -->
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
                <SizeBasedTriggeringPolicy size="500MB"/>
            </Policies>
            <!-- 最多8个日志 -->
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>

        <!-- 服务端错误日志 -->
        <RollingFile name="asyncerror" fileName="${LOG_HOME}/error.log"
                     filePattern="${LOG_HOME}/error_%d{yyyy-MM-dd}_%i.log">
            <Filters>
                <!-- 打印error日志 -->
                <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="ACCEPT"/>
            </Filters>
            <PatternLayout charset="UTF-8"
                           pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} [%L] - %msg%n"/>
            <Policies>
                <!-- 更新时间 -->
                <TimeBasedTriggeringPolicy modulate="true"
                                           interval="1"/>
                <SizeBasedTriggeringPolicy size="500MB"/>
            </Policies>
            <!-- 最多8个日志 -->
            <DefaultRolloverStrategy max="8"/>
        </RollingFile>

        <RollingFile name="asyncmonitor" fileName="${LOG_HOME}/monitor.log"
                     filePattern="${LOG_HOME}/report_%d{yyyy-MM-dd}_%i.log">
            <PatternLayout charset="UTF-8" pattern="%d{HH:mm:ss.SSS} - %msg%n"/>
            <Policies>
                <!-- 更新时间 -->
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
                <SizeBasedTriggeringPolicy size="500MB"/>
            </Policies>
            <!-- 最多8个日志 -->
            <DefaultRolloverStrategy max="8"/>
        </RollingFile>

        <Async name="service" bufferSize="102400">
            <AppenderRef ref="asyncservice"/>
        </Async>
        <Async name="error" bufferSize="102400">
            <AppenderRef ref="asyncerror"/>
        </Async>
        <Async name="monitor" bufferSize="102400">
            <AppenderRef ref="asyncmonitor"/>
        </Async>
    </appenders>


    <loggers>
        <Logger name="monitor" level="info" additivity="false">
            <AppenderRef ref="monitor"/>
        </Logger>
        <root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="service"/>
            <AppenderRef ref="error"/>
        </root>
    </loggers>

</configuration>

其中主要使用了log4j2的异步缓冲池,5秒刷新配置,自动分日期打包文件等特性。

2目标

我们主要关注

pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} [%L]  - %msg%n"

打出来的日志基本是这样:

2018-03-27 21:22:19.048 [pool-4-thread-1] INFO  com.common.monitor.MonitorService []  - 监控redis连接#执行结果:OK,监控状态:redis状态:true(0,0)

我决定使用logstash的grok插件,过滤信息

3成果

input{
    file {
        path => ["/logdata-local/*/*.log"]
        exclude => "*_*.log"
        max_open_files => "18600"
        codec => multiline {
                pattern => "^\s"
                what => "previous"
                }
        }
}
filter{
        grok {
             match =>{
                "message" =>"%{TIMESTAMP_ISO8601:logtime}\s\[%{DATA:logthread}\]\s%{LOGLEVEL:loglevel}\s\s%{DATA:logclass}\s\[\].{4}%{GREEDYDATA:logcontent}"
                }
                remove_field => ["message"]
            }
        date {
                match => ["logtime", "yyyy-MM-dd HH:mm:ss.SSS"]
                target => "@timestamp"
                }
        mutate {
            add_field => { "filepath" => "%{path}" }
              }
        mutate{
        split => ["filepath","/"]
            add_field =>   {
                "idx" => "%{[filepath][1]}-%{[filepath][2]}-%{[filepath][3]}"
            }
            add_field =>   {
                "filename" => "%{[filepath][3]}"
            }
        }
        mutate{
                lowercase => [ "idx" ]
        }
}
output {
        elasticsearch {
                hosts => ["192.168.193.47:9200","192.168.193.47:9200","192.168.193.47:9200"]
                index => "logstash-bank-%{idx}-%{+YYYY.MM.dd}"
                user => elastic
                password => elastic
         }
}

过滤器意思将其自动生成的message信息解析,然后移除。将文件路径的“/”转化为“-”建立索引。索引不能有大写,最后都小写化。

解析出的日志时间,覆盖原始的@timestamp字段。

其基本将每条日志的时间、线程、日志级别、类和内容字段分析了出来,以后看运维同事有什么查询需求,将规范化内容再细化解析。

4kibana呈现

elk

这样日志就像数据库一样,可以按照字段查询了。

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/104259

(5)
生而为人生而为人
上一篇 2018-07-30
下一篇 2018-07-31

相关推荐