Filebeat 已经完全替代了 Logstash-Forwarder 成为新一代的日志采集器,同时鉴于它轻量、安全等特点,经消息队列输出插件输出到消息队列中。目前 Logstash 支持 Kafka、Redis、RabbitMQ 等常见消息队列。然后 Logstash 通过消息队列输入插件从队列中获取数据,分析过滤后经输出插件发送到 Elasticsearch,最后通过 Kibana 展示
引入消息队列机制的架构
Ip地址 | 主机名 | 配置 | 角色 | 软件版本 |
---|---|---|---|---|
193.167.10.87 | elk-node1 | 4core8G,200G | es-node1 | elasticsearch-5.6.4 jdk-8u181 |
193.167.10.88 | elk-node2 | 4core8G,200G | es-node2 head插件 | elasticsearch-5.6.4 jdk-8u181 |
193.167.10.89 | elk-node3 | 4core8G,200G | es-node3 | elasticsearch-5.6.4 jdk-8u181 |
193.167.10.90 | elk-node4 | 16core16G,100G | redis+logstash+kibana | redis-3.2.12 logstash-5.6.4 kibana-5.6.4 jdk-8u181 |
安装配置软件
#解压软件,安装包存放在soft目录,运行目录在opt
rm -rf /opt/rh
mkdir /soft
cd /soft
rpm -ivh jdk-8u181-linux-x64.rpm
tar xf elasticsearch-5.6.4.tar -C /opt/
#新建es用户,修改相应权限
groupadd es
useradd es -g es
chown -R es.es /opt/elasticsearch-5.6.4
mkdir -p /data/{es_data,es_log}
chown -R es.es /data/
以收集Nginx访问日志为例,我们希望能统计到api接口调用排行,浏览器类型,操作系统类型,http状态分布,响应时间分布。虽然logstash可以通过內建模板解析Nginx日志字符串,不过直接在Nginx配置中直接json字符串最为方便。
nginx 的日志里含有中文的话,会将中文转为 Unicode 编码,如果不转的话,加入 escape=json 参数就可以了
log_format json escape=json'{ "@timestamp": "$time_iso8601", '
'"time": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"remote_user": "$remote_user", '
'"body_bytes_sent": "$body_bytes_sent", '
'"request_time": "$request_time", '
'"status": "$status", '
'"host": "$host", '
'"request": "$request", '
'"request_method": "$request_method", '
'"uri": "$uri", '
'"http_referrer": "$http_referer", '
'"body_bytes_sent":"$body_bytes_sent", '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"http_user_agent": "$http_user_agent" '
'}';
access_log /opt/nginx/logs/access.log json;
然后在各网站Nginx配置下指定json模板日志格式
access_log logs/access-lvxin.log json;
重启Nginx,日志格式输出结果示例如下:
{"@timestamp":"2018-10-16T00:05:07+08:00","host":"193.167.10.113","clientip":"61.144.107.92","size":73,"responsetime":0.003,"upstreamtime":"0.003","upstreamhost":"192.168.130.175:
49010","http_host":"gzhlk8.fangcang.com","url":"/fangcang-message-center-web/messagecenter/message/latestMessage","domain":"gzhlk8.fangcang.com","xff":"-","referer":"http://gzhlk8
.fangcang.com/UIS/?version=new","agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0","status"
:"200"}
filebeat.prospectors:
- input_type: log
enabled: true
paths:
- /usr/local/nginx/logs/nginx.access.log #指明读取文件的位置
tags: ["nginx_access"] ##列表中添加标签,方便过滤
document_type: nginx_access #定义写入ES 时的 _type 值
tail_files: true #是否从文件末尾开始读取
- input_type: log
enabled: true
paths:
- /usr/local/nginx/logs/access-lvxin.log
tags: ["nginx_lvxinaccess"]
document_type: nginx_lvxinaccess
tail_files: true
output.redis:
hosts: ["193.167.10.90"] #输出到redis的机器
port: 6379
db: 1 #redis数据库的一个整数索引标识,redis总共0-15默认16个库。
timeout: 5
key: "default_list" #以default_list的keys传输到redis
错误日志 ERR Error decoding JSON: invalid character ‘x’ in string escape code
nginx使用$uri 可以在nginx对URL进行更改或重写,但是用于日志输出可以使用$request_uri代替,如无特殊业务需求,完全可以替换
yum方式安装
cluster.name: cc-cluster #集群名称(自定义)
node.name: cc-1 #节点名称(自定义)
node.master: true #是否有资格成为master主节点,如只做存储则为false
node.data: true #是否做存储节点,当这两个都为false时,该节点作为client
path.data: /usr/local/ELK/elasticsearch-6.3.0/data #数据存储目录
path.logs: /usr/local/ELK/elasticsearch-6.3.0/logs #日志存储目录
network.host: 192.168.32.231 #监听本地ip
http.port: 9200 #http监听端口
#transport.tcp.port: 9300 #tcp通讯端口
#transport.tcp.compres: true
gateway.recover_after_nodes: 2 #一个集群中的N个节点启动后,才允许进行恢复处理
#gateway.recover_after_time: 5 #设置初始化恢复过程的超时时间,超时时间从上一个配置中配置的N个节点启动后算起
gateway.expected_nodes: 1 # 设置这个集群中期望有多少个节点.一旦这N个节点启动(并且recover_after_nodes也符合),立即开始恢复过程(不等待recover_after_time超时)
bootstrap.memory_lock: true #锁定内存,阻止操作系统管理内存,可以有效的防止内存数据被交换到磁盘空间,交换过程中磁盘会抖动,会对性能产生较大的影响。因为ES是基于JAVA开发的可以能过垃圾回收器来单独管理内存,所以关闭操作系统级别的内存管理可以提升性能
bootstrap.system_call_filter: false #关闭操作系统内核验证
discovery.zen.ping.unicast.hosts: ["192.168.32.231","192.168.32.230","192.168.32.232"] #集群初始化连接列表,节点启动后,首先通过连接初始化列表里的地址去发现集群。
discovery.zen.minimum_master_nodes: 2 #为了防止集群脑裂,目前的策略是当且仅当节点有超过半数的master候选者存活时(当前两台master),集群才会进行master选举
1. 自己的配置文件
[root@elk-node1 ~]# cat /opt/elasticsearch-5.6.4/config/elasticsearch.yml |egrep -v "^#"
cluster.name: elk-nginx
node.name: elk-node1
node.master: true
node.data: true
path.data: /data/es_data
path.logs: /data/es_log
bootstrap.memory_lock: false
network.host: 193.167.10.87
http.port: 9200
discovery.zen.ping.unicast.hosts: ["elk-node1","elk-node2", "elk-node3"]
discovery.zen.minimum_master_nodes: 2
gateway.recover_after_nodes: 2
http.cors.enabled: true
http.cors.allow-origin: "*"
2. 安装head插件
5.0以上,elasticsearch-head 不能放在elasticsearch的 plugins、modules 目录下,否则elasticsearch启动会报错
git clone https://github.com/mobz/elasticsearch-head.git
安装node js
curl -sL https://rpm.nodesource.com/setup_8.x | bash
yum install -y nodejs
安装grunt
npm install -g grunt-cli
npm install
vi /opt/elasticsearch-5.6.4/elasticsearch-head/Gruntfile.js
connect: {
server: {
options: {
port: 9100,
hostname: '*', #此行为新增加
base: '.',
keepalive: true
}
}
}
});
vi /opt/elasticsearch-5.6.4/elasticsearch-head/_site/app.js
this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://192.168.10.88:9200";#修改localhost为定义的地址
运行head
grunt server &
访问方式 http://193.167.10.88:9100/
input {
redis {
data_type =>"list"
key =>"default_list"
host =>"127.0.0.1"
port => 6379
threads => "8"
db => 1
#codec => json
}
}
filter {
json {
source => "message"
remove_field => ["tags","beat","message"]
}
#使用geoip库定位ip
geoip {
source => "clientip" #nginx日志中外部访问ip对应字段
database => "/opt/GeoLite2-City.mmdb"
#去掉显示geoip显示的多余信息
remove_field => ["[geoip][latitude]", "[geoip][longitude]", "[geoip][country_code]", "[geoip][country_code2]", "[geoip][country_code3]", "[geoip][timezone]", "[geoip][continent_code]", "[geoip][region_code]", "[geoip][ip]"]
#add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ]
#add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ]
target => "geoip"
}
mutate {
convert => [ "[geoip][coordinates]", "float" ]
}
}
output {
if [type] == "nginx_lvxinaccess" {
elasticsearch {
hosts => ["193.167.10.87:9200","193.167.10.88:9200","193.167.10.89:9200"]
index => "logstash-nginx_lvxinaccess-%{+yyyy.MM.dd}" #注意此处索引名称,一定要以logstash开头命名,后者地图功能不可用(mapping)
document_type => "%{type}"
}
}
if [type] == "nginx_access" {
elasticsearch {
hosts => ["193.167.10.87:9200","193.167.10.88:9200","193.167.10.89:9200"]
index => "logstash-nginx_access-%{+yyyy.MM.dd}"
document_type => "%{type}"
}
}
}