本文介紹了如何基于 kube-prometheus 設計一個監(jiān)控系統(tǒng), 以靈活簡單的方式對 kubernetes 上的應用進行指標采集,并實現(xiàn)監(jiān)控報警功能。
本文提供了作者的應用示例,另外還記錄了作者在學習、使用 Prometheus 過程中的一些筆記,如 arm 版鏡像獲取、一些工具的使用等。
前言
眾所周知,大數(shù)據(jù)產(chǎn)品作為底層平臺,其運維監(jiān)控一直是生產(chǎn)實踐的痛點難點,且在穩(wěn)定運行的基礎(chǔ)之上,往往還需要對性能進行評估優(yōu)化,所以其監(jiān)控系統(tǒng)的建設顯得尤為重要。
Prometheus 作為云原生時代最火的監(jiān)控軟件,很多大數(shù)據(jù)組件或原生或以第三方插件 / exporter 的形式對 Prometheus 做了支持。
我使用的大數(shù)據(jù)平臺是基于 kubernetes 運行的,有部署靈活管理方便的優(yōu)點,更容易與 Prometheus 進行結(jié)合。
下面將對設計思路和技術(shù)實現(xiàn)進行闡述探討。
設計思路
監(jiān)控系統(tǒng)的核心任務是將暴露出來的指標數(shù)據(jù)進行抓取,在此之上進行分析、告警 所以有以下幾個要明確的問題:
監(jiān)控對象是什么
監(jiān)控對象如何暴露指標數(shù)據(jù)
監(jiān)控系統(tǒng)如何對指標進行抓取
如何實現(xiàn)告警規(guī)則動態(tài)配置、管理
監(jiān)控對象
以 pod(容器)形式運行在 kubernetes 集群上的各個大數(shù)據(jù)組件。
指標暴露方式
各組件根據(jù)對 Prometheus 的支持程度,可分為 3 種類型的指標暴露方式:
直接暴露 Prometheus 指標數(shù)據(jù) (直接,拉)
主動將指標數(shù)據(jù)推送到 prometheus-pushGateway,由 pushGateway 暴露數(shù)據(jù)(間接,推)
自定義 exporter 將其他形式的指標數(shù)據(jù)轉(zhuǎn)換為符合 Prometheus 標準的格式進行暴露(exporter,直接,拉)
個別組件同時支持多種方式,如 flink 支持直接和間接方式,spark 支持直接方式而且也有第三方 exporter。大部分組件都有官方 / 第三方的 exporter,極少數(shù)需要自己開發(fā)。
一般情況下直接方式就可以了。
需要注意的是,像 flink(spark) on yarn 模式運行的時候,flink 節(jié)點是跑在 yarn 容器里面的。這種情況下 Prometheus 很難對其直接進行抓取,這種時候就只能用間接方式,主動將數(shù)據(jù)推送到 pushGateway。
另外那些短暫生命周期的組件也建議用主動 push 到 pushGateway。
指標抓取方式
不管是 exporter 還是 pushGateway,到最后必然是由 Prometheus 主動對這些目標進行抓取。
Prometheus 主要通過 Pull 的方式來抓取目標服務暴露出來的監(jiān)控接口,因此需要配置對應的抓取任務來請求監(jiān)控數(shù)據(jù)并寫入到 Prometheus 提供的存儲中,目前 Prometheus 服務提供了如下幾個任務的配置:
原生 Job 配置:提供 Prometheus 原生抓取 Job 的配置。
Pod Monitor:在 K8S 生態(tài)下,基于 Prometheus Operator 來抓取 Pod 上對應的監(jiān)控數(shù)據(jù)。
Service Monitor:在 K8S 生態(tài)下,基于 Prometheus Operator 來抓取 Service 對應 Endpoints 上的監(jiān)控數(shù)據(jù)。
既然都上了 kubernetes 環(huán)境了,一般當然是推薦直接用 podMonitor。配置更簡潔易懂。podMonitorSelector 的過濾在 prometheus-prometheus.yaml 配置。
prometheus-prometheus.yaml 是核心配置文件,不宜頻繁修改 (會導致 Prometheus 重啟)。
主要配置項為:serviceMonitorSelector,podMonitorSelector,ruleSelector,alertmanagers。
其中 service 監(jiān)控選擇器和 pod 監(jiān)控選擇器默認選擇所有,這里建議把 ruleSelector 也修改為選擇所有。
不過一個 podMonitor 一般只對應一種類型的 pod,在已有 pod 類型較多的情況下,還可以考慮一種更取巧的方法就是 Prometheus 的 kubernetes 服務發(fā)現(xiàn)功能。即 kubernetes_sd_config。這種屬于原生 Job 配置,建議使用additional-scrape-config[1]進行配置。
kubernetes_sd_config[2]賦予了 Prometheus 通過 kubernetes rest api 感知 kubernetes 資源的功能,利用該能力,可以使用原生 Job 配置自動發(fā)現(xiàn) pod,將其作為監(jiān)控目標。再利用 Prometheus 的Relabel 功能[3]可以改寫發(fā)現(xiàn)的標簽,進行前置處理、轉(zhuǎn)換。實現(xiàn) pod 篩選,修改抓取配置的效果。而自動發(fā)現(xiàn)的 pod 的標簽的來源又可以是 pod 資源的 label/annotation 等。
最終實現(xiàn)的效果如下:
這是一個 pushGateway 的 pod 的配置 , 則 Prometheus 會通過其 19091 端口訪問 / metrics 路徑獲取其指標數(shù)據(jù)
annotations: prometheus.io/scrape:"true" prometheus.io/scheme:"http" prometheus.io/path:"/metrics" prometheus.io/port:"19091"
podMonitor 是官方支持,簡潔易懂。kubernetes_sd_config+relabel 的方案較復雜,難度較高,但不用寫那么多的 podMonitor。自行抉擇就行,也可以一起用。
告警設計
告警流程
prometheus 的監(jiān)控告警基本流程是:
服務發(fā)生異常
觸發(fā) prometheus 服務器發(fā)出告警信息(alert)
alertmanager 收到告警信息
alertmanager 根據(jù)預配置的規(guī)則對告警信息進行處理,實現(xiàn)業(yè)務邏輯,如分組、抑制、觸發(fā)短信郵箱等
當然具體的流程沒那么簡單,有很多細節(jié)需要注意,特別是觸發(fā)告警時機,是個重點。
這些屬于 Prometheus 的機制實現(xiàn),這里就不展開贅述,推薦閱讀以下文章:
Prometheus 一條告警的觸發(fā)流程、等待時間[4]
AlertManager 何時報警[5]
后邊會給出一個本人實際應用測試的例子,可供參考,會直觀一些。
告警的動態(tài)配置
kube-prometheus 的告警規(guī)則分兩部分:
alertmanager: 即對告警信息的處理策略
核心是 alertmanager-secret.yaml 配置文件,該文件以 secret 的形式被 Alertmanager 讀取。Alertmanager 會自動讀取 secret 中的配置進行更新。
alertRule: 即具體的告警規(guī)則
在 kubernetes 中是以 PrometheusRule 類型操作,所以管理起來跟 pod 一樣,直接使用 kubelet 增刪改即可。
接入自定義告警平臺
從個人實踐的角度來看,AlertManager 處理 web hook 之外的告警接收插件,如短信、郵箱等只適合測著玩。生産使用還是要通過 web hook 將告警信息發(fā)送到自己的告警平臺。可以根據(jù)業(yè)務需要對告警信息做高度定制化處理、記錄等。另外可以在告警信息中攜帶具體告警規(guī)則等信息指導告警平臺進行處理。
這里要做個區(qū)分,AlertManager 是告警信息的前置處理,負責非業(yè)務性前置操作,如告警信息分組、平抑等。而自定義告警平臺則負責告警信息的業(yè)務處理,如記錄、去敏、發(fā)送到多終端等。
AlertManager 可能收到 1w 條告警信息,經(jīng)過處理最終只發(fā)了 1 條到自定義告警平臺。而自定義告警平臺可以將這 1 條告警信息記錄起來,修改內(nèi)容,同時使用郵箱、短信通知到多個負責人。
告警層級標簽設計
監(jiān)控對象的粒度決定告警的層級,體現(xiàn)在配置上則是告警規(guī)則的分組。分組信息決定 alertManager 的處理方式。
alertManager 對告警信息的路由策略是樹狀的,所以可通過多個分組標簽實現(xiàn)多層級路由處理。
具體設計應結(jié)合業(yè)務需求,不在這里展開,感興趣的可以看我下面的實現(xiàn)舉例。
技術(shù)實現(xiàn)
技術(shù)實現(xiàn)主要分以下幾部分:
kubernetes 環(huán)境下 prometheus 的部署 (kube-prometheus)
kube-prometheus 的增強配置 : 即 kubernetes_sd_config+relabel 方案的實現(xiàn)
bigdata-exporter 的實現(xiàn)
告警設計實例
kubernetes 環(huán)境下 prometheus 的部署
1) kube-prometheus vs prometheus-operator
github 上 coreos 下有兩個項目:kube-prometheus 和 prometheus-operator,兩者都可以實現(xiàn) prometheus 的創(chuàng)建及管理。
需要注意的是,kube-prometheus 上的配置操作也是基于 prometheus-operator 的,并提供了大量的默認配置,故這里使用的是 kube-prometheus 項目的配置。
另外使用前需注意 k8s 版本要求,找到對應的 kube-prometheus 版本,弄清楚對應的 prometheus-operator 版本。如:k8s1.14 版本最高可使用 kube-prometheus 0.3,對應的 prometheus-operator 版本是 0.32,閱讀文檔時注意對應版本。
2) kube-prometheus 使用前說明
kube-prometheus 使用 jsonnet 編寫配置模板文件,生成 k8s 配置清單。已提供默認清單文件,在 manifests 文件夾下。如果需要修改默認清單配置,需要在 go 環(huán)境下使用 jp 編譯清單。
下面都以默認配置為例
3) 安裝教程
參考官方說明即可
1、git clone 項目 并切換到指定分支
2、kubectl create
清單文件中各配置已附帶 namespace 信息,故執(zhí)行時不需要指定 namespace,否則可能出錯。
官方命令如下:
#CreatethenamespaceandCRDs,andthenwaitforthemtobeavailblebeforecreatingtheremainingresources $kubectlcreate-fmanifests/setup $untilkubectlgetservicemonitors--all-namespaces;dodate;sleep1;echo"";done $kubectlcreate-fmanifests/
kubernetes_sd_config+relabel 方案的實現(xiàn)
bigdata-exporter 的實現(xiàn)
hdfs、yarn、hbase、yarn 等組件都提供了 web 獲取 jmx 指標的方式。
這里的思路是使用一個 bigdata-exporter,去采集多個組件多個節(jié)點的指標數(shù)據(jù),并進行轉(zhuǎn)換,然后以 Prometheus 規(guī)定的格式對外公開。
指標數(shù)據(jù)的轉(zhuǎn)換規(guī)則可以查看 github 上的一些項目,要注意版本,也可以像我一樣自己寫,更可靠。
bigdata-exporter 如何感知到采集目標?
除了部署 ip 不同,不同組件不同角色的指標對外端口、路徑、內(nèi)容(解析規(guī)則)也都不一樣。
這里可以參考上面 kubernetes_sd_config+relabel 的方案,做得優(yōu)雅一些:
授予 bigdata-exporter 調(diào)用 kubernetes app 的能力,
利用 label 和 annotations 進行篩選和信息傳遞,確定捕捉目標和途徑。
使用 role 代表解析內(nèi)容的類型,根據(jù) role 確定解析規(guī)則
labels: bigData.metrics.object:pod annotations: bigData.metrics/scrape:"true" bigData.metrics/scheme:"https" bigData.metrics/path:"/jmx" bigData.metrics/port:"29871" bigData.metrics/role:"hdfs-nn,common"
告警設計示例
這里以組和實例兩個維度為例,用 groupId 和 instanceId 表示。
1) alertManager 配置示例
以下是 alertmanager 的規(guī)則配置,有兩個接收者,其中 test.web.hook 指向自定義告警平臺。default 是空白接收者,不做處理。路由策略是根據(jù) groupId,instanceId 分組,對節(jié)點磁盤使用率、kafka 隊列堆積兩個組處理,instanceId 還沒有展開。
舊版本是用 secret 的 data 字段,需要將配置內(nèi)容轉(zhuǎn)成 base64 編碼格式。新版本直接用 stringData 字段。推薦用 stringData 字段配置。其實只要看一下 kube-prometheus 的 alertmanager-secret.yaml 文件就知道怎么回事了。
使用 data 字段的配置方法:寫好 config 文件,以 alertmanager.yaml 命名(不能使用其他名稱)。執(zhí)行以下命令 , 即可更新 secret。
$kubectl-nmonitoringcreatesecretgenericalertmanager-main--from-file=alertmanager.yaml--dry-run-oyaml|kubectl-n=monitoringapply-f-
global: resolve_timeout:5m receivers: -name:'default' -name:'test.web.hook' webhook_configs: -url:'http://alert-url' route: receiver:'default' group_wait:30s group_interval:5m repeat_interval:2h group_by:[groupId,instanceId] routes: -receiver:'test.web.hook' continue:true match: groupId:node-disk-usage -receiver:'test.web.hook' continue:true match: groupId:kafka-topic-highstore
2) alertRule 配置示例
組代表一個類型的所有目標:即所有節(jié)點。實例則代表具體的某個節(jié)點。
disk-usage.yaml 磁盤使用率告警配置示例如下:
注意:${path}為監(jiān)控的磁盤路徑,${thresholdValue}為使用率閾值,需自行替換。labels 中的 userIds 和 receivers 為傳遞給自定義告警平臺的參數(shù),以指導告警平臺如何操作。
在這個任務中,我們的目標是組粒度的(所有節(jié)點),所以不需要設置 instanceId。
apiVersion:monitoring.coreos.com/v1 kind:PrometheusRule metadata: creationTimestamp:null labels: role:alert-rules name:node-disk-usage namespace:monitoring spec: groups: -name:node-disk-usage rules: -alert:node-disk-usage expr:100*(1-node_filesystem_avail_bytes{mountpoint="${path}"}/node_filesystem_size_bytes{mountpoint="${path}"})>${thresholdValue} for:1m labels: groupId:node-disk-usage userIds:super receivers:SMS annotations: title:"磁盤警告:節(jié)點{{$labels.instance}}的${path}目錄使用率已達到{{$value}}%" content:"磁盤警告:節(jié)點{{$labels.instance}}的${path}目錄使用率已達到{{$value}}%"
kafka-topic-highstore.yaml kafka 隊列消費堆積告警配置示例如下:
我們只關(guān)心個別隊列的消費情況,所以這里的粒度為 instance。
注意:${uniqueName}為隊列名,${consumergroup}為消費組名稱,${thresholdValue}為堆積數(shù)量閾值。
apiVersion:monitoring.coreos.com/v1 kind:PrometheusRule metadata: creationTimestamp:null labels: role:alert-rules name:kafka-topic-highstore-${uniqueName} namespace:monitoring spec: groups: -name:kafka-topic-highstore rules: -alert:kafka-topic-highstore-${uniqueName} expr:sum(kafka_consumergroup_lag{exporterType="kafka",consumergroup="${consumergroup}"})>${thresholdValue} for:1m labels: groupId:kafka-topic-highstore instanceId:${uniqueName} userIds:super receivers:SMS annotations: title:"KAFKA警告:消費組${consumergroup}的堆積數(shù)量達到:{{$value}}" content:"KAFKA警告:消費組${consumergroup}的堆積數(shù)量達到:{{$value}}"
其他
告警流程示例
這里以兩個節(jié)點 node1 和 node2 配置了磁盤空間監(jiān)控為例,空間使用到達閾值則觸發(fā)告警。(測試過程中可通過生成、刪除指定體積的文件來控制空間占用)
其中配置項如下:
告警規(guī)則 : node-disk-usage
for 為 1m
告警中心 : alertManager
group_wait: 30s
group_interval: 5m
repeat_interval: 10m
收到的告警短信內(nèi)容及時間線如下:
1014 收到第一次警報:node1 于 1044 進入異常
1014 收到第二次警報:node1 于 1044 進入異常 node2 于 1044 進入異常
1029 收到第三次警報:node1 于 1044 進入異常 node2 于 1044 進入異常
1044 收到第四次警報:node1 于 1044 進入異常 node2 于 1044 進入異常
1044 收到第五次警報:恢復告警 node1 于 1044 進入異常,并于 1044 恢復 node2 于 1044 進入異常,并于 1014 恢復
總共收到 5 次短信,第 1 次是 node1 異常,第 2 到 4 次是 node1 和 node2 都異常,因為屬于同個分組 group,所以合并發(fā)送。第 5 次是已經(jīng)恢復正常了。
根據(jù)短信內(nèi)容和時間,整理出告警邏輯時間線如下:
node1 等待 for1 分鐘后警報進入 group
node1 記錄異常時間為 1044,實際異常狀態(tài)至少在 1044 的一分鐘前
group 等待 group_wait30s后發(fā)送第一次告警
firing:node1
node2 等待 for1 分鐘后警報進入 group
node2 記錄異常時間為 1044,實際異常狀態(tài)至少在 1044 的一分鐘前,此時 group 中有兩個異常目標 node1 和 node2。
group 等待 group_interval5m后發(fā)送第二次告警
firing:node1,node2
注意:因為 group 發(fā)生了變化,所以這里用的是 group_interval。
group 等待 repeat_interval10m后發(fā)送第三次告警
firing:node1,node2
注意:因為 group 沒有變化,屬于重復告警,用的是 repeat_interval。
group 等待 repeat_interval10m后發(fā)送第四次告警
firing:node1,node2
同上一次。
第四次告警后的 前 5 分鐘:node2 恢復正常
第四次告警后的 后 5 分鐘:node1 恢復正常
group 等待 repeat_interval10m后發(fā)送第五次告警
resolved:node1,node2
注意,這里 node1,node2 都恢復正常用的也是 repeat_interval。
綜上:
for 是告警規(guī)則個體的監(jiān)控配置,用來衡量服務多久檢測不通過才算異常。
group_wait:初次發(fā)送告警的等待時間
用于 group 創(chuàng)建后的等待,這個值通常設置較小,在幾分鐘以內(nèi)。
group_interval:同一個組其他新發(fā)生的告警發(fā)送時間間隔
是 group 內(nèi)容發(fā)生變化后的告警間隔。
repeat_interval:重復發(fā)送同一個告警的時間間隔
group 內(nèi)容沒有變化且上一次發(fā)生成功時用的發(fā)生間隔。
需要注意,恢復正常不屬于 group 變化,用的是 repeat_interval。這有點反直覺,且個人認為不是很合理,不知道是不是測試有問題,也沒有找到比較好的資料說明。希望知道的可以指教一下。
exporter 的位置
exporter 可以以 sidecar 的形式和原容器放在同一個 pod 內(nèi)(1 對 1),也可以以獨立部署的形式存在(1 對 1/1 對多)。
這個視具體情況而定,技術(shù)上沒什么不同,sidecar 可以綁定生命周期,視為對原有組件的補充。獨立部署則耦合度更低,更靈活。像單節(jié)點的 mysql,用 sidecar 則只需要 1 個 pod,不會太復雜。
而如果像多節(jié)點的 kafka 集群,用獨立部署則只需要一個 exporter 就可以實現(xiàn)對多個節(jié)點的采集監(jiān)控。
這里出于減小耦合、節(jié)省資源的目的,我主要使用的是獨立部署形式。
使用 promtool 檢查指標格式是否正確
promtool 使用方法:
#進入pod $kubectl-n=monitoringexec-itprometheus-k8s-0sh #查看幫助 $promtool-h #檢查指標格式 $curl-shttp://ip:9999/metrics|promtoolcheckmetrics
比方說 指標 name、labelname 不能使用小數(shù)點
使用 port-forward 臨時提供 Prometheus 外部訪問
#prometheus $nohupkubectlport-forward--address0.0.0.0service/prometheus-k8s19090:9090-n=monitoring& #grafana $nohupkubectlport-forward--address0.0.0.0service/grafana13000:3000-n=monitoring& #alertmanager $nohupkubectlport-forward--address0.0.0.0service/alertmanager-main9093:9093-n=monitoring&
用jobs -l可以查看
kube-prometheus 對 arm 的支持
目標是找到 kube-prometheus 用到的鏡像的 arm 版本。
可以使用https://quay.io/[6]搜索。
以下是用到的鏡像和各自對 arm 的支持情況。注意對照自己使用的版本,很多鏡像高版本都支持 arm 了。
未標記(不支持)其實也是可以用,但不保證:
quay.io/prometheus/prometheus:v2.11.0支持 arm(v2.10.0 開始)
quay.io/prometheus/alertmanager:v0.18.0支持 arm(v0.17.0 開始)
quay.io/coreos/kube-state-metrics:v1.8.0未標記(不支持)
quay.io/coreos/kube-rbac-proxy:v0.4.1未標記(不支持)
quay.io/prometheus/node-exporter:v0.18.1支持 arm(v0.18.0 開始)
quay.io/coreos/prometheus-operator:v0.34.0不支持 arm(v0.39 開始)。修改成使用 0.39.0,0.39 以后的 prometheus 要求 k8s 必須 >=1.16
quay.io/coreos/configmap-reload:v0.0.1未標記(不支持)
grafana/grafana:6.4.3官方說支持 arm,但其實不支持,有 bug。
quay.io/coreos/k8s-prometheus-adapter-amd64:v0.5.0未找到 arm 版本鏡像。最新的官方版本已經(jīng)改用 directxman12/k8s-prometheus-adapter:v0.8.4。而 directxman12/k8s-prometheus-adapter:v0.5.0 開始支持 arm。
審核編輯:湯梓紅
-
監(jiān)控系統(tǒng)
+關(guān)注
關(guān)注
21文章
3866瀏覽量
173511 -
大數(shù)據(jù)
+關(guān)注
關(guān)注
64文章
8864瀏覽量
137310 -
云原生
+關(guān)注
關(guān)注
0文章
242瀏覽量
7939 -
kubernetes
+關(guān)注
關(guān)注
0文章
223瀏覽量
8698 -
Prometheus
+關(guān)注
關(guān)注
0文章
27瀏覽量
1707
原文標題:基于 Prometheus 的監(jiān)控神器,看完不信你不會,簡單靈活!
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論