從 Kubernetes 成爲容器管理領域的事實標準開始,基於雲原生也就是基於 Kubernetes 原生。在雲的體系下,基礎硬件基本上都被抽象化、模糊化,硬故障須要人爲干預的頻次在逐漸下降,健康檢查、失敗自愈、負載均衡等功能的提供,也使得簡單的、毀滅性的故障變少。而隨着服務的拆分和模塊的堆疊,不可描述的、模糊的、莫名其妙的故障卻比之前更加的頻繁。node
「看到指標」只是對於數據簡單的呈現,在目前雲的環境下,並不能高效地幫助咱們找到問題。而「可觀測性」體現的是對數據的再加工,旨在挖掘出數據背後隱藏的信息,不只僅停留在展示數據層面,更是通過對數據的解析和再組織,體現出數據的上下文信息。mysql
爲了達成「可觀測性」的目標,就須要更加_標準化、簡潔化的指標數據,以及更便捷的收集方式,更強更豐富的語義表達能力,更快更高效的存儲能力。_本篇文章將主要探討時序指標的採集結構和採集方式,數據也是指時序數據,存儲結構以及 tracing、log、event 等監控形式不在本次討論範圍以內。git
提到時序數據,讓咱們先看看幾個目前監控系統比較經常使用的時序數據庫:_opentsdb,influxdb,prometheus_ 等。github
經典的時序數據基本結構你們都是有統一認知的:web
- 惟一序列名標識,即指標名稱;
- 指標的標籤集,詳細描述指標的維度;
- 時間戳與數值對,詳細描述指標在某個時間點的值。
時序數據基本結構爲指標名稱 + 多個 kv 對的標籤集 + 時間戳 + 值,可是在細節上各家又各有不一樣。redis
1[ 2{ 3 "metric": "sys.cpu.nice", 4 "timestamp": 1346846400, 5 "value": 18, 6 "tags": { 7 "host": "web01", 8 "dc": "lga" 9 } 10}, 11{ 12 "metric": "sys.cpu.nice", 13 "timestamp": 1346846400, 14 "value": 9, 15 "tags": { 16 "host": "web02", 17 "dc": "lga" 18 } 19} 20]
<左右滑動以查看完整代碼>
sql
opentsdb 使用你們耳熟能詳的 json 格式,多是用戶第一反應中結構化的時序數據結構。只要瞭解基本時序數據結構的人一眼就能知道各個字段的含義。數據庫
1<measurement>[,<tag_key>=<tag_value>[,<tag_key>= <tag_value>]] <field_key>=<field_value>[,<field_key>=<field_value>] [<timestamp>] 2例如: 3cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000
<左右滑動以查看完整代碼>json
1metric_name [ 2"{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `"` } [ "," ] "}" 3] value [ timestamp ] 4例如: 5http_requests_total{method="post",code="200"} 1027 1395066363000
<左右滑動以查看完整代碼>網絡
5&wx_lazy=1&wx_co=1)
influxdb 和 prometheus 都使用了自定義文本格式的時序數據描述,經過固定的語法格式將 json 的樹狀層級結構打平,而且沒有語義的丟失,行級的表述形式更便於閱讀。
○ 更符合人類閱讀習慣
○ 行級的表述結構對文件讀取的內存優化更友好
○ 減小了層級的嵌套
○ 解析成本更高
○ 校驗相對更麻煩
wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
使用過 Prometheus 的同窗可能會注意到其實 Prometheus 的採集結構不是單行的,每類指標每每還伴隨着幾行註釋內容 ,其中主要是兩類HELP 和 TYPE ,分別表示指標的簡介說明和類型。格式大概是:
1# Anything you want to say 2# HELP http_requests_total The total number of HTTP requests. 3# TYPE http_requests_total counter 4http_requests_total{method="post",code="200"} 1027 1395066363000 5http_requests_total{method="post",code="400"} 3 1395066363000
<左右滑動以查看完整代碼>
Prometheus 主要支持4類指標類型:
- Counter:只增不減的計數器。
- Gauge:可增可減的數值。
- Histogram:直方圖,分桶採樣。
- Summary:數據彙總,分位數採樣。
其中 Counter 和 Gauge 很好理解,Histogram 和 Summary 可能一時間會讓人迷惑。其實 Histogram 和 Summary 都是爲了從不一樣維度解決和過濾長尾問題。
例如,我和首富的平均身價並不能真實反映出我本身的身價。所以分桶或者分位數才能更準確的描述數據真實的分佈狀態。
而 Histogram 和 Summary 主要區別就在於對分位數的計算上,Histogram 在客戶端只進行分桶計算,所以能夠在服務端進行總體的分位數計算。Summary 則是在客戶端環境下計算了分位數,所以失去了在總體視圖上進行分位數計算的可能性。官方也給出了 Histogram 和 Summary 的區別:
須要說明的是,截止到目前爲止的 Prometheus 版本 2.20.1,這些 metric types 僅僅使用在客戶端庫(client libraries)和傳輸協議(wire protocol)中,服務端暫時沒有記錄這些信息。因此若是你對一個 Gauge 類型的指標使用 histogram_quantile(0.9,xxx) 也是能夠的,只不過由於沒有 xxx_bucket 的存在,計算不出來值而已。
時序監控數據的採集,從監控端來看,數據獲取的形式只有兩種,pull 和 push,不一樣的採集方式也決定了部署方式的不一樣。
仍是經過 opentsdb,prometheus 來舉例,由於 influxdb 集羣版本方案爲商業版,暫不作討論。
![]
上圖爲 opentsdb 架構圖 ,其中:
- Servers:表示被採集數據的服務,C則是表示採集指標的工具,能夠理解爲 opensdb 的 agent,servers 經過C將數據推送到下游的 TSD。
- TSD:對應實際進程名 TSDMain 是 opentsdb 組件,理解爲接收層,每一個TSD都是獨立的,沒有 master 和 slave 的區分,也沒有共享狀態。
- HBase:opentsdb實際的最終數據存儲在 hbase 中。
從架構圖能夠看出,若是推送形式的數據量大量增加的狀況下,能夠經過多級組件,或者擴容無狀態的接收層等方式較爲簡單的進行吞吐量的升級。
&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
上圖爲 prometheus 架構圖,主要看下面幾個部分:
- Prometheus Server:用於抓取和存儲時間序列化數據。
- Exporters:主動拉取數據的插件。
- Pushgateway:被動拉取數據的插件。
拉取的方式,一般是監控端定時從配置的各個被監控端的 Exporter 處拉取指標。這樣的設計方式能夠下降監控端與被監控端的耦合程度,被監控端不須要知道監控端的存在,這樣將指標發送的壓力從被監控端轉義到監控端。
對比一下 pull 和 push 方式各自的優劣勢:
○ 上下游解耦
○ 被監控端不會由於 push 數據到監控端失敗,而致使自身不穩定。
○ 監控端自身的壓力狀況基本上能夠預測,下降由於被監控端突增的發送流量致使的自身風險,例如 DDoS。
○ 能夠作到被監控端的自動發現機制。
○ 主動權在監控端這邊,能夠更靈活的配置須要監控什麼,尤爲是在調試過程當中。
○ 週期性不明顯,或者週期明顯短於採集週期的指標缺失精度。
○ 實時性較差。
○ 可能因爲防火牆等複雜的網絡環境設置,致使拉取不到數據。
○ 若是數據有缺失,很難進行補數據。
簡單對比了 pull 和 push 各自的特色,在雲原生環境中,prometheus 是目前的時序監控標準,爲何會選擇pull的形式,這裏有官方的解釋(https://prometheus.io/docs/in...)。
上面簡單介紹了一下從監控端視角看待數據採集方式的 pull 和 push 形式,而從被監控端來看,數據獲取的方式就多種多樣了,一般能夠分爲如下幾種類型:
- 默認採集
- 探測採集
- 組件採集
- 埋點採集
下面一一舉例說明。
默認採集一般是通俗意義上的全部人都會須要觀察的基礎指標,每每與業務沒有強關聯,例如 cpu、memory、disk、net 等等硬件或者系統指標。一般監控系統都會有特定的 agent 來固定採集這些指標,而在雲原生中很是方便的使用 node_exporter、CAdvisor、process-exporter,分別進行節點機器、容器以及進程的基礎監控。
探測採集主要是指從外部採集數據的方式。例如域名監控、站點監控、端口監控等都屬於這一類。採集的方式對系統沒有侵入,由於對網絡的依賴比較強,因此一般會部署多個探測點,減小由於網絡問題形成的誤報,可是須要特別當心的是,必定要評估探測採集的頻次,不然很容易對被探測方形成請求壓力。
一般是指已經有現成的採集方案,只須要簡單的操做或者配置就能夠進行詳細的指標採集,例如 mysql 的監控,redis 的監控等。在雲原生環境中,這種採集方式比較常見,得益於 prometheus 的發展壯大,常見的組件採集 exporter 層出不窮,prometheus 官方認證的各類 exporter。對於如下比較特殊或者定製化的需求,也徹底能夠按照 /metrics 接口標準本身完成自定義 exporter 的編寫。
對於一個系統的關鍵性指標,自己的研發同窗是最有發言權的,經過埋點的方式能夠精準的獲取相關指標。在 prometheus 體系中能夠很是方便的使用 github.com/prometheus/client_* 的工具包來實現埋點採集。
本文對監控系統的第一個階段「採集」,從「採集結構」和「採集方式」兩方面作了簡單的介紹和梳理。相比於以往,在雲原生的環境中,服務顆粒度拆分的更細緻,迭代效率更高,從開發到上線造成了更快節奏的反饋循環,這也要求監控系統可以更快速的反映出系統的異常,「採集結構」和「採集方式」雖然不是監控系統最核心的部分,可是簡潔的採集結構和便捷的採集方式也爲後續實現「可觀測性」提供了基礎。目前在雲原生環境中,使用 prometheus 能夠很是方便快捷的實現監控,雖然仍有許多工做須要作,例如集羣化、持久化存儲等,可是隨着 Thanos 等方案的出現,prometheus 也在漸漸豐滿中。