基于DaemonSet的Process Exporter監(jiān)控實踐指南
導語
作為一名Kubernetes管理員,你是否經(jīng)歷過:
- 服務正常卻找不到CPU飆升的根本原因?
- 容器進程異常但無法快速定位根源?
- 缺乏完整的進程級監(jiān)控體系導致故障排查困難?
本文將帶你掌握 Process Exporter 的完整使用鏈路,涵蓋基礎部署、Prometheus集成、Grafana可視化及告警規(guī)則配置,即使是新手也能輕松上手!
一、初識Process Exporter
1.什么是Process Exporter?
- 官方出品:Prometheus生態(tài)標準exporter
- 輕量級:鏡像僅15MB,支持容器/宿主機進程監(jiān)控
- 核心能力:
? 進程CPU/內(nèi)存占用? 文件描述符數(shù)量? 線程數(shù)與運行時長? 支持正則表達式過濾進程
2.為什么必須用它?
對比項 | Node Exporter | Process Exporter |
監(jiān)控粒度 | 節(jié)點級別 | 進程級別(精確到PID) |
核心指標 | CPU/內(nèi)存/磁盤IO | CPU/內(nèi)存/線程/文件描述符 |
典型場景 | 整體資源負載分析 | 異常進程根因定位 |
典型業(yè)務價值:
- 識別惡意進程占用資源
- 監(jiān)控Java應用GC行為
- 分析MySQL連接池耗盡原因
3. 部署控制器選擇
- 全節(jié)點覆蓋:確保每個Worker節(jié)點運行監(jiān)控實例
- 混合監(jiān)控:同時采集容器進程和宿主機關鍵服務(如kubelet、sshd)
- 資源占用優(yōu)化:避免Deployment模式下多副本的資源浪費
二、快速部署Process Exporter
1.架構(gòu)設計圖
2.部署YAML模板
# 1. 創(chuàng)建RBAC權(quán)限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: process-exporter
rules:
- apiGroups: [""]
resources: ["nodes/proxy"]
verbs: ["get", "list", "watch"]
---
# 2. 配置DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: process-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: process-exporter
template:
metadata:
labels:
app: process-exporter
spec:
hostPID: true # 共享宿主機 PID 命名空間
hostNetwork: true # 可選:共享宿主機網(wǎng)絡命名空間
# 添加容忍規(guī)則
tolerations:
- operator: Exists # 容忍所有污點
containers:
- name: process-exporter
image: prometheus/process-exporter:v1.7.0
args:
- "-procfs=/host/proc" # 指定宿主機 /proc 路徑
- "-config.path=/etc/process-exporter/config.yaml"
volumeMounts:
- name: config-volume
mountPath: /etc/process-exporter/config.yaml # 掛載為文件
subPath: config.yaml # 指定子路徑
- name: proc # 掛載宿主機的 /proc
mountPath: /host/proc
readOnly: true
ports:
- containerPort: 9256
resources:
limits:
cpu: "200m"
memory: "256Mi"
securityContext:
capabilities:
add:
- SYS_PTRACE # 允許追蹤進程
- SYS_ADMIN # 可選:訪問宿主機資源
volumes:
- name: config-volume
configMap:
name: process-exporter-config
items: # 明確指定 ConfigMap 的鍵和路徑
- key: config.yaml # ConfigMap 中的鍵名
path: config.yaml # 掛載到容器內(nèi)的文件名
- name: proc
hostPath:
path: /proc # 宿主機 /proc 目錄
---
apiVersion: v1
kind: Service
metadata:
name: process-exporter
namespace: monitoring
labels:
app: process-exporter # 必須與 ServiceMonitor 的 selector 匹配
spec:
ports:
- port: 9256
targetPort: 9256
protocol: TCP
name: http # 端口名稱必須與 ServiceMonitor 的 endpoints.port 匹配
selector:
app: process-exporter # 關聯(lián)到 Deployment 的 Pod 標簽
3.configmap配置
apiVersion: v1
kind: ConfigMap
metadata:
name: process-exporter-config
namespace: monitoring
data:
config.yaml: |
process_names:
- name: "{{.Comm}}" # 進程組名稱模板(使用進程名作為標簽)
cmdline: # 匹配命令行參數(shù)的正則表達式
- '.+' # 匹配所有進程
4.驗證部署
# 查看Pod狀態(tài)
kubectl get pods -n monitoring -l app=process-exporter
# 測試數(shù)據(jù)采集
kubectl exec -it <pod-name> -- curl http://localhost:9103/metrics | grep java_process_cpu_seconds_total
三、與Prometheus監(jiān)控體系集成
1.Prometheus Operator自動接入
步驟1:單獨創(chuàng)建ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: process-exporter
namespace: monitoring
spec:
endpoints:
- port: http
interval: 15s
path: /metrics
relabelings:
- sourceLabels: [__meta_kubernetes_pod_node_name]
targetLabel: node # 自動添加節(jié)點標簽
namespaceSelector:
matchNames:
- monitoring # 監(jiān)控的命名空間
selector:
matchLabels:
app: process-exporter
步驟2:自動化數(shù)據(jù)同步
Operator會自動完成以下操作:
- 創(chuàng)建TargetGroup
- 注冊到Prometheus Server
- 自動生成Recording Rules
2.Grafana看板和指標
(1)關鍵指標
在實際監(jiān)控進程時,主要使用的指標就是cpu和內(nèi)存。
- process-exporter中進程的指標以namedprocess_namegroup開頭:
- namedprocess_namegroup_cpu_seconds_total:cpu使用時間,通過mode區(qū)分是user還是system
- namedprocess_namegroup_memory_bytes:內(nèi)存占用,通過memtype區(qū)分不同的占用類型
- namedprocess_namegroup_num_threads:線程數(shù)
- namedprocess_namegroup_open_filedesc:打開的文件句柄數(shù)
- namedprocess_namegroup_read_bytes_total:進程讀取的字節(jié)數(shù)
- namedprocess_namegroup_thread_context_switches_total:線程上下文切換統(tǒng)計
- namedprocess_namegroup_thread_count:線程數(shù)量統(tǒng)計
- namedprocess_namegroup_thread_cpu_seconds_total:線程的cpu使用時間
- namedprocess_namegroup_thread_io_bytes_total:線程的io
(2)cpu相關
cpu是我們最經(jīng)常關注的指標,如果使用node-exporter采集節(jié)點的指標數(shù)據(jù),可以得到機器的cpu占比。
而使用process-exporter采集的是進程的指標,具體來說就是采集/proc/pid/stat中與cpu時間有關的數(shù)據(jù):
- 第14個字段:utime,進程在用戶態(tài)運行的時間,單位為jiffies
- 第15個字段:stime,進程在內(nèi)核態(tài)運行的時間,單位為jiffies
- 第16個字段:cutime,子進程在用戶態(tài)運行的時間,單位為jiffies
- 第17個字段:cstime,子進程在內(nèi)核態(tài)運行的時間,單位為jiffies
那么通過上述值就可以得到進程的單核CPU占比:
- 進程的單核CPU占比=(utime+stime+cutime+cstime)/時間差
- 進程的單核內(nèi)核態(tài)CPU占比=(stime+cstime)/時間差
因此,進程的單核CPU占比的promsql語句為increase(namedprocess_namegroup_cpu_seconds_total{mode="user",groupname="procname"}[30s])*100/30,單核內(nèi)核態(tài)CPU占比的promsql語句為increase(namedprocess_namegroup_cpu_seconds_total{mode="system",groupname="procname"}[30s])*100/30。
注意:實測發(fā)現(xiàn),process-exporter獲取的數(shù)據(jù)與/proc/pid/stat中的有一定差異,需要進一步看下。
(3)memory
process-exporter采集內(nèi)存的指標時將內(nèi)存分成5種類型:
- resident:進程實際占用的內(nèi)存大小,包括共享庫的內(nèi)存空間,可以從/proc/pid/status中的VmRSS獲取
- proportionalResident:與resident相比,共享庫的內(nèi)存空間會根據(jù)進程數(shù)量平均分配
- swapped:交換空間,系統(tǒng)物理內(nèi)存不足時,會將不常用的內(nèi)存頁放到硬盤的交換空間,可以從/proc/pid/status中的VmSwap獲取
- proportionalSwapped:將可能被交換的內(nèi)存頁按照可能性進行加權(quán)平均
- virtual:虛擬內(nèi)存,描述了進程運行時所需要的總內(nèi)存大小,包括哪些還沒有實際加載到內(nèi)存中的代碼和數(shù)據(jù),可以從/proc/pid/status中的VmSize獲取
對于一般的程序來說,重點關注的肯定是實際內(nèi)存,也就是resident和virtual,分別表示實際在內(nèi)存中占用的空間和應該占用的總空間
(4)看板
process-exporter基于上述指標提供了grafana的面板可以直接導入:https://grafana.com/grafana/dashboards/249-named-processes/
可以看到,面板中的cpu和讀寫是直接基于指標和rate函數(shù)得到的,內(nèi)存則是直接基于指標而來的。
四、配置說明
proces-exporter的配置包括兩部分的配置項,一個是process-exporter的一些參數(shù)控制,另一個是進程信息的配置。
一般來說,exporter都會有幾部分的參數(shù)控制采集:
- config/config.path:指定配置文件路徑
- web.listen-address:指定監(jiān)聽端口,通常都會有默認的端口,prometheus就是訪問該端口獲取指標數(shù)據(jù)
- web.telemetry-path:指標數(shù)據(jù)的url,通常都是/metrics
除了有以上配置項之外,process-exporter還有其他特有的配置項:
- children:如果某個進程被采集,那么它的子進程也屬于該組
- namemapping:名稱映射,
- procfs:proc文件系統(tǒng)的路徑,默認是/proc
- procnames:需要采集的進程名列表
- threads:是否采集線程,默認為是
基于性能的考慮,process-exporter只能對事先配置的進程進行指標采集,因此,需要對進程進行過濾,只采集需要的進程的指標。
在過濾進程時,會將進程進行分組,因此,就會有分組的名稱,以及將進程放到分組的規(guī)則。例如,如果使用deb/rpm安裝process-exporter時,默認的配置文件是:
process_names:
- name: "{{.Comm}}"
cmdline:
- '.+'
process_names是個數(shù)組,每個成員表示一個分組。
name是分組的名稱,這里使用模版。cmdline用于對分組中的進程進行過濾,這里的正則表達式就表示過濾所有進程。
因此,上述配置文件的含義是:采集所有進程的指標數(shù)據(jù),當遍歷到某個進程時,獲取該進程的進程名,然后放到進程名對應的分組。
name字段可以使用固定的字符串,也可以使用以下模版:
- {{.Comm}}:進程名
- {{.ExeBase}}:可執(zhí)行文件的文件名,與進程的區(qū)別是,進程名有長度15的限制
- {{.ExeFull}}:可執(zhí)行文件的全路徑
- {{.Username}}:進程的有效用戶名
- {{.Matches}}:用正則匹配cmdline等字段時得到的匹配項的map,例如下面的Cfgfile
- {{.PID}}:pid,使用pid表示這個組只會有這一個進程
- {{.StartTime}}:進程的起始時間
- {{.Cgroups}}:進程的cgoup,可以用于區(qū)分不同的容器
進行分組進程過濾除了使用cmdline字段,還可以使用comm和exe,分別表示進程名和二進制路徑,并且遵循以下規(guī)則:
- 如果使用了多個字段,則必須都匹配,例如,如果既使用了comm,又使用了exe,兩個過濾必須都滿足
- 對于comm和exe,它們是字符串數(shù)組,并且是OR的關系
- 對于cmdline,則是正則表達式數(shù)組,并且是AND的關系
例如:
process_names:
# 進程名過濾,超過15個字符會被截斷
- comm:
- bash
# argv[0],如果開頭不是/,說明匹配進程名
# 如果開頭是/,則需要使用二進制路徑全匹配
- exe:
- postgres
- /usr/local/bin/prometheus
# 如果使用多個字段進行匹配,則需要都匹配
- name: "{{.ExeFull}}:{{.Matches.Cfgfile}}"
exe:
- /usr/local/bin/process-exporter
cmdline:
- -config.path\s+(?P<Cfgfile>\S+)
# 監(jiān)控NVIDIA GPU進程
filter:
- name: gpu-process
pattern: "^nvidia-smi"
env: ["NVIDIA_VISIBLE_DEVICES=all"]
五、結(jié)語
通過DaemonSet部署的Process Exporter,配合Prometheus Operator和Grafana看板,可構(gòu)建覆蓋 容器進程-宿主機服務-硬件資源 的全維度監(jiān)控體系。建議按照以下步驟落地:
- 分階段實施:從測試環(huán)境到生產(chǎn)逐步推進
- 制定監(jiān)控SLA:明確不同級別進程的監(jiān)控指標閾值
- 定期演練:模擬進程異常驗證告警有效性
延伸學習
- 官方文檔:https://process_exporter.readthedocs.io
- Kubernetes監(jiān)控白皮書(https://example.com/k8s-monitoring-whitepaper)