控制面指标接入与容量水位告警 —— 变更档案(SOP)¶
日期:2026-10-03 | 工程:
control-plane-metrics-20261003| 类型:C 类生产变更 对象:k8s-master-01(192.168.31.10)控制面组件 +monitoring/kube-prometheus-stackrelease 来源待办:docs/HANDOFF.md§3.3「监控 G2/G8」、docs/LOGGING-GAP.md#14(容量水位告警)
一、背景¶
两件事一起做,都落在监控链路的缺口上:
- G2 控制面盲区(
docs/MONITORING-ROADMAP.md§3):etcd / kube-scheduler / kube-controller-manager / kube-proxy 四类组件的 metrics 监听地址均为127.0.0.1, 集群内抓不到;prometheus_deploy/values.yaml因此把它们整体关闭。变更前实测up==0的 target 恰为这四类(kube-etcd 1、kube-scheduler 1、kube-controller-manager 1、 kube-proxy 4)。 - 容量水位告警缺失且失真(LOGGING-GAP #14 "磁盘/分片写满前无预警"):复核发现两处真缺口——
① 承载全部监控数据(Prometheus TSDB + Elasticsearch)的宿主
dell-r620NFS 后端盘, 现有ExternalHostDiskSpace*的 selector 是cluster=~"slurm|lustre|lsf|hpc|license", 不含该宿主,完全无预警;② 现成KubePersistentVolumeFillingUp对 nfs-csi 卷失效 (原因见 §八)。
另发现四个控制面 ServiceMonitor 是孤儿资源:Helm 标签与 release-name 注解均在,
但 helm get manifest 已不含它们(历史上从 release 移除过、对象未随之删除),
配置处于"生效但不可见"状态。
二、目标¶
| 目标 | 可验证状态 |
|---|---|
| 控制面四类指标可抓 | up{job=~"kube-(etcd\|scheduler\|controller-manager\|proxy)"} 全为 1 |
| 消除孤儿资源 | 四个 ServiceMonitor 与对应 PrometheusRule 出现在 helm get manifest 中 |
| 容量水位补齐 | 新增 capacity-watermark-alerts:宿主 NFS 后端盘 warn/critical + Prometheus TSDB |
| 无退化 | 全集群 up==0 为 0;告警邮件链路(SMTP 授权码)未丢 |
三、前置条件¶
- 本机(
192.168.31.249)已配置root@192.168.31.10免密 ssh;kubectl、helm可用。 kube-prometheus-stackrelease 处于 deployed(本次前为 revision 12)。- SMTP 授权码不落盘:升级 Alertmanager 配置时必须注入,取用命令见 §五 步骤 4。
- 执行前只读检查:
kubectl get nodes # 预期 4 节点 Ready
kubectl -n monitoring get prometheusrule | wc -l # 记录基线条数
kubectl get --raw "/api/v1/namespaces/monitoring/services/kube-prometheus-stack-prometheus:9090/proxy/api/v1/query?query=count%20by%20(job)%20(up%3D%3D0)"
# 预期:kube-etcd / kube-scheduler / kube-controller-manager / kube-proxy 四项
四、影响范围¶
| 对象 | 动作 | 影响 |
|---|---|---|
k8s-master-01 etcd |
改 --listen-metrics-urls 后静态 Pod 重建 |
单成员 etcd(quorum=1),重建期间 API 瞬断(秒级) |
k8s-master-01 kube-scheduler / kube-controller-manager |
改 --bind-address 后静态 Pod 重建 |
重建期间调度/控制器短暂暂停(各约 20~60s) |
| 4 个节点 kube-proxy | 改 ConfigMap 后 DaemonSet 滚动重启 | 逐个重建,iptables 规则短暂刷新 |
kube-prometheus-stack |
helm upgrade | 仅新增 ServiceMonitor/PrometheusRule;Alertmanager 重载配置;不重启 Prometheus |
无需停服;窗口选低峰(本次为凌晨)。单控制面无冗余,四个组件逐个改、逐个验,不并行。
五、分步操作¶
步骤 1:备份(高危动作的前置,不可跳过)¶
备份控制面 manifest、kube-proxy ConfigMap、values.yaml 与 helm 现场 values。
D=/home/rain/Documents/k8s_ins/control-plane-metrics-20261003
S=$(date +%Y%m%d-%H%M%S)
mkdir -p "$D/backup/root/etc/kubernetes/manifests" "$D/backup/kube-system" "$D/backup/prometheus_deploy"
for f in etcd kube-scheduler kube-controller-manager; do
scp root@192.168.31.10:/etc/kubernetes/manifests/$f.yaml \
"$D/backup/root/etc/kubernetes/manifests/$f.yaml.bak.$S"
done
kubectl -n kube-system get cm kube-proxy -o yaml > "$D/backup/kube-system/cm-kube-proxy.yaml.bak.$S"
cp -a prometheus_deploy/values.yaml "$D/backup/prometheus_deploy/values.yaml.bak.$S"
helm get values kube-prometheus-stack -n monitoring > "$D/backup/prometheus_deploy/helm-get-values.pre-upgrade.txt"
预期:备份目录下四个文件齐备(本次为 *.bak.20261003-012914 与 *.bak.20261003-013609)。
失败判断:scp 非 0 → 免密或网络问题,未备份不得继续。
步骤 2:打开控制面 metrics 监听¶
四项变更,etcd 放最后(它是单成员,重建会瞬断 API,会影响其余步骤的 kubectl 调用——
本次首轮即因此让 kube-proxy 的 patch 失败,已调整顺序)。保留 127.0.0.1 是为了让 kubelet
的 liveness/readiness 探针继续可用(探针 host 固定 127.0.0.1;--bind-address 改 0.0.0.0
后回环仍可访问)。
# 2.1 kube-scheduler / kube-controller-manager:--bind-address 127.0.0.1 -> 0.0.0.0
ssh root@192.168.31.10 "sed -i 's/--bind-address=127.0.0.1/--bind-address=0.0.0.0/' \
/etc/kubernetes/manifests/kube-scheduler.yaml \
/etc/kubernetes/manifests/kube-controller-manager.yaml"
# 2.2 kube-proxy:metricsBindAddress 置为 0.0.0.0:10249(ConfigMap 内 config.conf 一段)
kubectl -n kube-system get cm kube-proxy -o jsonpath='{.data.config\.conf}' | grep metricsBindAddress
kubectl -n kube-system patch cm kube-proxy --type=json -p \
'[{"op":"replace","path":"/data/config.conf","value":"<替换 metricsBindAddress 后的完整 config.conf>"}]'
kubectl -n kube-system rollout restart daemonset/kube-proxy
# 2.3 etcd:追加节点 IP(保留 127.0.0.1:2381 供探针)
ssh root@192.168.31.10 "sed -i \
's#--listen-metrics-urls=http://127.0.0.1:2381#--listen-metrics-urls=http://127.0.0.1:2381,http://192.168.31.10:2381#' \
/etc/kubernetes/manifests/etcd.yaml"
预期:静态 Pod 由 kubelet 自动重建(约 20~60s),kubectl -n kube-system get pod 中
etcd-k8s-master-01 / kube-scheduler-k8s-master-01 / kube-controller-manager-k8s-master-01
重新 Running;daemonset/kube-proxy successfully rolled out。
失败判断:Pod 未回到 Running → 用步骤 1 备份覆盖对应 manifest,kubelet 重建即回滚。
本步已实现为幂等脚本(连跑第二次全 SKIP):control-plane-metrics-20261003/apply.py
(--check 只读、--dry-run 预览、无参执行)。
步骤 3:验证监听已打开¶
curl -s -o /dev/null -w "etcd:%{http_code}\n" http://192.168.31.10:2381/metrics
curl -sk -o /dev/null -w "scheduler:%{http_code}\n" https://192.168.31.10:10259/metrics
curl -sk -o /dev/null -w "ccm:%{http_code}\n" https://192.168.31.10:10257/metrics
curl -s -o /dev/null -w "kube-proxy:%{http_code}\n" http://192.168.31.10:10249/metrics
预期:etcd / kube-proxy 返回 200;scheduler / ccm 返回 403(secure 端口,403 即监听已开、
仅缺认证,Prometheus 带 SA token 抓取正常)。
步骤 4:收编 ServiceMonitor 并升级 release¶
values.yaml 中把四项 enabled 由 false 改 true,并把 defaultRules.rules 的
etcd / kubeSchedulerAlerting / kubeSchedulerRecording / kubeControllerManager / kubeProxy
置 true。SMTP 授权码不入库,从现网 Alertmanager secret 取回后注入:
SMTP=$(kubectl -n monitoring get secret alertmanager-kube-prometheus-stack-alertmanager \
-o jsonpath='{.data.alertmanager\.yaml}' | base64 -d | python3 -c \
"import sys,yaml; print(yaml.safe_load(sys.stdin)['global']['smtp_auth_password'])")
helm upgrade kube-prometheus-stack prometheus_deploy/charts/kube-prometheus-stack-91.4.1.tgz \
-n monitoring -f prometheus_deploy/values.yaml \
--set alertmanager.config.global.smtp_auth_password="$SMTP" \
--timeout 15m --wait
坑:只传 overlay 而不带 -f values.yaml(现场基线)会让其余配置回落到 chart 默认值并
触发全栈重建(P1 历史事故,见 docs/BASELINE.md §3)。可先加 --dry-run=server 验证无冲突。
预期:STATUS: deployed;helm get manifest ... | grep -c 'kube-prometheus-stack-kube-' > 0
(四个 SM 进入 release 管理);secret 中 smtp_auth_password 非空。
步骤 5:应用容量水位规则¶
kubectl apply -f control-plane-metrics-20261003/manifests/capacity-watermark-alerts.yaml
预期:prometheusrule.monitoring.coreos.com/capacity-watermark-alerts created。
六、验证¶
# 6.1 控制面 target 全 up
kubectl get --raw "/api/v1/namespaces/monitoring/services/kube-prometheus-stack-prometheus:9090/proxy/api/v1/query?query=up%7Bjob%3D~%22kube-(etcd%7Cscheduler%7Ccontroller-manager%7Cproxy)%22%7D"
# 预期:kube-etcd / kube-scheduler / kube-controller-manager 各 1 条,kube-proxy 4 条,值均为 1
# 6.2 全集群无 down target
kubectl get --raw ".../api/v1/query?query=count%20by%20(job)%20(up%3D%3D0)"
# 预期:空
# 6.3 容量水位规则已加载且无误报
kubectl get --raw ".../api/v1/rules?type=alert" # 组 capacity-watermark 三条规则 health=ok
# 预期:EnvNFSBackendDiskSpaceLow/Critical、PrometheusTSDBApproachingRetention 均 inactive
# 6.4 邮件链路未丢
kubectl -n monitoring get secret alertmanager-kube-prometheus-stack-alertmanager \
-o jsonpath='{.data.alertmanager\.yaml}' | base64 -d | grep -c 'smtp_auth_password: ""'
# 预期:0(非空)
本次实测结果:控制面 7 条 target 全 up=1;up==0 为空;
capacity-watermark 三条规则均 inactive / ok;SMTP 保留;所有 monitoring Pod Running。
七、回滚¶
备份位置:control-plane-metrics-20261003/backup/,逐条登记见其 README.md。
D=/home/rain/Documents/k8s_ins/control-plane-metrics-20261003/backup
S=20261003-012914 # 控制面 manifest / kube-proxy cm
T=20261003-013609 # values.yaml
# 7.1 控制面:恢复 manifest(kubelet 自动重建)
for f in etcd kube-scheduler kube-controller-manager; do
scp "$D/root/etc/kubernetes/manifests/$f.yaml.bak.$S" root@192.168.31.10:/etc/kubernetes/manifests/$f.yaml
done
kubectl replace -f "$D/kube-system/cm-kube-proxy.yaml.bak.$S" # 还原 kube-proxy ConfigMap
kubectl -n kube-system rollout restart daemonset/kube-proxy
# 7.2 helm:恢复 values.yaml(需同样注入 SMTP)
cp -a "$D/prometheus_deploy/values.yaml.bak.$T" prometheus_deploy/values.yaml
helm rollback kube-prometheus-stack -n monitoring # 或按 7.2 重新 upgrade
# 7.3 容量水位规则
kubectl delete -f control-plane-metrics-20261003/manifests/capacity-watermark-alerts.yaml
回滚后验证:§六 6.1 的四个 job 应回到 up=0(即恢复变更前状态),helm history 出现新 revision。
八、风险说明¶
| 风险 | 缓解 |
|---|---|
| 单成员 etcd 重建导致 API 瞬断 | 四项逐个改、etcd 放最后;避开业务高峰;先备份 manifest |
| 控制面 metrics 端口暴露到内网(firewalld 已禁用,无包过滤) | scheduler/ccm 为 secure 端口(403 已验证需认证);etcd/kube-proxy 为明文 http,仅暴露版本/leader 等运行信息,内网可接受;如收紧可在宿主侧加白名单 |
| helm upgrade 丢现场配置 | 必带 -f values.yaml(现场基线,2026-10-03 已回写);SMTP 授权码从 secret 注入;先 --dry-run=server |
新增 defaultRules 规则误报 |
曾担心单成员 etcd 触发 etcdInsufficientMembers;实测该规则组全部 inactive,无误报 |
nfs-csi 的 kubelet_volume_stats_* 不可信 |
实测同一 NFS 后端上 conf-openldap-0(1Gi) / data-openldap-0(8Gi) / prometheus(100Gi) / elasticsearch(50Gi) 的 used 全部为 7.47~7.48GiB、capacity 全部报后端卷总量 491GiB → 该类指标不能用于 PVC 水位判据。NFS 卷水位改由宿主物理盘(node_filesystem_*)覆盖;本地 PV(local-ssd)的 used/capacity 准确,由现成 KubePersistentVolumeFillingUp 覆盖 |
| 遗留:ES 应用层(分片/JVM/cluster status)仍无指标 | 未部署 elasticsearch-exporter,属剩余缺口,需要时单独立项 |
附录 A. 交付物清单¶
| 交付物 | 路径 |
|---|---|
| 本档案 | control-plane-metrics-20261003/docs/SOP.md |
| 幂等变更脚本 | control-plane-metrics-20261003/apply.py |
| 容量水位规则 | control-plane-metrics-20261003/manifests/capacity-watermark-alerts.yaml |
| G8 取数脚本 | control-plane-metrics-20261003/probe_g8.py |
| 备份台账 | control-plane-metrics-20261003/backup/README.md |
| 被改文件 | prometheus_deploy/values.yaml、k8s-master-01:/etc/kubernetes/manifests/{etcd,kube-scheduler,kube-controller-manager}.yaml、kube-system/kube-proxy ConfigMap |
附录 B. G8 容量复核结论(2026-10-03 实测)¶
| 项 | 数值 | 判读 |
|---|---|---|
| 序列数 head_series | 134,826 | 较 2026-09-19(87,571)增 54%;较 P2 复核时继续上升 |
| TSDB blocks | 5.25 GiB | retention 15d / retentionSize 90GiB 兜底,PVC 声明 100GiB |
| TSDB 日增 | 395.7 MiB/天 | 15 天外推 ≈ 5.9 GiB,占声明容量 6%,容量充裕 |
| 采样写入速率 | ~677 样本/秒(抓取面)/ 4295 样本/秒(含记录规则) | — |
| Prometheus 内存 WSS | 768.9 MiB | limit 4Gi,余量充足 |
| 宿主 NFS 后端盘水位 | /srv/nfs/k8s 5.3%、/srv/nfs/k8s-hdd 2.5%、/data 40.3% | 均低于告警线 |
| 抓取 target 总数 | 58(含本次新增 7 条控制面) | 无 down |
结论:Prometheus 容量预算充裕,无需扩容或降采样;G8 的"单副本 + 与 NFS 同源故障域" 属可用性设计取舍,非容量问题,仍按既有结论保留。
附录 C. 本次一并处理的决策项(原 HANDOFF 未完成项)¶
| 原待办 | 结论 | 落点 |
|---|---|---|
| 纳管扩面余项:香港(frp 隧道 TLS 加固) | 不做(2026-10-03 决策) | 本条 |
| 宿主 rsyslog 514/udp 明文无认证 | 不做(接受内网明文现状) | 本条 |
| 监控 G2 | 已做(本文档) | 本文档 |
| 监控 G8 | 已做(附录 B) | 本文档 |
| A/B 规则改动的对照验证(≥3 可比样本) | 已完成(2026-10-02 复测并结项) | ~/.trae-cn/skills/ops-execution-efficiency/references/lessons-and-retractions.md §三 |
杂项(技能阶段开关收口|calibre.license.dat 归档|作业/占用类指标仅空负载验证|kas/registry 未纳黑盒) |
不做(2026-10-03 决策) | 本条 |
| 安全/审计、可靠性、成本三类(LOGGING-GAP #8–#11、#6/#7/#12、#13 冷热分层、P2 降采样) | 不做(2026-10-02 决策) | docs/LOGGING-GAP.md §2 |
来源:
/home/rain/Documents/k8s_ins/control-plane-metrics-20261003/docs/SOP.md| 最后更新:2026-10-03 01:41(由build/sync.py同步,请勿在站点侧修改)