elk+redis已是目前很多中小型公司比较青睐的开源日志搜集组合之一,主要是因为安装配置简单,社区活跃、开源免费等等.
随着公司业务的变多,日志量追渐增大,单节点的elk+redis已经满足不了业务的需求,这时候扩容或许是一件非常普遍的行为,那么如何做到自动扩容和"缩容"呢?
先来看一张简化版的扩谱图
在看完这张简化版的扩谱图之后,我们首先要明白elasticsearch cluster是如何做到Discovery的?
Elasticsearch是一个点对点的系统,节点之间直接通信并且节点之间的关系都是对等的;
2.0版本之后,为了安全考虑,默认禁用了multicast(组播)功能;但是Es还支持单播(unicast)方式
如果不涉及到Es性能优化,其实配置集群相当简单,只需要配置以下核心参数即可:
discovery.zen.ping.unicast.hosts: ["10.100.100.81", "10.100.100.82"] # 指定Es集群中每个节点的host地址,集群中所有的配置保持一致. discovery.zen.minimum_master_nodes: 2 # 指定master节点的个数(hosts / 2)+ 1 # 这里的hosts是指集群节点数之和.
(1) Logstash插件介绍
# logstash-shipping logstash-input-file # 数据源. logstash-output-redis # 输出到消息队列. # logstash-indexing logstash-input-redis # 从消息队列中取数据. logstash-output-elasticsearch # 输入到elasticsearch 持久化存储.
(2) 为什么会有这个架构呢?
2015.10 elk+redis(v1) 上线 2016.5 elk+redis(v2) 方案已定(扩谱图) elk_v1 上线之后 研发使用后的反应很好. 在elk_v1使用的过程中国区测试环境没有出过问题,但是美国正式环境就经常性问题不断?比如 1> redis堵了; 2> kibana界面打不开或者打开之后之后一直处于Searching状态,无法正常打开日志. 3> kibana界面崩溃了 4> es所在的机器cpu非常吃紧 主要原因是因为美国正式环境日志量比中国测试环境日志量大的多,经过heap插件查看日志量在20~40G/天 个人临时性的解决办法就是 elasticsearch集群; 于是乎就"悄悄"的在美国正式环境上部署了一套3个节点的es集群,完成后告诉大领导,大领导回复 "3台实例比较贵,日志只是偶尔看.",大领导想实现一种如果哪天日志量比较大的话我们就扩容,如果日志量小的我们就缩容 但是要保证日志尽可能不能丢失,因为我们使用的亚马逊的AWS费用比较昂贵.
(3) 如何实现动态扩容和缩容呢?
首先要明白elasticsearch集群的原理?
logstash-output-elasticsearch hosts 类型为 数组 默认是本地的['127.0.0.1'] 假如你搭建了三个节点的elasticsearch集群,并指定master和node节点,这个时候我们只需要在 output-elasticsearch插件做以下更改就可以了 hosts => ["cluster-node1", "cluster-node2", "cluster-node3"], 之后kibana连接任何一台elasticsearch就可以完整的查看所有数据.
(3.1) 基于以上原则 我们做了改变,也就是上面的扩谱图.
1. 每台要搜集日志的机器上都运行一个logstash-shipping服务 并指定input插件为日志文件或日志文件目录 而output插件就是消息队列redis、kafka、mq等 2. 集群的任何一个节点上都运行logstash-indexing、redis、elasticsearch、kibana、haproxy服务. redis就是消息队列服务; logstash-indexing从消息队列中取数据并写入到elasticsearch; kibana从elasticserach查询数据; 这里有两个问题要特别说明: 1> elasticsearch如何自动建立集群的 # Pass an initial list of hosts to perform discovery when new node is started: discovery.zen.ping.unicast.hosts: ["127.0.0.1", "[::1]"] # Prevent the "split brain" by configuring the majority of nodes (total number of nodes / 2 + 1): discovery.zen.minimum_master_nodes: 2 因为以上参数的都是动态可变的,因此选择用consul-template来自动更改,然后reload服务。 关于consul-template的一些高级用法可以参考官方文档,挺详细的 也可以私下交流 2> haproxy是代理什么服务? haproxy是对redis服务的代理; 看以下几个参数 logstash-output-redis host array # 解决队列的单点故障,可以同时指定多个redis实例. logstash-input-redis host string # 只能指定一个redis实例. 如果output-redis指定的是多个redis实例,不能解决多个redis的请求、压力负载是均衡的, 如果这里指定haproxy的代理redis实例的地址,用haproxy的负载均衡策略就可以解决 redis负载不均衡的问题?
扩展总结:
核心在于集群的每个节点上都要启动logstash-indexing、redis、elasticsearch、kibana、haproxy以上四个服务,elasticsearch和haproxy代理redis等这些动态的都是通过service discovery(consul)以及consul-template刷新完成的
单节点elk+redis瓶颈及解决办法?
(1) Redis队列堵了?
(2) 如何解决Redis队列堵了问题?
(3) 如何动态监控redis队列?
(4) 什么情况下要扩展到Es集群?
(1) logstash-output-redis data_type => list logstash的output插件到Redis,通常情况下我们指定的数据类型为list; 前些天遇到这样一个场景,在某一时间段持续半小时左右日志量并发1w左右,这个时候Redis堵了, 可能是因为达到了redis使用内存的最大上限导致的; 最终导致了Redis服务down掉啦!启动redis服务多次仍然失败,redis的日志文件中提示端口已存在, 使用"ps -ef |grep redis"发现进程不在,最终使用了"netstat -app | grep 6379"找到了 原因可能是因为有大量已建立的链接并没有中断导致你启动redis失败. (2) logstash总共有三个插件,分别是input、filter(暂时不聊这个)、output 在logstash-shipping端如果logstash-output-redis写的很快,那么如果不想让redis堵,那只能在 logstash-indexing端的logstash-input-redis读快,这个时候写和读才能达到均衡;调整以下参数 output => elasticsearch 批量参数调整 flush_size 批量写入ES数量 idle_flush_time 批量写入ES频率 (3) 要注意监控redis队列长度,如果长时间堆集说明elasticsearch出问题了 每2S检查一下redis中数据列表长度,100次 redis-cli -r 100 -i 2 llen logstash:redis (4) 观察过很长时间Es对cpu的影响比较大,内存往往都挺正常的; 硬件配置4核cpu、8G内存; 如果你登录kibana去查看日志,然后在登录到对应es的服务器上用top看服务器的性能,如果cpu 在300%左右或更高并且kibana界面一直处于Searching状态,那么建议你换Es集群吧! 观察io也正常、内存也正常、就是cpu偶尔会很高.
关于Es的性能优化 我也测试过几次,下次再聊Es集群!