(原文地址:https://blog.goquxiao.com/posts/2015/02/17/ji-yu-zabbix-dockerkai-fa-de-jian-kong-xi-tong/)php
團隊所開發的持續監測網站/APP的產品,須要有一項監控功能,具體來講就是,對URL/域名進行週期性(小於1分鐘)監測,而且能對異常事件進行實時告警。在最近這幾個月,我一直將大部分時間和精力花在了設計開發這套系統上面,一共經歷了兩個大版本。下文就對這套監控系統進行介紹,分享給你們。前端
本身以前沒有這類系統的開發設計經驗,因而問了下週圍同事。和同事討論的結果是:既然如今人手不夠(就我一我的),我以前也沒開發過這類系統,時間又比較緊迫(領導給的排期是「越快越好」……),那麼找一個已有的開源監控系統進行二次開發,應該是一個不錯的選擇。那麼,選擇哪一種開源監控系統呢?根據同事以往的經驗,能夠考慮zabbix,本身也調研過一段時間zabbix,它的優勢有以下幾條:docker
架構簡單、清晰數據庫
文檔豐富,代碼註釋十分詳細express
agent/server部署方便編程
包含整套監控流程:包括採集、觸發、告警後端
agent支持用戶自定義監控項服務器
觸發器表達式豐富網絡
暴露了一套HTTP + JSON的接口架構
另外,除了以上這樣,還有一個比較重要的一個緣由:團隊中的同事以前也調研過zabbix。在人手不足、時間又緊的狀況下,這一個因素的權重就顯得相對較高。因此,最終選擇了在zabbix基礎上進行二次開發。
至於使用docker,是考慮到監控的對象,會由於用戶的增加、以及用戶的操做,有動態的變化。做爲設計者,天然但願有一種機制,可以可編程地、動態地控制zabbix agent的數量。咱們既不讓某一個agent(具體應該是agent的端口)有過多的監控項,致使監控項沒法在一個週期內完成數據採集;又不想有生成過多的agent,形成系統資源的浪費。目前勢頭正勁的docker,怎能不進入個人視野?社區活躍、文檔完善、相對其餘虛擬化技術又很輕,都成爲了我選擇docker的緣由。
這個監控系統的設計目標是:但願可以提供秒級時間粒度的監控服務,實時監控用戶網頁的可用性指標,作到快速反饋。
具體的需求爲:當用戶在咱們的產品中建立持續監測任務,對於用戶輸入的URL進行兩種類型的監控,即HTTP返回碼以及PING返回時間。當某一類監控的採樣數據異常時——例如HTTP返回500、PING超時——就會在用戶界面上返回告警事件,用以提醒用戶;採樣數據正常時,再返回告警事件的狀態。
第一個版本中,系統的設計特色爲:
一臺物理服務器對應一個zabbix的host
監控項使用被動採集方式
每一個zabbix agent處於一個docker container內,每生成一個container,就在物理機上面開放一個端口,並生成一個對應的zabbix agent interface
對於上游的每一個監控任務,會在每一個IDC節點各生成了一組zabbix採集監控任務,具體對應關係爲:(groupid, hostid, interfaceid, itemid, triggerid)
告警事件的生成,採用了輪詢trigger狀態的方式,當上遊監控任務對應的處於PROBLEM狀態的節點數大於總節點數時,產生告警事件;當全部節點均爲OK狀態時,產生告警恢復事件
第一個版本的架構,以下圖所示:
Monitor Web
模塊,做爲後端的接口供前端來調用,主要提供監測任務添加、修改、刪除,告警事件列表返回、告警事件刪除等功能。Monitor Syncer
模塊,用於按期檢查每一個監測任務對應的zabbix trigger的狀態,根據trigger的狀態,來生成告警事件以及告警恢復事件。Zabbix Server
和Zabbix Agent
就構成了監控系統的核心服務。其中,一臺物理機器中,包含了多個Docker container,每一個container中運行這一個zabbix agent。
以建立監控任務爲例,當前端發出建立監測任務時,Monitor Web
模塊接收到該請求,進行以下操做:
在每個IDC(對於zabbix中的group)中,各建立一個container,在container中啓動zabbix agent,記錄其對外開放的端口
根據獲得的端口,在zabbix host中,建立zabbix interface(和agent的端口一一對應)
根據獲得的interface,建立HTTP和PING兩種類型的zabbix item和trigger,分別監控URL的HTTP返回碼,以及host的PING返回值。zabbix server開始進行數據採集和監控
在業務數據庫表中添加該條監測任務記錄
Monitor Syncer
每隔一個週期(30s),掃描一遍目前全部監測任務,再從zabbix數據庫中查找到對應trigger的狀態。若是trigger狀態爲PROBLEM的超過了半數,那麼該監控任務就處於了告警狀態,最後再根據該任務目前是否處於告警狀態,來決定是否須要添加告警事件;那麼對應的,若是trigger狀態均爲OK,而且目前任務處於告警狀態,那麼則須要爲告警事件添加對應的恢復狀態。
這樣,就完成了添加任務 -> 告警 -> 恢復的整個監控系統的典型流程。
對第一個版本進行了性能測試,獲得瞭如下性能指標:
(3臺服務器,1臺部署Zabbix Server,2臺部署Docker + Zabbix Agent。服務器配置:Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz X 24,128G 內存,千兆網卡)
樣本採集項:1111 item
樣本採集頻率:60s
最大入口流量: 68 kbps
最大出口流量: 270 kbps
每秒下發採集請求: ~19 qps
由於開發時間所限,以及對於新技術的調研不夠深刻,第一個版本有很多不足,主要體現以下:
zabbix agent採用的是被動模式,每次採集數據zabbix server都須要向zabbix agent查詢監控項,網絡出口數據量較大
因爲數據採集都是進行須要發起網絡操做,而每一個採集數據的頻率又較高,所以會出現數據採集不完整、沒法連續採集的現象
採用輪詢方式探測故障事件,效率較低,實時性不高,同時也有單點問題
任務請求沒有進行持久化,若是由於模塊問題而丟失或操做失敗,沒法回滾
針對初版本發現的問題,在設計上作了一些升級,具體升級點和設計上面的特色以下:
再也不採用物理機器和Zabbix Host一一對應的關係,而是採用Docker container和Zabbix Host一一對應(這裏的Zabbix Host就是一個虛擬Host的概念)
採用etcd進行分佈式狀態管理,動態自主註冊Zabbix Host
採集項使用Agent自主上傳方式
Zabbix Host和監控項之間的比例可配置,即配置每一個Zabbix Host上最多進行的監控項數量
監控項自動轉移,若是一個Zabbix Host出現異常,系統能夠將上面的監控項遷移至其餘健康的Zabbix Host
藉助Zabbix Action,將異常狀態的改變實時傳遞給系統,而不是由系統進行輪詢
任何請求將進行持久化,方便查看以及請求的回滾
第二版的架構變成了這樣:
上圖中,Monitor Web
一方面接收前端的請求,它收到請求作的惟一的事情就是將請求數據寫入數據庫進行持久化;另外一方面,它還會接收來自Zabbix Server
的事件請求,這裏的事件表示trigger狀態的改變。
Monitor Admin
有兩個職責:1)按期檢測未完成的請求(添加/刪除監控任務),拿到請求以後經過Zabbix API在對應的Zabbix Agent中添加/刪除監控項(item + trigger);2)偵聽ETCD中的key狀態變化,進行相應地Zabbix Host建立/刪除,以及監控項的遷移。
每當啓動一個Docker container,就會將物理機的IDC、ETCD Server地址、Zabbix Server地址等參數傳遞至container,而後在內部啓動zabbix_agentd
,而且按期檢查zabbix_agentd
是否存活,若是存活的話,則生成一個惟一的key,向ETCD發起key建立/更新請求;若是不存活,則key會天然的過時。這樣,Monitor Admin
就經過ETCD得知了各個zabbix_agentd
的健康情況,而且在內存中存儲一份agent的拓撲結構。
啓動了多個container,在Zabbix Server中就對應了多個Zabbix Host,以下圖所示:
除了總體架構的升級,還在了許多方面(主要是Zabbix)進行了調優,好比:
儘可能增長agent的超時時間
由於咱們的監控採集項,都是須要對URL或者域名進行網絡操做,這些操做每每都會比較耗時,並且這是正常的現象。所以,咱們須要增長在Zabbix agent的採集超時,避免正常的網絡操做還沒完成,就被判斷爲超時,影響Server的數據獲取。
### Option: Timeout # Spend no more than Timeout seconds on processing # # Mandatory: no # Range: 1-30 # Default: # Timeout=3 Timeout=30
不要在採集腳本中加上超時
既然Zabbix agent中已經配置了採集超時時間,就不須要在採集腳本中添加超時了。一方面增長了維護成本,另外一方面若是配置不當,還會形成Zabbix agent中的超時配置失效。(以前在腳本中使用了timeout
命令,因爲設置不正確,致使採集項老是不連續,調試了很久才查明緣由。)
增長Zabbix Server的Poller實例
默認狀況,用於接收Zabbix agent採集數據的Poller實例只有5個。對於週期在1分鐘內、數量會達到千級別的採集項來講,Poller實例顯然是不夠的,須要增大實例數,充分利用好服務器資源。例如:
### Option: StartPollers # Number of pre-forked instances of pollers. # # Mandatory: no # Range: 0-1000 # Default: # StartPollers=5 StartPollers=100
利用好Zabbix trigger expression
若是隻把trigger expression理解爲「判斷某個item value大於/小於某個閾值」,那就過低估Zabbix的trigger expression了,它其實能夠支持不少複雜的邏輯。好比,爲了防止網絡抖動,須要當最近的連續兩個採集項異常時,才改變trigger的狀態,表達式能夠寫成:(假設item_key<0
爲異常)
{host:item_key.last(#1)}<0&{host:item_key.last(#2)}<0
再舉個例子,一樣是爲了防止採集的服務不穩定,咱們能夠規定,當目前trigger的狀態爲PROBLEM,而且最近5分鐘的採集數據均正常的時候,才能夠將trigger狀態改成OK,表達式能夠這樣寫:
({TRIGGER.VALUE}=0&{host:item_key.last(#1)}<0&{host:item_key.last(#2)}<0) | ({TRIGGER.VALUE}=1&{host:item_key.min(5m)}<0)
具體能夠參考Trigger expression
測試環境:
3臺服務器,硬件參數與以前保持一致
Zabbix Server * 1
監控服務器 * 1
ETCD Server * 1
Docker container * 500 (在1臺物理機中)
性能指標:
樣本採集項:7100
樣本採集頻率:60s
Zabbix Server每秒處理監控項: 130 個監控項 / 秒 (初版爲~19 qps)
平均入口流量:454.25 kbps
最大入口流量:916.12 kbps (初版爲68 kbps)
平均出口流量:366.65 kbps
最大出口流量:1.68 Mbps (初版爲270 kbps)
部分性能指標的監測圖以下:
Zabbix Server每秒處理監控項數目
Zabbix Server網卡入口流量
Zabbix Server網卡出口流量
能夠看出,跟初版相比,最大可採集的數據量是原來的近7倍,Zabbix Server的進出口流量有明顯的提高,監控項的處理吞吐率也和採集項數量有了一致的提升,是原來的6.8倍,而且沒有出現監控項在一個週期內沒法採集到的狀況(若是再增長監控項,則會不按期出現採樣不連續的狀況),性能提高仍是比較明顯的。
本文從架構上介紹了若是基於Zabbix以及Docker,構建一個監控系統。
(廣告時間,感興趣的朋友能夠登陸咱們的官網進行註冊,使用咱們的評測/監測/加速等服務,而且經過添加PC持續監測任務來對網站進行實時監控。)
固然,目前的版本仍然不夠完美,目前「抗住」了,而後須要考慮「優化」,年後預計會有較大改動,架構上以及技術上,本身已經在考量中。
(又是廣告時間,團隊急需後端小夥伴,能夠經過咱們的官網瞭解到咱們的產品,也過年了,年終獎也發了,感興趣的、有想法的朋友,歡迎將簡歷發送至hr@mmtrix.com
,謝謝!)
-- EOF --