隨着大數據時代的來臨,運維工做的難度愈來愈大,每一個運維人員都要面臨不可勝數的服務器和海量的數據,如何保證衆多服務器和業務系統穩定高效地運行並儘可能減小死機時間,成爲考覈運維工做的重要指標,而要實現大規模的運維,必需要有一套行之有效的智能運維監控管理系統,本章就詳細介紹下如何構建一套完善的運維監控報警平臺。php
運維的核心工做能夠分爲運行監控和故障處理兩個方面,對業務系統進行精確、完善的監控,保證可以在第一時間發現故障並迅速通知運維人員處理故障是運維監控系統要實現的基礎功能;一個功能完善的智能監控系統,不但能夠自動處理一些簡單故障,減小運維工做量,還應該在應用可能出現故障時預先發出報警,預防故障的發生。所以,構建一個智能的運維監控平臺,必須以運行監控和故障報警這兩個方面爲重點,將全部業務系統中涉及的網絡資源、硬件資源、軟件資源、數據庫資源等歸入統一的運維監控平臺中,並經過消除管理軟件的差異,數據採集手段的差異,對各類不一樣的數據來源實現統一管理、統一規範、統一處理、統一展示、統一用戶登陸、統一權限控制,最終實現運維規範化、自動化、智能化的大運維管理。python
一個智能的運維監控平臺,通常的設計架構從低到高能夠分爲6層,三大模塊,以下圖所示。mysql
其中:ios
數據收集層:位於最底層,主要收集網絡數據、業務系統數據、數據庫數據、操做系統數據等,而後將收集到的數據進行規範化並進行存儲。
數據展現層:位於第二層,是一個Web展現界面,主要是將數據收集層獲取到的數據進行統一展現,展現的方式能夠是曲線圖、柱狀圖、餅狀態等,經過將數據圖形化,能夠幫助運維人員瞭解一段時間內主機或網絡的運行狀態和運行趨勢,並做爲運維人員排查問題或解決問題的依據。
數據提取層:位於第三層,主要是對從數據收集層獲取到的數據進行規格化和過濾處理,提取須要的數據到監控報警模塊,這個部分是監控和報警兩個模塊的銜接點。
報警規則配置層:位於第四層,主要是根據第三層獲取到的數據進行報警規則設置、報警閥值設置、報警聯繫人設置和報警方式設置等。
報警事件生成層:位於第五層,主要是對報警事件進行實時記錄,將報警結果存入數據庫以備調用,並將報警結果造成分析報表,以統計一段時間內的故障率和故障發生趨勢。
用戶展現管理層:位於最頂層,是一個Web展現界面,主要是將監控統計結果、報警故障結果進行統一展現,並實現多用戶、多權限管理,實現統一用戶和統一權限控制。
在這6層中,從功能實現劃分,又分爲三個模塊,分別是數據收集模塊、數據提取模塊和監控報警模塊,每一個模塊完成的功能以下:
數據收集模塊:此模塊主要完成基礎數據的收集與圖形展現。數據收集的方式有不少種,能夠經過SNMP實現,也能夠經過代理模塊實現,還能夠經過自定義腳本實現。經常使用的數據收集工具備Cacti、Ganglia等。
數據提取模塊:此模板主要完成數據的篩選過濾和採集,將須要的數據從數據收集模塊提取到監控報警模塊中。能夠經過數據收集模塊提供的接口或自定義腳本實現數據的提取。
監控報警模塊:此模塊主要完成監控腳本的設置、報警規則設置,報警閥值設置、報警聯繫人設置等,並將報警結果進行集中展示和歷史記錄。常見的監控報警工具備Nagios、Centreon等。git
在瞭解了運維監控平臺的通常設計思路以後,接下來詳細介紹下如何經過軟件實現這樣一個智能運維監控系統。github
上圖是根據上圖的設計思路造成的一個運維監控平臺實現拓撲圖,從圖中能夠看出,主要有三大部分組成,分別是數據收集模塊、監控報警模塊和數據提取模塊,其中,數據提取模塊用於其餘兩個模塊之間的數據通訊,而數據收集模塊能夠有一臺或多臺數據收集服務器組成,每一個數據收集服務器能夠直接從服務器羣組收集各類數據指標,通過規範數據格式,最終將數據存儲到數據收集服務器中。監控報警模塊經過數據抽取模塊從數據收集服務器獲取須要的數據,而後設置報警閥值、報警聯繫人等,最終實現實時報警。報警方式支持手機短信報警、郵件報警等,另外,也能夠經過插件或者自定義腳原本擴展報警方式。這樣一整套監控報警平臺就基本實現了。web
關於Ganglia的基本應用,在前面章節已經詳細介紹過,這裏將Ganglia做爲監控報警平臺的數據收集模塊,主要基於如下幾方面的緣由:正則表達式
一、靈活的分佈式、分層體系結構,使Ganglia支持上萬個監控節點的數據收集,而且性能表現穩定,同時,Ganglia也能夠根據地域環境、網絡結構的不一樣,分地域、分層次靈活部署Ganglia數據收集點,而對於數據收集節點能夠動態添加或刪除,對Ganglia總體監控不產生任何影響,所以,能夠靈活擴展Ganglia數據收集節點。sql
二、收集數據更加精確,不但能夠收集實時數據,以圖表的形式展現出來,並且還容許用戶查看歷史統計數據,所以,用戶能夠經過這些數據,作出性能調整、升級、擴容等決策,從而保證應用系統可以知足不斷增加的業務需求。shell
三、能夠經過組播、單播的方式收集數據。在監控的節點較多時經過組播方式收集數據能夠大大下降數據收集的負載,提升監控和數據收集性能。而對於不能使用組播收集數據的網絡環境,還能夠經過單播的方式收集數據,所以Ganglia在數據收集方式上很是靈活。
四、可收集各類度量的數據。Ganglia默承認收集cpu、memory、disk、I/O、process、network六大方面的數據,同時還提供了C或者Python接口,用戶經過這個接口能夠自定義數據收集模塊,而且這些模塊能夠被直接插入到Ganglia中以監控用戶自定義的應用。
基於以上這些優勢,Ganglia很是適合做爲監控報警平臺的數據收集模塊。雖然Cacti也能夠實現數據的收集和圖形報表的展現,可是當監控節點愈來愈多時,Cacti的缺點就慢慢暴露出來了,數據收集的準確性、實時性就很可貴到保障了。所以,要構建一個高性能的監控報警平臺,Ganglia是首選的數據收集模塊。
有了Ganglia收集數據仍是不夠的,運維人員不可能每天盯着數據報表,所以,還須要對收集到的數據進行監控和報警:對每一個須要監控的主機或服務,設置一個報警閥值,當收集到的數據超過這個閥值時,在第一時間能自動報警並通知運維人員,而在收集到的數據沒有超過指定的報警閥值時,運維人員就能夠去作別的事情,而不用時刻盯着數據報表,這是構建智能監控報警平臺必需要實現的一個功能。
對主機或服務的狀態值進行監控,當達到指定閥值時進行報警,要實現這個功能並非什麼難的事情,寫個簡單的腳本就能實現,可是這樣太原始了,沒有層次,維護性差,而且當須要監控報警的主機或服務愈來愈多時,腳本的性能就變得不好,管理也很是不方便,更別說有什麼可視化效果了,所以,須要有一個專業的監控報警工具來實現這個功能。
Centreon就是這樣一個專業的分佈式監控、報警工具,它經過第三方組件能夠實現對網絡、操做系統和應用程序的監控與報警。在底層,Centreon經過nagios做爲監控軟件;在數據層,Centreon經過ndoutil模塊將監控到的數據定時寫入數據庫中;在展現層,Centreon提供了Web界面來配置、管理須要監控的主機或服務,並提供多種報警通知方式,同時還能夠展示監控數據和報警狀態,而且可查詢歷史報警記錄。
關於Centreon的介紹和使用,在前面專欄已經作過很是詳細的介紹,這裏再也不多說。經過對Centreon的使用可知,Centreon不管在配置、管理、可視化等方面都作得很是專業和完善,而且在多主機、多服務監控的環境下,性能表現也很是穩定,所以,將Centreon做爲智能監控報警平臺的監控報警模塊很是適合。
經過前面的介紹,肯定了以Ganglia做爲數據收集模塊,Centreon做爲監控報警模塊的方案,這樣,一個智能監控報警平臺兩大主要功能模塊已經基本實現了。但如今的問題是,如何將收集到的數據傳送給監控報警模塊呢,這就是數據抽取模塊要完成的功能。
數據抽取模塊要完成的功能是:從數據收集模塊中定時採集指定的數據,而後將採集到的數據與指定的報警閥值進行比較,若是發現採集到的數據大於或小於指定的報警閥值,那麼就經過監控報警模塊設置的報警方式進行故障通知。在這個過程當中,只有採集數據在數據收集模塊中完成,其餘操做,例如:採集數據時間間隔、報警閥值設置、報警方式設置、報警聯繫人設置等都在監控報警模塊中完成。
從數據抽取模塊完成的功能能夠看出,此模塊主要用來銜接數據收集模塊和監控報警模塊,進而實現Ganglia和Centreon的無縫整合。要實現數據抽取模塊的功能,方法有不少,最簡單最直接的方法就是編寫監控腳本,這裏提供幾個經常使用的數據抽取腳本,而後將腳本添加到Centreon中,下面介紹具體的操做過程。
這裏提供一個數據抽取腳本,是基於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(3)