kube-prometheus-stack 运行手册(RUNBOOK)¶
适用对象:接手
monitoring命名空间日常运维与值班的人。目标是拿着就能做,不假设你熟悉 Prometheus Operator。 变更实施与回滚过程见同目录 SOP.md;本文面向"平时怎么用、怎么查、怎么救"。
目录¶
一、服务概览¶
1.1 这是什么¶
集群 rainchen-k8s 的统一监控与可视化平台,由 Helm chart kube-prometheus-stack 交付,负责采集集群与业务指标、评估告警规则、提供看板。
1.2 组件构成¶
| 组件 | 工作负载 | 副本 | 作用 | 缺失时的后果 |
|---|---|---|---|---|
| Prometheus | StatefulSet prometheus-kube-prometheus-stack-prometheus |
1 | 采集与存储时序数据、评估告警规则 | 指标断档,AI 侧全部查询失败 |
| Alertmanager | StatefulSet alertmanager-kube-prometheus-stack-alertmanager |
1 | 告警去重、分组、抑制、发送 | 告警不再外发(当前未接渠道,影响有限) |
| Grafana | Deployment kube-prometheus-stack-grafana |
1 | 看板与查询入口 | 无法看图,Prometheus 直查仍可用 |
| Prometheus Operator | Deployment kube-prometheus-stack-operator |
1 | 依据 CR 生成并维护上述工作负载、注入配置 | 改了 CR 不会生效;既有 Pod 不受影响 |
| kube-state-metrics | Deployment kube-prometheus-stack-kube-state-metrics |
1 | 把 K8s 对象状态转成指标 | 所有 kube_* 指标消失,工作负载类看板空白 |
| node-exporter | DaemonSet kube-prometheus-stack-prometheus-node-exporter |
4(每节点一个) | 采集节点 CPU/内存/磁盘/网络 | 对应节点指标消失 |
| kubelet / apiserver 抓取 | 无独立工作负载,由 ServiceMonitor 定义 | - | 采集控制面与 kubelet 指标 | 对应 target 变 down |
1.3 依赖¶
| 依赖 | 说明 | 缺失时的直接后果 |
|---|---|---|
NFS 服务端 192.168.31.249 |
提供全部持久化:Prometheus(HDD)、Grafana 与 Alertmanager(SSD) | Prometheus 挂载丢失后会卡在 IO 等待或重启;该主机同时承载 4 台 k8s 节点的 qcow2 磁盘,属同源故障域 |
| traefik | 提供 *.rainchen.top 的 HTTPS 入口(k8s-master-01 hostPort 443) |
域名不可访问,port-forward 方式不受影响 |
| CoreDNS | 集群内服务名解析 | 组件间互相抓取失败 |
内部 CA 证书 traefik-selfsigned-tls |
位于 traefik 命名空间 |
浏览器证书告警加重 |
1.4 重要性等级¶
中。监控系统故障不影响业务链路,但会在故障发生时让你"看不见"。因此它自身的可用性问题应当天处理,不必按 P0 对待。
二、接入与凭据¶
2.1 访问地址¶
| 入口 | 地址 | 认证 | 备注 |
|---|---|---|---|
| Prometheus Web UI | https://prometheus.rainchen.top | 无认证 | 可直接查询与看图;属已知信息暴露面,见第九章 |
| Grafana | https://grafana.rainchen.top | 账号密码 | 看板与即席查询 |
| Alertmanager | 无对外路由 | 无认证 | 只能 port-forward 访问,见 2.3 |
| Prometheus API | https://prometheus.rainchen.top/api/v1/... | 无认证 | 脚本化查询走这里 |
若客户端未配 DNS,可在命令里用
--resolve指定入口 IP:curl -sk --resolve prometheus.rainchen.top:443:192.168.31.10 https://prometheus.rainchen.top/-/ready。
2.2 凭据清单¶
| 凭据 | 用途 | 存放位置 | 取用命令 |
|---|---|---|---|
| Grafana admin 密码 | 登录 Grafana | Kubernetes Secret grafana-admin(monitoring 命名空间) |
kubectl -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-password}' | base64 -d; echo |
| Grafana admin 用户名 | 同上 | 同上(键 admin-user) |
固定为 admin |
| 集群 kubeconfig | kubectl / helm 操作 | 本机 ~/.kube/config |
已就绪,默认 context kubernetes-admin@kubernetes |
| NFS 服务端 root | 直接查看/备份存储数据 | ssh root@192.168.31.249 |
需另行获取凭据,本手册不涉及 |
| 集群节点 root | 节点侧排障 | ssh root@192.168.31.10(master,已验证免密钥) |
无需密码 |
文档内不记录任何密码明文。若
grafana-admin的密码遗失,见 5.3 轮换 Grafana admin 密码。
2.3 本地端口转发(无 DNS 或需访问 Alertmanager 时)¶
# Prometheus → 本机 19090
kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 19090:9090
# Grafana → 本机 13000
kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 13000:80
# Alertmanager → 本机 19093(唯一的访问方式,无对外路由)
kubectl -n monitoring port-forward svc/kube-prometheus-stack-alertmanager 19093:9093
预期:终端打印 Forwarding from 127.0.0.1:19090 -> 9090 并保持占用;另开终端访问 http://localhost:19090。中断后重跑即可(无状态)。
三、日常速查表¶
| 目的 | 命令 |
|---|---|
| 看全局是否健康 | kubectl -n monitoring get pods -o wide |
| 看事件(异常优先) | kubectl -n monitoring get events --sort-by=.lastTimestamp \| tail -20 |
| 看某组件日志 | kubectl -n monitoring logs -f statefulset/prometheus-kube-prometheus-stack-prometheus |
| 抓取目标是否有掉线 | kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 19090:9090 & 后 curl -s http://localhost:19090/api/v1/targets \| python3 -c 'import sys,json;d=json.load(sys.stdin)["data"]["activeTargets"];print(len(d),[t["labels"]["job"] for t in d if t["health"]!="up"])' |
| 重启 Grafana | kubectl -n monitoring rollout restart deployment/kube-prometheus-stack-grafana |
| 重启 Prometheus | kubectl -n monitoring delete pod prometheus-kube-prometheus-stack-prometheus-0 |
| 看告警(当前 firing) | 浏览器打开 https://prometheus.rainchen.top/alerts |
| 改配置并生效 | 编辑 prometheus_deploy/values.yaml 后 helm upgrade --install kube-prometheus-stack prometheus_deploy/charts/kube-prometheus-stack-91.4.1.tgz -n monitoring -f prometheus_deploy/values.yaml --timeout 30m --wait |
| 备份 Grafana 看板 | 见 6.2 |
| 回滚上次变更 | helm history kube-prometheus-stack -n monitoring 找到上一个 deployed 的 revision 后 helm rollback kube-prometheus-stack <revision> -n monitoring |
| 查组件资源占用 | kubectl -n monitoring top pods |
| 查 PVC 用量 | kubectl -n monitoring get pvc |
四、日常操作¶
4.1 状态检查¶
kubectl -n monitoring get pods -o wide
# 预期:9 个 Pod 全 Running,RESTARTS 为 0 或历史值
# 不符时:kubectl -n monitoring describe pod <Pod名> 看 Events 段
kubectl -n monitoring get pvc
# 预期:3 个 PVC 均 Bound
# 不符时:见第八章「PVC 未绑定」
kubectl -n monitoring get prometheus,alertmanager -o wide
# 预期:两个 CR 的 READY 为 1/1,STATUS 正常
4.2 重启¶
| 对象 | 命令 | 说明 |
|---|---|---|
| Grafana | kubectl -n monitoring rollout restart deployment/kube-prometheus-stack-grafana |
滚动重建,约 30 秒;会写入 restartedAt 注解(不影响功能) |
| kube-state-metrics | kubectl -n monitoring rollout restart deployment/kube-prometheus-stack-kube-state-metrics |
同上 |
| operator | kubectl -n monitoring rollout restart deployment/kube-prometheus-stack-operator |
重启期间 CR 变更不生效,约 20 秒 |
| node-exporter | kubectl -n monitoring rollout restart daemonset/kube-prometheus-stack-prometheus-node-exporter |
4 个节点依次重建 |
| Prometheus | kubectl -n monitoring delete pod prometheus-kube-prometheus-stack-prometheus-0 |
不要对其用 rollout restart:该 StatefulSet 由 operator 托管,注解会被覆盖 |
| Alertmanager | kubectl -n monitoring delete pod alertmanager-kube-prometheus-stack-alertmanager-0 |
同上,由 operator 托管 |
Prometheus 重启后需重新加载 TSDB,/-/ready 通常 10~30 秒内返回 200:
kubectl -n monitoring get pod prometheus-kube-prometheus-stack-prometheus-0 -w
# 预期:最终 READY 2/2(含 config-reloader 边车)
4.3 扩缩容¶
| 目标 | 操作 | 生效方式 |
|---|---|---|
| 提高 Prometheus 资源上限 | 改 values.yaml 中 prometheus.prometheusSpec.resources |
helm upgrade 后 Pod 重建 |
| 提高保留期 | 改 prometheus.prometheusSpec.retention 或 retentionSize |
helm upgrade;operator 更新 CR,无需重建 Pod |
| 扩大磁盘 | 改 prometheus.prometheusSpec.storageSpec...storage 后 helm upgrade |
PVC 支持在线扩容(SC 的 allowVolumeExpansion: true);只能增不能减 |
| Prometheus 副本数(HA) | 改 prometheus.prometheusSpec.replicas: 2 + podAntiAffinity |
属独立变更,需评估;两副本不会自动去重 |
| Grafana 副本数 | 改 grafana.replicas |
多副本需共享数据库或接受 SQLite 不一致,一般保持 1 |
4.4 查看日志¶
# Prometheus 主容器
kubectl -n monitoring logs statefulset/prometheus-kube-prometheus-stack-prometheus -c prometheus --since=30m
# 只找错误(先定位再过滤,避免全量读取)
kubectl -n monitoring logs statefulset/prometheus-kube-prometheus-stack-prometheus -c prometheus --since=2h \
| grep -iE 'error|fail|fatal|timeout|no space|denied'
# Grafana(多容器:grafana / 两个 sidecar)
kubectl -n monitoring logs deployment/kube-prometheus-stack-grafana -c grafana --since=30m
# operator(看 CR 处理失败原因,最常用来解释"改了为什么不生效")
kubectl -n monitoring logs deployment/kube-prometheus-stack-operator --since=30m | grep -iE 'error|fail|level=error'
4.5 进入容器与主机排障¶
Prometheus、Grafana、node-exporter、kube-state-metrics 均为 distroless 镜像,容器内没有 shell,kubectl exec -it <pod> -- sh 会报 executable file not found。替代手段:
# 手段一:多数问题看日志与事件即可,优先用 4.1 / 4.4
# 手段二:需要看容器内文件时,挂到临时调试容器(会拉取 busybox,节点网络慢时较久)
kubectl -n monitoring debug pod/prometheus-kube-prometheus-stack-prometheus-0 -it --image=busybox:1.38.0
# 手段三:看持久化数据是否真的写进去了 —— 直接在 NFS 服务端看
ssh root@192.168.31.249 'ls -l /srv/nfs/k8s-hdd/ && du -sh /srv/nfs/k8s-hdd/pvc-*'
# 手段四:节点侧排障(网络、磁盘、kubelet)
ssh root@192.168.31.10 'journalctl -u kubelet --since "30 min ago" | grep -iE "error|fail" | tail -20'
五、配置管理¶
5.1 配置的四个层次¶
| 层次 | 位置 | 改法 | 生效方式 |
|---|---|---|---|
| 部署参数(唯一推荐入口) | prometheus_deploy/values.yaml |
编辑后跑 helm upgrade |
依参数而定:改 CR 字段由 operator 更新;改 Pod 模板触发重建 |
| 告警规则 | chart 内置(30 个 PrometheusRule),可另加自定义 | 新增自定义 PrometheusRule 或改 defaultRules.rules.* 开关 |
operator 自动重载,秒级生效 |
| 抓取目标 | ServiceMonitor / PodMonitor CR | 新建 CR 并打上 release: kube-prometheus-stack 标签 |
operator 自动重载 |
| 运行时数据 | Prometheus / Grafana PVC 内的数据 | 不直接改,走界面或 API | 立即 |
5.2 标准变更流程¶
基线状态(2026-10-03 起):
values.yaml已回写为现场完整基线(含 Alertmanager 邮件路由与抑制、 GrafananodeSelector/内存、node-exporter relabel),单文件-f values.yaml升级不再丢配置 —— 变更过程与复核判据见prometheus-baseline-align-20261003/docs/SOP.md。 唯一例外:SMTP 授权码不入库,升级时须额外注入--set alertmanager.config.global.smtp_auth_password="$SMTP_AUTH_PASSWORD", 取值来源见dell-r620-monitor-20260929/config/monitor.yaml的alertmanager.smtp.password_file/password_var。
cd prometheus_deploy
# 1) 改前先留档(高危动作前必做)
mkdir -p backup/manifests
helm get manifest kube-prometheus-stack -n monitoring > backup/manifests/pre-upgrade-$(date +%Y%m%d-%H%M%S).yaml
helm get values kube-prometheus-stack -n monitoring > backup/values/pre-upgrade-$(date +%Y%m%d-%H%M%S).yaml
# 2) 编辑 values.yaml 后先预演,确认渲染无异常
helm template kube-prometheus-stack charts/kube-prometheus-stack-91.4.1.tgz -n monitoring -f values.yaml > /dev/null
# 预期:无输出即渲染成功;报 values 校验错误则说明参数名写错,对照 charts/values-default-91.4.1.yaml 核对
# 3) 比对将要发生的变化
helm template kube-prometheus-stack charts/kube-prometheus-stack-91.4.1.tgz -n monitoring -f values.yaml | kubectl diff -f -
# 预期:只列出你确实想改的对象;出现意外对象说明 values 改错了地方
# 注意:带 helm.sh/hook 注解的 admission 资源会恒定报差异,属已知噪音,忽略即可
# 4) 执行(授权码不入库,须运行时注入;先 source 取值、禁止打印)
helm upgrade --install kube-prometheus-stack charts/kube-prometheus-stack-91.4.1.tgz \
-n monitoring -f values.yaml \
--set alertmanager.config.global.smtp_auth_password="$SMTP_AUTH_PASSWORD" \
--timeout 30m --wait
# 预期:STATUS: deployed
# 5) 验证(见第七章与 SOP 第六章)
kubectl -n monitoring get pods
易错点
| 易错点 | 后果 | 规避 |
|---|---|---|
直接用 kubectl edit 改 Deployment/StatefulSet |
与 helm 的期望状态漂移,下次 helm upgrade 可能被覆盖;gen 与 revision 对不上 |
一切改动回 values.yaml |
| 改 CRD 后忘记 CRD 是独立管理的 | helm upgrade 不会更新 CRD |
CRD 变更需单独 kubectl apply --server-side -f prometheus_deploy/manifests/crds/ |
对 operator 托管的 StatefulSet 用 rollout restart |
注解被 operator 覆盖,看似无效果 | 用 delete pod,让 STS 重建 |
忘记 --timeout 30m |
节点网络慢时必然超时失败 | 固定带上该参数 |
自定义 ServiceMonitor 未打 release 标签 |
Prometheus 不采集它,且无任何报错 | 加 labels: {release: kube-prometheus-stack} |
5.3 轮换 Grafana admin 密码¶
# 生成新密码并原地更新 Secret(不改 values,不影响其他配置)
NEW_PW="$(openssl rand -base64 24 | tr -d '/+=' | cut -c1-18)"
kubectl -n monitoring create secret generic grafana-admin \
--from-literal=admin-user=admin --from-literal=admin-password="$NEW_PW" \
--dry-run=client -o yaml | kubectl apply -f -
# 重启 Grafana 使新凭据生效
kubectl -n monitoring rollout restart deployment/kube-prometheus-stack-grafana
kubectl -n monitoring rollout status deployment/kube-prometheus-stack-grafana --timeout=3m
验证:用新密码登录 https://grafana.rainchen.top,或
kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 13000:80 &
curl -s -u "admin:$NEW_PW" http://localhost:13000/api/health
# 预期:{"database":"ok","version":"13.2.2",...}
最后把 prometheus_deploy/logs/grafana-admin-password.txt 更新为新密码并保持 600 权限。
六、备份与恢复¶
6.1 备份对象与策略¶
| 对象 | 数据重要度 | 备份方式 | 建议频率 |
|---|---|---|---|
| Grafana 看板与数据源定义 | 高(人工调整过的看板丢了要重画) | API 导出 JSON(见 6.2) | 每次改看板后 |
| Grafana 数据库(含用户、偏好) | 中 | NFS 服务端目录打包 | 每月 |
| Prometheus TSDB | 低(历史指标,过期即弃) | NFS 服务端目录打包 | 按需,一般不备 |
| helm release 定义 | 高(重建依据) | helm get manifest / get values |
每次变更前 |
| CRD 定义 | 高(重建依据) | 已在 prometheus_deploy/manifests/crds/ |
随交付目录版本管理 |
| 定制 values | 高 | 已在 prometheus_deploy/values.yaml |
随交付目录版本管理 |
NFS 服务端上的实际目录名来自 PV 的 volumeHandle,例如 Grafana 为
/srv/nfs/k8s/pvc-5ca538f8-7751-4ab2-b706-9292b635cb58。用kubectl get pv -o custom-columns='SC:.spec.storageClassName,HANDLE:.spec.csi.volumeHandle'可查当前对应关系。
6.2 手工备份¶
# —— Grafana:导出全部看板 JSON ——
kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 13000:80 &
PW=$(kubectl -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-password}' | base64 -d)
mkdir -p backup/grafana-dashboards
for uid in $(curl -s -u "admin:$PW" 'http://localhost:13000/api/search?type=dash-db&limit=500' \
| python3 -c 'import sys,json;print(" ".join(d["uid"] for d in json.load(sys.stdin)))'); do
curl -s -u "admin:$PW" "http://localhost:13000/api/dashboards/uid/$uid" \
| python3 -c 'import sys,json;print(json.dumps(json.load(sys.stdin),ensure_ascii=False,indent=1))' \
> "backup/grafana-dashboards/$uid.json"
done
ls backup/grafana-dashboards | wc -l
# 预期:25 个 json 文件
# —— Grafana / Alertmanager 数据目录(在 NFS 服务端 192.168.31.249 上执行,需 root)——
ssh root@192.168.31.249 'mkdir -p /data/backup && \
tar czf /data/backup/grafana-pvc-$(date +%Y%m%d).tar.gz -C /srv/nfs/k8s pvc-5ca538f8-7751-4ab2-b706-9292b635cb58 && \
ls -lh /data/backup/grafana-pvc-$(date +%Y%m%d).tar.gz'
# —— helm release 定义 ——
mkdir -p backup/manifests backup/values
helm get manifest kube-prometheus-stack -n monitoring > backup/manifests/$(date +%Y%m%d-%H%M%S)-manifest.yaml
helm get values kube-prometheus-stack -n monitoring > backup/values/$(date +%Y%m%d-%H%M%S)-values.yaml
Prometheus 默认未开 admin API,无法用快照接口做一致性备份;其数据为可再采集的历史指标,建议不备份,需要长期保留时改走远端写入(属独立变更)。
6.3 恢复¶
场景一:Grafana 看板被误删或数据卷重建
kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 13000:80 &
PW=$(kubectl -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-password}' | base64 -d)
# 逐个导回(覆盖同 uid 的同名看板)
for f in backup/grafana-dashboards/*.json; do
curl -s -u "admin:$PW" -X POST -H 'Content-Type: application/json' \
-d "{\"dashboard\": $(cat "$f" | python3 -c 'import sys,json;d=json.load(sys.stdin);print(json.dumps(d.get("dashboard",d)))'), \"overwrite\": true}" \
http://localhost:13000/api/dashboards/db > /dev/null
done
curl -s -u "admin:$PW" 'http://localhost:13000/api/search?type=dash-db&limit=500' \
| python3 -c 'import sys,json;print("恢复后看板数:",len(json.load(sys.stdin)))'
# 预期:25
场景二:整套栈重建
按 prometheus_deploy/SOP.md 第五章顺序执行即可(CRD → 命名空间 → 凭据 → helm → 路由),values 与 chart 包均已在交付目录内,不依赖外网仓库。
场景三:从 NFS 服务端恢复 Grafana 数据目录(含用户与偏好)
# 高危:会覆盖当前 Grafana 数据,先停 Grafana 避免写入
kubectl -n monitoring scale deployment/kube-prometheus-stack-grafana --replicas=0
ssh root@192.168.31.249 'cd /srv/nfs/k8s/pvc-5ca538f8-7751-4ab2-b706-9292b635cb58 && \
tar xzf /data/backup/grafana-pvc-<日期>.tar.gz --strip-components=0 -C .'
kubectl -n monitoring scale deployment/kube-prometheus-stack-grafana --replicas=1
kubectl -n monitoring rollout status deployment/kube-prometheus-stack-grafana --timeout=3m
恢复后验证:Grafana /api/health 返回 database: ok,且看板数量与备份时一致。
6.4 演练记录¶
| 日期 | 演练内容 | 结果 |
|---|---|---|
| 2026-09-17 | 幂等复跑:重复执行 apply 与 helm upgrade | 通过。apply 全部 unchanged,Pod/PVC uid 未变,零重建(详见 SOP 6.6) |
| 2026-09-19 | 数据落盘核对:head series 87,571、TSDB 1113 MiB | 通过。数据确实写入 srv/nfs/k8s-hdd |
| - | 备份恢复演练(Grafana 看板导出/导回、数据卷恢复) | 未执行,建议上线后一月内补做 |
七、监控与告警¶
7.1 看哪里¶
| 目的 | 入口 |
|---|---|
| 看集群总览 | Grafana → Kubernetes / Compute Resources / Cluster |
| 看某节点 | Grafana → Kubernetes / Compute Resources / Node |
| 看某工作负载 | Grafana → Kubernetes / Compute Resources / Workload |
| 即席查询 | https://prometheus.rainchen.top/graph |
| 看告警规则与当前状态 | https://prometheus.rainchen.top/alerts |
| 看告警详情与静默 | Alertmanager:kubectl -n monitoring port-forward svc/kube-prometheus-stack-alertmanager 19093:9093 → http://localhost:19093 |
7.2 当前能力边界(重要)¶
| 项 | 现状 | 影响 |
|---|---|---|
| 告警外发 | 未接入任何渠道,Alertmanager 的 receiver 为 null |
告警不会主动通知你,必须主动看 /alerts 页面 |
| 控制面指标 | etcd / kube-scheduler / kube-controller-manager / kube-proxy 未采集 | 这四类故障无法通过本平台提前发现 |
| 采集范围 | 集群内置指标 + 各命名空间暴露的 ServiceMonitor | 业务自定义指标需自行创建 ServiceMonitor |
7.3 需要重点盯的告警¶
| 告警 | 含义 | 阈值 | 处置方向 |
|---|---|---|---|
KubeHpaMaxedOut |
某 HPA 持续处于最大副本数 | 15 分钟 | 该业务已达扩容上限,需评估提高 maxReplicas 或加资源。当前正处于 firing:server 命名空间的 gitlab-sidekiq-all-in-1-v2(1→2 已顶满) |
KubePodCrashLooping |
Pod 反复重启 | 15 分钟内多次 | 见第八章「Pod 无法启动」 |
KubePersistentVolumeFillingUp |
PVC 使用率过高 | >85% 持续 | 见第八章「磁盘写满」 |
KubeletDown / KubeNodeNotReady |
节点或 kubelet 掉线 | 即时 | 上节点查 kubelet 与网络 |
PrometheusTSDBCompactionsFailing |
TSDB 压缩失败 | 即时 | 多为存储 IO 异常,见第八章「存储异常」 |
Watchdog |
心跳告警,设计上恒定 firing | - | 正常现象,看到它说明告警链路本身是通的,无需处理 |
7.4 平台自身的健康指标(自查)¶
| 指标 | 健康值 | 含义 |
|---|---|---|
up == 1 的目标数 |
26(随 ServiceMonitor 增减) | 抓取目标总量 |
count(up == 0) |
0(无掉线目标时该表达式返回空结果集,不是 0) | 掉线目标数,建议用 count(up) - count(up==1) 替代查询以恒有数值 |
prometheus_tsdb_head_series |
当前约 8.8 万 | 活跃时间线数,突增说明 label 基数异常 |
prometheus_tsdb_storage_blocks_bytes |
当前约 866 MB | 已落盘的块大小 |
prometheus_tsdb_wal_storage_size_bytes |
当前约 251 MB | WAL 大小,持续增长不回落说明 compaction 有问题 |
prometheus_tsdb_compaction_duration_seconds |
观察趋势 | 变长说明存储 IO 变差(本平台 TSDB 在 HDD 上,需重点关注) |
一键自查:
kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 19090:9090 &
for q in 'count(up==1)' 'count(up) - count(up==1)' 'prometheus_tsdb_head_series' 'prometheus_tsdb_wal_storage_size_bytes'; do
printf '%-45s ' "$q"
curl -s --get --data-urlencode "query=$q" http://localhost:19090/api/v1/query \
| python3 -c 'import sys,json;d=json.load(sys.stdin)["data"]["result"];print(d[0]["value"][1] if d else "无数据")'
done
# 预期:26 / 0 / 8.7 万量级 / 约 2.5 亿(bytes,即 ~244 MiB)
# 说明:用 count(up) - count(up==1) 而非 count(up==0),因为后者在无掉线目标时返回空结果集
八、故障处置¶
场景 1:抓取目标掉线(Prometheus 显示某些 target 非 up)¶
症状:https://prometheus.rainchen.top/targets 出现红色 target;Grafana 上对应看板出现断点。
诊断
kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 19090:9090 &
# 1) 列出非 up 的 target 及其错误原因
curl -s http://localhost:19090/api/v1/targets | python3 -c '
import sys,json
for t in json.load(sys.stdin)["data"]["activeTargets"]:
if t["health"] != "up":
print(t["labels"].get("job"), t["scrapeUrl"], "|", t.get("lastError","")[:150])'
# 预期:无输出(当前 26/26 全 up)
# 2) 若 job 为 kubelet:确认目标节点 kubelet 是否在服务
ssh root@192.168.31.10 'systemctl is-active kubelet && curl -sk https://localhost:10250/healthz'
# 预期:active 与 ok
# 3) 若 job 为 kube-apiserver:确认 token Secret 是否存在
kubectl -n monitoring get secret kube-prometheus-stack-prometheus-token
# 预期:存在(chart 自动创建,供 apiserver/kubelet 抓取使用)
处置
| 诊断结果 | 处置 |
|---|---|
| 单个节点相关 target 掉线 | 该节点 kubelet 异常 → ssh root@<节点> 'systemctl restart kubelet'(先确认节点上无关键业务正在运行) |
| 全部 target 掉线 | Prometheus 自身问题 → 见场景 2 |
| 仅自定义业务 target 掉线 | 检查目标的 ServiceMonitor 标签与业务自身的 metrics 端点 |
| apiserver target 报 401/403 | token Secret 丢失 → helm upgrade --install(参数见 5.2)重建 |
验证
curl -s http://localhost:19090/api/v1/query --get --data-urlencode 'query=count(up==0)' \
| python3 -c 'import sys,json;d=json.load(sys.stdin)["data"]["result"];print("掉线目标数:",d[0]["value"][1] if d else 0)'
# 预期:0
场景 2:Pod 无法启动 / 反复重启¶
症状:kubectl -n monitoring get pods 出现 CrashLoopBackOff、ImagePullBackOff、Pending 或 Init:Error。
诊断
# 1) 先看 Pod 处于什么状态、上一次为什么退出
kubectl -n monitoring get pods
kubectl -n monitoring describe pod <Pod名> | tail -25 # 看 Events 段
# 2) 按状态分流
# 2a) ImagePullBackOff:确认镜像可达性(本集群需直连海外仓库,偶发超时)
kubectl -n monitoring get events --field-selector involvedObject.name=<Pod名> --sort-by=.lastTimestamp | tail -5
# 预期出现 "Failed to pull image ... TLS handshake timeout" 之类
# 2b) CrashLoopBackOff:看上次退出原因
kubectl -n monitoring logs <Pod名> --previous --tail=50
# 2c) Pending:看调度原因
kubectl -n monitoring describe pod <Pod名> | grep -A5 Events
处置
| 状态 | 处置 |
|---|---|
ImagePullBackOff |
多为节点到仓库网络抖动,等待自动重试;持续失败则手动预热:ssh root@<Pod所在节点> 'crictl pull <镜像>'。仍失败则需检查节点出网策略 |
CrashLoopBackOff(Prometheus) |
常见为 TSDB 目录不可写或 WAL 损坏。先看日志中是否 permission denied / not a directory;权限问题见场景 3 |
CrashLoopBackOff(Grafana) |
常见为 SQLite 数据库损坏。可临时用备份的 grafana.db 覆盖(见 6.3 场景三) |
Pending |
资源不足或污点未容忍。kubectl -n monitoring describe pod <Pod名> 会直接给出原因;节点资源不足则先释放其他工作负载 |
| 全部 Prometheus 侧组件异常,且改动刚发生 | 回滚:helm history kube-prometheus-stack -n monitoring → helm rollback kube-prometheus-stack <上一个 deployed 的 revision> -n monitoring |
验证
kubectl -n monitoring get pods
# 预期:目标 Pod 转为 Running 且 RESTARTS 停止增长(观察 5 分钟)
场景 3:PVC 未绑定或存储异常(Prometheus 卡在 IO 等待)¶
症状:PVC 处于 Pending;或 Prometheus 日志出现 no space left on device、input/output error、stale file handle、进程处于 D 状态。
诊断
# 1) PVC 状态与绑定关系
kubectl -n monitoring get pvc
kubectl -n monitoring describe pvc <PVC名> | tail -15
# 预期:Bound;Pending 时 Events 段会给出 provisioner 报错
# 2) 确认 NFS 服务端可达(这是最关键的一步)
ssh root@192.168.31.10 'showmount -e 192.168.31.249; df -h /srv/nfs 2>/dev/null'
timeout 10 ssh root@192.168.31.249 'df -h / /data; ls -l /srv/nfs/k8s-hdd | head'
# 预期:能列出导出与目录。超时或 refused 说明 NFS 服务端故障
# 3) 看 Prometheus 是否在等 IO
kubectl -n monitoring logs statefulset/prometheus-kube-prometheus-stack-prometheus -c prometheus --since=30m \
| grep -iE 'no space|i/o error|stale|permission|timeout'
处置
| 诊断结果 | 处置 |
|---|---|
| NFS 服务端不可达 | 恢复 192.168.31.249 的 NFS 服务(属宿主机侧故障,注意该机同时承载 4 台 k8s 节点磁盘,重启它会波及整个集群,需先确认影响面) |
| PVC Pending 且 provisioner 报错 | 检查 SC 与 mount-options Secret:kubectl -n kube-system get secret nfs-mount-options;必要时重建 PVC(高危:Delete 策略会丢数据) |
no space left on device |
见场景 4 |
| 权限问题(容器以 nobody 运行) | 确认 values.yaml 中 securityContext.fsGroup: 65534 未被改动,且 NFS 导出含 no_root_squash |
验证
kubectl -n monitoring get pvc
# 预期:Bound
kubectl -n monitoring logs statefulset/prometheus-kube-prometheus-stack-prometheus -c prometheus --since=5m | tail -20
# 预期:无 IO 错误,且出现 TSDB 正常写入/压缩相关日志
场景 4:Prometheus 磁盘将满¶
症状:告警 KubePersistentVolumeFillingUp;或 /api/v1/status/tsdb 显示数据量接近上限。
诊断
kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 19090:9090 &
# 1) 当前占用
curl -s --get --data-urlencode 'query=kubelet_volume_stats_used_bytes{namespace="monitoring",persistentvolumeclaim=~"prometheus.*"}/1024/1024/1024' \
http://localhost:19090/api/v1/query | python3 -c 'import sys,json;d=json.load(sys.stdin)["data"]["result"];print("占用 GiB:",round(float(d[0]["value"][1]),2) if d else "无数据")'
# 预期:当前约 1.1 GiB(配额 100 GiB)
# 2) 时间线规模
curl -s http://localhost:19090/api/v1/status/tsdb | python3 -c 'import sys,json;print("head series:",json.load(sys.stdin)["data"]["headStats"]["numSeries"])'
处置
| 情况 | 处置 |
|---|---|
| 数据正常增长但接近上限 | 确认 retentionSize: 90GiB 已生效(它会先于写满自动清理);如需更长保留期,扩容 PVC(见 4.3) |
| series 异常暴涨 | 定位来源:curl -s http://localhost:19090/api/v1/status/tsdb 的 seriesCountByMetricName 前几位,多为某业务的 label 基数爆炸,找业务方收敛 |
| 确认要立即释放空间 | 临时降低 retention 后 helm upgrade(如 7d),数据会在下一轮清理时释放 |
验证:占用停止增长,且 retentionSize 相关清理日志出现在 Prometheus 日志中。
场景 5:Grafana 无法登录或看不到看板¶
症状:浏览器 401/502;登录后侧边栏没有 Kubernetes 看板。
诊断
# 1) Grafana 进程健康
kubectl -n monitoring get pod -l app.kubernetes.io/name=grafana
kubectl -n monitoring logs deployment/kube-prometheus-stack-grafana -c grafana --tail=50 | grep -iE 'error|fail|level=error'
# 2) 凭据是否正确
PW=$(kubectl -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-password}' | base64 -d)
kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 13000:80 &
curl -s -o /dev/null -w '%{http_code}\n' -u "admin:$PW" http://localhost:13000/api/health
# 预期:200。401 说明 Secret 中的密码与你在用的不一致(可能刚轮换过)
# 3) 看板为何缺失:看 sidecar 是否把 ConfigMap 转成了看板
kubectl -n monitoring logs deployment/kube-prometheus-stack-grafana -c grafana-sc-dashboard --tail=30
curl -s -u "admin:$PW" 'http://localhost:13000/api/search?type=dash-db&limit=500' \
| python3 -c 'import sys,json;print("看板数:",len(json.load(sys.stdin)))'
# 预期:25
处置
| 诊断结果 | 处置 |
|---|---|
| 401 | 用 kubectl -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-password}' \| base64 -d 取当前密码;若确需重置见 5.3 |
| 502 / Pod 非 Running | 见场景 2 |
| 看板数为 0 且 sidecar 日志报错 | sidecar 未能读取 ConfigMap:确认 kubectl -n monitoring get cm \| grep grafana 有 25 个看板 ConfigMap;缺失则 helm upgrade 重建 |
| 数据源报错 | 确认 Prometheus Service 可达:kubectl -n monitoring get svc kube-prometheus-stack-prometheus |
验证:/api/health 返回 200 且 database: ok,看板数为 25,随机打开一个看板能出图。
场景 6:域名无法访问(入口层)¶
症状:浏览器打不开两个域名,但集群内 Pod 正常。
诊断
# 1) traefik 是否在运行、是否占着宿主 443
kubectl -n traefik get pods -o wide
ssh root@192.168.31.10 'ss -lntp | grep -E ":80|:443"'
# 预期:traefik 进程监听 80 与 443
# 2) 路由是否存在
kubectl -n monitoring get ingressroute
# 预期:grafana 与 prometheus 两条
# 3) 绕过 DNS 直连验证
curl -sk --resolve grafana.rainchen.top:443:192.168.31.10 -o /dev/null -w '%{http_code}\n' https://grafana.rainchen.top/login
# 预期:200。若这里 200 而浏览器打不开,则是 DNS 或客户端证书信任问题
处置
| 诊断结果 | 处置 |
|---|---|
| 路由缺失 | kubectl apply -f prometheus_deploy/manifests/02-ingressroute.yaml |
| traefik Pod 异常 | 见 traefik_deploy/SOP.md;注意其单副本 + hostPort,升级时有数秒中断 |
| 仅本机打不开 | 检查 DNS 解析(nslookup grafana.rainchen.top)与客户端是否导入内部 CA |
验证:两个域名均返回 200。
九、安全与权限¶
9.1 访问控制现状¶
| 入口 | 认证 | 风险与建议 |
|---|---|---|
| Prometheus Web UI / API | 无 | 任何能访问 prometheus.rainchen.top 的人都能查询全部指标、查看 targets 与配置。建议后续加 BasicAuth 中间件(traefik Middleware,属独立变更) |
| Grafana | 账号密码 | 密码为随机生成,强度足够;避免共享账号 |
| Alertmanager | 无(仅内网 port-forward) | 无对外路由,风险低 |
| Kubernetes 侧 | 继承集群 RBAC,本次未新增用户 | operator 以自身 ServiceAccount 运行,权限范围见 9.2 |
9.2 RBAC 范围¶
本次变更创建了以下集群级权限对象(均由 chart 管理):
kubectl get clusterrole,clusterrolebinding -o name | grep kube-prometheus-stack
# 预期:operator、prometheus、kube-state-metrics、admission 等若干条
| 主体 | 权限范围 | 用途 |
|---|---|---|
| operator 的 ServiceAccount | 集群级:对 monitoring.coreos.com CR 全量读写,对 Pod/Service/Endpoints/Secret 等只读 |
依据 CR 生成工作负载 |
| Prometheus 的 ServiceAccount | 集群级只读:list/watch Pod/Service/Endpoints/Node/Ingress 等 | 服务发现;另有一个长期 token Secret 供抓取 apiserver/kubelet |
| kube-state-metrics 的 ServiceAccount | 集群级只读 | 读取对象状态转指标 |
| admission 的 ServiceAccount | 集群级只读 + 命名空间 Role | webhook 证书签发(hook 执行期用,成功后 Job 被删) |
9.3 证书与密钥¶
| 对象 | 位置 | 用途 | 轮换方式 |
|---|---|---|---|
traefik-selfsigned-tls |
traefik 命名空间 |
两个域名的 HTTPS 证书,内部 CA 签发,有效期至 2036-09-13 | 用 traefik_deploy/certs/ 下的 CA 重签后更新 Secret,详见 traefik_deploy/SOP.md |
grafana-admin |
monitoring 命名空间 |
Grafana 登录凭据 | 见 5.3 |
kube-prometheus-stack-prometheus-token |
monitoring 命名空间 |
抓取 apiserver / kubelet 的 Bearer Token | 由集群自动管理;若抓取报 401,helm upgrade 重建 |
kube-prometheus-stack-admission |
monitoring 命名空间 |
operator webhook 的 TLS 证书 | 由 hook Job 自动签发与续期 |
9.4 数据敏感性¶
本平台采集全集群指标,包含 Pod 名、镜像名、命名空间、节点名、资源用量等元数据;不采集业务数据内容。https://prometheus.rainchen.top 无认证这一点,意味着上述元数据对内网可见。
十、容量与性能¶
10.1 当前水位基线(2026-09-19,运行 2 天)¶
| 对象 | 已用 | 配额 | 水位 |
|---|---|---|---|
| Prometheus TSDB | 1113 MiB(blocks 866 MB + WAL 251 MB) | PVC 100 GiB | 约 1.1% |
| Grafana 数据 | 212 MiB | PVC 10 GiB | 约 2% |
| Alertmanager 数据 | 211 MiB | PVC 10 GiB | 约 2% |
| Prometheus 时间线 | 87,571 series | - | 内存请求 2Gi / 上限 4Gi,实测 599 Mi |
| NFS 后端整体 | HDD 侧 491 GiB、SSD 侧 118 GiB 可用 | - | 充裕 |
组件资源实况:
| 组件 | CPU | 内存 |
|---|---|---|
| Prometheus | 142m | 599 Mi |
| Grafana | 17m | 436 Mi |
| kube-state-metrics | 4m | 44 Mi |
| operator | 5m | 32 Mi |
| Alertmanager | 2m | 44 Mi |
| node-exporter | 每实例 1~5m | 每实例 16~20 Mi |
节点水位:CPU 5%~15%,内存 25%~33%。
10.2 扩容触发条件¶
| 指标 | 阈值 | 动作 |
|---|---|---|
prometheus_tsdb_head_series |
持续 > 50 万 | 提高 Prometheus 内存上限至 8Gi;评估是否分片或引入远端存储 |
| Prometheus PVC 占用 | 15 天保留期内 > 80 GiB | 扩容 PVC(4.3)或将 retention 降到 7d |
| Prometheus 内存 | 接近 limits(4 GiB)出现 OOMKilled | 提高 limits |
prometheus_tsdb_compaction_duration_seconds |
持续增长且明显拖慢抓取 | 把 TSDB 从 nfs-csi-hdd 迁到 nfs-csi(SSD)(换 storageClassName 并重建 PVC) |
| 节点内存使用率 | 持续 > 70% | 评估是否将监控组件与业务错峰调度 |
10.3 已知瓶颈¶
- TSDB 落在机械盘上:
nfs-csi-hdd是 dell-R620/data上的 ext4 loop 镜像,与 4 台 k8s VM 的 qcow2 共用物理盘。当前写入量小(约 0.55 GiB/天),压力可控,但 series 数量级增长后 compaction 会明显变慢。观察窗口:prometheus_tsdb_compaction_duration_seconds与宿主机iostat -x 1的%util/await。 - 单副本无冗余:Prometheus 重启期间约 10~30 秒无采集。
- NFS 单点:服务端 192.168.31.249 同时承载 k8s 节点磁盘,二者故障域重合。
- 镜像拉取慢:节点直连海外仓库,单个大镜像可达 2 分钟,节点重建或大批量重建时耗时会比较明显。
十一、附录¶
11.1 术语表¶
| 术语 | 含义 |
|---|---|
| ServiceMonitor / PodMonitor | Prometheus Operator 的自定义资源,声明"抓取哪些目标" |
| PrometheusRule | 声明告警与记录规则的自定义资源 |
| TSDB | Prometheus 的时序数据库,含 WAL(预写日志)与 block(落盘块) |
| head series | 当前活跃的时间线数量,决定内存占用 |
| compaction | 把多个小块合并成大块的过程,IO 密集 |
| retentionSize | 按容量触发的保留策略,先于按时间的 retention 生效 |
| distroless | 只含应用与运行时的极简镜像,无 shell,不能 exec 进去排障 |
11.2 相关文档¶
| 文档 | 位置 | 内容 |
|---|---|---|
| 变更 SOP | prometheus_deploy/SOP.md |
本次部署的背景、步骤、验证、回滚、风险 |
| 备份台账 | prometheus_deploy/backup/README.md |
回滚资产的登记与清理说明 |
| 定制 values | prometheus_deploy/values.yaml |
唯一的配置改动入口 |
| Traefik 入口 SOP | traefik_deploy/SOP.md |
入口与证书体系 |
| NFS 存储 SOP | nfs-storage/SOP.md |
StorageClass 与存储后端 |
| 上游文档 | https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack | chart 官方说明与 values 全量清单 |
11.3 修订记录¶
| 日期 | 修改人 | 变更内容 |
|---|---|---|
| 2026-09-19 | 运维 | 初版。基于 2026-09-17 部署后的实际状态编写,含 2 天运行水位基线 |
来源:
/home/rain/Documents/k8s_ins/prometheus_deploy/RUNBOOK.md| 最后更新:2026-10-03 01:03(由build/sync.py同步,请勿在站点侧修改)