The Future of Monitoring
可擴展的Zabbix – 9400NVPS經驗分享
對於我們這些大規模使用Zabbix的用戶來說,最關心的問題之一就是:Zabbix能承受多大規模的數據寫入量?我最近的一些工作正好以此為中心,遠期來看,我可能會有一個超大量級的環境(大約32000+台設備)需要通過Zabbix實現完全監控。在Zabbix論壇里有一個模塊討論大型環境的監控,但是不走運的是,我並沒有找到一個完善的系列解決方案來實現大型環境的監控。
在此,我想為大家展示一下我是如何配置來處理大規模環境監控的。下圖是我當前環境的一些統計數據:

需要指出的一點是“ Required server performance”參數這一欄的實際意思,並不代表有多少數據實際上進入了Zabbix。它只是計算Zabbix通過查找每個項監控采集時間間隔估算每秒值個數。由於Zabbix采集器監控項沒有指定采集間隔,他們不被包含在計算中。在我自有的環境中,我很大程度上地使用了Zabbix采集器監控項,所以這就是我的環境實際上處理了多少NVPS(每秒新值)。
正如報表所示,在2天時間內,Zabbix Sever平均處理大約9.26k的NVPS。實際上我有短暫的峰值一直到大約15k,sever照樣處理的很好。總之非常好!
架構
首要問題之一是考慮所使用的架構類型。Zabbix server需要高可用嗎?一兩個小時的宕機時間有關系嗎?如果Zabbix數據庫down了,會導致什么后果呢?Zabbix的數據庫需要怎樣的磁盤類型和raid模式呢?Zabbix server和Proxies之間是哪種網絡類型呢?是否有大量的潛在因素。數據怎么進入Zabbix-數據是被動采集或者主動采集。
我將詳細介紹我如何解決這些問題。當我開始學習搭建我的Zabbix環境時,我並沒有關於網絡和延遲的認識。但是正如你現在所見,忽視這些問題將導致一些很難弄明白的問題。下面是我使用的架構圖解:
硬件
甄別合適的硬件資源並不簡單。在該小節的底部,我列出了我使用的硬件信息,僅供參考。Zabbix數據庫需要大量的I/O處理能力,所以我給我的數據庫選擇了高性能的SAN空間。理論上,數據庫磁盤處理越快,Zabbix可以處理越多的數據。並且cpu和內存對於一個mysql數據庫而言是很重要的。較大的內存允許Zabbix在內存中迅速的訪問數據從而提升性能。起初我想要給我的數據庫server分配64G的內存,但是到目前為止,32G的內存看上去工作的也不錯。
在這個性能相當強的Zabbix server背后,我認為有必要評估成千上萬的觸發器。這將占用一些cpu性能,所以充足的cpu資源有益無害。由於我的Zabbix server上沒有跑很多進程(自監控消耗很小),我也可以把內存降低到12G。
Zabbix proxies不需要大量硬件資源,所以我選擇了VM虛擬機。我主要使用主動類型監控項,我的Proxies大多情況作為收集點使用,其自身不用去收集大量的數據。
Zabbix server | Zabbix database |
---|---|
HP ProLiant BL460c Gen8 12x Intel Xeon E5-2630 16GB memory 128GB disk CentOS 6.2 x64 Zabbix 2.0.6 |
HP ProLiant BL460c Gen8 12x Intel Xeon E5-2630 32GB memory 2TB SAN-backed storage (4Gbps FC) CentOS 6.2 x64 MySQL 5.6.12 |
Zabbix proxies | SAN |
---|---|
VMware Virtual Machine 4x vCPU 8GB memory 50GB disk CentOS 6.2 x64 Zabbix 2.0.6 MySQL 5.5.18 |
Hitachi Unified Storage VM 2x 2TB LUN Tiered storage (with 2TB SSD) |
服務器高可用
現在讓我們來考慮下Zabbix server的架構。通常在一個大型的環境中,我們無法忍受監控服務器長時間的宕機(超過幾分鍾)。由於Zabbix server進程的運行方式,不能同時運行多個Zabbix server實例。圍繞着該問題,我使用Pacemaker和CMAN組件實現Linux高可用。作為安裝時的基礎,你需要了解RedHat 6.4的快速指南(←點擊查看詳情),不巧的是,我上次使用之后,這個指南就已經更改了,但是我可以將我最后一次配置的客戶端結果分享給你們。以下是配置高可用需要的四個服務:
- 共享的IP地址
- 在發生故障時,IP將與之前的server失去關聯同時在新活動的server使用
- 這個IP地址總是與活動的服務器關聯。有以下三點好處。
- 更便於發現哪台server是活動的
- 來自活動的Zabbix server的所有連接都來自相同的IP(通過在zabbix_server.conf中設置“SourceIP”配置)
- 可以將所有的proxies/agents配置為簡單地就能共享IP地址以訪問活動的Zabbix server
- Zabbix server 進程
- 在發生故障時,在之前的sever上的zabbix_server進程將會停止,並在新的活動的server上啟動
- 一個符號鏈接的crons
- 這指向一個目錄,該目錄包含的只在活動的server上運行的crons。每個server上的crontab應該通過此符號鏈接訪問所有的crons。
- 在發生故障時。符號鏈接將先在之前的server上刪除,並且在新的活動的server上創建。
- Cron進程(crond)
- 在發生故障時,crond守護程序將在之前的server上停止,並在新的活動的server上啟動。
可以在此處下載(←點擊下載)所有這些樣本配置文件和LSB兼容的Zabbix server init腳本。在樣本配置文件中需要修改一些參數(包含在“<>”標簽內)。此外,編寫init腳本的想法是所有的Zabbix文件都放在一個公共的區域(對我來說,所有的文件都在“/usr/local/zabbix”)。如果不是這種情況,你需要自行修改一下init腳本。
數據庫高可用
如果數據庫很容易就出現故障,那么高可用的Zabbix sever進程就沒有多大用處。高可用MySQL有很多種方法——這里只介紹我采用的方法。
我也使用Pacemaker和CMAN的Linux高可用方式實現數據庫高可用。我發現它有一些非常好的功能來管理MySQL復制。我使用(請參閱本文的“待解決的問題”部分)復制來維護我的主動和被動MySQL server之間的同步。有關於執行Linux高可用基本安裝的文檔鏈接,請參考上文關於Zabbix server高可用的部分。這是我關於我的數據庫高可用的一些想法:
- 共享的IP地址
- 在發生故障時,IP將與之前的sever失去關聯同時在新活動的server使用
- 這個IP地址總是與活動的服務器關聯。有以下兩點好處。
- 更便於發現哪台server是活動的
- 在故障發生時,Zabbix服務器不需要做出改變去表明新活動的數據庫。
- 備份IP地址
- 當Zabbix數據庫只可以通過只讀方式訪問,必須使用這個IP。這樣點對點的類型事件使用備份的IP地址(如果他是up的)代替了主up
- 這個IP地址並不是在主server或者備server上。它完全是由以下信息決定的:
- 如果備份server在線並且其MySQL比起主服務器沒有超過60s的延時,IP將在備份server上。
- 如果備份server離線或者比起主服務器有超過60s的延時,IP將在主server上。
- MySQL進程(mysqld)
- 故障發生時,最新活動的MySQL實例成為主MySQL,一旦最新的備份server變成可用了,MySQL將變成新主機的備份。
可以在此處下載(←點擊下載)所有這些樣本配置文件和LSB兼容的Zabbix server init腳本。在樣本配置文件中需要修改一些參數(包含在“<>”標簽內)。此外,為了使其正常工作,你可能需要下載不同的MySQL 資源agent以與pacemaker一起使用。在Percona github存儲庫(←點擊查看詳情)中使用pacemaker設置MySQL主/從集群的一些很不錯的文檔中可以找到它的鏈接。如果文檔的鏈接由於一些原因失效了,可以在此處(←點擊下載)獲取副本。
Zabbix Proxies
對於之前沒有接觸過Proxy的讀者,我強烈建議您去手冊里學習了解,Proxy真的很棒!Zabbix server在眾多的機器中分出來一部分來給Proxies監控。Proxies之后將所有收集到的數據發送給Zabbix server。關於Zabbix proxies,你還應該知道的有很多:
- 搭建好Proxies后,他們可以處理海量的錄入數據。在測試期間,我有一個服務器(proxy A)處理了大約1500-1750 NVPS,沒有發現異常。它是一個用SQLite3的數據庫,2vCPU和4GB內存。“proxy A”和Zabbix server在同一數據中心因而不存在潛在的延遲。“proxy A”忙於處理這些指標信息,但是proxies和被監控對象之間有很少量的網絡問題,Zabbix server可以處理大量的數據,注意“proxy A”是一個活動的proxy,它所監控的大部分監控項來自於活動的Zabbix agent監控項。
- 還記住早些時候我怎么告訴你們proxies和Zabbix server之間的網絡延遲的嗎?我保證沒有開玩笑。我發現Zabbix proxy處理的數據量與發送到Zabbix server的數據量近乎相等,這是一個網絡延遲的函數。我有一個監控項跟蹤proxy發送到Zabbix server的值。如果忽略網絡延遲,可能會發生以下情況:

