winxcoder 2019-08-01
1.1 平台环境:
OS:CentOS release 6.4(Final)
ElasticSearch:6.3.2
Logstash:6.3.2
Kibana:6.3.2
JRE:1.8
注:由于Logstash的运行依赖于Java环境, 而Logstash 1.5以上版本不低于java 1.7,因此推荐使用最新版本的Java。因为我们只需要Java的运行环境,所以可以只安装JRE,不过这里我依然使用JDK
1.2 ELK下载:https://www.elastic.co/downloads/
cd /data/package/ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.tar.gz wget https://artifacts.elastic.co/downloads/logstash/logstash-6.3.2.tar.gz wget https://artifacts.elastic.co/downloads/kibana/kibana-6.3.2-linux-x86_64.tar.gz
1.3 安装准备
#配置iptables,保证内网之间可以互通 [root@Elk_Server]# iptables -F;iptables -I INPUT -s 192.168.0.0/16 -j ACCEPT [root@Elk_Server]# service iptables save;service iptables restart #关闭selinux [root@Elk_Server]# setenforce 0 [root@Elk_Server]# vim /etc/sysconfig/selinux SELINUX=disabled
1.4 时间同步
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime yum install ntpdate -y;ntpdate time.windows.com echo '01 00 * * * ntpdate time.windows.com' >>/etc/crontab
1.5 配置yum源
这个其实也是ELK中的核心,启动的时候一定要注意,因为es不可以进行root账户启动,所以你还需要开启一个elsearch账户。**
2.1.1 yum方式安装
[root@Elk_Server ~]# sudo yum install elasticsearch -y
2.1.2 源码安装(本文为编译安装配置)
#将解压后的文件复制三份 tar zxvf elasticsearch-6.3.2.tar.gz -C /usr/local/ mv /usr/local/elasticsearch-6.3.2 /usr/local/es-master cp -rf /usr/local/es-master /usr/local/es-data1 cp -rf /usr/local/es-master /usr/local/es-data2 groupadd elasticsearch useradd elasticsearch -g elasticsearch
2.2 创建elasticsearch数据目录
mkdir -p /data{,1,2}/elasticsearch/data mkdir -p /data{,1,2}/elasticsearch/logs chown -R elasticsearch:elasticsearch /data{,1,2}/elasticsearch
2.3 编辑Elasticsearch集群配置文件
cp /usr/local/es-master/config/elasticsearch.yml /usr/local/es-master/config/elasticsearch.yml-bak #创建软连接 mkdir /etc/elasticsearch/ ln -s /usr/local/es-master/config/elasticsearch.yml /etc/elasticsearch/es-master.yml ln -s /usr/local/es-data1/config/elasticsearch.yml /etc/elasticsearch/es-data1.yml ln -s /usr/local/es-data2/config/elasticsearch.yml /etc/elasticsearch/es-data2.yml
主节点配置:
vim /etc/elasticsearch/es-master.yml # ======================== Elasticsearch Configuration ========================= # cluster.name: elk-cluster node.name: node-master node.attr.rack: r1 # ----------------------------------- Paths ------------------------------------ #设置data存放的路径为/data/elasticsearch/data path.data: /data/elasticsearch/data #设置logs日志的路径为/data/elasticsearch/logs path.logs: /data/elasticsearch/logs # ---------------------------------- Network ----------------------------------- #本机地址 network.host: 192.168.6.108 #开启监听的端口为9200 http.port: 9200 #tcp通讯端口 transport.tcp.port: 9330 #是否作为主机 node.master: true #是否作为数据节点 node.data: false node.max_local_storage_nodes: 3 #在删除索引时,是否需要明确指定名称.该值为false时,则可通过正则或_all删除: action.destructive_requires_name: true # --------------------------------- Discovery ---------------------------------- #集群信息,默认的通讯接口是9300 discovery.zen.ping.unicast.hosts: ["192.168.6.108:9330", "192.168.6.108:9331","192.168.6.108:9332"] #在新集群搭建初期,总会出现某几个节点与其他节点通信异常导致节点频繁加入、退出集群。这个过程是自动执行的。通过配置discovery.zen.ping_timeout来控制节点加入某个集群或者开始选举的响应时间(默认3s)。 discovery.zen.ping_timeout: 60s #这个关闭了自动创建索引。为的也是安全考虑,否则即使是内网,也有很多扫描程序,一旦开启,扫描程序会自动给你创建很多索引。 action.auto_create_index: false # ---------------------------------- Gateway ----------------------------------- # # Block initial recovery after a full cluster restart until N nodes are started: #设置集群中N个节点启动时进行数据恢复,默认为1。 gateway.recover_after_nodes: 2 #设置初始化数据恢复进程的超时时间,默认是5分钟。 gateway.recover_after_time: 3m #设置集群中节点的数量,默认为2,一旦这N个节点启动,就会立即进行数据恢复。 gateway.expected_nodes: 3 # ---------------------------------- Various ----------------------------------- #开启跨域访问支持,默认为false http.cors.enabled: true #跨域访问允许的域名地址,(允许所有域名)以上使用正则 http.cors.allow-origin: /.*/
数据1节点配置:
vim /etc/elasticsearch/es-data1.yml # ======================== Elasticsearch Configuration ========================= # cluster.name: elk-cluster node.name: node-data1 node.attr.rack: r1 # ----------------------------------- Paths ------------------------------------ #设置data存放的路径为/dat1/elasticsearch/data path.data: /data1/elasticsearch/data #设置logs日志的路径为/data1/elasticsearch/logs path.logs: /data1/elasticsearch/logs # ---------------------------------- Network ----------------------------------- #本机地址 network.host: 192.168.6.108 #开启监听的端口为9201 http.port: 9201 #tcp通讯端口 transport.tcp.port: 9331 #是否作为主机 node.master: false #是否作为数据节点 node.data: true node.max_local_storage_nodes: 3 #在删除索引时,是否需要明确指定名称.该值为false时,则可通过正则或_all删除: action.destructive_requires_name: true # --------------------------------- Discovery ---------------------------------- #集群信息,默认的通讯接口是9300 discovery.zen.ping.unicast.hosts: ["192.168.6.108:9330", "192.168.6.108:9331","192.168.6.108:9332"] discovery.zen.ping_timeout: 60s action.auto_create_index: false # ---------------------------------- Gateway ----------------------------------- # # Block initial recovery after a full cluster restart until N nodes are started: #设置集群中N个节点启动时进行数据恢复,默认为1。 gateway.recover_after_nodes: 2 #设置初始化数据恢复进程的超时时间,默认是5分钟。 gateway.recover_after_time: 3m gateway.expected_nodes: 3 # ---------------------------------- Various ----------------------------------- #开启跨域访问支持,默认为false http.cors.enabled: true #跨域访问允许的域名地址,(允许所有域名)以上使用正则 http.cors.allow-origin: /.*/
数据2节点配置:
vim /etc/elasticsearch/es-data2.yml # ======================== Elasticsearch Configuration ========================= # cluster.name: elk-cluster node.name: node-data2 node.attr.rack: r1 # ----------------------------------- Paths ------------------------------------ #设置data存放的路径为/data2/elasticsearch/data path.data: /data2/elasticsearch/data #设置logs日志的路径为/data2/elasticsearch/logs path.logs: /data2/elasticsearch/logs # ---------------------------------- Network ----------------------------------- #本机地址 network.host: 192.168.6.108 #开启监听的端口为9202 http.port: 9202 #tcp通讯端口 transport.tcp.port: 9332 #是否作为主机 node.master: false #是否作为数据节点 node.data: true node.max_local_storage_nodes: 3 #在删除索引时,是否需要明确指定名称.该值为false时,则可通过正则或_all删除: action.destructive_requires_name: true # --------------------------------- Discovery ---------------------------------- #集群信息,默认的通讯接口是9300 discovery.zen.ping.unicast.hosts: ["192.168.6.108:9330", "192.168.6.108:9331","192.168.6.108:9332"] discovery.zen.ping_timeout: 60s #这个关闭了自动创建索引。为的也是安全考虑,否则即使是内网,也有很多扫描程序,一旦开启,扫描程序会自动给你创建很多索引。 action.auto_create_index: false # ---------------------------------- Gateway ----------------------------------- # # Block initial recovery after a full cluster restart until N nodes are started: #设置集群中N个节点启动时进行数据恢复,默认为1。 gateway.recover_after_nodes: 2 #设置初始化数据恢复进程的超时时间,默认是5分钟。 gateway.recover_after_time: 3m gateway.expected_nodes: 3 # ---------------------------------- Various ----------------------------------- #开启跨域访问支持,默认为false http.cors.enabled: true #跨域访问允许的域名地址,(允许所有域名)以上使用正则 http.cors.allow-origin: /.*/
使用外网搭建集群时需注意:
network.host需要修改为0.0.0.0,同时要暴露你的外网地址,代码如下:
network.host: 0.0.0.0 network.publish_host: xx.xx.xx.xx
discovery.zen.ping.unicast.hosts修改为各个服务器的外网地址和通讯端口即可。
2.4 安装head插件
head插件能够生成集群的统计数据,并提供浏览器查询,同时还能对elasticsearch索引进行结构化查询。
cd /usr/local/es-master/ mkdir head &&cd head git clone https://github.com/mobz/elasticsearch-head.git cd elasticsearch-head/ #install node v7.x curl --silent --location https://rpm.nodesource.com/setup_7.x | bash - sudo yum install nodejs npm config set registry=http://registry.npm.taobao.org npm install ##运行缓慢 npm install -g grunt-cli ##修改配置文件 [root@Elk_Server elasticsearch-head]# vim Gruntfile.js connect: { server: { options: { port: 9100, hostname: '192.168.6.108', ##添加这行,冒号后面有空格 base: '.', keepalive: true } } }
2.5 系统参数调整
##修改es三个节点的JVM运行内存,这个可以根据需要更改,但是-Xms和-Xmx的值必须一样,不然启动报错 [root@Elk_Server ]# vim /usr/local/es-master/config/jvm.options [root@Elk_Server ]# vim /usr/local/es-data1/config/jvm.options [root@Elk_Server ]# vim /usr/local/es-data2/config/jvm.options ------------------------------------------------------------------------- -Xms2g -Xmx2g ##修改Linux最大打开文件数 vim /etc/security/limits.conf * soft nofile 655350 ##在末尾添加 * hard nofile 655350 ##这一步需要重启linux使配置生效 reboot [root@Elk_Server~]# ulimit -n 655350 ##修改sysctl.conf文件 [root@Elk_Server ~]# vim /etc/sysctl.conf vm.max_map_count=655350 [root@Elk_Server ~]# sysctl -p
2.6 将ES的head插件启动
cd /usr/local/es-master/head/elasticsearch-head && grunt server & [3] 5946 ##会开启9100端口。
2.7 启动Elasticsearch(ES只能使用普通用户启动)
2.9 验证启动
ps axu |grep elasticsearch 方法一: curl 'http://192.168.6.108:9200/_search?pretty' ----- { "took" : 9, "timed_out" : false, "_shards" : { "total" : 0, "successful" : 0, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 0, "max_score" : 0.0, "hits" : [ ] } } 方法二: //或者通过浏览器访问:http://192.168.6.108:9200/
#检查es版本信息 curl -u <user>:<passwd> http://192.168.6.108:9200 #此时观察ES集群状态: curl http://192.168.6.108:9200/_cluster/health?pretty #观察集群内各索引状态: curl http://192.168.6.108:9200/_cat/indices?pretty #查询elasticsearch节点状态: curl -XGET http://192.168.6.108:9200/_cat/shards |grep UNASSIGNED #查看节点列表 http://IP:9200/_cat/nodes?v curl 'IP:9200/_cat/nodes?v' #列出所有索引及存储大小 http://IP:9200/_cat/indices?v curl 'IP:9200/_cat/indices?v'--查询所有索引及数据大小 #创建索引 创建索引名为XX,默认会有5个分片,1个索引 curl -XPUT 'IP:9200/XX?pretty' #添加一个类型 curl -XPUT 'IP:9200/XX/external/2?pretty' -d ' { "gwyy": "John" }' #更新一个类型 curl -XPOST 'IP:9200/XX/external/1/_update?pretty' -d ' { "doc": {"name": "Jaf"} }' #删除指定索引 curl -XDELETE 'IP:9200/_index?pretty'
Logstash的功能如下:
其实它就是一个收集器而已,我们需要为它指定Input和Output(当然Input和Output可以为多个)。由于我们需要把Java代码中Log4j的日志输出到ElasticSearch中,因此这里的Input就是Log4j,而Output就是ElasticSearch。
3.1 安装Logstash
tar zxvf logstash-6.3.2.tar.gz -C /usr/local/ mv /usr/local/logstash-6.3.2 /usr/local/logstash ln -s /usr/local/logstash/bin/logstash /usr/bin/ mkdir -p /data/logs/logstash
3.2 验证安装是否成功,从下图中可以看到,当前开启的是9600端口
logstash -e 'input { stdin { } } output { elasticsearch { hosts => ["192.168.6.108:9200"] } stdout { codec => rubydebug }}' ###等待片刻后出现“The stdin plugin is now waiting for input:”,输入“test”回车,返回下面标准的输出。 ----- [2018-07-31T07:34:23,968][INFO ][logstash.agent ] Successfully started Logstash API endpoint {:port=>9600} test { "@version" => "1", "host" => "Elk_Server", "message" => "test", "@timestamp" => 2018-07-31T07:34:40.422Z }
3.3 logstash配置
##接下来是重点,也是ELK的难点吧,就是将日志进行分析,使用正则匹配过滤日志中想要的内容。
[root@Elk_Server logstash]# cat /data/logs/test.log 120.79.189.51 - - [10/Jun/2018:12:58:12 +0800] "POST /wp-cron.php?doing_wp_cron=1528606692.3628709316253662109375 HTTP/1.1" 499 0 "-" "WordPress/4.8; http://120.79.189.51"
##这是日志中的一行,logstash的正则匹配默认是匹配一行,以回车符作为分隔符。
##当然如果日志是json格式的那么就没有需要处理直接输出即可。
#我们到config目录中新建一个logstash.conf配置。 [root@Elk_Server logstash]# vim /etc/logstash/conf.d/logstash.conf input { file { path => "/data/logs/test.log" type => "test.log" start_position => "beginning" } } filter { grok { match => { "message" => "(?<ip_addr>\d+?\.\d+?\.\d+?\.\d+?)\s-\s-\s\[(?<log_date>\d+?/\w+?/\d+?):(?<log_time>\d+?:\d+?:\d+?)\s+" } } } output { stdout {codec => rubydebug} }
##这是logstash的日志分析文件,总共分为三个大部分,input、flter、output,其中input是输入日志,这里选择的是file文件,path是文件的路径,type是文件的类型,这个可以自定义,主要用来区分每个日志,start_position是设定为beginning是指从文件的开头开始读取。
##flter是处理日志的部分,使用grok这个强大的组件进行信息过滤,对于日志的正则匹配最总会以json的格式输出,所以正则匹配的格式是(?<字段名>正则表达式过滤将要匹配的内容)在每个括号内创建过滤的内容,将不需要的内容放在括号外,可以一直做匹配知道日志结束,这里我只是简单匹配日志前面的ip地址和日期时间。
针对正则匹配字段详细说明:
##正则匹配字段通过“(?<字段名>正则表达式)”来定义,我们看到“(?<ip_addr>\d+?.\d+?.\d+?.\d+?”匹配了日志中的IP地址,然后将不需要的内容放在括号外面匹配,接着是日期和时间,使用同样的方式,然后不需要的内容放在外面因为这里我只匹配了前面的一点内容,如果有需要提取,可以一直匹配,知道这一行结束,logstash默认只会匹配日志以行作为分割,下一行又是新的一次匹配了。
#output是处理输出部分,这里我只是简单输出到终端,先实验正则匹配没问题后,将输出指向elasticsearch。
[root@Elk_Server logstash]# logstash -r -f /etc/logstash/conf.d/logstash.conf .............. { "path" => "/data/logs/test.log", "host" => "Elk_Server", "type" => "test.log", "log_date" => "10/Jun/2018", "@version" => "1", "log_time" => "12:58:12", "@timestamp" => 2018-07-31T09:45:16.247Z, "ip_addr" => "120.79.189.51", "message" => "120.79.189.51 - - [10/Jun/2018:12:58:12 +0800] \"POST /wp-cron.php?doing_wp_cron=1528606692.3628709316253662109375 HTTP/1.1\" 499 0 \"-\" \"WordPress/4.8; http://120.79.189.51\"" }
接下来将日志输出到elasticsearch,修改output里面的内容即可。
output { elasticsearch { ##指定输出到ES action => "index" ##建立索引 hosts => "192.168.6.108:9200" ##ES地址端口 index => "test_log-%{+yyyy.MM.dd}" ##索引的名称 } stdout {codec => rubydebug} }
3.4 验证配置,并报告错误
logstash -f /etc/logstash/conf.d/logstash.conf --config.test_and_exit \\或者 logstash -t -f /etc/logstash/conf.d/logstash.conf
3.5 服务启动
nohup logstash -f /etc/logstash/conf.d/logstash.conf --config.reload.automatic -l /data/logs/logstash & \\或者 nohup logstash -r -f /etc/logstash/conf.d/logstash.conf -l /data/logs/logstash &
--config.reload.automatic选项启用自动配置重新加载,这样您每次修改配置文件时都不必停止并重新启动Logstash。
3.6 结合filebeat案例
日志内容如下:
2018-12-20 17:40:50.665 INFO 1 --- [Thread-422] f.s.j.e.common.iml.AbstractJobWorker : no task in app f.s.job.executor.social.users's job 0 2018-12-22 11:23:55.947 INFO -- [cluster-ClusterId{value='5xxx001145200', description='null'}-dds-xxxc9e41.mongodb.rds.aliyuncs.com:3717] org.mongodb.xxx.cluster : Server xxx:3717 is no longer a member of the replica set. Removing from client view of cluster.
filebeat配置文件:
#=========================== Filebeat inputs ============================= filebeat.inputs: - type: log enabled: true paths: - /data/log/*.log fields: app: tomcat type: all fields_under_root: true #multiline.pattern: '^\[' multiline.pattern: '^\d+\-\d+\-\d+\s+\d+\:\d+\:\d+' multiline.negate: true multiline.match: after multiline.max_lines: 200 multiline.timeout: 10s #tags: ["filebeat"] #exclude_lines: ['^\d+\-\d+\-\d+\s+\d+\:\d+\:\d+\s+DEBUG'] #include_lines: ['^ERR', '^WARN'] #----------------------------- Logstash output -------------------------------- output.logstash: # enabled: true hosts: ["127.0.0.1:5044"] # index => "filebeat-%{+YYYY.MM.dd}" # worker: 4 # bulk_max_size: 1024 # compression_level: 6 # loadbalance: false # backoff.max: 120s
logstash配置文件:
[root@Elk_Server logstash]# vim /etc/logstash/conf.d/logstash.conf input { beats { host => '0.0.0.0' port => "5044" } } filter { grok { match => { "message" => ["%{TIMESTAMP_ISO8601:date}\s+(?:%{LOGLEVEL:loglevel}|%{LOGLEVEL:loglevel}\s+\d) \-+ \[%{NOTSPACE:servicename}\] %{JAVALOGMESSAGE:message}", "%{TIMESTAMP_ISO8601:date}\s+(?:%{LOGLEVEL:loglevel}|%{LOGLEVEL:loglevel}\s+\d) \-+ \[%{NOTSPACE:servicename}\{%{DATA:description}\}-%{DATA:db}\] %{JAVALOGMESSAGE:message}"] } 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 => ["date", "dd/MMM/yyyy:HH:mm:ss Z"] } } output { elasticsearch { hosts => [ "192.168.6.108:9200" ] index => "logstash-%{type}-%{+YYYY.MM.dd}" } # stdout {codec => rubydebug} }
4.1 安装Kibana
tar zxvf kibana-6.3.2-linux-x86_64.tar.gz -C /usr/local/ mv /usr/local/kibana-6.3.2-linux-x86_64 /usr/local/kibana
4.2 配置Kibana
cd /usr/local/kibana/ vim config/kibana.yml #把以下注释放开,使配置起作用。 ----- server.port: 5601 server.host: "192.168.6.108" elasticsearch.url: "http://192.168.6.108:9200" kibana.index: ".kibana"
4.3 启动Kibana并进行测试访问,从日志中可以看出,当前开了5601端口
./bin/kibana #后台启动 nohup /usr/local/kibana/bin/kibana & ----- log [03:30:39.833] [info][status][plugin:[email protected]] Status changed from uninitialized to green - Ready log [03:30:39.882] [info][status][plugin:[email protected]] Status changed from uninitialized to yellow - Waiting for Elasticsearch log [03:30:40.026] [info][status][plugin:[email protected]] Status changed from uninitialized to green - Ready log [03:30:40.033] [info][status][plugin:[email protected]] Status changed from uninitialized to green - Ready log [03:30:40.037] [info][status][plugin:[email protected]] Status changed from uninitialized to green - Ready log [03:30:40.061] [info][listening] Server running at http://192.168.30.211:5601 log [03:30:40.117] [info][status][plugin:[email protected]] Status changed from yellow to green - Ready
4.4 查看启动没有报错,可以通过192.168.6.108:5601在浏览器进行访问了。
①点击Discover出现以下界面,在logstash日志分析文件里面有建立了一个索引,索引的名称是test_log-${日期}这样的形式,它是 Elasticsearch 中的一个索引名称开头。Kibana 会自动检测在 Elasticsearch 中是否存在该索引名称。
②按照注释配置,然后点击Next step,在第二页 选择@timestamp点击create创建
③创建完成之后,可以看到以下一个界面,红框内是 自动生成的域,也可以理解为 跟数据库中的字段类似,其中有一个message字段,就是我们想要的日志信息。
④再次点击Discover出现以下界面,可以看到默认搜索的是最后15分钟的日志,可以通过点击设置搜索的时间范围.
⑤可以点击右侧域的add设置需要显示的字段
添加完成之后,日志显示如下:
⑥也可以查看请求体和响应体
另外一部分,则需要先做聚类、分类处理,将聚合出的分类结果存入ES集群的聚类索引中。数据处理层的聚合结果存入ES中的指定索引,同时将每个聚合主题相关的数据存入每个document下面的某个field下。