ELK服务基础
什么是ELK?
通俗来讲,ELK是由Elasticsearch、Logstash、Kibana三个开源软件组成的一个组合体,这三个软件当中,每个软件用于完成不同的功能,ELK又称为ELK stack,官方域名为static.co,ELK-stack的主要优点有如下几个:
处理方式灵活:elasticsearch是实时全文索引,具有强大的搜索功能。
配置相对简单:elasticsearch全部使用JSON接口,logstash使用模板配置,kibana的配置文件部分更简单。
检索性能高效:基于优秀的设计,虽然每次查询都是实时,但是也可以达到百亿级数据的查询秒级响应。
集群线性扩展:elasticsearch和logstash都可以灵活线性扩展。
前端操作绚丽:kibana的前端设计比较绚丽,而且操作简单。
什么是Elasticsearch:
是一个高度可扩展的开源全文搜索和分析引擎,它可实现数据的实时全文搜索、支持分布式可实现高可用、提供API接口,可以处理大规模日志数据,比如Nginx、Tomcat、系统日志等功能。
什么是Logstash:
可以通过插件实现日志收集和转发,支持日志过滤,支持普通log、自定义json格式的日志解析。
什么是Kibana:
主要是通过接口调用elasticsearch的数据,并进行前端数据可视化的展现。
Beats 比 logstash 更轻量级,不需要装java环境。
1. elasticsearch 部署
环境初始化
最小化安装 Centos-7.2-x86_64操作系统的虚拟机,vcpu-2,内存4G或更多,操作系统盘50G,主机名设置规则
为linux-hostX.example.com,其中host1和host2为elasticsearch服务器,为保证效果特额外添加一块单独的
数据磁盘大小为50G并格式化挂载到/data。
1.1 主机名和磁盘挂载
# 修改主机名 hostnamectl set-hostname linux-hostx.example.com && rebbot hostnamectl set-hostname linux-host2.example.com && rebbot # 磁盘挂载 mkdir /data mkfs.xfs /dev/sdb blkid /dev/sdb /dev/sdb: UUID="bb780805-efed-43ff-84cb-a0c59c6f4ef9" TYPE="xfs" vim /etc/fstab UUID="bb780805-efed-43ff-84cb-a0c59c6f4ef9" /data xfs defaults 0 0 mount -a # 各服务器配置本地域名解析 vim /etc/hosts 192.168.182.137 linux-host1.example.com 192.168.182.138 linux-host2.example.com
1.2 关闭防火墙和SELinux,调整文件描述符
1.3 设置epel源、安装基本操作命令并同步时间
yum install -y net-tools vim lrzsz tree screen lsof tcpdump wget ntpdate cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 添加计划任务 echo "*/5 * * * * ntpdate time1.aliyun.com &>/dev/null && hwclock-w" >> /var/spool/cron/root systemctl restart crond
1.4 安装elasticsearch
在host1和host2分别安装elasticsearch
在两台服务器准备java环境:
方式一:直接使用yum安装openjdk
yum install java-1.8.0*
方式二:本地安装在oracle官网下载rpm安装包
yum localinstall jdk-8u92-linux-x64.rpm
方式三:下载二进制包自定义profile环境变量
tar xvf jdk-8u121-linux-x64.tar.gz -C /usr/local/ ln -sv /usr/local/jdk-8u121-linux-x64 /usr/local/jdk vim /etc/profile java -version
安装elasticsearch
yum install jdk-8u121-linux-x64.rpm elasticsearch-5.4.0.rpm
1.5 配置elasticsearch
grep "^[a-Z]" /etc/elasticsearch/elasticsearch.yml cluster.name: elk-cluster node.name: elk-node1 path.data: /data/elkdata path.logs: /data/logs bootstrap.memory_lock: true network.host: 192.168.152.138 http.port: 9200 discovery.zen.ping.unicast.hosts: ["192.168.152.138", "192.168.152.139"]
另外一个节点,只需要更改节点名称和监听地址即可:
grep "^[a-Z]" /etc/elasticsearch/elasticsearch.yml cluster.name: elk-cluster node.name: elk-node2 path.data: /data/elkdata path.logs: /data/logs bootstrap.memory_lock: true network.host: 192.168.152.139 http.port: 9200 discovery.zen.ping.unicast.hosts: ["192.168.152.138", "192.168.152.139"]
创建数据和日志目录并授权:
mkdir /data/elkdata mkdir /data/logs chown -R elasticsearch.elasticsearch /data/
在启动脚本中修改,开启内存锁定参数:
vim /usr/lib/systemd/system/elasticsearch.service LimitMEMLOCK=infinity
注意:不开启内存锁定参数,会因为 bootstrap.memory_lock: true 这个参数而启不来。
调整内存大小,默认是2g:
vim /etc/elasticsearch/jvm.options -Xms2g -Xmx2g
注意:
将Xmx设置为不超过物理RAM的50%,以确保有足够的物理RAM留给内核文件系统缓存。
elasticsearch内存最高不要超过32G。
https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
启动服务:
systemctl restart elasticsearch.service systemctl enable elasticsearch.service
# 检查状态
curl -sXGET http://192.168.152.139:9200/_cluster/health?pretty=true
2.elasticsearch插件之head部署
插件是为了完成不同的功能,官方提供了一些插件但大部分是收费的,另外也有一些开发爱好者提供的插件,可以实现对elasticsearch集群的状态监控与管理配置等功能。
在elasticsearch5.x版本以后不再支持直接安装head插件,而是需要通过启动一个服务方式,git地址:https://github.com/mobz/elasticsearch-head
# NPM 的全称是Node-Package Manager,是随同NodeJS一起安装的包管理和分发工具,它很方便让JavaScript开发者下载、安装、上传以及管理以及安装的包。
安装部署:
cd /usr/local/src git clone git://github.com/mobz/elasticsearch-head.git cd elasticsearch-head/ yum install npm -y npm install grunt -save ll node_modules/grunt # 确认生成文件 npm install # 执行安装 npm run start & 后台启动服务
修改elasticsearch服务配置文件:
开启跨域访问支持,然后重启elasticsearch服务
vim /etc/elasticsearch/elasticsearch.yml http.cors.enabled: true #最下方添加 http.cors.allow-origin: "*"
重启服务:
systemctl restart elasticsearch systemctl enable elasticsearch
粗得是主分片,其他的是副分片是细的 用于备份。
2.1 docker 版本启动head插件
安装docker:
yum install docker -y systemctl start docker && systemctl enable docker
下载镜像:
docker run -p 9100:9100 mobz/elasticsearch-head:5
如果已有镜像,则导入镜像:
# docker load < elasticsearch-head-docker.tar.gz
查看镜像:
docker images
启动镜像:
docker run -d -p 9100:9100 docker.io/mobz/elasticsearch-head:5
监控脚本:
vim els-cluster-monitor.py #!/usr/bin/env python #coding:utf-8 import smtplib from email.mime.text import MIMEText from email.utils import formataddr import subprocess body="" false="false" obj=subprocess.Popen(("curl -sXGET http://192.168.152.139:9200/_cluster/health?pretty=true"),shell=True,stdout=subprocess.PIPE) data=obj.stdout.read() data1=eval(data) status = data1.get("status") if status == "green": print "50" else: print "100"
注意: 如果通过head做数据浏览, /var/lib/docker/overlay2/840b5e6d4ef64ecfdccfad5aa6d061a43f0efb10dfdff245033e90ce9b524f06/diff/usr/src/app/_site/vendor.js /var/lib/docker/overlay2/048d9106359b9e263e74246c56193a5852db6a5b99e4a0f9dd438e657ced78d3/diff/usr/src/app/_site/vendor.js 更改application/x-www-form-urlencoded 为 application/json
3.logstash部署
logstash环境准备及安装:
Logstash是一个开源的数据收集引擎,可以水平伸缩,而且logstash整个ELK当中拥有最多插件的一个组件,其可以接收来自不同来源的数据并统一输出到指定的且可以是多个不同目的地。
环境准备:
关闭防火墙和selinux,并且安装java环境
sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config yum install jdk-8u121-linux-x64.rpm
安装logstash:
yum install logstash-5.3.0.rpm -y
# 权限更改为logstash用户和组,否则启动的时候日志报错
chown logstash.logstash /usr/share/logstash/data/queue -R
测试logstash:
测试标准输入和输出:
/usr/share/logstash/bin/logstash -e 'input{ stdin{} } output{stdout{ codec=>rubydebug}}' #标准输入和输出 hello { "@timestamp" => 2017-11-18T13:49:41.425Z, #当前事件的发生时间, "@version" => "1", #事件版本号,一个事件就是一个ruby对象 "host" => "linux-host2.example.com", #标记事件发生在哪里 "message" => "hello" #消息的具体内容 } # 时间不用管它,浏览器会帮我们转换得。
# 压缩文件
/usr/share/logstash/bin/logstash -e 'input{ stdin{} } output{file{path=>"/tmp/test-%{+YYYY.MM.dd}.log.tar.gz" gzip=>true}}'
# 测试输出到elasticsearch
/usr/share/logstash/bin/logstash -e 'input{ stdin{} } output{ elasticsearch {hosts => ["192.168.152.138:9200"] index => "logstash-test-%{+YYYY.MM.dd}"}}'
# 索引存放位置
ll /data/elkdata/nodes/0/indices/ total 0 drwxr-xr-x. 8 elasticsearch elasticsearch 65 Nov 18 20:17 W8VO0wNfTDy9h37CYpu17g
# 删除索引有两种方式:
一种是elasticsearch,一种是通过api
logstash配置文件之收集系统日志:
# 配置文件说明:conf结尾,名字自定义,一个配置文件可以收集多个日志 vim /etc/logstash/conf.d/system.conf input { file { path => "/var/log/messages" type => "systemlog" # 日志类型 start_position => "beginning" #第一次从头收集,之后从新添加的日志收集 stat_interval => "2" # 多长时间去收集一次,两秒 } } output { elasticsearch { # 定义插件名称 hosts => ["192.168.152.138:9200"] index => "logstash-systemlog-%{+YYYY.MM.dd}" # 为什么要加logstash,主要是后期再地图上显示客户端显示城市,模板上必须要以logstash开头 } }
更改/var/log/messages权限:
# 由于logstash对message没有读得权限 chmod 644 /var/log/messages
检查配置文件是否有报错:
# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/system.conf -t WARNING: Could not find logstash.yml which is typically located in $LS_HOME/config or /etc/logstash. You can specify the path using --path.settings. Continuing using the defaults Could not find log4j2 configuration at path /usr/share/logstash/config/log4j2.properties. Using default config which logs to console Configuration OK 15:43:39.440 [LogStash::Runner] INFO logstash.runner - Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash # 启动服务: systemctl restart logstash
# 启动成功后,显示logstash-systemlog:
# 添加到kibana:
4.kibana部署
kibana可以单独安装到一台服务器
yum install kibana-5.4.0-x86_64.rpm -y 更改配置文件: grep "^[a-Z]" /etc/kibana/kibana.yml server.port: 5601 #端口 server.host: "192.168.152.138" #监听地址 elasticsearch.url: "http://192.168.152.139:9200" #URL地址 # 查看kibana状态 http://192.168.152.138:5601/status # 启动kibana systemctl restart kibana systemctl enable kibana
# kibana 匹配:
[logstash-test]-YYYY.MM.DD
# 显示
5. if判断多个type类型
cat /etc/logstash/conf.d/system.conf input { file { path => "/var/log/messages" type => "systemlog" start_position => "beginning" stat_interval => "2" } file { path => "/var/log/lastlog" type => "system-last" start_position => "beginning" stat_interval => "2" }} output { if [type] == "systemlog"{ elasticsearch { hosts => ["192.168.152.138:9200"] index => "logstash-systemlog-%{+YYYY.MM.dd}" } file{ path => "/tmp/last.log" }} if [type] == "system-last" { elasticsearch { hosts => ["192.168.152.138:9200"] index => "logstash-lastmlog-%{+YYYY.MM.dd}" }} } # 检查配置是否正确 /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/system.conf -t # 重启服务 systemctl restart logstash
在elastic-head查看节点:
添加到kibana:
6.收集nginx访问日志
部署nginx服务:
编辑配置文件并准备web页面:
# 添加到nginx.conf vim conf/nginx.conf # 添加json格式的日志 log_format access_json '{"@timestamp":"$time_iso8601",' '"host":"$server_addr",' '"clientip":"$remote_addr",' '"size":$body_bytes_sent,' '"responsetime":$request_time,' '"upstreamtime":"$upstream_response_time",' '"upstreamhost":"$upstream_addr",' '"http_host":"$host",' '"url":"$uri",' '"domain":"$host",' '"xff":"$http_x_forwarded_for",' '"referer":"$http_referer",' '"status":"$status"}'; access_log /var/log/nginx/access.log access_json; # 添加站点 location /web{ root html; index index.html index.htm; } # 创建目录 mkdir /usr/local/nginx/html/web # 首页文件 echo 'Nginx webPage!' > /usr/local/nginx/html/web/index.html # 不stop,日志格式会乱 /usr/local/nginx/sbin/nginx -s stop # 授权 chown nginx.nginx /var/log/nginx # 启动 /usr/local/nginx/sbin/nginx # 查看访问日志 [root@linux-host2 conf]# tail -f /var/log/nginx/access.log {"@timestamp":"2017-11-20T23:51:00+08:00","host":"192.168.152.139","clientip":"192.168.152.1","size":0,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"192.168.152.139","url":"/web/index.html","domain":"192.168.152.139","xff":"-","referer":"-","status":"304"}
模拟访问:
# 模拟多个访问 yum install httpd-tools -y # 一千个请求,每次处理100个,共10次处理完。 ab -n1000 -c100 http://192.168.152.139/web/index.html
添加logstash配置:
vim /etc/logstash/conf.d/nginx-accesslog.conf input { file { path => "/var/log/nginx/access.log" type => "nginx-access-log" start_position => "beginning" stat_interval => "2" } } output { elasticsearch { hosts => ["192.168.152.139:9200"] index => "logstash-nginx-access-log-%{+YYYY.MM.dd}" } } # 检查配置文件: /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/nginx-accesslog.conf -t # 重启logstash systemctl restart logstash
查看是否已添加到es:
添加到kibana:
7.Tomcat日志转json并收集
服务器部署tomcat服务:
安装java环境,并自定义一个web界面进行测试。
配置java环境并部署Tomcat:
yum install jdk-8u121-linux-x64.rpm cd /usr/local/src [root@linux-host1 src]# tar -xf apache-tomcat-8.0.27.tar.gz [root@linux-host1 src]# cp -rf apache-tomcat-8.0.27 /usr/local/ [root@linux-host1 src]# ln -sv /usr/local/apache-tomcat-8.0.27/ /usr/local/tomcat "/usr/local/tomcat" -> "/usr/local/apache-tomcat-8.0.27/" [root@linux-host1 webapps]# mkdir /usr/local/tomcat/webapps/webdir [root@linux-host1 webapps]# echo "Tomcat Page" > /usr/local/tomcat/webapps/webdir/index.html [root@linux-host1 webapps]# ../bin/catalina.sh start Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started. [root@linux-host1 webapps]# ss -lnt | grep 8080 LISTEN 0 100 :::8080 :::*
配置tomcat的server.xml配置文件:
[root@linux-host1 conf]# diff server.xml server.xml.bak 136,137c136,137 < prefix="tomcat_access_log" suffix=".log" < pattern="{"clientip":"%h","ClientUser":"%l","authenticated":"%u","AccessTime":"%t","method":"%r","status":"%s","SendBytes":"%b","Query?string":"%q","partner":"%{Refere}i","Agentversion":"%{User-Agent}i"}"/> --- > prefix="localhost_access_log" suffix=".txt" > pattern="%h %l %u %t "%r" %s %b" /> [root@linux-host1 conf]# ../bin/startup.sh stop Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started. [root@linux-host1 conf]# ../bin/startup.sh start Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started.
查看日志:
[root@linux-host1 tomcat]# tail -f logs/tomcat_access_log.2017-11-21.log | jq { "clientip": "192.168.152.1", "ClientUser": "-", "authenticated": "-", "AccessTime": "[21/Nov/2017:23:45:45 +0800]", "method": "GET /webdir2/ HTTP/1.1", "status": "304", "SendBytes": "-", "Query?string": "", "partner": "-", "Agentversion": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36" } { "clientip": "192.168.152.1", "ClientUser": "-", "authenticated": "-", "AccessTime": "[21/Nov/2017:23:45:45 +0800]", "method": "GET /webdir2/ HTTP/1.1", "status": "200", "SendBytes": "13", "Query?string": "", "partner": "-", "Agentversion": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36" }
添加logstash配置:
[root@linux-host2 ~]# vim /etc/logstash/conf.d/tomcat_access.conf input { file { path => "/usr/local/tomcat/logs/tomcat_access_log.*.log" type => "tomcat-accesslog" start_position => "beginning" stat_interval => "2" } } output { if [type] == "tomcat-accesslog" { elasticsearch { hosts => ["192.168.152.138:9200"] index => "logstash-tomcat152139-accesslog-%{+YYYY.MM.dd}" }} } # 检查配置文件: /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/nginx-accesslog.conf -t
注意:
path => "/usr/local/tomcat/logs/tomcat_access_log.*.log "中一定不要有空格,不然会找不到索引,血得教训。
path日志 * 代表匹配所有日志,如果需要直观定位哪台机器的索引,可以添加后两位的ip地址。
查看es:
添加到kiban:
测试并发:
[root@linux-host2 tomcat]# ab -n10000 -c100 http://192.168.152.139:8080/webdir/index.html This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.152.139 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: Apache-Coyote/1.1 Server Hostname: 192.168.152.139 Server Port: 8080 Document Path: /webdir/index.html Document Length: 12 bytes Concurrency Level: 100 Time taken for tests: 17.607 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 2550000 bytes HTML transferred: 120000 bytes Requests per second: 567.96 [#/sec] (mean) Time per request: 176.068 [ms] (mean) Time per request: 1.761 [ms] (mean, across all concurrent requests) Transfer rate: 141.44 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 22 24.1 11 158 Processing: 19 154 117.4 116 2218 Waiting: 1 141 113.7 95 2129 Total: 19 175 113.6 142 2226 Percentage of the requests served within a certain time (ms) 50% 142 66% 171 75% 204 80% 228 90% 307 95% 380 98% 475 99% 523 100% 2226 (longest request)
8.收集java日志
使用codec的multiline插件实现多行匹配,这是一个可以将多行进行合并的插件,而且可以使用what指定将匹配到的行与前面的行合并还是和后面的行合并,
https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html
在elasticsearch服务器部署logstash示例:
chown logstash.logstash /usr/share/logstash/data/queue -R ll -d /usr/share/logstash/data/queue cat /etc/logstash/conf.d/java.conf input{ stdin{ codec=>multiline{ pattern=>"^\[" #当遇到[开头的行时候将多行进行合并 negate=>true #true 为匹配成功进行操作,false为不成功进行操作 what=>"previous" #与上面的行合并,如果是下面的行合并就是next }} } filter{ #日志过滤,如果所有的日志都过滤就写这里,如果只针对某一个过滤就写在input里面的日志输入里面 } output{ stdout{ codec=>rubydebug }}
测试匹配代码:
/usr/share/logstash/bin/logstash -e 'input { stdin { codec => multiline { pattern => "^\[" negate => true what => "previous" }}} output { stdout { codec => rubydebug}}'
注意:如果匹配空行,使用$
测试匹配输出:
日志格式:
[root@linux-host1 ~]# tail /data/logs/elk-cluster.log [2017-11-23T00:11:09,559][INFO ][o.e.c.m.MetaDataMappingService] [elk-node1] [logstash-nginx-access-log-2017.11.22/N8AF_HmTSiqBiX7pNulkYw] create_mapping [elasticsearch-java-log] [2017-11-23T00:11:10,777][INFO ][o.e.c.m.MetaDataCreateIndexService] [elk-node1] [elasticsearch-java-log-2017.11.22] creating index, cause [auto(bulk api)], templates [], shards [5]/[1], mappings [] [2017-11-23T00:11:11,881][INFO ][o.e.c.m.MetaDataMappingService] [elk-node1] [elasticsearch-java-log-2017.11.22/S5LpdLyDRCq3ozqVnJnyBg] create_mapping [elasticsearch-java-log] [2017-11-23T00:11:12,418][INFO ][o.e.c.r.a.AllocationService] [elk-node1] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[elasticsearch-java-log-2017.11.22][3]] ...]).
生产配置文件:
vim /etc/logstash/conf.d/java.conf input { file { path => "/data/logs/elk-cluster.log" type => "elasticsearch-java-log" start_position => "beginning" stat_interval => "2" codec => multiline { pattern => "^\[" negate => true what => "previous" } }} output { if [type] == "elasticsearch-java-log" { elasticsearch { hosts => ["192.168.152.138:9200"] index => "elasticsearch-java-log-%{+YYYY.MM.dd}" }} }
验证语法:
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/java.conf -t WARNING: Could not find logstash.yml which is typically located in $LS_HOME/config or /etc/logstash. You can specify the path using --path.settings. Continuing using the defaults Could not find log4j2 configuration at path /usr/share/logstash/config/log4j2.properties. Using default config which logs to console Configuration OK 00:06:47.228 [LogStash::Runner] INFO logstash.runner - Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
重启服务:
systemctl restart logstash
查看es状态:
添加到kibana:
kibana展示:
9.收集TCP日志
如果一些日志丢失,可以通过这种方式来进行了补一些日志。
https://www.elastic.co/guide/en/logstash/current/plugins-inputs-tcp.html
# 测试配置文件
vim /etc/logstash/conf.d/tcp.conf input { tcp { port => 5600 mode => "server" type => "tcplog" } } output { stdout { codec => rubydebug } }
# 验证配置是否正确语法
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/tcp.conf -t
# 启动
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/tcp.conf
在其他服务器安装nc命令:
NetCat简称nc,在网络工具中有“瑞士军刀”美誉,其功能实用,是一个简单、可靠的网络工具,可通过TCP或UDP协议传输读写数据,另外还具有很多其他功能。
yum install nc -y
# 发送数据
echo "nc test"|nc 192.168.56.16 9889
验证logstash是否接收到数据:
{ "@timestamp" => 2017-11-23T15:36:50.938Z, "port" => 34082, "@version" => "1", "host" => "192.168.152.138", "message" => "tcpdata", "type" => "tcplog" }
通过nc命令发送一个文件:
nc 192.168.152.139 5600 < /etc/passwd
通过伪设备的方式发送消息:
在类Unix操作系统中,设备节点并不一定要对应物理设备。没有这种对应关系的设备是伪设备。操作系统运用了它们提供的多种功能,tcp只是dev下面众多伪设备当中的一种设备。
echo "伪设备" > /dev/tcp/192.168.152.139/5600 echo "2222" > /dev/tcp/192.168.152.139/5600
生产配置:
vim /etc/logstash/conf.d/tomcat_tcp.conf input { file { path => "/usr/local/tomcat/logs/tomcat_access_log.*.log" type => "tomcat-accesslog" start_position => "beginning" stat_interval => "2" } tcp { port => 5600 mode => "server" type => "tcplog" } } output { if [type] == "tomcat-accesslog" { elasticsearch { hosts => ["192.168.152.138:9200"] index => "logstash-tomcat152139-accesslog-%{+YYYY.MM.dd}" }} if [type] == "tcplog" { elasticsearch { hosts => ["192.168.152.138:9200"] index => "tcplog-test152139-%{+YYYY.MM.dd}" }} }
查看ES:
查看kibana:
发送数据:
11.架构规划
在下面的图当中从左向右看,当要访问ELK日志统计平台的时候,首先访问的是两天Nginx+keepalived做的负载高可用,访问的地址是keepalived的IP,当一台nginx代理服务器挂掉之后也不影响访问,然后nginx将请求转发到kibana,kibana再去elasticsearch获取数据,elasticsearch是两台做的集群,数据会随机保存在任意一台elasticsearch服务器,redis服务器做数据的临时保存,避免web服务器日志量过大的时候造成的数据收集与保存不一致导致的日志丢失,可以临时保存到redis,redis可以是集群,然后再由logstash服务器在非高峰时期从redis持续的取出即可,另外有一台mysql数据库服务器,用于持久化保存特定的数据,web服务器的日志由filebeat收集之后发送给另外的一台logstash,再有其写入到redis即可完成日志的收集,从图中可以看出,redis服务器处于前端结合的最中间,其左右都要依赖于redis的正常运行,那么我们就先从部署redis开始,然后将日志从web服务器收集到redis,在安装elasticsearch、kibana和从redis提取日志的logstash。
12. logstash收集日志并写入redis
用一台服务器按照部署redis服务,专门用于日志缓存使用,用于web服务器产生大量日志的场景,例如下面的服务器内存即将被使用完毕,查看是因为redis服务保存了大量的数据没有被读取而占用了大量的内存空间。
如果占用内存太多,这时候需要添加logstash服务器了,增加读取速度。
安装并配置redis:
ln -sv /usr/local/src/redis-4.0.6 /usr/local/redis cp src/redis-server /usr/bin/ cp src/redis-cli /usr/bin/ bind 192.168.152.139 daemonize yes # 允许后台启动 # 打开save "",save 全部禁止 save "" #save 900 1 #save 300 10 #save 60 10000 # 开启认证 requirepass 123456 启动: redis-server /usr/local/redis/redis.conf 测试: [root@linux-host2 redis-4.0.6]# redis-cli -h 192.168.152.139 192.168.152.139:6379> KEYS * (error) NOAUTH Authentication required. 192.168.152.139:6379> auth 123456 OK 192.168.152.139:6379> KEYS (error) ERR wrong number of arguments for 'keys' command 192.168.152.139:6379> KEYS * (empty list or set) 192.168.152.139:6379>
配置logstash将日志写入至redis:
将tomcat服务器的logstash收集之后的tomcat访问日志写入到redis服务器,然后通过另外的logstash将redis服务器的数据取出再写入elasticsearch服务器。
官方文档:
www.elastic.co/guide/en/logstash/current/plugins-outputs-redis.html
redis-cli -h 192.168.152.139 -a 123456 LLEN rsyslog-5612 LPOP rsyslog-5612 # 弹一条 查看数据: redis-cli -h 192.168.152.139 -a 123456 #查询数据 SELECT 1 #查看数据 KEYS *
logstash配置:
input { redis { data_type => "list" host => "192.168.152.139" db => "1" port => "6379" key => "rsyslog-5612" password => "123456" } } output { elasticsearch { hosts => ["192.168.152.139:9200"] index => "redis-rsyslog-5612-%{+YYYY.MM.dd}" } }
待补充:
通过rsyslog收集haproxy日志: 在centos 6及之前的版本叫做syslog,centos7开始叫做rsyslog,根据官方的介绍,rsyslog(2013年版本)可以达到每秒转发百万条日志的级别,官方网址http://www.rsyslog.com/,确认系统安装的版本命令如下: 安装: yum install gcc gcc-c++ pcre pcre-devel openssl openss-devel -y make TARGET=linux2628 USER_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 PREFIX=/usr/local/haproxy make install PREFIX=/usr/local/haproxy # 查看版本 /usr/local/haproxy/sbin/haproxy -v 准备启动脚本: vim /usr/lib/systemd/system/haproxy.service [Unit] Description=HAProxy Load Balancer After=syslog.target network.target [Service] EnvironmentFile=/etc/sysconfig/haproxy ExecStart=/usr/sbin/haproxy-systemd-wrapper -f /etc/sysconfig/haproxy.cfg -p /run/haproxy.pid $OPTIONS ExecReload=/bin/kill -USR2 $MAINPID [Install] WantedBy=multi-user.target [root@linux-host2 haproxy-1.7.9]# cp /usr/local/src/haproxy-1.7.9/haproxy-systemd-wrapper /usr/sbin/ [root@linux-host2 haproxy-1.7.9]# cp /usr/local/src/haproxy-1.7.9/haproxy /usr/sbin/ vim /etc/sysconfig/haproxy #系统级配置文件 OPTIONS="" mkdir /etc/haproxy vim /etc/sysconfig/haproxy.cfg global maxconn 100000 chroot /usr/local/haproxy uid 99 gid 99 daemon nbproc 1 pidfile /usr/local/haproxy/run/haproxy.pid log 127.0.0.1 local6 info defaults option http-keep-alive option forwardfor maxconn 100000 mode http timeout connect 300000ms timeout client 300000ms timeout server 300000ms listen stats mode http bind 0.0.0.0:9999 stats enable log global stats uri /haproxy-status stats auth headmin:123456 #frontend web_port frontend web_port bind 0.0.0.0:80 mode http option httplog log global option forwardfor ###################ACL Setting################### acl pc hdr_dom(host) -i www.elk.com acl mobile hdr_dom(host) -i m.elk.com ###################USE ACL ###################### use_backend pc_host if pc use_backend mobile_host if mobile ################################################# backend pc_host mode http option httplog balance source server web1 192.168.56.11:80 check inter 2000 rise 3 fall 2 weight 1 backend mobile_host mode http option httplog balance source server web1 192.168.56.11:80 check inter 2000 rise 3 fall 2 weight 1 vim /etc/rsyslog.conf $ModLoad imudp $UDPServerRun 514 $ModLoad imtcp $InputTCPServerRun 514 local6.* @@192.168.152.139:5160 重新启动rsyslog服务: systemctl restart rsyslog input{ syslog { type => "rsyslog-5612" port => "5160" } } output { stdout { codec => rubydebug } } ########################### input{ syslog { type => "rsyslog-5612" port => "5160" } } output { if [type] == "rsyslog-5612"{ elasticsearch { hosts => ["192.168.152.139:9200"] index => "rsyslog-5612-%{+YYYY.MM.dd}" }} }
使用filebeat替代logstash收集日志
Filebeat是轻量级单用途的日志收集工具,用于在没有安装java的服务器上专门收集日志,可以将日志转发到logstash、elasticsearch或redis等场景中进行下一步处理。 官网下载地址:https://www.elastic.co/downloads/beats/filebeat 官方文档:https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-configuration-details.html 确定日志格式为json格式: 先访问web服务器,以产生一定的日志,然后确认是json格式: ab -n100 -c100 http://192.168.56.16:8080/web 安装: yum -y install filebeat-5.4.0-x86_64.rpm https://www.elastic/guide/en/beats/filebeat/current/filebeat-configuration-details.html [root@linux-host2 src]# grep -v "#" /etc/filebeat/filebeat.yml | grep -v "^$" filebeat.prospectors: - input_type: log paths: - /var/log/*.log - /var/log/messages exclude_lines: ["^DBG","^$"] #如果有空行,日志往数据写会报错 document_type: system-log-5612 #日志类型 output.file: path: "/tmp" name: "filebeat.txt" [root@linux-host2 src]# systemctl restart filebeat 测试使用echo形式: echo "test" >> /var/log/messages [root@linux-host2 src]# tail -f /tmp/filebeat {"@timestamp":"2017-12-21T15:45:05.715Z","beat":{"hostname":"linux-host2.example.com","name":"linux-host2.example.com","version":"5.4.0"},"input_type":"log","message":"Dec 21 23:45:01 linux-host2 systemd: Starting Session 9 of user root.","offset":1680721,"source":"/var/log/messages","type":"system-log-5612"} logstash收集日志并吸入redis: 输出到redis: output.redis: hosts: ["192.168.56.12:6379"] db: "1" #使用第几个库 timeout: "5" #超时时间 password: "123456" #redis密码 key: "system-log-5612" #为了后期日志处理,建议自定义 查看数据: SELECT 3 KYES * LLEN system-log-5612 RPOP system-log-5612 从redis取日志: input { redis { data_type => "list" host => "172.20.8.13" db => "1" port => "6379" key => "system-log-0840" password => "123456" } } output { if [type] == "system-log-0840" { elasticsearch { hosts => ["172.20.8.12:9200"] index => "system-log-0840-%{+YYYY.MM.dd}" } } } logstash 一般是每秒几百行的数据,redis每秒钟上百万行数据
监控redis数据长度
实际环境当中,可能会出现redis当中堆积了大量的数据而logstash由于种种原因未能及时提取日志,此时会导致redis服务器的内存被大量使用,甚至出现如下内存即将被使用完毕的情景: 查看redis中的日志队列长度发现有大量的日志堆积在redis当中: 安装redis模块: yum install python-pip -y pip install redis 报警脚本: #!/usr/bin/env python #coding:utf-8 #Author import redis def redis_conn(): pool = redis.ConnectionPool(host="192.168.56.12",port=6379,db=1,password=123456) conn = redis.Redis(connection_pool=pool) data = conn.llen('tomcat-accesslog-5612') print(data) redis_conn()
结合logstash进行输出测试
vim beats.conf input{ beats{ port => 5044 } } output{ stdout { codec => rubydebug } } #将输出改为文件进行临时输出测试 output{ file{ path => "/tmp/filebeat.txt" } } filebeat配置文件由redis更改为logstash: output.logstash: hosts: ["192.168.56.11:5044"] #logstash 服务器地址,可以是多个 enabled: true #是否开启输出至logstash,默认即为true worker: 2 #工作线程数 compression_level: 3 #压缩级别 loadbalance: true #多个输出的时候开启负载 配置logstash的配置文件收集beats的文件,再存入redis: vim beats.conf input{ beats{ port => 5044 } } output{ if [type] == "filebeat-system-log-5612"{ redis { data_type => "list" host => "192.168.56.12" db => "3" port => "6379" key => "filebeat-system-log-5612-%{+YYYY.MM.dd}" password => "123456" }} } 由redis中取数据,并写入elastsearch: vim redis-es.yaml input { redis { data_type => "list" host => "192.168.56.12" db = > "3" port => "6379" key => "filebeat-system1-log-5612" password => "123456" } } output { if [type] == "filebeat-system1-log-5612" { elasticsearch { hosts => ["192.168.56.11:9200"] index => "filebeat-system1-log-5612-%{+YYYY.MM.dd}" }} }
filebeat收集tomcat日志
filebeat配置中添加如下配置: - input_type: log paths: - /usr/local/tomcat/logs/tomcat_access_log.*.log document_type: tomcat-accesslog-5612 grep -v "#" /etc/filebeat/filebeat.yml | grep -v "^$" filebeat.prospectors: - input_type: log paths: - /var/log/messages - /var/log/*.log exclude_lines: ["^DBG","^$"] document_type: filebeat-system-log-5612 - input_type: log paths: - /usr/local/tomcat/logs/tomcat_access_log.*.log document_type: tomcat-accesslog-5612 output.logstash: hosts: ["192.168.56.11:5044"] enabled: true worker: 2 compression_level: 3 logstash收集redis中的日志,传给redis: vim beats.conf input{ beats{ port => 5044 } } output{ if [type] == "filebeat-system-log-5612"{ redis { data_type => "list" host => "192.168.56.12" db => "3" port => "6379" key => "filebeat-system-log-5612-%{+YYYY.MM.dd}" password => "123456" }} if [type] == "tomcat-accesslog-5612" { redis { data_type => "list" host => "192.168.56.12" db => "4" port => "6379" key => "tomcat-accesslog-5612" password => "123456" }} } LPOP验证一下redis: 由redis中取数据,并写入elastsearch: vim redis-es.yaml input { redis { data_type => "list" host => "192.168.56.12" db => "3" port => "6379" key => "filebeat-system1-log-5612" password => "123456" } redis { data_type => "list" host => "192.168.56.12" db => "4" port => "6379" key => "tomcat-accesslog-5612" password => "123456" } } output { if [type] == "filebeat-system1-log-5612" { elasticsearch { hosts => ["192.168.56.11:9200"] index => "filebeat-system1-log-5612-%{+YYYY.MM.dd}" }} if [type] == "tomcat-accesslog-5612" { elasticsearch { hosts => ["192.168.56.12:9200"] index => "tomcat-accesslog-5612-%{+YYYY.MM.dd}" }} } 添加到kibana:
添加代理
添加haproxy代理: ##################ACL Setting################# acl pc hdr_dom(host) -i www.elk.com acl mobile hdr_dom(host) -i m.elk.com acl kibana hdr_dom(host) -i www.kibana5612.com ##################USE ACL###################### use_backend pc_host if pc use_backend mobile_host if mobile use_backend kibana_host if kibana ############################################### backend kibana_host mode http option httplog balance source server web1 127.0.0.1:5601 check inter 2000 rise 3 fall 2 weight 1 kibana配置: server.port: 5601 server.host: "127.0.0.1" elasticsearch.url: "http://192.168.56.12:9200" systemctl start kibana systemctl enable kibana Nginx代理并授权: vim nginx.conf include /usr/local/nginx/conf/conf.d/*.conf; vim /usr/local/nginx/conf/conf.d/kibana5612.conf upstream kibana_server { server 127.0.0.1:5601 weight=1 max_fails=3 fail_timeout=60; } server { listen 80; server_name www.kibana5611.com; location /{ proxy_pass http://kibana_server; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } yum install httpd-tools -y #第一次需要加-c htpasswd -bc /usr/local/nginx/conf/htpasswd.users luchuangao 123456 #第二次需要把-c去掉,否则会覆盖原有得。 htpasswd -b /usr/local/nginx/conf/htpasswd.users luchuangao 123456 #查看tail /usr/local/nginx/conf/htpasswd.users ... #授权 chown nginx.nginx /usr/local/nginx/conf/htpasswd.users #重启服务 /usr/local/nginx/sbin/nginx -s reload 添加进nginx配置文件: vim /usr/local/nginx/conf/conf.d/kibana5612.conf upstream kibana_server { server 127.0.0.1:5601 weight=1 max_fails=3 fail_timeout=60; } server { listen 80; server_name www.kibana5611.com; auth_basic "Restricted Access"; auth_basic_user_file /usr/local/nginx/conf/htpasswd.users; location /{ proxy_pass http://kibana_server; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }
elk定时删除索引
http://www.iyunw.cn/archives/elk-mei-ri-qing-chu-30-tian-suo-yin-jiao-ben/