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隊列堵了? logstash-output-redis data_type => list logstash的output插件到Redis,通常情況下我們指定的數據類型爲list; 如果你的App日誌產生量在某一段時間內特別大,這個時候Redis有可能出現隊列的長度幾百萬,這個 時候你應該從哪裏入手以及解決呢?從以下兩點入手: 1> 日誌量不大,日誌只寫到Redis,但是不從Redis取,導致了只寫不出. 2> 日誌量很大,日誌量寫的很快,但是從Redis取的很慢,導致了Redis每秒鐘都在不停的增加. (2) 如何解決Redis隊列堵了問題? 增加線程數、增加往Es寫入的頻率和一次從Redis消費的數目 flush_size 批量寫入ES數量 idle_flush_time 批量寫入ES頻率 (3) 如何動態監控redis隊列? 要注意監控redis隊列長度,如果長時間堆集說明elk出問題了,要儘快解決否則Redis服務有可能會掛; 每2S檢查一下redis中數據列表長度,100次 # redis-cli -r 100 -i 1 llen logstash:redis (4) 什麼情況下要擴展到Es集羣? 觀察過很長時間Es對cpu的影響比較大,內存往往都挺正常的; 硬件配置4核cpu、8G內存; 如果你登錄kibana去查看日誌,然後在登錄到對應es的服務器上用top看服務器的性能,如果cpu 在300%左右或更高並且kibana界面一直處於Searching狀態,那麼建議你換Es集羣吧! 觀察io也正常、內存也正常、就是cpu偶爾會很高.