由於分布式系統的日志集中采集的需求非常強烈,我們組通過調研和實踐搭建了一套基於Docker的日志收集系統Amethyst。
我們首先在測試環境搭建了一套基於Docker swarm集群的ELK分布式環境。
測試雲
docker swarm 配置:
[elastic@host-10-191-51-44 ~]$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION qjdc5dhfauxz9b6bxlj12k0b4 * host-10-191-51-44 Ready Active Reachable 18.09.4 sn0uy2i8rwfpk1z8jjwkmb3un host-10-191-51-45 Ready Active Reachable 18.09.4 rjsxhmbrstpxadw9vc4rzbc4e host-10-191-51-46 Ready Active Leader 18.09.4 xl24brlx3b6r1r9bm22nl3s95 host-10-191-51-47 Ready Active 18.09.4
四台linux主機配置各為:
Kernel Version: 3.10.0-327.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 8 Total Memory: 15.51GiB
Docker swarm service包括
NAME SERVICES ORCHESTRATOR es 4 Swarm kafka 3 Swarm kibana 1 Swarm log 1 Swarm zk 3 Swarm
五種service關系如下圖所示:
Filebeat主機和Amethyst處於同一個測試網網段,ip地址直接可以連接,狀態一切正常,kibana里可以看見測試數據,所以我們測試兩個月后便准備投入生產,從此記錄從評審開始遇到的主要問題。
評審階段:
關鍵詞:網絡如何限流
解決辦法:kafka consumer配額,Filebeat的壓力感知功能可以在kafka限流時降低自身發送日志的速率。
參考 https://www.cnblogs.com/huxi2b/p/8609453.html
也考慮過使用容器tc限流,但是發現tc只能對輸出流量做限制,故放棄。
第一次發布:
關鍵詞:1) filebeat 跨區跨防火牆連接kafka IP地址不通.
2) docker程序所屬用戶為manag
問題1:由於kafka的三個IP地址做了NAT映射,filebeat 中配置連接IP為kafka映射后的地址,連接kafka時,kafka會返回給filebeat注冊到zookeeper的對外地址,也就是KAFKA_ADVERTISED_LISTENERS;這里出現一個問題:1)當我們把kafka集群中的KAFKA_ADVERTISED_LISTENERS配置為映射前地址,kafka集群狀態正常但是,filebeat連接時會收到kafka返回的映射前地址,所以filebeat無法連接,導致i/o wait。2)當我們把kafka集群中的KAFKA_ADVERTISED_LISTENERS配置為映射后地址,會導致KAFKA集群之間無法通訊,從而集群狀態異常。
解決辦法:
網絡通訊不使用IP地址的方式,通過主機名和/etc/hosts映射的方式通訊,當把KAFKA_ADVERTISED_LISTENERS配置為主機名后,kafka返回給filebeat的地址就是hostname:port,這里只要在Filebeat主機中在/etc/hosts 添加映射后的IP和hostname關系便可以讓filebeat獲得hostname后依然可以找到映射地址。
問題2:這是因為我們通過Docker啟動進程時,默認會指定進程的uid為1000,而生產環境上uid=1000的用戶正是manage用戶,故docker啟動的進程顯示為manage所屬。
解決辦法:可以通過在docker swarm stack配置文件中指定服務uid來限定docker進程的名稱。
第二次發布:
關鍵詞:1) kafka集群狀態異常導致
問題1: 當把kafka配置的KAFKA_ADVERTISED_LISTENERS修改為hostname后,發現各主機用hostname之間無法ping通,而在測試網中嘗試均可以通過hostname ping通(后面了解應該是測試雲的openstack內置的dns解析可以在openstack虛擬機外部解析hostname),這里想當然的修改elk集群中的/etc/hosts 各IP和主機映射;這時啟動kafka集群狀態還是異常。在嘗試在物理機上部署kafka后,集群狀態就正常了;正准備讓logstash從kafka里消費數據時發現logstash也無法讀取kafka配置文件中的hostname,這里想到其實最初在kafka集群中添加/etc/hosts的操作應該是在各Docker內部完成!此時配置uid=“0”,啟動kafka_stack和logstash_stack,在容器內部添加/etc/hosts條目。
解決辦法:在kafka和logstash內部添加/etc/hosts條目。
研究方向:
kafka通訊機制
docker的uid機制