雖說監控系統最側重的功能是指標採集、儲存、分析、告警,為了能夠快速恢復故障,告警自愈機制也是需要重點投入建設的,所有可以固化為指令碼的應急預案都可以使用告警自愈機制來快速驅動。夜鶯開源專案從 v7 版本開始內建了告警自愈模組,本文將詳細介紹告警自愈的原理和實現。
夜鶯專案介紹
夜鶯監控是一款開源雲原生觀測分析工具,採用 All-in-One 的設計理念,集資料採集、視覺化、監控告警、資料分析於一體,與雲原生生態緊密整合,提供開箱即用的企業級監控分析和告警能力。夜鶯於 2020 年 3 月 20 日,在 github 上釋出 v1 版本,已累計迭代 100 多個版本。
夜鶯最初由滴滴開發和開源,並於 2022 年 5 月 11 日,捐贈予中國計算機學會開源發展委員會(CCF ODC),為 CCF ODC 成立後接受捐贈的第一個開源專案。夜鶯的核心研發團隊,也是 Open-Falcon 專案原核心研發人員,從 2014 年(Open-Falcon 是 2014 年開源)算起來,也有 10 年了,只為把監控這個事情做好。
夜鶯專案的 Github 地址是:https://github.com/ccfos/nightingale,國內用這個開源專案的公司也比較多了,我就不過多介紹了。直接開始正題。
告警自愈原理
夜鶯告警引擎在產生告警事件之後,除了可以透過多種通知媒介通知相關人員,也可以自動化的執行某個動作。主要是透過兩種方式來驅動這些自動化動作:
- Webhook:透過 Webhook 的方式把告警事件推送到外部系統,外部系統可以根據告警事件的內容來執行相應的動作
- 指令碼:直接到告警的機器上(或者指定的中控機)執行指令碼,指令碼可以是 shell 指令碼、python 指令碼、bat 指令碼等等
本文重點講解的是第二種,透過指令碼的方式。
要能夠去告警的機器上執行指令碼,機器上需要部署一個 agent,這個 agent 週期性和服務端發起心跳,拉取要執行的指令碼,並把指令碼的執行結果上報給服務端。在夜鶯的生態裡,這個 agent 就是 categraf。
告警事件產生之後,告警引擎發現這個事件需要執行自愈動作,就會在服務端建立一個指令碼任務,等著 agent 來拉取執行。所以本質上,是告警引擎 + 命令執行通道共同協作達成了告警自愈的效果。
部署配置
首先需要夜鶯 v7.0.0-beta.2.0.1 以上的版本,之前的版本也有告警自愈的能力,但之前的版本需要額外安裝部署 ibex 模組,從這個版本開始就不需要單獨的 ibex 模組了。
修改夜鶯服務端的配置
在夜鶯的配置檔案:etc/config.toml
中搜尋 Ibex,把 Enable 設定為 true:
[Ibex]
Enable = true
RPCListen = "0.0.0.0:20090"
重啟夜鶯,讓配置生效。此時透過 ss 或 netstat 命令可以看到夜鶯服務端監聽了 20090 埠。這是 categraf 拉取指令碼任務、上報指令碼結果的埠。
ss -tln|grep 20090
注意
如果夜鶯使用的資料庫連線賬號是具備建表許可權的,程序啟動之後會自動建立 ibex 相關的表,就是告警自愈相關的表,如果夜鶯使用的資料庫連線賬號沒有建表許可權,就需要手工建表了,建表 sql 在這裡:https://github.com/flashcatcloud/ibex/blob/master/sql/ibex.sql 注意,從第 7 行開始複製,把這些表建到夜鶯的庫(預設是 n9e_v6)裡,不要建到 ibex 庫裡了。老版本的告警自愈依賴單獨的 ibex 模組,ibex 模組用的庫是 ibex 庫,現在夜鶯新版本內建了 ibex 的能力,資料庫也就合併到一起了。
如果你是從老版本的夜鶯升級上來的,需要把之前的 ibex 庫中的表遷移到 n9e_v6 庫中,遷移命令如下:
mysqldump -u username -p ibex > ibex.sql
mysql -u root -p n9e_v6 < ibex.sql
修改 categraf 的配置
categraf 的配置檔案是 conf/config.toml
。在 conf/config.toml
中搜尋 ibex,把 enable 設定為 true,並正確配置夜鶯服務端的地址和埠:
[ibex]
enable = true
interval = "1000ms"
servers = ["127.0.0.1:20090"]
meta_dir = "./meta"
如果你的機器量比較大,比如超過 10000 臺,建議把 interval 調整的稍微大一些,比如 2500ms,要不然容易給服務端造成太大壓力。servers 配置是個陣列,配置所有的夜鶯服務端的地址,如果你有多個夜鶯服務端例項,categraf 啟動的時候會自動探測,連到那個網路延遲最小的例項上,如果夜鶯服務端例項掛了,categraf 會自動切換到另外一個例項上,保證高可用。
改完配置之後重啟 categraf,讓配置生效。
注意
如果使用了夜鶯的邊緣部署模式,這裡的 servers 就配置為 n9e-edge 的地址即可。當然,邊緣模式的話 n9e-edge 的配置檔案中要開啟 Ibex。
測試命令通道
告警自愈依賴命令通道,我們先來測試一下命令通道是否正常。其實即便不用告警自愈,命令通道也是很有用的,可以用來批次遠端執行命令,比如批次重啟服務、批次清理日誌、批次執行命令檢視輸出、批次安裝個軟體等等。
去機器列表裡,選中要執行命令的機器,點選標識欄上面的複製按鈕,複製相關的機器標識,然後去【告警自愈】-【任務】頁面,建立臨時任務。把剛才複製的機器列表填寫到 Host 框中,然後在 Script 中填寫要執行的指令碼內容即可。預設 Script 中已經有一個 ss -tln
的命令了,可以不用修改直接執行。
執行完成之後,結果如下,可以點選 stdouts 檢視所有機器的指令碼執行的 stdout 結果:
建立任務的時候,欄位內容比較多,各個欄位都有說明,我這裡就不贅述了。核心就是去一批機器上跑個指令碼。因為要跑指令碼,需要控制許可權,如果是 Admin 賬號,所有機器都可以執行命令,如果是普通賬號,只能去有許可權的機器上執行指令碼,哪些機器有許可權?就看我管理了哪些業務組,我管理的這些業務組下的機器我就有許可權。
建立自愈指令碼
命令通道測通了。接下來就是和監控告警引擎聯動,讓告警事件產生的時候自動建立一個指令碼任務,讓 agent 去執行這個指令碼任務。建立自愈指令碼的選單入口:【告警自愈】-【指令碼】,比如我建立瞭如下指令碼:
自愈指令碼建立的時候,Host 欄位留空即可。因為告警的時候才知道具體是哪個機器觸發告警,Host 欄位會被告警引擎動態填充。自動建立指令碼任務。
當然,上面這些指令碼都是我隨便寫的,僅做演示用。假設我現在要建立一個告警規則:“機器磁碟快滿了”,如果觸發告警,就自動執行 ID 為 19 的指令碼,此時要怎麼做呢?很簡單,在告警規則裡配置一個回撥地址 ${ibex}/19
即可:
這樣,當告警事件產生的時候,告警引擎會自動建立一個指令碼任務,讓 agent 去執行這個 ID 為 19 的指令碼。這個指令碼任務的執行結果會上報給服務端,你可以在【告警自愈】-【任務】頁面檢視這個任務的執行結果。
通常一個告警規則對應一個自愈指令碼,如果想把指令碼做的很通用,想用一個指令碼幹很多事,應對不同的場景。那就需要在指令碼里拿到告警事件的詳情,然後根據告警事件中的資訊來做不同的處理。這個夜鶯也是支援的,夜鶯會把告警事件的關鍵資訊放到指令碼的 stdin 中傳給指令碼,你就可以在指令碼里透過 stdin 拿到告警事件的內容了,比如我們準備一個這樣的告警自愈指令碼:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import sys
import json
payload = json.load(sys.stdin)
print(payload)
這是一個很簡單的 Python 指令碼,從 stdin 中讀取內容,json decode(夜鶯把告警事件關鍵資訊組裝成一個 json map 塞入 stdin,所以指令碼這裡要 json decode 一下) 一下放到 payload 變數裡,然後用 print 把 payload 列印出來。列印的結果如下:
{'__name__': 'system_load_norm_1', 'alert_severity': '2', 'alert_trigger_value': '0.195', 'env': 'ENV', 'ident': 'dev-n9e-01', 'rulename': '測試告警自愈引數-勿刪23'}
嗯,nice~ 這樣我們就可以在指令碼里根據告警事件的內容來做不同的處理了。
注意:告警事件中需要有 ident 標籤(表示是哪個機器告警了),ident 對應的機器需要在機器列表裡,且告警規則的最後修改人對這個機器有操作許可權,夜鶯才會去對應的機器執行指令碼。
參考資料
- 夜鶯監控官方文件: https://flashcat.cloud/docs/content/flashcat-monitor/nightingale-v7/monitor/ibex/
- categraf 專案地址: https://github.com/flashcatcloud/categraf
- ibex 專案地址:https://github.com/flashcatcloud/ibex