顯而易見地,一個proxy需要傳遞給持續運行的server無數的值。“proxy b”采集大約500nvps的數據。還記得之前和Zabbix server處在同一數據中心的Proxy,它可以處理3-3.5倍的數據量嗎?Proxy到Server之間不大可能有嚴重的延遲的。“proxy B”在新加坡,而Zabbix server在南美。兩個server之間的網絡延遲大約在230ms。考慮到proxy發送數據到server的處理方式,網絡延遲會有很大的影響。在這種情況下,“proxy b”每2-3秒鍾能僅僅發送1000收集的值到Zabbix server上。下面我將要告訴你的是在嘗試發送數據到server上所發生的事情:
- proxy與server之間建立連接
- proxy最多發送1000個值
- proxy關閉連接
所有這些步驟都根據需要執行多次.由於存在兩個主要問題,因此延遲時間很長:
- 初始連接慢,在這個情況下,建立初始連接發費至少0.25s,天啊!
- 在發送1000個值后連接會關閉,因此TCP連接不會存在這么長時間的連接去加速鏈路上可用的帶寬。
這個真的是很慢了,對比之下,Proxy A在相同的虛擬硬件下,2-3秒內發送40000個值,表現更佳!
數據庫性能
由於Zabbix使用數據庫存儲所有數據,因此數據庫性能對於可擴展的解決辦法絕對至關重要。顯然由於大量數據寫入到數據庫server里,I/O性能是最容易受到影響的瓶頸之一。我非常幸運地有固態硬盤的SAN,但僅僅因為我有快速的I/O並不意味着我的環境不受數據庫問題的影響!例子如下:
當我開始在我的大型環境中研究Zabbix的用處的時候,我跑的是MYSQL5.5.18,數據庫跑了一段時間后,一旦我運行了大約700-750的NVPS時,我server上的MySQL進程就將占用100%的CPU,數據庫性能停滯不前。我嘗試在數據庫中配置設置,啟用large pages(←點擊查看詳情),分區表,調整不同的Zabbix設置。比我聰明的多的妻子建議將MySQL升級到5.6看看會發生什么。令人驚訝的是,升級之后的數據庫性能太完美了。我從來沒有使用5.5.18工作過,但5.6.12在我目前的環境中運行良好。作為參考,這是my.cnf 文件(←點擊查看詳情)的副本。
下圖顯示了我的環境中每秒運行的查詢數:

