維監(jiān)控實(shí)戰(zhàn):從故障可見到可控可定位的完整體系搭建)
干了這么多年運(yùn)維我最大的感觸是系統(tǒng)出故障不可怕可怕的是故障發(fā)生之后你盯著滿屏的告警郵件卻說不清楚現(xiàn)在到底是什么掛了、影響多大、從哪開始查。那種“明明知道出事了卻無從下手”的無力感比通宵加班更折磨人。可視化運(yùn)維監(jiān)控要解決的就是把這個(gè)過程從“靠猜、靠問、靠翻日志”變成“靠看、靠點(diǎn)、靠鉆取”讓故障從發(fā)生到定位有一條清晰的路。這篇文章我想圍繞“可見、可控、可定位”這三個(gè)關(guān)鍵詞把我自己做監(jiān)控體系搭建時(shí)的思路、工具選型、踩坑記錄和排查經(jīng)驗(yàn)完整梳理一遍。不管你是剛接手公司監(jiān)控系統(tǒng)的運(yùn)維新人還是準(zhǔn)備把現(xiàn)有監(jiān)控從“能用”升級到“好用”的負(fù)責(zé)人這篇文章應(yīng)該都能給你一些可以直接抄作業(yè)的參考。1. 故障可見監(jiān)控體系的地基是先讓你“看得見”1.1 你真正需要看見的是什么很多人一提到可視化監(jiān)控第一反應(yīng)就是“搞個(gè)大屏把 CPU、內(nèi)存、磁盤畫成花花綠綠的圖表”。這個(gè)方向不能說錯但太淺了。做了幾年監(jiān)控之后我總結(jié)了一句話可視化的本質(zhì)不是畫圖而是壓縮信息。你在一個(gè)面板上看到的每一個(gè)數(shù)字、每一條曲線都是在幫你回答四個(gè)問題什么東西出故障了影響面有多大持續(xù)了多久當(dāng)前是正在惡化還是在恢復(fù)所以第一步不是選工具而是先盤點(diǎn)你的監(jiān)控對象。一個(gè)典型的業(yè)務(wù)系統(tǒng)你至少要把下面幾個(gè)層面拆出來基礎(chǔ)設(shè)施層物理機(jī)或虛擬機(jī)的 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)流量、硬件健康狀態(tài)比如 RAID 陣列卡、電源、風(fēng)扇。中間件層MySQL、Redis、Kafka、Elasticsearch 這些組件的連接數(shù)、主從延遲、內(nèi)存碎片率、隊(duì)列積壓量。應(yīng)用層接口的 QPS、響應(yīng)時(shí)間、錯誤率、JVM 或 Go runtime 的 GC 情況。業(yè)務(wù)層訂單量、支付成功率、用戶登錄失敗次數(shù)這些直接反映用戶體驗(yàn)的指標(biāo)。這四層缺哪一塊你的監(jiān)控面板都會“偏科”。只盯 CPU 和內(nèi)存你根本不知道 Redis 已經(jīng)積壓了幾萬條消費(fèi)消息只盯應(yīng)用日志你可能凌晨四點(diǎn)才會發(fā)現(xiàn)磁盤早就滿了。1.2 從采集到展示一條完整的數(shù)據(jù)鏈路可視化不是平白無故變出來的它背后是一條完整的數(shù)據(jù)管道。我自己搭監(jiān)控的時(shí)候習(xí)慣把它拆成四段來看采集從目標(biāo)機(jī)器或應(yīng)用里把指標(biāo)揪出來。最常見的開源方案是 Prometheus 的各類 exporter比如 node_exporter 負(fù)責(zé)機(jī)器基礎(chǔ)指標(biāo)mysqld_exporter 負(fù)責(zé)數(shù)據(jù)庫指標(biāo)redis_exporter 負(fù)責(zé) Redis 指標(biāo)。如果你的應(yīng)用是 Java 寫的還可以直接暴露 Micrometer 格式的端點(diǎn)讓 Prometheus 來抓。存儲指標(biāo)數(shù)據(jù)是典型的時(shí)間序列數(shù)據(jù)不適合往 MySQL 里塞。Prometheus 自帶 TSDB 存儲默認(rèn)保留時(shí)間夠用我一般設(shè)置 15 天左右如果要長期留存可以再接一套 Thanos 或者 VictoriaMetrics。展示Grafana 是繞不開的選擇它跟 Prometheus 配合得最舒服支持的圖表類型也足夠豐富從折線圖到熱力圖到儀表盤都能做。告警Prometheus 的 Alertmanager 負(fù)責(zé)根據(jù)規(guī)則觸發(fā)告警再通過 webhook 投遞到釘釘、企業(yè)微信、飛書或者郵件。這里我多說一句選型的事。經(jīng)常有人問我用 Zabbix 不也能做監(jiān)控嗎為什么非要用 Prometheus 這一套我的看法是Zabbix 在傳統(tǒng)網(wǎng)絡(luò)設(shè)備監(jiān)控和純內(nèi)網(wǎng)環(huán)境里確實(shí)很成熟但如果你有大量動態(tài)擴(kuò)縮容的容器環(huán)境或者應(yīng)用是微服務(wù)架構(gòu)Prometheus 的標(biāo)簽label設(shè)計(jì)、服務(wù)發(fā)現(xiàn)機(jī)制和活躍的生態(tài)會順手得多。反過來如果你公司環(huán)境非常固定、沒有容器化需求那 Zabbix 反而是省心選擇。工具沒有絕對的好壞只有跟場景合不合適。1.3 可視化大屏的設(shè)計(jì)信息分層比炫酷重要說到可視化大屏我得潑一盆冷水。很多人只看過那些數(shù)據(jù)大屏的 demo覺得“夠炫”就要求運(yùn)維也做一個(gè)。實(shí)際上真正在生產(chǎn)環(huán)境里扛過故障的監(jiān)控大屏設(shè)計(jì)原則是反著來的寧可樸素不可花哨。我后來把大屏信息分成三層第一層是全局健康度一眼掃過去就知道今天有沒有大事。這一層放最頂級的幾個(gè)數(shù)字比如整體可用率、當(dāng)前嚴(yán)重告警數(shù)、核心服務(wù)的平均延遲。我習(xí)慣給這層加顏色邏輯正常情況下綠色有 P0 告警就整塊變紅配合閃爍效果值班的人抬頭就能看到。第二層是趨勢和關(guān)聯(lián)讓你快速判斷故障是正在發(fā)展還是逐漸恢復(fù)。這里放核心服務(wù)的 QPS、錯誤率、P99 延遲再加幾條關(guān)鍵中間件的連接數(shù)和積壓量曲線。這層的重點(diǎn)是曲線不是數(shù)字因?yàn)橼厔荼人矔r(shí)值更能說明問題。第三層才是明細(xì)入口本質(zhì)上是“鉆取”的起點(diǎn)。大屏上每一個(gè)看起來能點(diǎn)的區(qū)塊背后都要能跳到對應(yīng)的 Grafana Dashboard甚至繼續(xù)下鉆到具體機(jī)器的具體進(jìn)程。我踩過最大的坑就是把大屏做成“數(shù)據(jù)堆砌”八塊屏幕全放著相似的折線圖真出了故障所有圖都在波動但你根本不知道先看哪一塊。后來我立了一條規(guī)矩每一屏只回答一個(gè)問題裝不下的問題就翻頁不要硬塞。2. 故障可控告警機(jī)制才是監(jiān)控的靈魂2.1 告警不是越多越好先學(xué)會分級可視化解決的是“看得見”但“看見”之后你得有動作否則多好看的大屏也只是個(gè)觀賞屏。告警體系說白了就是給監(jiān)控裝上手腳。告警最忌諱的是什么是“一視同仁”。如果磁盤快滿了和數(shù)據(jù)庫主從斷開的告警用的是同一個(gè)通知渠道、同一個(gè)優(yōu)先級那運(yùn)維人員遲早會對所有告警脫敏最后連真告警也被忽略了。我自己的分級邏輯是這樣的P0 級核心服務(wù)不可用、數(shù)據(jù)丟失風(fēng)險(xiǎn)、大面積故障轉(zhuǎn)移失敗。要求立即響應(yīng)通知到值班負(fù)責(zé)人和研發(fā)負(fù)責(zé)人支持電話和短信雙重轟炸。P1 級核心功能受損但還可用比如接口 P99 延遲翻倍、數(shù)據(jù)庫連接數(shù)逼近上限、Redis 內(nèi)存淘汰頻繁。要求 15 分鐘內(nèi)響應(yīng)。P2 級非核心功能異常或資源接近瓶頸比如某臺非核心機(jī)器 CPU 持續(xù) 90%、日志目錄磁盤使用率超過 80%。要求當(dāng)天處理。P3 級輕微波動、已知問題的重復(fù)提醒這類告警甚至可以選擇不通知只記錄在案。做這個(gè)分級的時(shí)候我一直提醒自己一句話告警的等級不能拍腦袋定要看它對業(yè)務(wù)的實(shí)際影響。一個(gè)冷門報(bào)表服務(wù)的 CPU 飆到 95%可能只是定時(shí)任務(wù)在跑不用拉響 P0但支付鏈路的 P99 延遲漲了 200ms哪怕絕對值也不高也得嚴(yán)肅對待。2.2 告警抑制與收斂躲開告警風(fēng)暴告警風(fēng)暴這個(gè)詞做過線上運(yùn)維的人一定不陌生。某個(gè)核心數(shù)據(jù)庫一抖動依賴它的幾十個(gè)服務(wù)全開始報(bào)告警一瞬間你的釘釘群、郵件、短信全炸了。我遇到最夸張的一次是某個(gè)基礎(chǔ)組件升級失敗觸發(fā)了級聯(lián)告警一晚上收到了 3000 多條通知真正有用的信息早就被淹沒在垃圾里了。從那次之后我認(rèn)認(rèn)真真研究了 Alertmanager 的抑制inhibit和路由分組group機(jī)制這才算把告警風(fēng)暴給管住。抑制規(guī)則的核心邏輯是如果出現(xiàn)了一個(gè)高級別告警那么由它引發(fā)的低級別告警都先閉嘴。舉個(gè)例子如果某個(gè)數(shù)據(jù)庫實(shí)例掛了它下面的所有主從延遲、連接數(shù)異常、慢查詢類告警都不要發(fā)了。我只需要知道“數(shù)據(jù)庫掛了”然后順著數(shù)據(jù)庫往下排查就行。分組機(jī)制解決的是“同類告警刷屏”的問題。比如一個(gè)服務(wù)有 30 個(gè)實(shí)例同時(shí)出現(xiàn) CPU 告警不需要發(fā) 30 條消息應(yīng)該按告警名分組一條消息里列出哪些實(shí)例受影響就夠。我通常把 group_by 設(shè)置成告警名稱和告警級別這樣同類告警會被合并到同一條通知里。這里有一個(gè)我能直接分享的 Alertmanager 配置片段核心就是 inhibit 規(guī)則inhibit_rules: - source_matchers: - severityP0 target_matchers: - severityP1|P2 equal: - alertname這個(gè)規(guī)則的意思是如果存在 P0 告警那么相同 alertname 的 P1 和 P2 告警都會被抑制。有了這個(gè)兜底級聯(lián)故障時(shí)消息量至少能砍掉七成。2.3 通知路由讓告警找到對的人告警被收斂之后下一個(gè)問題是發(fā)給誰不同團(tuán)隊(duì)的職責(zé)邊界不一樣基礎(chǔ)架構(gòu)告警應(yīng)該讓基礎(chǔ)設(shè)施團(tuán)隊(duì)看到業(yè)務(wù)應(yīng)用告警應(yīng)該讓對應(yīng)業(yè)務(wù)的研發(fā)收到。我見過很多公司是一個(gè)大群接收所有告警結(jié)果就是“人人都在群里人人都不覺得該自己動手”。我的做法是給告警規(guī)則打上團(tuán)隊(duì)標(biāo)簽通過 Alertmanager 的 route 做分叉。每個(gè)團(tuán)隊(duì)獨(dú)立的釘釘群或企業(yè)微信機(jī)器人只接收跟自己相關(guān)的告警。只有 P0 級告警才會廣播到所有管理者和核心負(fù)責(zé)人確保一件事情有且只有一個(gè)第一責(zé)任人。通知內(nèi)容本身也非常重要。純文字告警說“CPU 高”沒有任何上下文等于沒報(bào)。我一般在告警模板里帶上這幾樣?xùn)|西告警對象、當(dāng)前指標(biāo)數(shù)值、持續(xù)了多長時(shí)間、對應(yīng)的 Grafana 面板鏈接、最近一次變更記錄。讓收到消息的人不用再登機(jī)器查一遍才知道發(fā)生了什么。2.4 告警自愈把重復(fù)勞動交給自動化告警可控的更高一級形態(tài)是讓一部分告警根本不需要人處理。運(yùn)維時(shí)間應(yīng)該花在復(fù)雜故障上而不是每天重復(fù)“重啟一下服務(wù)”這種瑣碎操作。我碰到過一種場景某個(gè)定時(shí)任務(wù)每天凌晨都會把內(nèi)存吃滿然后觸發(fā) OOM 告警值班同事每天到點(diǎn)手動重啟。后來我把這個(gè)操作做成了告警聯(lián)動Prometheus 觸發(fā)特定告警后通過 webhook 調(diào)起一個(gè)腳本檢查服務(wù)進(jìn)程、清理緩存、自動重啟并記錄操作日志。只要自愈成功告警會自動關(guān)閉人只需要第二天看總結(jié)報(bào)告確認(rèn)這不是一個(gè)需要根治的問題。不過自愈要克制只對“動作明確、風(fēng)險(xiǎn)低、可回滾”的操作開啟。比如自動重啟一個(gè)無狀態(tài)服務(wù)是可以的自動切換數(shù)據(jù)庫主從或者自動清理數(shù)據(jù)這類高風(fēng)險(xiǎn)操作還是老老實(shí)實(shí)讓值班人員確認(rèn)后再執(zhí)行。3. 故障可定位從“知道掛了”到“知道為什么掛”3.1 可觀測性的三支柱指標(biāo)、日志、鏈路追蹤可視化大屏可以讓你一秒發(fā)現(xiàn)“訂單服務(wù)響應(yīng)變慢了”但這只是開始。真正困難的是從“變慢”定位到“是 SQL 慢查詢導(dǎo)致的還是下游 Redis 抖動導(dǎo)致的還是 GC 停頓導(dǎo)致的”。所以我一直強(qiáng)調(diào)可視化只是入口定位故障需要完整的可觀測性體系。業(yè)內(nèi)常說的三支柱——指標(biāo)Metrics、日志Logs、鏈路追蹤Traces一個(gè)都不能少。指標(biāo)回答“發(fā)生了什么”比如延遲升高、錯誤率上升。這部分由 Prometheus 負(fù)責(zé)。日志回答“細(xì)節(jié)是什么”比如報(bào)錯堆棧、參數(shù)內(nèi)容、具體的 SQL。由 Loki、Elasticsearch 或 ClickHouse 負(fù)責(zé)。鏈路追蹤回答“問題出在哪個(gè)環(huán)節(jié)”一次請求經(jīng)過了 A、B、C、D 四個(gè)服務(wù)時(shí)間都耗在哪了由 Jaeger 或 Zipkin 負(fù)責(zé)。三者缺一不可。沒有指標(biāo)你連“故障發(fā)生的時(shí)間點(diǎn)”都難確定沒有日志你找到了異常服務(wù)卻不知道它具體報(bào)了什么錯沒有鏈路追蹤微服務(wù)架構(gòu)下你根本不知道一次慢請求到底慢在哪個(gè)下游。3.2 從可視化面板“鉆取”到根因我追求的效果是一個(gè)人在 Grafana 上看到某條指標(biāo)不對勁點(diǎn)一下能直接跳到對應(yīng)的日志搜索頁和鏈路查詢頁。具體做起來就是統(tǒng)一標(biāo)簽。Prometheus 指標(biāo)里有 service、instance 這些標(biāo)簽日志在采集進(jìn) Loki 時(shí)也打上相同的 service、instance 標(biāo)簽鏈路追蹤同樣帶上這類元信息。這樣在 Grafana 里通過 Explore 功能就能實(shí)現(xiàn)“指標(biāo)查詢”和“日志查詢”的聯(lián)動。舉個(gè)例子我在 Grafana 看到order_service_http_requests_total這個(gè)指標(biāo)的錯誤率突然升高我點(diǎn)擊面板上的“View logs”按鈕Grafana 會自動跳轉(zhuǎn)到 Loki 查詢頁面并且?guī)?serviceorder-service 這個(gè)過濾條件。再點(diǎn)一下具體的 trace_id就能看到整條請求鏈路上每個(gè)服務(wù)耗時(shí)多少、哪一步返回了 5xx。整個(gè)過程不需要手動復(fù)制粘貼查詢語句也就大大縮短了故障定位的時(shí)間窗口。這個(gè)聯(lián)動機(jī)制我強(qiáng)烈建議每個(gè)做監(jiān)控的人都去配一下因?yàn)樗拇_是我這些年用下來單位時(shí)間收益最高的一個(gè)功能。3.3 K8s 集群場景故障轉(zhuǎn)移時(shí)該盯哪些指標(biāo)說到故障定位不得不提 K8s 集群?,F(xiàn)在生產(chǎn)環(huán)境用 K8s 的團(tuán)隊(duì)越來越多而 K8s 的故障有個(gè)特點(diǎn)很多故障直接影響用戶但故障源藏在很深的調(diào)度和編排層。比如一個(gè)節(jié)點(diǎn)出了問題Pod 被重新調(diào)度到其他節(jié)點(diǎn)這個(gè)過程本身有自愈能力但如果節(jié)點(diǎn)頻繁 NotReady、Pod 不斷 Evicted業(yè)務(wù)就會間歇性抖動。這種故障光盯業(yè)務(wù)指標(biāo)很難看出來你看到的只是錯誤率曲線像鋸齒一樣波動但找不到規(guī)律。我的建議是K8s 的監(jiān)控必須分層做控制面層API Server 的請求延遲和錯誤率、etcd 的 fsync 耗時(shí)和 leader 穩(wěn)定性。etcd 一旦出問題整個(gè)集群都會受影響。節(jié)點(diǎn)層節(jié)點(diǎn)的 CPU、內(nèi)存、磁盤壓力尤其要盯kubelet的 heartbeat 延遲。工作負(fù)載層Pod 重啟次數(shù)、Pending 狀態(tài)的 Pod 數(shù)量、副本數(shù)與期望副本數(shù)的差值。資源層HPA 的擴(kuò)縮容事件、資源限額LimitRange有沒有導(dǎo)致容器頻繁被殺。這里有個(gè)很典型的案例有一次我們公司的業(yè)務(wù)偶爾抖動現(xiàn)象是每隔幾分鐘就有幾條 502。一開始所有人都在看網(wǎng)關(guān)日志排查了半天沒結(jié)果。后來我拉出了 K8s 節(jié)點(diǎn)層指標(biāo)發(fā)現(xiàn)某個(gè)節(jié)點(diǎn)的磁盤 IO 延遲周期性飆升再往下查原來是那個(gè)節(jié)點(diǎn)上跑了一個(gè)寫日志特別頻繁的 Pod把節(jié)點(diǎn)磁盤 IO 打滿了導(dǎo)致 etcd 心跳超時(shí)觸發(fā)了 Pod 驅(qū)逐。業(yè)務(wù)側(cè)看只是偶發(fā) 502但真實(shí)原因在基礎(chǔ)設(shè)施層。這就是分層監(jiān)控的價(jià)值也是鏈路追蹤替代不了的排查路徑。3.4 硬件級故障別讓 RAID 陣列卡成為盲區(qū)軟件層的監(jiān)控大家比較熟悉但硬件層的故障很多人會忽略。這幾年我在實(shí)際運(yùn)維中吃過一次虧就是服務(wù)器用的是 RAID 陣列卡硬盤快故障預(yù)故障狀態(tài)時(shí)系統(tǒng)層面完全沒有明顯異常直到有硬盤徹底掉線陣列降級甚至數(shù)據(jù)重建失敗才追悔莫及。這里我要推薦一個(gè)實(shí)踐用 storcli 或 megacli 監(jiān)控 RAID 卡狀態(tài)并把結(jié)果暴露成 Prometheus 指標(biāo)。比如 LSI 9361-8i 陣列卡可以通過定時(shí)執(zhí)行storcli /c0 /vall show來獲取每個(gè)硬盤的狀態(tài)重點(diǎn)關(guān)注“Predictive Failure”或“Media Error”這類預(yù)警信息。把這些輸出解析成指標(biāo)后接入 Grafana再配上告警規(guī)則就能在硬盤剩余壽命耗盡之前及時(shí)發(fā)現(xiàn)把故障消滅在“還沒影響業(yè)務(wù)”的階段。有次我朋友的服務(wù)器就是預(yù)先報(bào)出了“Predictive Failure”提前做了數(shù)據(jù)遷移后來那塊硬盤果然在幾天之內(nèi)徹底壞掉了但因?yàn)樘崆疤幚砹藰I(yè)務(wù)一點(diǎn)沒受影響。這種硬件監(jiān)控你說它是可視化也好是告警也罷核心價(jià)值就是讓你把故障定位在最早期、代價(jià)最小的階段。4. 一個(gè)完整的排查實(shí)戰(zhàn)Redis 主從切換的監(jiān)控與定位4.1 故障現(xiàn)象業(yè)務(wù)側(cè)延遲突增我覺得理論講再多不如完整過一遍案例。這里我挑一個(gè)比較典型又不復(fù)雜的故障Redis 集群主從切換。某天下午我們收到告警說訂單服務(wù)的 P99 延遲從 20ms 跳到了 800ms持續(xù)時(shí)間大概兩分鐘。但詭異的是等我們打開 Grafana 想看曲線時(shí)延遲已經(jīng)恢復(fù)了。這種“過去式”故障最讓人頭疼。我當(dāng)時(shí)的排查邏輯是這樣走的。先看訂單服務(wù)的應(yīng)用指標(biāo)面板發(fā)現(xiàn)延遲曲線確實(shí)有個(gè)尖峰同時(shí)錯誤率并沒有升高說明服務(wù)沒掛只是變慢。接著看下游依賴的中間件面板發(fā)現(xiàn) Redis 的連接數(shù)有個(gè)斷崖式下跌又快速回升的過程這通常是主從切換的典型特征。再點(diǎn)開 Redis 實(shí)例面板確認(rèn)了確實(shí)發(fā)生過一次 failover切換過程中部分請求因?yàn)檫B接重連而出現(xiàn)了延遲尖峰。4.2 定位過程從指標(biāo)到日志再到底層原因確認(rèn)了“Redis 發(fā)生過主從切換”之后下一個(gè)問題就是為什么會切換我按照下面的順序查下去第一步看 Redis 的日志我這里是用文件采集接入日志平臺做全文檢索的。主從切換分為主動切換和被動切換。被動切換通常是因?yàn)橹鞴?jié)點(diǎn)失聯(lián)哨兵或集群檢測到心跳超時(shí)后發(fā)起的選舉。日志里如果看到failover-election相關(guān)的記錄說明走的是被動流程。第二步看主節(jié)點(diǎn)的健康指標(biāo)。我打開了主節(jié)點(diǎn)的監(jiān)控面板發(fā)現(xiàn)切換發(fā)生前CPU 使用率有一個(gè)階梯式上升內(nèi)存碎片率也異常偏高。這提示我主節(jié)點(diǎn)當(dāng)時(shí)可能已經(jīng)處于“亞健康”狀態(tài)只是還沒有徹底宕機(jī)。第三步順著排查底層的資源限制。登錄主節(jié)點(diǎn)機(jī)器確認(rèn)是集群規(guī)格偏小內(nèi)存被大量緩存數(shù)據(jù)占滿觸發(fā)了頻繁的內(nèi)存淘汰淘汰過程帶來額外 CPU 開銷最后在高峰期撐不住了觸發(fā)了故障轉(zhuǎn)移。到這里整條鏈就串起來了業(yè)務(wù)延遲升高 → Redis 主從切換 → 主節(jié)點(diǎn)資源不足、內(nèi)存淘汰嚴(yán)重 → 集群規(guī)格需要擴(kuò)容。4.3 這次故障暴露的問題事后我復(fù)盤發(fā)現(xiàn)這次故障其實(shí)在半小時(shí)前就有征兆內(nèi)存監(jiān)控面板上used_memory 早就逼近 maxmemory 了只是當(dāng)時(shí)值班的人沒有把“內(nèi)存水位”和“故障轉(zhuǎn)移”這兩件事關(guān)聯(lián)起來看。所以我在 Grafana 里專門建了一個(gè)“Redis 健康總覽”面板把內(nèi)存使用率、內(nèi)存淘汰鍵數(shù)、主從切換次數(shù)、集群狀態(tài)這幾個(gè)關(guān)鍵指標(biāo)放在同一個(gè)頁面。再加一條告警規(guī)則當(dāng) Redis 內(nèi)存使用率連續(xù) 5 分鐘超過 85%并且內(nèi)存淘汰鍵數(shù)開始增長時(shí)自動升為 P1 告警。這樣下次還沒到故障轉(zhuǎn)移那一步我們就能提前介入。這套做法也可以平移到其他中間件上核心思路就是不要等故障發(fā)生了才開始定位把可能導(dǎo)致故障的隱患點(diǎn)預(yù)先做成可視化和告警故障才會真正“可控”。5. 落地過程中我踩過的坑5.1 儀表盤“好看但沒用”的陷阱做監(jiān)控可視化的第一年我花了很多時(shí)間整 Grafana 的排版、配色、交互做出來的面板截圖發(fā)到群里大家都說漂亮。但真有一次線上事故那個(gè)漂亮的儀表盤竟然沒能幫我快速定位問題我才醒過來。原因是儀表盤上的圖表粒度太粗時(shí)間范圍默認(rèn)是 6 小時(shí)故障發(fā)生前 5 分鐘的變化曲線在這種視圖下被拉平成了一條幾乎看不見的毛刺。等我手動把時(shí)間范圍縮到 15 分鐘才發(fā)現(xiàn)異常早就開始了。這是我的第一個(gè)經(jīng)驗(yàn)儀表盤默認(rèn)時(shí)間范圍一定不能太長。我自己現(xiàn)在的默認(rèn)值是 1 小時(shí)關(guān)鍵面板甚至默認(rèn) 30 分鐘。另外每個(gè)核心服務(wù)都要準(zhǔn)備兩套視圖一套是“總覽版”適合長期盯屏一套是“排障版”默認(rèn)時(shí)間短、粒度細(xì)還帶自動刷新適合點(diǎn)擊進(jìn)入后直接判斷。5.2 數(shù)據(jù)采集本身的誤差可視化監(jiān)控依賴的是采集數(shù)據(jù)但采集過程本身也會引入誤差這個(gè)很多人沒意識到。最典型的是 Prometheus 的拉取機(jī)制如果你使用scrape_interval默認(rèn)的 15 秒那某些持續(xù)時(shí)間很短的問題比如只有 30 秒的 CPU 毛刺很可能被漏掉。我還碰到過一次非常搞笑的誤判因?yàn)?node_exporter 采集腳本里用了rate()函數(shù)去計(jì)算磁盤 IO但沒有處理 counter 重置的問題導(dǎo)致磁盤 IO 指標(biāo)在 Grafana 上畫出來的曲線像鋸齒一樣瘋狂跳動告警規(guī)則差點(diǎn)誤報(bào)。所以我的建議是監(jiān)控告警規(guī)則上線之前一定要拿歷史數(shù)據(jù)“回測”一遍。把過去一周的真實(shí)指標(biāo)數(shù)據(jù)拉到告警規(guī)則里跑一遍看它會在哪些時(shí)間點(diǎn)觸發(fā)觸發(fā)的告警是不是都真實(shí)有效。這個(gè)動作成本不高但能幫你省掉深夜被誤報(bào)警吵醒的痛苦。5.3 告警渠道失靈發(fā)了等于沒發(fā)告警鏈路的最后一環(huán)是通知渠道。我遇到過企業(yè)微信機(jī)器人 webhook 地址配錯、消息發(fā)不出去結(jié)果整個(gè)團(tuán)隊(duì)在故障期間完全沒收到提醒的情況。更尷尬的是那時(shí)候所有人都在排查為什么服務(wù)沒告警結(jié)果發(fā)現(xiàn)是 webhook 掛了。這個(gè)問題的解決辦法說穿了也不復(fù)雜告警鏈路本身也要監(jiān)控。Alertmanager 自己會暴露指標(biāo)比如alertmanager_notifications_total我把這個(gè)指標(biāo)接入 Grafana并設(shè)了一條規(guī)則如果通知投遞失敗率連續(xù) 10 分鐘超過 50%就通過備用渠道短信通知到值班人。第二道保險(xiǎn)是每周自動發(fā)送一次“告警自檢報(bào)告”里面列出本周所有告警是否都成功送達(dá)。這樣至少能保證告警通道本身不成為盲區(qū)。5.4 給新手的落地順序建議最后說一下我建議的落地順序。很多人一上來就想搞一套完備的可觀測性平臺結(jié)果項(xiàng)目體量太大最后不了了之。我的建議是三步走第一步先把基礎(chǔ)監(jiān)控做扎實(shí)。用 Prometheus node_exporter 把機(jī)器指標(biāo)管理起來再接入 Grafana配上最基礎(chǔ)的 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)告警。即使只有這些東西已經(jīng)能覆蓋相當(dāng)一部分基礎(chǔ)設(shè)施故障了。第二步接中間件和應(yīng)用指標(biāo)。把公司里最核心的 MySQL、Redis、Kafka 等組件指標(biāo)接進(jìn)來應(yīng)用自己暴露的 HTTP 指標(biāo)或 JVM 指標(biāo)也想辦法接到 Prometheus。建好 3 到 5 個(gè)核心業(yè)務(wù)儀表盤。第三步再考慮日志聯(lián)動、鏈路追蹤、告警自愈這些進(jìn)階能力。不用貪多每加一塊都要保證它是真正被用起來的不然就是維護(hù)負(fù)擔(dān)。按照這個(gè)順序走通常兩到三周就能讓監(jiān)控體系從“沒有”變成“初步可用”之后隨著對業(yè)務(wù)的深入理解再逐步迭代而不是一開始就鋪一個(gè)大攤子。我個(gè)人做了這么多年可視化運(yùn)維監(jiān)控最大的體會是監(jiān)控本質(zhì)上是在跟時(shí)間賽跑可視化、告警、鏈路追蹤所有這些技術(shù)手段最終目的都是把故障定位的時(shí)間從小時(shí)級壓縮到分鐘級。每個(gè)系統(tǒng)、每個(gè)團(tuán)隊(duì)的情況都不一樣但方向是一致的——讓故障可見、可控、可定位這三件事做到了運(yùn)維的底氣就完全不一樣了。