https://www.sohu.com/a/258553446_411876
本文根據dbaplus社群第162期線上分享整理而成。
一、前言
隨着業務的飛速發展,數據庫服務器量級飛速增長,比如Oracle、MySQL、Redis、MongoDB的使用更加普及,對數據庫運維人員的要求也越來越高,構建一個真正好用的監控系統是一項艱巨的任務。在監控系統的開源軟件中,可供選擇的工具眾多,然而真正適合自己需求、能夠真正解決自己數據庫問題的監控系統軟件卻鳳毛麟角。
Zabbix和Ansible分別是兩款非常流行的開源監控和自動化工具。具有上手簡單,學習曲線平滑、配置簡單、功能強大、擴展性強等優點。
本次將分享如何使用Zabbix並結合Ansible打造自動化數據庫監控體系。
二、Zabbix自動化核心功能介紹
Zabbix是企業級監控解決方案,和自動化相關的核心功能包括:LLD、API、Zabbix_trapper。
1、LLD
在數據庫監控中監控的對象往往是變化的,以部署Redis來說:近幾年硬件發展迅速,在企業中新購的X86服務器配置基本都在32C、256GB以上,大家都知道Redis是用“單線程-多路復用IO模型”來實現高性能的內存數據服務,只能用到一個CPU核心,內存配置一般也在8G-16G左右,為了提高資源利用率,一般會選擇在一台服務器上部署多個實例。當需要監控的內容比較多的時候,此時每次添加一批實例都去手動部署監控、配置告警的話就會造成大量人力的消耗。
此時通過LLD能自動發現並自動發現添加新部署實例的監控項,包括Item、Trigger這些的自動添加,做到一次部署永久受益,提高數據庫監控人員的幸福值。
LLD的核心思路是給服務端發送一個JSON的數據格式,下面以Redis Standalone類型實例為例說明。
- 首先模板中添加discovey rules增加一個trapper類型:
- 然后增加宏{#REDISPORT}:
- 當關聯好Redis的模板后,使用zabbix_sender發送給如下的數據:
{
"data":[
{
"{#REDIS_PORT}":6379
}
]
}
就完成了Redis的監控添加,其中一項Item示例如下:
2、API
API是Zabbix中非常強大的功能,通過調用API可以將Zabbix和其他系統串聯到一起,在自動化運維環境中非常有用。
Zabbix API是一個JSON-RPC的API,通過http請求,它提供了幾乎所有Zabbix的功能,比如更新Item、添加Host監控等。
API使用流程如下:
官方也提供了詳細的API功能說明。
官方API:
https://www.zabbix.com/documentation/3.2/manual/api
下面通過調用user.login的例子來說明:
- JSON RPC:標准的JSON RPC參數以標示協議版本。所有的請求都會保持不變。
- Method:定義了需要執行的方法。
- Params:這里通過傳遞JSON對象來作為特定方法的參數。
- ID:用於綁定JSON請求和響應。響應會跟請求有相同的ID。
- Auth:"0424bd59b807674191e7d77572075f33",這是一個認證令牌用以鑒別用戶、訪問API。
在Python項目上一般可以使用第三方的py-Zabbix或者自己封裝(urllib、requests)來實現訪問。
其中py-Zabbix的網址如下:
https://github.com/adubkov/py-zabbix
使用示例如下:
3、Zabbix_trapper
Zabbix_trapper是不通過zabbix-client收集數據,直接主動向Zabbix Server發送數據的一種方式。
我們監控數據庫,如果使用Agent的方式發送,要用到agent conf文件中的userParameter,這樣需要接受一個參數,來返回對應的監控數據,這樣等於有多少個Item就要在一次監控周期內執行多少次命令,並且對數據庫說也是要建立相應次的短鏈接,增加了數據庫的負擔。
此外,在監控的數據庫實例比較多的情況下,也將給Zabbix Server帶來較大的壓力,可以通過使用trapper的方式,一次搜集所有的監控數據到一個JSON中,並且只給Zabbix Server發送一次。
使用方式如下:
- 直接調用:
- 使用py-Zabbix:
三、監控自動化
監控運維自動化的目的在於解放、簡化、方便運維人員的工作,提高效率,減少人為故障,思路是能自動堅決不手動,將高頻率低風險的監控操作全部自動。自動化的基礎是基礎信息的准確性和各種配置信息規則的規范化。
1、監控規范化
約定服務器主機名規范:見到這個主機名就能知道這個設備是部署了什么樣的服務,以及是什么業務來使用的。
約定服務器網卡IP規范:比如一台服務器可能有多個IP:應用IP、數據IP等,監控要用哪個IP以及哪塊網卡綁定IP,需要統一。
約定服務部署規范:統一所有被監控服務器的Zabbix Agent部署目錄,監控腳本部署目錄。還有包括數據庫的標准化比如,如Oracle、MySQL、Redis這些常見服務的應用初始化流程、部署更新流程等。
報警等級的規范:用於區分報警發給誰、怎么發、如何做報警升級等,還可以根據等級和監控項進行自動處理,等級較高的優先處理,較低的可以集中處理等。
等這些標准規范固化下來之后,消除了各種差異,才能為后續的自動化開發鋪平前進的道路。因為連標准都沒有的話,那就毫無自動化構建可言。
2、自動化部署
我們自己的項目后端開發語言為Python,Ansible基於Python開發,能夠很好的支持Python項目進行二次開發發布。在不需要考慮大規模並發性能的情況下,Ansible是最合適的自動化工具,只需要一台能夠SSH到其他服務器的管理機。
上圖為Ansible的基礎架構圖,由以下部分組成:
- Ansible:核心;
- Core Modules:Ansible自帶的核心模塊;
- Custom Modules:自定義模塊;
- Plugins:Ansible插件,包括郵件插件、日志插件、連接插件等;
- Playbooks:劇本,Ansible配置、部署、編排語言,定義主機執行的Task集合;
- Host Inventory:Ansible管理遠程主機和組之間的關系清單,記錄主機SSH端口、賬號密碼等。
如上圖所示,只需要在Ansible Server上執行:
就可完成所有工作。(如果是自動化項目,可以通過封裝Ansible API來實現)
這里的main.yml如下:
```
- hosts: "{{ host_list }}"
gather_facts: True
roles:
- role: "{{ role_name }}"
```
其中host_list指傳入被監控服務器的信息;role_name指傳入自定義的Zabbix監控角色。
這里需要注意的是通過Auto Register關聯模板,當添加主機、加入主機組后,關聯到相應的模板,才能使整個流程形成閉環。
那么如何做呢?
例如我們上面的Ansible命令,會同時添加zabbix_agentd.conf這個agent的配置文件,其中有一個參數是HostMetadata=MySQL。
Zabbix Server會提前為Discovery創建Action:
這樣就完成了對MySQL模板的管理,從而形成閉環。
四、數據庫監控項目
下面介紹如何根據Oracle、MySQL、Redis、Mongo以及自己的需求情況使用Python開發一套DBA_Monitor項目,使監控更加全面、豐富、靈活,使交付更加快速、穩定、高效。
項目目錄結構如下:
其中authzabbix.py封裝了共用的Zabbix API的方法,Lib目錄主要存放全局的變量信息,包括Zabbix API地址、Zabbix用戶、各類數據庫的監控用戶、路徑等信息,Log目錄用於存放監控日志,Template用來存放Zabbix模板信息。
pyora.py是Oracle的監控腳本,mysql_db_status.py是MySQL的監控腳本,redis_db_status.py是Redis的監控腳本,mongo_db_status.py是Mongo的監控腳本。
Ansible把DBA_Monitor包推送到被監控機后,會根據不同的數據庫服務類型來啟動對應的監控腳本。如果再有新的數據庫類型需要監控,也可以方便的進行擴展。
下面將對Oracle、MySQL、Redis、MongoDB監控的關鍵點進行講解。
1、Oracle
Oracle監控使用了Pyora這套腳本,Pyora大量使用了Python反射(自省),從而實現了非常靈活的Oracle監控,自定義自己想監控的指標相當方便,只需要添加相關函數就能獲得相應的Item值。
Pyora通過組件cx_Oracle來連接Oracle數據庫,獲取到的數據傳遞給Zabbix的Agent,從而獲取到相關監控數據。
Pyora的網址:
https://github.com/bicofino/Pyora
下面對Pyora中的關鍵代碼進行注釋說明:
如果我們想要添加新的監控user_status,只需在Checks增加相應的方法:
非常靈活。
2、MySQL
MySQL的監控主要使用MySQLdb這個包,通過show global variables、show global status、show slave status管理命令獲取,然后進行計算,存在一個Python的dict數據結構中,key為監控項,value為取到的值。
因為新版本的MySQL對硬件的利用率很高,這里沒有使用多實例監控,所以沒有過多難點。在MySQL模板里定義item為trapper類型,通過zabbix_sender將dict中的數據發送給zabbix_server就完成了。
下圖是對trapper類型MySQL監控的模板配置示例:
3、Redis
Redis實例的監控是使用Python-Redis通過info命令來獲取信息,並對信息進行處理來完成。Redis Standalone和Cluster都可以在一次LLD添加item后通過info命令收集數據來監控,而Seninel稍微特殊,下面主要說明Seninel的監控技巧。
首先要用LLD發現Seninel的實例,這個和Standalone類似,上圖中的Sentinel discover,就是第一次LLD。在前面的LLD章節已有說明,這里主要說明是如何發現Seninel中監控的Master實例信息,即上圖中的Sentinel master。
在發現了Seninel的實例后,通過info sentinel命令可以抓取如下類似的關鍵信息:
master0:name=redis-coretest,status=ok,address=172.2.8.72:6387,slaves=1,sentinels=5
master1:name=redis-buitest,status=ok,address=172.2.8.72:6394,slaves=1,sentinels=5
master2:name=redis-batchtest,status=ok,address=172.2.8.72:6389,slaves=1,sentinels=5
master3:name=redis-agenttest,status=ok,address=172.2.8.72:6399,slaves=1,sentinels=5
這些信息通過再次LLD來添加到Zabbix Server的item中,用來監控Seninel中存儲的被監控Master的狀態,並且如果有新加入的Master也能自動LLD發現,也就是兩次LLD監控Seninel中的被監控Master的狀態信息。
需要注意的是其中這里的Seninel master需要同時接收到{#REDISPORT}和{#SENTINELMASTER}兩個宏信息。
包括item也要設置{#REDISPORT}和{#SENTINELMASTER}兩個宏信息:
4、Mongo
線上環境基本都會選擇MongoDB Sharded cluster架構,MongoDB Sharded cluster共有三種不同類型的服務:Mongos、Mongod、Config Server。
在MongoDB的監控中,為了滿足自動化的需求,最好是在一個腳本中里同時完成:
發現實例(LLD)
判斷出實例類型,在Zabbix添加對應的監控,是Mongos就添加Mongos模板,是Mongod和Config Server都是添加Mongo模板。
發送數據
判斷實例類型,收集相應數據並發送給Zabbix Server,這里監控Mongo使用的是PyMongo包,通過Mongo中的管理命令serverStatus、replSetGetStatus(mongos無此命令,需要過濾)來獲取信息,並進行處理。代碼片段如下:
這里通過serverStatus中的process是否為Mongod來區分實例類型:
發現實例的代碼如下,通過netstat查詢出這台主機上所有的不同的Mongo實例,實例的信息,放入一個List里面返回:
run函數用來組裝數據,並通過zabbix_sender來發送LLD信息,完成實例的添加:
最終通過LLD發現的Mongod和Mongos監控Item示例如下:
五、總結
Zabbix結合Ansible一鍵部署監控,做到了安裝Zabbix Agent,修改Agent配置文件、Agent加入開機啟動、啟動Zabbix Agent、添加客戶端Host、添加Host的模板等一系列動作,並且可以和CMDB結合,進行自動部署,簡化了數據庫監控操作步奏,提高數據庫監控人員的工作效率。