注意,“Com_update”每秒的查詢數最多。原因在於Zabbix檢索的每個值都會導致數據庫中“items”表的更新。另外要指出的是數據庫寫入占比很大。這意味着MySQL的查詢緩存對於性能提升沒有幫助。實際上,由於修改的數據在查詢時標記為無效,因此可能會導致性能的下降。
另一個在大型環境中可能摧毀數據庫性能的是Zabbix Housekeeper。強烈建議在大型環境中關閉Zabbix Housekeeper。可以將“Zabbix_server.conf”(←點擊查看詳情)中的“DisableHousekeeping”設置為“l”來實現。當然,如果沒有Zabbix Housekeeper,則不會刪除任何歷史/事件/動作數據。解決此限制的方法之一是在數據庫上啟用分區。對於我來說,這就是我的MySQL。MySQL 5.6.12的一個限制是分區不能用於具有外鍵的表。不幸的是,外鍵在Zabbix2.0.x使用的很多,但歷史數據表中沒有。對歷史數據表進行分區有2個好處:
- 在其自己的分區中自包含表中特定日/周/月的任何歷史數據。這樣以后可以輕松刪除舊數據,幾乎不會對數據庫server產生任何影響,並且無論你的分區時間范圍是多少,都可以查看到該環境下提取了多少數據量。
- 使用MySQL InnoDB表,刪除數據不會釋放磁盤空間。 它只是在InnoDB命名空間中創建區域,以后可以保存新數據。 縮小InnoDB命名空間是不可能的,但是可以隨意刪除分區。 刪除分區將會釋放磁盤空間。
學習怎么分區可能很煩,但是在Zabbixzone.com(←點擊查看詳情)上有一篇很好的關於分區表的文章。可以通過修改歷史記錄和趨勢表的指令來應用到2.0x。其他用戶對該文章的很多評論都很有用,並且修改了帖子中出現的原始程序的版本。此處(←點擊查看詳情)提供了用於添加/刪除分區的存儲過程的副本。這些過程創建每日的趨勢/歷史記錄分區,並且是Zabbixzone.com上的文章中的過程修改后的版本。請注意在你使用存儲過程之前,必須先在歷史數據表中創建分區。此外,我的程序版本永遠不會刪除“trend”或者“trend_unit”分區,我的趨勢數據理論上永遠存在。
輪詢或者
Zabbix提供兩種不同的獲取數據的方法:主動或被動(←點擊查看詳情)。如果你不清楚區別是什么,請認為就像Zabbix server/proxies從Zabbix agents中獲取被動類型監控項的數據,Zabbixagents中Zabbix agent(active)類型監控項的數據推送給Zabbix server/proxies。根據定義,Zabbix采集器(←點擊查看詳情)類型的監控項是主動式的,因為他們需要將數據發送到Zabbix server/proxies(使用“Zabbix_sender”或其他一些方法)。
我之所以提到這一點,是因為所使用的監控類型會對Zabbix成功獲取的數據量產生巨大的影響。被動檢測需要Zabbix server/proxies上的一個輪詢進程向代理發出請求,然后等待響應。根據你的網絡和正在檢測的server的性能,輪詢器可能需要幾秒鍾才能獲得響應。即便只訪問一千台servers,也可以將輪詢轉換為一個非常緩慢的過程。
現在讓我們來談談主動監控。通過主動監控,Zabbix server/proxies只需等待來自Zabbix agent的連接。每個單獨的代理將定期連接到Zabbix server/proxies來獲取需要檢測的項目列表。之后proxies將根據其監控項采集間隔發送數據。只有當agent實際上有數據需要發送的時候,和server/proxies之間的連接才會建立起來。這種監測方法可以防止ZABBIX server/proxies在獲取數據之前需要等待檢測完成。這樣可以提高獲取數據的速度。在我的環境中我是這樣使用的。
server/proxy監測
我直截了當地說–如果你認為在不監測內部服務器進程的情況下可以適當地進行Zabbix安裝,你就錯了。你必須監測這些進程以了解任何瓶頸的位置,縮減規模以節省資源。有關這些監控項的文檔在這里(←點擊查看詳情)可以找到。關於這些監控項的好blogpost也在Zabbix的博客(←點擊查看詳情)上。Zabbix 2.0.x附帶的默認Zabbix server模板已經配置了這些項。確保將這些項添加到Zabbix server上!
可以表明數據庫問題的統計信息之一是歷史寫入緩存(server配置文件中的“HistoryCacheSize)變量。此條目的值應始終接近100%,如果此緩存持續變滿,這意味着Zabbix無法足夠快地將傳入數據寫入數據庫。
不幸的是,proxies不支持這些監控項,這使得識別問題的位置變得有點困難。proxies的另一個問題是Zabbix中沒有內置鍵值追蹤proxy還有多少數據沒有同步到server。值得慶幸的是,有一種方法可以監控代理的落后程度。很有必要對數據庫執行一條查詢語句:
SELECT ((SELECT MAX(proxy_history.id) FROM proxy_history)-nextid) FROM ids WHERE field_name='history_lastid'
查詢將返回proxy仍需要發送到Zabbix server的值的數量。如果您碰巧使用SQLite3作為proxy的數據庫,只需將此命令作為UserParameter添加到proxy上的agent配置文件中:
UserParameter=zabbix.proxy.items.sync.remaining,/usr/bin/sqlite3 /path/to/the/sqlite/database "SELECT ((SELECT MAX(proxy_history.id) FROM proxy_history)-nextid) FROM ids WHERE field_name='history_lastid'" 2>&1
設置一個觸發器,當你的proxy開始備份時進行檢測,並且你可以捕獲慢速proxies。這里是一個例子:
{Hostname:zabbix.proxy.items.sync.remaining.min(10m)}>100000
整體性能結果
以下是我的server的一些性能圖表。7月16日你會注意到一些峰值/波動,我不確定那個事件里發生了什么。我不得不在我的proxies上重新初始化數據庫來解決事件(我當時使用的sqlite3)。自從將數據庫換成MySQL后,我的proxies沒有再發現這個問題。圖中的其它峰值來自負載測試。通過查看這些圖表,很容易看出我使用的硬件在未來一段時間后可能會過度。
以下是我的數據庫server的性能圖表。你將注意到每1到2天在網絡流量上的大幅增長。那些是我的數據庫備份運行時發生的(mysqldump)。由於我上面提到的問題,你還會在16日的每秒查詢圖表中看到大幅下降。
配置管理
我當前的環境總共有2台Zabbix server,2台MySQL servers,16台Zabbix proxies和數千個Zabbix agents。有這么多的server需要管理,手動更改配置文件並不是一個真正的選擇。我公司目前使用Puppet來部署應用程序,但目前尚未設置配置管理。因此我必須以自己的方法來管理開發,分期和生產環境中的配置文件。
值得慶幸的是,我可以訪問git來存儲所有配置文件。我的所有servers都可以訪問該git,因此我利用它來存儲任何腳本,配置文件或者我希望在servers之間同步的任何其它內容。我寫了一個腳本可以通過所有agents上可用的自定義參數調用。當我調用自定義腳本時,它會自動轉到git,拉取所有最新文件,修改配置文件后重啟agent/proxy/server。通過這種方式,對我的整個環境進行更改就像使用“Zabbix_get”命令一樣簡單。
除了管理配置文件外,在Zabbix中手動創建數千個主機不可行。我公司有一個CMDB來存儲有關我們所有服務器及其上面運行的服務器信息。我有另一個腳本每小時從CMDB中拉取信息,然后再與Zabbix中的內容進行比較。然后它將根據需要增加/刪除/啟動/禁用主機,創建主機組,移動主機到主機組,給主機分配模板。通過這種方式,添加我需要關注的主機的唯一部分就在於是否需要實現新的監控項/觸發器。
然而,由於們與我們的系統緊密集成,我不能在這里發布腳本。
需要解決的問題
即使我們已經完成了所有工作,仍然有一個重要問題需要解決。
一旦我達到了8000-9000 NVPS,我的數據庫復制將不能與主機同步。實際上,這使得高可用在我的數據中不存在。關於高可用的這一點,我有一些想法,但沒有實際測試/實現他們中的任何一個,以下是我的一些想法。
- 將Linux高可用與DRBD一起用於我的數據庫分區
- 在SAN上設置LUN復制,以將所有更改復制到另一個LUN上
- 采用Percona XtraDB集群。 5.6版本還沒有發布,所以我不得不等待嘗試這個選項(因為我的MySQL 5.5存在性能問題)
參考文獻
以下是在這篇文章中全部引用的下載/URL列表
- Zip file with all downloads from the article (also includes my Zabbix configuration files)
- Large environment forum thread
- Zabbix server configuration documentation
- Zabbix proxy distributed monitoring documentation
- Zabbix active/passive item documentation
- Zabbix internal item documentation
- Zabbix blogpost on internal items
- Pacemaker/CMAN quickstart guide
- MySQL Pacemaker configuration guide
- MySQL Large Pages
- Partitioning the Zabbix database