SOP — 将集群外主机 Dell R620 硬件温度/风扇监控接入 K8s¶
变更主题:把集群外主机
dell-R620(192.168.31.250)的 IPMI 温度/风扇指标经 node-exporter 接入本机 K8s 集群monitoring命名空间的 kube-prometheus-stack,并配齐告警规则、看板与邮件通知 执行时间:2026-09-29 22:00–22:19(CST)|执行主机:本机dell-R620(Ubuntu 24.04.3)+ K8s 集群(v1.36.4) 工程根:dell-r620-monitor-20260929/
目录¶
附录 A:交付物清单|附录 B:实测时间线与证据|附录 C:决策经过
1. 背景¶
老板 K8s 集群(CentOS 7.9 + Docker 运行时)曾用 Docker 容器化 node-exporter + IPMI 采集脚本把 Dell R620 的硬件温度/风扇接入 Prometheus,并沉淀了告警规则与 Grafana 看板。
本环境重建后,K8s 升级到 v1.36.4(containerd 运行时),主机侧已不再有 Docker;且本次要求:
- 把集群外主机
dell-R620的硬件指标接入本机 K8s 的monitoring命名空间 (helm releasekube-prometheus-stack,chart 91.4.1,app v0.94.0); - 主机侧改为 apt 包 + systemd 方案(
prometheus-node-exporter+ oneshot/timer 采集), 不再依赖容器运行时; - 告警不再只停留在 Prometheus,而要经 Alertmanager 邮件通道投递(
category=hardware路由)。
触发条件:监控缺口。该主机此前无任何硬件温度/风扇监控,CPU 过热、风扇停转等故障无从发现。
2. 目标¶
变更完成后应达到并可验证的状态:
- 主机侧
prometheus-node-exporter.serviceactive且监听9100;ipmi-collector.timeractive且enabled,每 30s 产出一份/opt/node-exporter/textfile/ipmi_metrics.prom; http://192.168.31.250:9100/metrics中可查到ipmi_temperature_celsius(温度)、ipmi_fan_rpm(风扇)等指标,且node_hwmon_temp_celsius(CPU 核心温度)可用;monitoring命名空间内Service/Endpoints/ServiceMonitor(同名external-node-exporter)、PrometheusRule/hp-r620-hardware-alerts(8 条)、ConfigMap/hp-r620-temp-dashboard均存在且与清单一致;- Prometheus 中抓取目标
external-node-exporterhealth=up,ipmi_temperature_celsius有样本,8 条告警已加载; - Alertmanager 运行配置含邮件接收器
hp-r620-email且按category = "hardware"路由; - Grafana 已由 sidecar 自动导入看板
uid=hp-r620-temp(8 面板); - 邮件通道可用:投递一封
category=hardware测试告警,alertmanager_notification_requests_total{integration="email"}自 0 增至 ≥1,且..._failed_total{integration="email"}=0; - 幂等:重复执行
deploy第二次两个模块均「已达标,整体跳过」,零变更;drift结论「漂移 0 项」。
3. 前置条件¶
| 项 | 要求 |
|---|---|
| 执行身份 | 必须 root(apt 安装、写 /etc/systemd/system、写 /etc/default、读 /dev/ipmi0 均需 root)。非 root 时预检查 privilege 项直接 BLOCK |
| 主机系统 | 本机 dell-R620,Ubuntu 24.04.3,os_family=debian(工程仅实现 apt/dpkg 适配) |
| 主机工具 | ipmitool(/usr/bin/ipmitool)、/dev/ipmi0(内核 ipmi_devintf/ipmi_si 已加载)、systemctl、ss、curl、dpkg-query |
| 集群访问 | kubectl / helm 可用,kubernetes.kubeconfig=/home/rain/.kube/config(工程以 root 运行,必须显式指定管理账号 kubeconfig,否则用不到默认上下文) |
| 上游依赖 | kube-prometheus-stack 已部署于 monitoring;chart 文件 prometheus_deploy/charts/kube-prometheus-stack-91.4.1.tgz 存在 |
| 凭据 | SMTP 授权码存放于 0600 文件 /home/rain/.secrets/dell-r620-monitor.env,变量 DELL_R620_SMTP_AUTH_PASSWORD(值不入配置、不入版本管理、不落日志) |
| 执行前检查 | main.py precheck 无 BLOCK;9100 端口空闲(或已被本服务占用) |
4. 影响范围¶
- 主机(1 台,集群外):仅本机
dell-R620(br0管理 IP192.168.31.249,接入 Prometheus 的物理网卡eno2IP192.168.31.250)。 - 集群组件:
monitoring命名空间的 kube-prometheus-stack(Prometheus / Alertmanager / Grafana)。 - 是否停服:否。
helm upgrade仅更新 Alertmanager 配置(alertmanager.config); 配合--no-hooks跳过 pre-upgrade hook,不改 CRD / webhook 证书、不重启 Prometheus / Grafana。 主机侧只装包 + 起新单元,不动既有业务。 - 窗口期:单次
deploy约 15~20 分钟(含报警配置 reload 等待 ~2 分钟);主机侧动作耗时以秒~分钟计。 - 在跑作业:本机非 Slurm/LSF 计算节点,无调度作业;变更期间无停服窗口要求。
- 业务影响:无。唯一可感知变化是主机多监听一个
9100端口。
5. 分步操作¶
全部命令在本机
dell-R620上以 root 执行。多主机/多步骤编排由工程实现体承载, 步骤正文给出与之等价的可手工复现 shell 命令;每步末尾以一行标注对应实现文件。 工程入口(仅作附注,不作步骤正文):sudo -n .venv/bin/python main.py {precheck|deploy|verify|drift|rollback}。
步骤 1:环境预检(门禁,只读)¶
先确认「能不能做、做完有没有效果」。最关键的坑:若 Prometheus CR 的 serviceMonitorSelector /
ruleSelector 不是 release=kube-prometheus-stack,则部署「看似成功但完全无效果」——ServiceMonitor
与 PrometheusRule 会被静默忽略,故此项列为 BLOCK。另有一个误报坑:ss -ltnp 默认把进程名截断到
15 字符,apt 包的进程显示为 prometheus-node,若只匹配 node-exporter/node_exporter 会在复跑时误报
「9100 已被占用」——人工核对时需按多个 token 宽松匹配。
# 1) 执行身份(期望 0)
id -u
# 2) IPMI 设备与工具
ls -l /dev/ipmi0 # 期望存在(字符设备,仅 root 可读写)
test -x /usr/bin/ipmitool && echo ipmitool-ok
# 3) 抓取端口 9100(期望「空闲」或已被 node-exporter 占用)
ss -ltnpH | grep ':9100 ' || echo '9100 空闲'
# 4) 集群可达 + 命名空间
kubectl --kubeconfig /home/rain/.kube/config get ns monitoring
# 5) Prometheus CR 选择器(两项都应为 matchLabels: {release: kube-prometheus-stack})
kubectl --kubeconfig /home/rain/.kube/config -n monitoring get prometheus \
-o jsonpath='{range .items[*]}{.spec.serviceMonitorSelector}{"\n"}{.spec.ruleSelector}{"\n"}{end}'
# 6) Alertmanager Secret 存在
kubectl --kubeconfig /home/rain/.kube/config -n monitoring get secret alertmanager-kube-prometheus-stack-alertmanager
# 7) 上游 chart / values 模板 / 凭据文件(只看变量名,不打印值)
ls -l /home/rain/Documents/k8s_ins/prometheus_deploy/charts/kube-prometheus-stack-91.4.1.tgz \
manifests/04-alertmanager-email-values.yaml
grep -c '^DELL_R620_SMTP_AUTH_PASSWORD=' /home/rain/.secrets/dell-r620-monitor.env # 期望 1
预期:id -u 为 0;/dev/ipmi0 存在;选择器为 map[matchLabels:map[release:kube-prometheus-stack]];
Secret 存在;凭据文件变量计数为 1。
失败判断:任一项不满足即为 BLOCK,不得继续 deploy;按提示先修复(如 apt-get install -y ipmitool、
确认 CR 选择器标签)。--force 只对软性 WARN(端口占用、Grafana sidecar)有效,对 BLOCK 无效。
实现体:utils/precheck.py(run_all)、utils/config_validate.py;门禁汇总见 deployer.py(_gate)。
步骤 2:前置备份(高危)¶
helm upgrade 会以「现场 values + 我们的 overlay」为基线整体重放,缺少现场 values 基线会把整份 values 覆盖成只有邮件段——故变更前必须先导出现场 values 与 Alertmanager 现存配置。回滚时正是靠这两份备份 恢复(详见第 7 章)。
STAMP=$(date +%Y%m%d-%H%M%S)
install -d -m 755 backup/monitoring
# 高危:导出 helm 现场 values(作为 -f 基线与回滚参考)
helm --kubeconfig /home/rain/.kube/config get values kube-prometheus-stack -n monitoring -o yaml \
> "backup/monitoring/helm-live-values.yaml.bak.$STAMP"
# 高危:导出 Alertmanager 现存配置(回滚时用 --from-file 重建 Secret)
kubectl --kubeconfig /home/rain/.kube/config -n monitoring get secret \
alertmanager-kube-prometheus-stack-alertmanager \
-o jsonpath='{.data.alertmanager\.yaml}' | base64 -d \
> "backup/monitoring/alertmanager-变更前配置.yaml.bak.$STAMP"
chmod 600 "backup/monitoring/alertmanager-变更前配置.yaml.bak.$STAMP"
ls -l backup/monitoring/
预期:backup/monitoring/ 下生成两份 .bak.<时间戳> 文件,values 文件非空,Alertmanager 备份 0600。
失败判断:任一导出为空或命令非 0 → 中止变更(缺备份即失去回原点能力)。
实现体:modules/k8s_monitor.py(backup / _snapshot);备份台账 utils/cmd.py(ensure_backup_ledger)。
步骤 3:主机侧 —— node-exporter(apt) + IPMI 采集¶
把制品落盘并起服务。制品(artifacts/)为不可变真源,落盘内容与权限一律以制品为准。
本步对应实现体 modules/host_collector.py 的 execute(),顺序为:装包 → 建目录 → 落参数文件 →
落脚本 → 落单元 → daemon-reload → 启用单元 → 重启 node-exporter → 触发首轮采集。
注意事项与坑:
- 该 apt 包只有
/etc/default/prometheus-node-exporter这一个参数入口,采集器开关必须写在这个文件里; ipmitool需 root(/dev/ipmi0权限600),故采集单元以User=root运行;- 首轮采集就绪判定的时序坑:
systemctl enable --now ipmi-collector.timer的OnBootSec=30s可能 已先产出过一份 textfile。若在systemctl start之后才取产物快照,则「mtime 变化」永远等不到, 30s 超时失败。正确做法是触发前先取快照,并校验产物内容确实含ipmi_temperature_celsius(避免把 空/半成品判为就绪)。
# 3.1 安装 apt 包(已装则幂等跳过)
DEBIAN_FRONTEND=noninteractive apt-get install -y prometheus-node-exporter
dpkg-query -W -f='${Status} ${Version}\n' prometheus-node-exporter # 期望 install ok installed 1.7.0-1ubuntu0.3
# 3.2 创建 textfile 采集产物目录
install -d -o root -g root -m 0755 /opt/node-exporter/textfile
# 3.3 落 node-exporter 参数文件(开启 textfile/hwmon/thermal_zone 采集器)
install -o root -g root -m 0644 artifacts/prometheus-node-exporter.default \
/etc/default/prometheus-node-exporter
# 3.4 落 IPMI 采集脚本(root:root 0755)
install -o root -g root -m 0755 artifacts/ipmi_metrics.sh /opt/node-exporter/ipmi_metrics.sh
# 3.5 落 systemd 单元
install -o root -g root -m 0644 artifacts/ipmi-collector.service /etc/systemd/system/ipmi-collector.service
install -o root -g root -m 0644 artifacts/ipmi-collector.timer /etc/systemd/system/ipmi-collector.timer
# 3.6 重载单元定义并启用(timer 与 node-exporter 服务)
systemctl daemon-reload
systemctl enable --now ipmi-collector.timer
systemctl enable --now prometheus-node-exporter.service
# 3.7 参数文件变更后重启 node-exporter 使其生效
systemctl restart prometheus-node-exporter.service
# 3.8 触发首轮采集并就绪确认(快照必须在触发之前取)
BEFORE=$(find /opt/node-exporter/textfile -name '*.prom' -printf '%f %T@\n' 2>/dev/null | sort)
systemctl start ipmi-collector.service
for _ in $(seq 1 30); do
NOW=$(find /opt/node-exporter/textfile -name '*.prom' -printf '%f %T@\n' 2>/dev/null | sort)
grep -q ipmi_temperature_celsius /opt/node-exporter/textfile/*.prom 2>/dev/null \
&& [ "$NOW" != "$BEFORE" ] && { echo "采集产物已就绪"; break; }
sleep 1
done
grep -E '^ipmi_(temperature|fan)' /opt/node-exporter/textfile/ipmi_metrics.prom | head
预期:prometheus-node-exporter 与 ipmi-collector.timer 均 active;9100 处于监听;
ipmi_metrics.prom 中出现 ipmi_temperature_celsius(本环境 4 条:inlet / exhaust / cpu1 / cpu2)
与 ipmi_fan_rpm(14 个风扇 Fan1A–Fan7A、Fan1B–Fan7B)。
失败判断:30s 内无产物 → 检查 /dev/ipmi0 与 bash -x /opt/node-exporter/ipmi_metrics.sh。
命令返回非 0 → 见第 7 章回滚。
实现体:modules/host_collector.py(execute / _prime_collection);制品 artifacts/。
步骤 4:集群侧 —— 静态接入 + 告警规则 + 看板¶
主机不在集群内,无法被 PodMonitor 自动发现,故采用「无 selector 的 Service + 手工 Endpoints +
ServiceMonitor」静态接入;ServiceMonitor 必须带 release=kube-prometheus-stack 标签才会被
Prometheus CR 选中。三份清单幂等 apply。
KUBECONFIG=/home/rain/.kube/config
kubectl --kubeconfig "$KUBECONFIG" apply -f manifests/01-external-node-exporter.yaml
kubectl --kubeconfig "$KUBECONFIG" apply -f manifests/02-hp-r620-hardware-alerts.yaml
kubectl --kubeconfig "$KUBECONFIG" apply -f manifests/03-hp-r620-temp-dashboard.yaml
# 核对
kubectl --kubeconfig "$KUBECONFIG" -n monitoring get servicemonitor,service,endpoints external-node-exporter
kubectl --kubeconfig "$KUBECONFIG" -n monitoring get prometheusrule hp-r620-hardware-alerts
kubectl --kubeconfig "$KUBECONFIG" -n monitoring get configmap hp-r620-temp-dashboard
预期:servicemonitor/external-node-exporter created(Service、Endpoints 同名)、
prometheusrule/hp-r620-hardware-alerts created、configmap/hp-r620-temp-dashboard created。
失败判断:apply 报 schema/版本错 → 检查 apiversion(ServiceMonitor 属 monitoring.coreos.com/v1)。
实现体:modules/k8s_monitor.py(execute / _apply_manifest);清单 manifests/01~03。
步骤 5:集群侧 —— Alertmanager 邮件路由(helm upgrade,高危)¶
把 04 模板中的授权码占位符渲染成真值后,以现场 values 为基线叠加 overlay 执行 helm upgrade,
只改 alertmanager.config。
注意事项与坑:
- 授权码渲染不要用
sed:若授权码含&、|等字符会被sed解释。用 Python 做字面替换, 并把渲染产物写成0600临时文件(进程退出即删),值不落日志、不进版本管理。 - pre-upgrade hook 卡死坑:chart 的
kube-prometheus-stack-admission-createhook Job 需拉取ghcr.io/jkroepke/kube-webhook-certgen:1.8.8,本环境集群侧 ghcr.io 不可达,hook 会卡在ContainerCreating直到 10 分钟--timeout失败(release 变为failed(revision 3))。 本变更只更新 Alertmanager 配置,不涉 CRD / webhook 证书,故加--no-hooks跳过。 若日后 ghcr.io 可达或配了镜像代理,可去掉该项恢复默认。 - 配置生效有延迟坑:
helm upgrade返回后,prometheus-operator 需重新生成 Secretalertmanager-kube-prometheus-stack-alertmanager-generated,再由 config-reloader 触发 reload (本环境实测 22:14:52 开始 upgrade,22:15:58 reload 生效)。故校验不能一次性判定,须轮询等待 (上限ops.alertmanager_reload_timeout,默认 150s)。
KUBECONFIG=/home/rain/.kube/config
# 5.1 渲染授权码(字面替换,产物 0600,不落日志)
umask 077; RENDERED="$(mktemp /tmp/am-values.XXXXXX)"
set -a; . /home/rain/.secrets/dell-r620-monitor.env; set +a
python3 - "$RENDERED" <<'PY'
import os, sys
tpl = open("manifests/04-alertmanager-email-values.yaml", encoding="utf-8").read()
ph = "__SMTP_AUTH_PASSWORD__"
assert ph in tpl, "模板缺少占位符"
open(sys.argv[1], "w", encoding="utf-8").write(tpl.replace(ph, os.environ["DELL_R620_SMTP_AUTH_PASSWORD"]))
PY
# 5.2 以现场 values 为基线叠加 overlay 执行 helm upgrade(跳过 ghcr.io hook)
LIVE="$(ls -1t backup/monitoring/helm-live-values.yaml.bak.* | head -1)"
helm --kubeconfig "$KUBECONFIG" upgrade kube-prometheus-stack \
/home/rain/Documents/k8s_ins/prometheus_deploy/charts/kube-prometheus-stack-91.4.1.tgz \
-n monitoring -f "$LIVE" -f "$RENDERED" \
--timeout 10m --wait --no-hooks
rm -f "$RENDERED" # 清理渲染产物(含授权码)
# 5.3 确认 release 状态与邮件接收器已生效(轮询等待 reload)
helm --kubeconfig "$KUBECONFIG" -n monitoring history kube-prometheus-stack | tail -3
kubectl --kubeconfig "$KUBECONFIG" -n monitoring get secret \
alertmanager-kube-prometheus-stack-alertmanager -o jsonpath='{.data.alertmanager\.yaml}' | base64 -d | grep -E 'hp-r620-email|category'
预期:helm history 最新一行 STATUS=deployed(本环境 revision 4);Secret 的 alertmanager.yaml
含接收器 hp-r620-email 与 category = "hardware" 路由。
失败判断:upgrade 超时或 hook 卡住 → 删除残留 hook Job 后加 --no-hooks 重试;
STATUS=failed → 见第 7 章回滚。
实现体:modules/k8s_monitor.py(_helm_upgrade / _validate_alertmanager);配置 config/monitor.yaml
(kubernetes.helm_extra_args);模板 manifests/04-alertmanager-email-values.yaml。
步骤 6:后置链路验证¶
见第 6 章(一条条命令核对,全绿即成功)。实现体:modules/k8s_monitor.py(validate 及子校验)。
6. 验证¶
全部在变更后执行,逐项核对。任一不通过即为失败,按第 7 章处置。
KUBECONFIG=/home/rain/.kube/config
# 6.1 主机侧:单元运行 + 端口监听 + 指标存在
systemctl is-active ipmi-collector.timer prometheus-node-exporter.service # 期望 active active
systemctl is-enabled ipmi-collector.timer # 期望 enabled
ss -ltnH | awk '{print $4}' | grep -c ':9100$' # 期望 ≥1
curl -s http://192.168.31.250:9100/metrics | grep -E '^ipmi_temperature_celsius' | wc -l # 期望 4
# 6.2 Prometheus:抓取目标 up + 指标有样本 + 规则已加载
kubectl --kubeconfig "$KUBECONFIG" -n monitoring port-forward svc/kube-prometheus-stack-prometheus 9090:9090 &
sleep 3
curl -s 'http://127.0.0.1:9090/api/v1/targets' | python3 -c 'import json,sys;d=json.load(sys.stdin)["data"]["activeTargets"];print([(t["labels"].get("job"),t["health"],t["scrapeUrl"]) for t in d if "external-node-exporter" in str(t["labels"].get("job")) or "192.168.31.250" in t["scrapeUrl"]])'
curl -s 'http://127.0.0.1:9090/api/v1/query?query=ipmi_temperature_celsius' | python3 -c 'import json,sys;print(len(json.load(sys.stdin)["data"]["result"]))' # 期望 4
curl -s 'http://127.0.0.1:9090/api/v1/rules' | grep -c 'HPR620' # 期望 ≥8
# 6.3 Alertmanager:运行配置含邮件接收器
kubectl --kubeconfig "$KUBECONFIG" -n monitoring port-forward svc/kube-prometheus-stack-alertmanager 9093:9093 &
sleep 3
curl -s http://127.0.0.1:9093/api/v2/status | python3 -c 'import json,sys;print("hp-r620-email" in json.load(sys.stdin)["config"]["original"])' # 期望 True
# 6.4 Grafana:健康 + 看板已加载
kubectl --kubeconfig "$KUBECONFIG" -n monitoring port-forward svc/kube-prometheus-stack-grafana 3000:80 &
sleep 3
curl -s http://127.0.0.1:3000/api/health # 期望 {"commit":...,"database":"ok",...}
GU=$(kubectl --kubeconfig "$KUBECONFIG" -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-user}' | base64 -d)
GP=$(kubectl --kubeconfig "$KUBECONFIG" -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-password}' | base64 -d)
curl -s -u "$GU:$GP" http://127.0.0.1:3000/api/dashboards/uid/hp-r620-temp | grep -o '"uid":"hp-r620-temp"' # 期望命中
# 6.5 邮件通道:注入一封测试告警并核对投递计数
curl -s -XPOST http://127.0.0.1:9093/api/v2/alerts -H 'Content-Type: application/json' \
-d '[{"labels":{"alertname":"HPR620TestAlert","category":"hardware","severity":"warning"},"annotations":{"summary":"邮件通道测试"}}]'
sleep 20
curl -s http://127.0.0.1:9093/metrics | grep -E 'alertmanager_notification_requests_total\{integration="email"\}|alertmanager_notification_requests_failed_total\{integration="email"\}'
# 期望:requests_total 由 0 增至 ≥1;failed_total = 0
幂等与漂移(收尾必做,证明「重跑零变更」):
sudo -n .venv/bin/python main.py deploy # 第二次:两模块均「已达标,整体跳过」,零变更
sudo -n .venv/bin/python main.py drift # 结论「漂移 0 项 / 探测失败 0 项 / 已达标 13 项」,退出码 0
(drift 退出码:无漂移 0 / 有漂移 1 / 检测失败 2。本环境实测报告见
reports/drift-20260929-221806.md。)
7. 回滚¶
回滚顺序为「先集群侧、后主机侧」(逆序),避免出现「抓取一个已停采集的主机」。工程入口
sudo -n .venv/bin/python main.py rollback(高危)即按此顺序执行;下述为等价手工命令。
备份存放位置:本次变更的备份统一在工程内 backup/,结构与台账见
backup/README.md(monitoring/ 子目录下的
helm-live-values.yaml.bak.<时间戳> 与 alertmanager-变更前配置.yaml.bak.<时间戳>,后者 0600)。
回滚时按台账「备份文件」列取用。
KUBECONFIG=/home/rain/.kube/config
# 7.1 集群侧(先做):删除三类资源
kubectl --kubeconfig "$KUBECONFIG" -n monitoring delete servicemonitor external-node-exporter --ignore-not-found
kubectl --kubeconfig "$KUBECONFIG" -n monitoring delete service external-node-exporter --ignore-not-found
kubectl --kubeconfig "$KUBECONFIG" -n monitoring delete endpoints external-node-exporter --ignore-not-found
kubectl --kubeconfig "$KUBECONFIG" -n monitoring delete prometheusrule hp-r620-hardware-alerts --ignore-not-found
kubectl --kubeconfig "$KUBECONFIG" -n monitoring delete configmap hp-r620-temp-dashboard --ignore-not-found
# 7.2 集群侧:恢复 Alertmanager 变更前配置(优先用备份重建 Secret)
AMBAK="$(ls -1t backup/monitoring/alertmanager-变更前配置.yaml.bak.* | head -1)"
kubectl --kubeconfig "$KUBECONFIG" create secret generic alertmanager-kube-prometheus-stack-alertmanager \
-n monitoring --from-file=alertmanager.yaml="$AMBAK" --dry-run=client -o yaml \
| kubectl --kubeconfig "$KUBECONFIG" apply -f -
# 若无备份,则改用: helm --kubeconfig "$KUBECONFIG" -n monitoring rollback kube-prometheus-stack --wait --timeout 10m
# 7.3 主机侧(后做,高危):停用并删除自建单元、恢复参数文件
systemctl stop ipmi-collector.timer ipmi-collector.service
systemctl disable ipmi-collector.timer ipmi-collector.service
rm -f /etc/systemd/system/ipmi-collector.timer /etc/systemd/system/ipmi-collector.service
systemctl daemon-reload
DEFBAK="$(ls -1t backup/etc/default/prometheus-node-exporter.bak.* 2>/dev/null | head -1)"
if [ -n "$DEFBAK" ]; then install -o root -g root -m 0644 "$DEFBAK" /etc/default/prometheus-node-exporter; \
systemctl restart prometheus-node-exporter.service; fi
# 注:apt 包与 /opt/node-exporter 目录默认保留,不自动卸载/删除,按需人工处理
回滚后验证:
kubectl --kubeconfig "$KUBECONFIG" -n monitoring get servicemonitor external-node-exporter # 期望 NotFound
kubectl --kubeconfig "$KUBECONFIG" -n monitoring get secret alertmanager-kube-prometheus-stack-alertmanager \
-o jsonpath='{.data.alertmanager\.yaml}' | base64 -d | grep -c hp-r620-email # 期望 0
systemctl is-active ipmi-collector.timer # 期望 inactive
systemctl is-active prometheus-node-exporter.service # 期望 active(apt 服务保留)
8. 风险说明¶
| # | 风险点 | 影响 | 缓解措施 |
|---|---|---|---|
| 1 | Prometheus CR 选择器与资源标签不一致 | 部署「看似成功但无效果」 | 预检查列为 BLOCK,选择器不符即拒绝 deploy |
| 2 | helm upgrade 覆盖整份 values |
Alertmanager/grafana 既有配置丢失 | 变更前导出 live values 作 -f 基线,备份到 backup/;回滚用备份重建 |
| 3 | pre-upgrade hook 依赖 ghcr.io 不可达 | upgrade 卡到超时,release failed | --no-hooks 跳过;只改 Alertmanager 配置,不涉 CRD/webhook,跳过安全 |
| 4 | 授权码泄露 | 凭据外泄 | 只从 0600 凭据文件按变量名读取;渲染到 0600 临时文件,进程退出即删;不入配置、不落日志、不进版本管理 |
| 5 | Alertmanager 配置生效有延迟 | 校验误报失败 | 轮询等待(上限 150s),判据落在「运行配置含目标接收器」 |
| 6 | 采集脚本/源数据异常 | 指标缺失或陈旧 | 脚本失败保留上一份 textfile;HPR620IPMICollectorDown 规则在指标缺失/超 180s 未更新时告警 |
| 7 | 主机单点,无冗余 | 该主机监控失效即全盲 | HPR620NodeExporterDown 规则覆盖;主机侧服务设开机自启 |
附录 A:交付物清单¶
| 路径 | 说明 |
|---|---|
config/monitor.yaml |
工程唯一真源配置 |
artifacts/ |
不可变制品:ipmi_metrics.sh、ipmi-collector.service、ipmi-collector.timer、prometheus-node-exporter.default |
manifests/01~03*.yaml |
集群侧清单:静态接入、告警规则、看板 |
manifests/04-alertmanager-email-values.yaml |
邮件路由 values 模板(含授权码占位符) |
backup/README.md |
备份台账(本次两组备份见 backup/monitoring/) |
reports/ |
预检查报告(precheck-deploy-*.md)与漂移报告(drift-*.md) |
logs/dell-r620-monitor.log |
运行日志 |
docs/SOP.md / docs/RUNBOOK.md |
本文件与运行手册 |
附录 B:实测时间线与证据¶
| 时间(CST) | 事件 |
|---|---|
| 22:00–22:02 | 首轮 precheck + deploy;helm upgrade 因 ghcr.io hook 卡住,10 分钟后失败(revision 3 failed) |
| 22:02:51 | 产生第一组备份(backup/monitoring/*.bak.20260929-220251) |
| 22:14:41–22:14:54 | 配置 helm_extra_args: ["--no-hooks"] 后重跑 deploy;revision 4 deployed |
| 22:15:58 | Alertmanager reload 生效(含 hp-r620-email) |
| 22:18:06 | drift 结论:漂移 0 / 探测失败 0 / 已达标 13,退出码 0 |
全链路验证读数(实测):target external-node-exporter health=up
(http://192.168.31.250:9100/metrics);ipmi_temperature_celsius 样本 4 条;8 条 HPR620 规则加载;
Alertmanager 运行配置含 hp-r620-email;Grafana /api/health 正常且已加载看板 uid=hp-r620-temp;
邮件计数 notification_requests_total{integration="email"} 0→1、failed_total = 0。
温度实测:inlet 24°C、exhaust 39°C、CPU 64°C/58°C。
附录 C:决策经过¶
- 为何用 apt 包而非容器:本环境无 Docker,且集群外主机无 K8s;apt 包 + systemd 更贴合主机侧
生命周期管理,采集用 oneshot + timer 与
ServiceMonitor的 30s interval 对齐。 - 为何用「Service(无 selector) + 手工 Endpoints + ServiceMonitor」:节点不在集群内,无法被 PodMonitor/EndpointSlice 自动发现,静态 Endpoints 是最小侵入的接入方式。
- 为何
--no-hooks:本变更只改 Alertmanager 配置;hook 依赖不可达的 ghcr.io,跳过不影响正确性。 - 为何回滚先集群后主机:避免出现「抓取一个已停采集的主机」的中间态。
来源:
/home/rain/Documents/k8s_ins/dell-r620-monitor-20260929/docs/SOP.md| 最后更新:2026-09-29 22:21(由build/sync.py同步,请勿在站点侧修改)