一、智能運維監控報警平台的組成
隨着大數據時代的來臨,運維工作的難度越來越大,每個運維人員都要面臨不計其數的服務器和海量的數據,如何保證眾多服務器和業務系統穩定高效地運行並盡量減少死機時間,成為考核運維工作的重要指標,而要實現大規模的運維,必須要有一套行之有效的智能運維監控管理系統,本章就詳細介紹下如何構建一套完善的運維監控報警平台。
運維的核心工作可以分為運行監控和故障處理兩個方面,對業務系統進行精確、完善的監控,保證能夠在第一時間發現故障並迅速通知運維人員處理故障是運維監控系統要實現的基礎功能;一個功能完善的智能監控系統,不但可以自動處理一些簡單故障,減少運維工作量,還應該在應用可能出現故障時預先發出報警,預防故障的發生。因此,構建一個智能的運維監控平台,必須以運行監控和故障報警這兩個方面為重點,將所有業務系統中涉及的網絡資源、硬件資源、軟件資源、數據庫資源等納入統一的運維監控平台中,並通過消除管理軟件的差別,數據采集手段的差別,對各種不同的數據來源實現統一管理、統一規范、統一處理、統一展現、統一用戶登錄、統一權限控制,最終實現運維規范化、自動化、智能化的大運維管理。
一個智能的運維監控平台,一般的設計架構從低到高可以分為6層,三大模塊,如下圖所示。
其中:
數據收集層:位於最底層,主要收集網絡數據、業務系統數據、數據庫數據、操作系統數據等,然后將收集到的數據進行規范化並進行存儲。
數據展示層:位於第二層,是一個Web展示界面,主要是將數據收集層獲取到的數據進行統一展示,展示的方式可以是曲線圖、柱狀圖、餅狀態等,通過將數據圖形化,可以幫助運維人員了解一段時間內主機或網絡的運行狀態和運行趨勢,並作為運維人員排查問題或解決問題的依據。
數據提取層:位於第三層,主要是對從數據收集層獲取到的數據進行規格化和過濾處理,提取需要的數據到監控報警模塊,這個部分是監控和報警兩個模塊的銜接點。
報警規則配置層:位於第四層,主要是根據第三層獲取到的數據進行報警規則設置、報警閥值設置、報警聯系人設置和報警方式設置等。
報警事件生成層:位於第五層,主要是對報警事件進行實時記錄,將報警結果存入數據庫以備調用,並將報警結果形成分析報表,以統計一段時間內的故障率和故障發生趨勢。
用戶展示管理層:位於最頂層,是一個Web展示界面,主要是將監控統計結果、報警故障結果進行統一展示,並實現多用戶、多權限管理,實現統一用戶和統一權限控制。
在這6層中,從功能實現划分,又分為三個模塊,分別是數據收集模塊、數據提取模塊和監控報警模塊,每個模塊完成的功能如下:
數據收集模塊:此模塊主要完成基礎數據的收集與圖形展示。數據收集的方式有很多種,可以通過SNMP實現,也可以通過代理模塊實現,還可以通過自定義腳本實現。常用的數據收集工具有Cacti、Ganglia等。
數據提取模塊:此模板主要完成數據的篩選過濾和采集,將需要的數據從數據收集模塊提取到監控報警模塊中。可以通過數據收集模塊提供的接口或自定義腳本實現數據的提取。
監控報警模塊:此模塊主要完成監控腳本的設置、報警規則設置,報警閥值設置、報警聯系人設置等,並將報警結果進行集中展現和歷史記錄。常見的監控報警工具有Nagios、Centreon等。
在了解了運維監控平台的一般設計思路之后,接下來詳細介紹下如何通過軟件實現這樣一個智能運維監控系統。
上圖是根據上圖的設計思路形成的一個運維監控平台實現拓撲圖,從圖中可以看出,主要有三大部分組成,分別是數據收集模塊、監控報警模塊和數據提取模塊,其中,數據提取模塊用於其他兩個模塊之間的數據通信,而數據收集模塊可以有一台或多台數據收集服務器組成,每個數據收集服務器可以直接從服務器群組收集各種數據指標,經過規范數據格式,最終將數據存儲到數據收集服務器中。監控報警模塊通過數據抽取模塊從數據收集服務器獲取需要的數據,然后設置報警閥值、報警聯系人等,最終實現實時報警。報警方式支持手機短信報警、郵件報警等,另外,也可以通過插件或者自定義腳本來擴展報警方式。這樣一整套監控報警平台就基本實現了。
二、Ganglia作為數據收集模塊
關於Ganglia的基本應用,在前面章節已經詳細介紹過,這里將Ganglia作為監控報警平台的數據收集模塊,主要基於以下幾方面的原因:
1、靈活的分布式、分層體系結構,使Ganglia支持上萬個監控節點的數據收集,並且性能表現穩定,同時,Ganglia也可以根據地域環境、網絡結構的不同,分地域、分層次靈活部署Ganglia數據收集點,而對於數據收集節點可以動態添加或刪除,對Ganglia整體監控不產生任何影響,因此,可以靈活擴展Ganglia數據收集節點。
2、收集數據更加精確,不但可以收集實時數據,以圖表的形式展示出來,而且還允許用戶查看歷史統計數據,因此,用戶可以通過這些數據,做出性能調整、升級、擴容等決策,從而保證應用系統能夠滿足不斷增長的業務需求。
3、可以通過組播、單播的方式收集數據。在監控的節點較多時通過組播方式收集數據可以大大降低數據收集的負載,提高監控和數據收集性能。而對於不能使用組播收集數據的網絡環境,還可以通過單播的方式收集數據,因此Ganglia在數據收集方式上非常靈活。
4、可收集各種度量的數據。Ganglia默認可收集cpu、memory、disk、I/O、process、network六大方面的數據,同時還提供了C或者Python接口,用戶通過這個接口可以自定義數據收集模塊,並且這些模塊可以被直接插入到Ganglia中以監控用戶自定義的應用。
基於以上這些優點,Ganglia非常適合作為監控報警平台的數據收集模塊。雖然Cacti也可以實現數據的收集和圖形報表的展示,但是當監控節點越來越多時,Cacti的缺點就慢慢暴露出來了,數據收集的准確性、實時性就很難得到保障了。因此,要構建一個高性能的監控報警平台,Ganglia是首選的數據收集模塊。
三、Centreon作為監控報警模塊
有了Ganglia收集數據還是不夠的,運維人員不可能天天盯着數據報表,因此,還需要對收集到的數據進行監控和報警:對每個需要監控的主機或服務,設置一個報警閥值,當收集到的數據超過這個閥值時,在第一時間能自動報警並通知運維人員,而在收集到的數據沒有超過指定的報警閥值時,運維人員就可以去做別的事情,而不用時刻盯着數據報表,這是構建智能監控報警平台必須要實現的一個功能。
對主機或服務的狀態值進行監控,當達到指定閥值時進行報警,要實現這個功能並不是什么難的事情,寫個簡單的腳本就能實現,但是這樣太原始了,沒有層次,維護性差,並且當需要監控報警的主機或服務越來越多時,腳本的性能就變得很差,管理也非常不方便,更別說有什么可視化效果了,因此,需要有一個專業的監控報警工具來實現這個功能。
Centreon就是這樣一個專業的分布式監控、報警工具,它通過第三方組件可以實現對網絡、操作系統和應用程序的監控與報警。在底層,Centreon通過nagios作為監控軟件;在數據層,Centreon通過ndoutil模塊將監控到的數據定時寫入數據庫中;在展示層,Centreon提供了Web界面來配置、管理需要監控的主機或服務,並提供多種報警通知方式,同時還可以展現監控數據和報警狀態,並且可查詢歷史報警記錄。
關於Centreon的介紹和使用,在前面專欄已經做過非常詳細的介紹,這里不再多說。通過對Centreon的使用可知,Centreon無論在配置、管理、可視化等方面都做得非常專業和完善,並且在多主機、多服務監控的環境下,性能表現也非常穩定,因此,將Centreon作為智能監控報警平台的監控報警模塊非常適合。
四、Ganglia與Centreon的無縫整合
通過前面的介紹,確定了以Ganglia作為數據收集模塊,Centreon作為監控報警模塊的方案,這樣,一個智能監控報警平台兩大主要功能模塊已經基本實現了。但現在的問題是,如何將收集到的數據傳送給監控報警模塊呢,這就是數據抽取模塊要完成的功能。
數據抽取模塊要完成的功能是:從數據收集模塊中定時采集指定的數據,然后將采集到的數據與指定的報警閥值進行比較,如果發現采集到的數據大於或小於指定的報警閥值,那么就通過監控報警模塊設置的報警方式進行故障通知。在這個過程中,只有采集數據在數據收集模塊中完成,其他操作,例如:采集數據時間間隔、報警閥值設置、報警方式設置、報警聯系人設置等都在監控報警模塊中完成。
從數據抽取模塊完成的功能可以看出,此模塊主要用來銜接數據收集模塊和監控報警模塊,進而實現Ganglia和Centreon的無縫整合。要實現數據抽取模塊的功能,方法有很多,最簡單最直接的方法就是編寫監控腳本,這里提供幾個常用的數據抽取腳本,然后將腳本添加到Centreon中,下面介紹具體的操作過程。
4.1、數據抽取腳本
這里提供一個數據抽取腳本,是基於Python編寫的,介紹如下。
這個腳本的原理是通過Ganglia提供的數據匯總端口來獲取數據,然后將獲取到的數據與指定的閥值進行對比,以判斷服務是否有異常。腳本內容如下:
#!/usr/bin/env python import sys import getopt import socket import xml.parsers.expat class GParser: def __init__(self, host, metric): self.inhost =0 self.inmetric = 0 self.value = None self.host = host self.metric = metric def parse(self, file): p = xml.parsers.expat.ParserCreate() p.StartElementHandler = parser.start_element p.EndElementHandler = parser.end_element p.ParseFile(file) if self.value == None: raise Exception('Host/value not found') return float(self.value) def start_element(self, name, attrs): if name == "HOST": if attrs["NAME"]==self.host: self.inhost=1 elif self.inhost==1 and name == "METRIC" and attrs["NAME"]==self.metric: self.value=attrs["VAL"] def end_element(self, name): if name == "HOST" and self.inhost==1: self.inhost=0 def usage(): print """Usage: check_ganglia_metric \ -h|--host= -m|--metric= -w|--warning= \ -c|--critical= """ sys.exit(3) if __name__ == "__main__": ############################################################## ganglia_host = '127.0.0.1' ganglia_port = 8651 host = None metric = None warning = None critical = None try: options, args = getopt.getopt(sys.argv[1:], "h:m:w:c:s:p:", ["host=", "metric=", "warning=", "critical=", "server=", "port="], ) except getopt.GetoptError, err: print "check_gmond:", str(err) usage() sys.exit(3) for o, a in options: if o in ("-h", "--host"): host = a elif o in ("-m", "--metric"): metric = a elif o in ("-w", "--warning"): warning = float(a) elif o in ("-c", "--critical"): critical = float(a) elif o in ("-p", "--port"): ganglia_port = int(a) elif o in ("-s", "--server"): ganglia_host = a if critical == None or warning == None or metric == None or host == None: usage() sys.exit(