直接使用 Filebeat 在节点上采集日志数据然后直接传输给 Elasticsearch 存储。这种架构有利于日志数据的时效性,但是当日志规模较大时,可能导致 Elasticsearch 存储集群容量不足,或者出现性能瓶颈。
为了解决这一问题,可以使用缓存机制提高 ES 的可靠性和稳定性,即使 ES 集群宕机,在重新恢复之后可以从 Redis 中同步数据。Redis 是一种内存高速缓存数据库,以键值对的方式存储数据,具有可持久化,分布式扩展的特点。
ELK 使用 Redis 作为缓存的一个缺陷在于:Filebeat 采集的日志数据只能传输给 Redis 的单节点,不能传输给 Redis 集群或者 Redis 哨兵(在新版本中应该会有所改进)
ELK 使用 Redis 作为缓存的另一个缺陷在于:Elasticsearch 无法直接从 Redis 中读取数据,所以需要使用 Logstash 作为中间件,实现日志聚合,从 Redis 中读取缓存数据然后传递给Elasticsearch,形成如下结构
| 第一层 | 第二层 | 第三层 | 第四层 |
|---|---|---|---|
| Nginx+Filebeat | Redis | Logstash | Elasticsearch |
使用运维脚本管理 Redis,准备好Redis
root@master:/$ sh redis_shell.sh start 6379 # 启动Redis root@master:/$ sh redis_shell.sh login 6379 # 登录Redis root@master:/$ sh redis_shell.sh stop 6379 # 关闭Redis再删除数据,否则会触发持久化 # 删除原有数据 rm -rf /data/redis_cluster/redis_6379/*
配置Filebeat缓存日志数据到Redis Filebeat输出到Redis配置官方文档
在Filebeat的配置文件/etc/filebeat/filebeat.yml中修改输出配置,删除ES输出配置添加Redis输出配置如下
# ------------------------------ Redis Output ------------------------------- output.redis: hosts: ["172.16.255.131"] # password: "my_password" # 本机的Redis没有设置密码不进行配置 key: "filebeat" db: 0 timeout: 5
重启filebeat,并使用浏览器访问Nginx,产生日志数据,并查看Redis中是否成功缓存日志数据
root@master:/$ sh redis_shell.sh start 6379 # 启动Redis root@master:/$ sh redis_shell.sh login 6379 # 登录Redis 172.16.255.131:6379> keys * 172.16.255.131:6379> type filebeat # 查看类型 172.16.255.131:6379> LLEN filebeat 172.16.255.131:6379> LRANGE filebeat 1 5 # 查看filebeat对应1到5的值,即5条日志记录
查看如下,可以看到Nginx的日志数据被完整缓存在Redis中
2.2 LogStash 消费 Redis 缓存的日志数据使用Redis作为缓存,需要使用LogStash作为中间件读取日志数据到ES中,Logstash收集Redis日志数据需要对其进行配置
配置Logstash:Logstash的配置文件都放在/etc/logstash/conf.d/目录下
创建Logstash的Redis输入配置文件vim /etc/logstash/conf.d/redis.conf,并输入配置内容如下
# 输入源配置
input {
redis {
host => "172.16.255.131"
port => 6379
# password => "my_password" # 不需要配置密码时直接删除该行
db => "0"
key => "filebeat"
data_type => "list"
type => "redis"
codec => plain{
charset=>"UTF-8"
}
}
}
filter {
mutate{
convert => ["upstream_time","float"] # 解析时间
convert => ["request_time","float"] # 请求时间
}
# 解析为json格式
json {
source => "message"
}
}
# 输出配置
output{
stdout {}
elasticsearch {
hosts => "http://172.16.255.131:9200"
manage_template => false
index => "nginx_redis-%{+yyyy.MM}"
}
}
完成配置启动logstash后,logstash开始消费redis中的日志数据,并传送到ES中,redis中的数据被消费之后自动清除
03 ELK 使用 Redis 分类型缓存日志数据 3.1 Filebeat 分类型缓存日志数据到 Redis在Filebeat的配置文件/etc/filebeat/filebeat.yml中添加分类型的日志数据采集配置,并修改Redis输出配置如下
# 输入配置
# -----------------------------Nginx-----------------------------------
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
json.keys_under_root: true
json.overwrite_keys: true
tags: ["access"]
- type: log
enabled: true
paths:
- /var/log/nginx/error.log
tags: ["error"]
# 输出配置
output.redis:
hosts: ["172.16.255.131"]
keys:
- key: "nginx_access" # 根据tags标签将不同类型日志,存储到不同的redis列表中
when.contains:
tags: "access"
- key: "nginx_error"
when.contains:
tags: "error"
重启filebeat,并使用浏览器访问Nginx,产生正常和错误日志数据,并查看Redis中是否成功缓存日志数据
root@master:/$ sh redis_shell.sh start 6379 # 启动Redis root@master:/$ sh redis_shell.sh login 6379 # 登录Redis 172.16.255.131:6379> keys * # 查看是否产生了 "nginx_access" 和 "nginx_error" 两个key3.2 LogStash 分类型消费 Redis 缓存的日志数据
修改Logstash的Redis输入配置文件vim /etc/logstash/conf.d/redis.conf的配置内容如下
input {
# 添加两个针对不同Redis的key列表 "nginx_access"和"nginx_error"
redis {
host => "172.16.255.131"
port => 6379
db => "0"
key => "nginx_access"
data_type => "list"
type => "redis"
codec => plain{
charset=>"UTF-8"
}
}
redis {
host => "172.16.255.131"
port => 6379
db => "0"
key => "nginx_error"
data_type => "list"
type => "redis"
codec => plain{
charset=>"UTF-8"
}
}
}
filter {
mutate {
convert => ["upstream_time","float"]
convert => ["request_time","float"]
}
json {
source => "message"
}
}
output{
stdout {}
# 使用 if 判断来自不同Redis的key列表的日志数据
if "access" in [tags] {
elasticsearch {
hosts => "http://172.16.255.131:9200/"
manage_template => false
index => "nginx_access-%{+yyyy.MM}"
}
}
if "error" in [tags] {
elasticsearch {
hosts => "http://172.16.255.131:9200/"
manage_template => false
index => "nginx_error_redis-%{+yyyy.MM}"
}
}
}
完成配置启动logstash后,logstash开始消费redis中的日志数据,并传送到ES中
3.3 分类型缓存日志数据优化从上述例子中可以看到,区分不同类型日志的关键在于Filebeat中产生的日志标签tags,而tags标签又直接包含在日志数据中,所以可以只采用一个key存储所有类型日志数据。
所以,对Filebeat的输出配置和LogStash的输入配置可以进行如下修改
Filebeat的输出配置
output.redis: hosts: ["172.16.255.131"] key: "nginx" # 用一个key保存所有日志数据,根据日志数据中的tags标签区分不同类型日志
LogStash的输入配置
input {
redis {
host => "172.16.255.131"
port => 6379
db => "0"
key => "nginx" # 与Filebeat修改对应
data_type => "list"
type => "redis"
codec => plain{
charset=>"UTF-8"
}
}
}



