SOP — 日志 ↔ 指标互跳(第一阶段:静态互跳 + 裸主机名标签)¶
主题目录:
log-metrics-crosslink-20261002/| 负责人:运维 | 日期:2026-10-02 关联:docs/LOGGING-GAP.md#1(对齐键)、docs/HANDOFF.md§3.1 组一 #1
1. 背景¶
LOGGING-GAP #1「日志 ↔ 指标互跳」经 2026-10-02 实机核对,确认两侧无单一通用对齐键,
且存在一个格式差:指标侧主机标识是 instance="<主机名>:9100",日志侧是 host.name="<主机名>"。
Grafana 的跳转链接无法在 URL 里剥掉 :9100,故先给指标补一个裸主机名标签 hostname,
再在两侧各加一个静态入口链接(不做带选中值的动态 drilldown,那属第二阶段)。
2. 目标¶
可验证的完成状态:
- 14 台集群外主机的
up序列携带hostname标签,取值等于裸主机名(无端口); - Grafana 5 个环境大盘出现「查看日志(Kibana)」链接,可达
kibana.rainchen.top日志分域视图; - Kibana「日志分域视图」出现「查看指标(Grafana)」面板,内含 5 个域大盘链接;
- 两侧
drift退出码为 0,幂等复跑零变更。
3. 前置条件¶
- 环境:本机
192.168.31.249,可 root 免密 ssh 到 14 台主机;kubectl指向~/.kube/config。 - 凭据:
~/.secrets/efk.env(KIBANA_SYSTEM_PASSWORD等),由工程内部读取,不得 cat。 - 工程:
env-monitor-deploy(Grafana 大盘/指标)、monitoring-p2-20261001(Kibana/EFK)。 - 执行前检查:两侧
main.py drift均无待变更项(确认基线干净)。bash cd /home/rain/Documents/k8s_ins/env-monitor-deploy && .venv/bin/python main.py drift; echo "RC=$?" cd /home/rain/Documents/k8s_ins/monitoring-p2-20261001 && .venv/bin/python main.py drift; echo "RC=$?"预期:两条RC=0;有非零先查清再动手。
4. 影响范围¶
- 主机与组件:14 台集群外主机(Slurm/Lustre/LSF/HPC/FlexLM)的 抓取标签、5 个 Grafana 环境大盘、 Kibana 1 个仪表板 + 1 个新增 saved object。
- 是否停服:否。不改采集链路(Filebeat 与 node-exporter 均不动),仅改 Prometheus 目标标签与展示层。
- 窗口期:无特别要求,任一时刻可执行(本工程 deploy 幂等、可回滚)。
- 在跑业务:不影响;指标查询在 relabel 变更后有约 5 分钟的新旧序列并存期(见第 6 章)。
5. 分步操作¶
步骤 1:指标侧增加 hostname 裸主机名标签¶
ServiceMonitor 的 relabel 规则由实现体按配置逐台生成,hostname 与 cluster/role 并列,
取值即配置里的 nodes[].name(与日志侧 host.name 同源)。改动只有一处元组:
env-monitor-deploy/modules/k8s_ingest.py 的 _render_one()。
坑:模板 01-external-node-exporters.yaml.tpl 的头部注释同时声明了「每台几条 relabel」,
改了生成逻辑必须同步注释,否则下一个读者按注释核对会误判。
cd /home/rain/Documents/k8s_ins/env-monitor-deploy
# 修改点:modules/k8s_ingest.py 的 relabel 元组增加 ("hostname", name)
# manifests/01-external-node-exporters.yaml.tpl 注释「三条」→「四条」
.venv/bin/python main.py deploy
实现体:modules/k8s_ingest.py(_render_one → relabel 行)。
预期:抓取目标全部 up 达成:14/14;kubectl get servicemonitor external-node-exporters 的
relabelings[*].targetLabel 中出现 hostname。
失败判断:up 数不足 14 → 第 7 章回滚。
步骤 2:Grafana 大盘增加「查看日志(Kibana)」链接¶
大盘走「精简源 + 生成器」,链接写进精简源的顶层 extra.links,由生成器透传到大盘 JSON。
坑(本次实际踩到):overview.yaml 原本已有顶层 extra(内容为 version: 1)。
YAML 同名顶层键后写覆盖先写、且不报错,直接再写一个 extra: 会让新加的 links 被静默丢弃
(表现为 build-dashboards 报「未变」,链接根本没进产物)。必须把 links 合并进已有的 extra。
cd /home/rain/Documents/k8s_ins/env-monitor-deploy
# 修改点:dashboards/{overview,slurm,lustre,lsf,flexlm}.yaml
# overview → 在已有的 extra(version: 1)下追加 links
# 其余 4 个 → 新增 extra.links
.venv/bin/python main.py build-dashboards --check # 预期 5 个精简源各报 1 处差异
.venv/bin/python main.py build-dashboards # 预期 5 个「已生成」
.venv/bin/python main.py deploy
实现体:utils/dashboard_builder.py(extract 收集 extra、render 透传)。
预期:5 个 manifests/*-dashboard.yaml 各含 1 处 kibana.rainchen.top。
失败判断:--check 报「未变」而文件确实改过 → 检查是否有重复顶层 extra。
步骤 3:Kibana 侧新增「查看指标(Grafana)」面板¶
新增一个 legacy visualization + visState.type: markdown 的 saved object(8.19 仍支持),
并在分域视图仪表板的 panels 数组挂为 p10。仪表板的 references 由 main.py kibana
按 ref 自动构建,不需要手写。
坑:visState 是字符串化的 JSON,其中的换行要写成 \\n、引号要写成 \";
写错不会报错,只会在 Kibana 渲染成空白或乱码。
cd /home/rain/Documents/k8s_ins/monitoring-p2-20261001
# 新增 kibana/saved_objects/12-markdown-metrics-links.json
# 修改 kibana/saved_objects/06-dashboard-domain-overview.json(panels 加 p10:x0 y64 w48 h8)
.venv/bin/python main.py kibana --dry-run # 预期:dashboard pending + visualization pending
.venv/bin/python main.py kibana # 预期:已写入 2 个对象 + 复检通过
实现体:main.py kibana(main.py kibana → Kibana saved objects API)。
预期:复检通过:2 个对象均已与声明一致。
失败判断:pending 反复不消 → 检查 visState 转义与 ref/id 是否与仪表板一致。
6. 验证¶
# 1) hostname 标签 14/14(带 instance 区分新旧序列,避免被 stale 序列误导)
kubectl -n monitoring exec prometheus-kube-prometheus-stack-prometheus-0 -c prometheus -- \
promtool query instant http://localhost:9090 'count(up{job="external-node-exporters", hostname!=""})'
# 预期:{} => 14
# 2) 大盘 links 已入产物与集群对象
kubectl -n monitoring get cm env-monitor-overview -o jsonpath='{.data}' | grep -c 'kibana.rainchen.top'
# 预期:1
# 3) Kibana 对象一致(复跑应全部 done)
cd /home/rain/Documents/k8s_ins/monitoring-p2-20261001 && .venv/bin/python main.py kibana
# 4) 两侧漂移检测退出码
cd /home/rain/Documents/k8s_ins/env-monitor-deploy && .venv/bin/python main.py drift; echo "RC=$?"
cd /home/rain/Documents/k8s_ins/monitoring-p2-20261001 && .venv/bin/python main.py drift; echo "RC=$?"
# 预期:两条 RC=0
# 5) 幂等复跑:第二次 deploy / kibana 应零变更
注意(本次实测):relabel 变更后,Prometheus 会同时保留旧序列(无 hostname)约 5 分钟,
期间 count by (hostname) 会看到「空桶 + 带标签桶」并存,属正常;用 hostname!="" 过滤即可得真值。
UI 渲染验证:浏览器打开 https://kibana.rainchen.top 的「日志分域视图」,确认底部出现
「查看指标(Grafana)」;Grafana 任一大盘右上角出现「查看日志(Kibana)」。此项由用户确认
(内网自签证书下无头浏览器验证代价高)。
7. 回滚¶
回滚即用备份覆盖原文件,再重跑对应下发。
| 回滚对象 | 备份位置 | 回滚动作 |
|---|---|---|
env-monitor-deploy 的 3 类文件 |
backup/env-monitor-deploy/... |
覆盖后 build-dashboards + deploy |
monitoring-p2 的 06 仪表板 |
backup/monitoring-p2-20261001/... |
覆盖后 main.py kibana |
| 新增 12-markdown 面板 | 无备份(全新文件) | 删除该文件 + 回滚 06,再 main.py kibana |
备份结构与台账见 backup/README.md。
回滚后验证:drift 退出码 0;count(up{job="external-node-exporters", hostname!=""}) 归零;
大盘 ConfigMap 不再含 kibana.rainchen.top。
回滚触发判据(量化,任一成立即回滚):① drift 退出码非 0;② 抓取目标 up 数 < 14;
③ 大盘或 Kubana 面板渲染异常导致原布局不可用。
8. 风险说明¶
| 风险 | 缓解 |
|---|---|
| 改 ServiceMonitor 影响 14 台主机抓取 | 工程 deploy 幂等且有 drift 门禁;失败即回滚(判据见第 7 章) |
| YAML 重复顶层键静默覆盖 | 改精简源后必跑 --check,并在产物中 grep 关键字确认落地 |
| stale 序列造成「标签没生效」误判 | 验证用 hostname!="" 过滤,或等待 >5 分钟 |
| 静态链接不带当前选中主机/服务 | 已在面板与本文档标明为第一阶段;动态 drilldown 需先取得 Kibana 格式,列入第二阶段 |
| Kibana markdown 为 legacy 可视化,未来版本可能移除 | 已记录为依赖项;若升级 Kibana 需回归此面板 |
9. 第二阶段:动态互跳与服务目录(2026-10-02)¶
9.1 背景与目标¶
第一阶段只做了两侧静态入口链接(不带当前选中值),且未解决「服务」维度的对齐。 本阶段补上三块,闭环 LOGGING-GAP #1:
- Grafana → Kibana(动态):环境大盘的主机 Top15 面板加 data link,点击某个主机
直接带
host.name打开 Kibana 日志分域视图; - Kibana → Grafana(动态):Kibana 侧新增声明式 Vega 面板,按主机聚合日志量,
点击柱形打开该主机所属域的 Grafana 大盘(带
var-cluster); - 服务目录映射表:
cluster/service.name→ 指标侧定位(service-catalog.yaml)。
可验证的完成状态:① 两侧 drift 退出码 0、幂等复跑零变更;② Grafana 大盘出现
3 处「查看该主机日志(Kibana)」data link;③ Kibana 分域视图出现 p11「按主机日志量」面板。
9.2 关键技术结论(务必先读)¶
- Kibana 8.19 无法用 API 创建 URL drilldown:
/api/saved_objects/drilldown、url-drilldown等一律返回Unsupported saved object type;urlDrilldown插件虽为available,但 drilldown 内联在 dashboard 面板的embeddableConfig.enhancements.dynamicActions, 没有公开创建 API(新版/api/dashboards亦未启用)。故改用声明式 Vega 面板实现 Kibana → Grafana 跳转。 - Kibana 自签证书 + strict security 使无头浏览器不可用:内置浏览器报
ERR_CERT_AUTHORITY_INVALID;改经kubectl port-forward走 HTTP 后,Kibana 又以 「strict security requirements」拒绝非 HTTPS 会话。渲染类验证只能由人工在浏览器完成(见 9.4)。 - K8s 侧
host.name是 Filebeat Pod 名(filebeat-xxxxx),不是主机名,且无cluster字段; Vega 面板因此过滤掉无域标签的桶,只保留集群外主机。 - 服务名是「进程/单元」粒度:实测
service.name取值多为systemd/sshd/crond/lmgrd等单元或进程名,指标侧无同名字段,故服务维度经「域」转发到指标大盘。
9.3 分步操作(变更点)¶
| # | 变更点 | 文件 | 下发 |
|---|---|---|---|
| 1 | Vega 面板声明文件(由脚本生成,避免双重转义) | build-vega-panel.py → monitoring-p2-20261001/kibana/saved_objects/13-vega-host-metrics.json |
main.py kibana |
| 2 | 仪表板挂载 p11 面板 |
monitoring-p2-20261001/kibana/saved_objects/06-dashboard-domain-overview.json |
main.py kibana |
| 3 | 3 个主机 Top15 面板加 data link;CPU 面板查询补 hostname 标签 |
env-monitor-deploy/dashboards/overview.yaml |
build-dashboards → deploy |
| 4 | 服务目录映射表(新增) | log-metrics-crosslink-20261002/service-catalog.yaml |
无(数据源 / 文档) |
# Kibana 侧
cd /home/rain/Documents/k8s_ins/log-metrics-crosslink-20261002 && python3 build-vega-panel.py
cd /home/rain/Documents/k8s_ins/monitoring-p2-20261001
.venv/bin/python main.py kibana --dry-run # 预期:dashboard + visualization 各 pending
.venv/bin/python main.py kibana
# Grafana 侧
cd /home/rain/Documents/k8s_ins/env-monitor-deploy
.venv/bin/python main.py build-dashboards && .venv/bin/python main.py build-dashboards --check
.venv/bin/python main.py deploy
坑:① Vega 的 visState 与其内 params.spec 是双层字符串,必须用脚本生成,手写转义极易出错;
② host.name 在 K8s 侧是 Pod 名,聚合须过滤无 cluster 的桶,否则榜单被 Filebeat Pod 挤占;
③ Grafana data link 用 ${__field.labels.hostname},被聚合掉 hostname 的查询(如 CPU 的
avg by (instance, cluster))必须先补回 hostname,否则链接取不到值;
④ Kibana 的 _g filter 必须带 meta 段:meta:(alias:!n,disabled:!f,index:efk-all-logs,
key:host.name,negate:!f,params:(query:'<值>'),type:phrase) 外加 query:(match_phrase:(host.name:'<值>'))。
只写 query 段会被 Kibana 判为「Filter value is invalid or incomplete」,所有面板变空 ——
2026-10-02 实测踩到并修正;
⑤ 三个主机 Top15 的查询必须带 job="external-node-exporters":cluster / role 标签在
集群内 node-exporter(4 个 k8s 节点)与 external-node-exporter(单数,192.168.31.250)
上同样存在,只按 cluster/role 过滤会混入无 hostname 标签的序列;点中这类 bar 时链接取空,
表现为 Kibana 侧显示 host.name: (empty)、面板全空。2026-10-02 实测修正;
⑥ data link 变量只能用 ${__field.labels.hostname},不要用 ${__field.name}:
后者在 bargauge 中返回的是 Grafana 内部默认字段名 Value(实测 Kibana 侧显示 host.name: Value)。
legendFormat: '{{hostname}}' 只影响显示、与取值无关;链路取值靠 __field.labels,
故必须保证被点的序列带 hostname 标签(即坑 ⑤ 的 job 过滤是取值的前提)。2026-10-02 实测;
⑦ Vega 面板打开外部 URL 需显式开启:Kibana 默认禁外链,p11 面板顶部会红字提示
「External URLs are not enabled. Add vis_type_vega.enableExternalUrls: true to kibana.yml」。
本工程以环境变量注入(manifests/11-kibana.yaml):VIS_TYPE_VEGA_ENABLEEXTERNALURLS=true。
⚠ 改后 Kibana 会重启(Deployment 为 Recreate 策略,约 1~2 分钟入口不可用)。2026-10-02 实施。
9.4 验证¶
# 1) Grafana 产物含 3 处 data link
kubectl -n monitoring get cm env-monitor-overview -o jsonpath='{.data}' | grep -c '查看该主机日志(Kibana)' # 预期 3
# 2) node_* 指标普遍带 hostname 标签
kubectl -n monitoring exec prometheus-kube-prometheus-stack-prometheus-0 -c prometheus -- \
promtool query instant http://localhost:9090 'count(node_cpu_seconds_total{hostname!=""})' # 预期 592
# 3) Vega 对象存在
kubectl -n monitoring exec elasticsearch-0 -- bash -lc \
'E="elastic:$ELASTIC_PASSWORD"; curl -s -u "$E" -H "kbn-xsrf: true" "http://kibana:5601/api/saved_objects/visualization/efk-vega-host-metrics"'
# 4) 两侧幂等:第二次 deploy / kibana 零变更;drift 均 rc=0
UI 渲染验证(须人工,原因见 9.2):
- Grafana 环境总览大盘 →「CPU/内存/根分区使用率 Top15」→ 悬停柱形应出现「查看该主机日志(Kibana)」,
点击打开 Kibana 分域视图并已按该主机过滤;
- Kibana 日志分域视图 → 底部 p11「按主机日志量」→ 点击柱形应打开对应域 Grafana 大盘(带 var-cluster)。
9.5 回滚¶
| 回滚对象 | 备份位置 | 回滚动作 |
|---|---|---|
env-monitor-deploy/dashboards/overview.yaml |
backup/env-monitor-deploy/dashboards/... |
覆盖后 build-dashboards + deploy |
monitoring-p2-20261001/.../06-dashboard-domain-overview.json |
backup/monitoring-p2-20261001/kibana/saved_objects/... |
覆盖后 main.py kibana |
新增 13-vega-host-metrics.json / service-catalog.yaml / build-vega-panel.py |
无(全新文件) | 删除 13-*.json、回滚 06,再 main.py kibana |
回滚触发判据(任一成立即回滚):① 两侧 drift 退出码非 0;② 大盘或 Kibana 面板渲染异常
导致原布局不可用;③ 抓取目标 up 数 < 14。
10. 第三阶段:服务目录本土化 + 「服务 · 作业 · 主机」一张页(2026-10-02)¶
10.1 背景与目标¶
第二阶段遗留两条:① 服务维度只经「域」转发,未做「进程名 → 业务服务」归类; ② 指标与日志各有短板(Grafana 无日志数据源、Kibana 无指标),无法从「服务」这一层切入。 本阶段做两件事:
- 服务目录本土化:
service-catalog.yaml新增business_services段,把日志侧service.name的进程/单元粒度归并为业务服务(13 个),并给出该服务的域 / 主机名正则 / 进程取值 / 指标盘 uid / Kibana 过滤键值; - 统一入口盘:Grafana 新建
env-service-map「服务 · 作业 · 主机(统一入口)」 (4 组 13 面板 +svc/host两级级联变量),同一页看服务健康、作业与主机资源, 日志一律经 Kibana 链接下钻。
可验证的完成状态:① deploy 首次下发成功、幂等复跑零变更、drift rc=0;
② Grafana sidecar 写入 env-service-map-dashboard.json;③ 环境总览出现新盘 link。
10.2 关键技术结论(先读)¶
- 指标侧没有
service.name对应字段(第二阶段已记):服务 → 指标只有两条路 —— 集群外主机按hostname正则,K8s 平台服务按kubernetes.namespace(kube_*指标)。 故新盘的「服务」变量是 custom 类型(显示名 : 主机正则),不是指标派生变量。 hostname标签只加在job="external-node-exporters"(复数)上。2026-10-02 实测 Prometheus 中node_cpu_seconds_total分属三个 job:external-node-exporters(14 台,有hostname)、external-node-exporter(单数,宿主 192.168.31.250,无hostname)、node-exporter(4 台 K8s 节点,无hostname)。故新盘主机/服务面板只覆盖 14 台 集群外主机;宿主与 K8s 节点走「服务目录」表里的链接进入既有盘。- Grafana 侧看不到日志:所有日志入口是 Kibana 链接,且 markdown 表格里的 URL
必须把 rison 的括号编码为
%28/%29,否则 markdown 链接会在第一个)处截断。 dashboard description只能写在精简源的extra段:dashboard_builder.render()只识别 固定的顶层键(manifest/configmap/title/uid/tags/timezone/refresh/time/variables/groups), 写在顶层的description会被静默丢弃。svc变量与目录同源:service-catalog.yaml的business_services[].hosts_filter必须与精简源svc变量的选项值一一对应 —— 改其一必须同步另一处(无自动校验,属已知双轨)。
10.3 分步操作(变更点)¶
| # | 变更点 | 文件 | 下发 |
|---|---|---|---|
| 1 | 新增新盘精简源(uid env-service-map,4 组 13 面板) |
env-monitor-deploy/dashboards/service-map.yaml |
build-dashboards → deploy |
| 2 | 生成物(禁止手改,check_sync 门禁会拦) |
env-monitor-deploy/manifests/15-env-service-map-dashboard.yaml |
同上 |
| 3 | kubernetes.manifests 列表注册新盘 |
env-monitor-deploy/config/env-monitor.yaml |
同上 |
| 4 | 环境总览加「服务 / 作业 / 主机(统一入口)」link | env-monitor-deploy/dashboards/overview.yaml |
同上 |
| 5 | 服务目录本土化(business_services 段,13 个业务服务) |
log-metrics-crosslink-20261002/service-catalog.yaml |
无(数据源 / 文档) |
cd /home/rain/Documents/k8s_ins/env-monitor-deploy
.venv/bin/python main.py build-dashboards && .venv/bin/python main.py build-dashboards --check
.venv/bin/python main.py deploy # 首次下发
.venv/bin/python main.py deploy # 幂等复跑:应零变更、全跳过
.venv/bin/python main.py verify && .venv/bin/python main.py drift
坑:① 新盘 svc 变量是 custom(含 includeAll: false),host 变量依赖 $svc
(label_values(up{job="external-node-exporters", hostname=~"$svc"}, hostname))构成级联 ——
若把 svc 写成 query 变量,级联不成立;② 主机面板的 Kibana data link 仍需
job="external-node-exporters" 与 ${__field.labels.hostname}(第二阶段坑 ⑤⑥ 在此盘同样适用);
③ 空数据面板要显式 or vector(0)(如「副本不可用的 Deployment」无异常时返回空集,
Grafana 会显示 "No data" 而非 0)。
10.4 验证(2026-10-02 实测)¶
# 1) 新盘 ConfigMap 已落地且带 Grafana sidecar 标签
kubectl -n monitoring get cm env-service-map-dashboard -o jsonpath='{.metadata.labels}' # grafana_dashboard=1
# 2) Grafana 已真的加载该盘(**写文件 ≠ 已加载**,必须走 API 确证)
kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 13000:80 &
U=$(kubectl -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-user}' | base64 -d)
P=$(kubectl -n monitoring get secret grafana-admin -o jsonpath='{.data.admin-password}' | base64 -d)
curl -s -o /dev/null -w '%{http_code}\n' -u "$U:$P" http://localhost:13000/api/dashboards/uid/env-service-map # 预期 200
curl -s -u "$U:$P" "http://localhost:13000/api/search?tag=env-monitor" | grep -o '"title":"[^"]*"' # 应含「服务 · 作业 · 主机(统一入口)」
# 2026-10-02 实测:uid 查询 200(created 05:27:51Z),tag 查询返回 6 个盘含新盘
# 3) 环境总览已带新盘入口
kubectl -n monitoring get cm env-monitor-overview -o jsonpath='{.data}' | grep -c '服务 / 作业 / 主机(统一入口)' # 预期 1
# 4) 幂等与漂移
# 第二次 deploy:变更执行 0 次,k8s_ingest 状态 skipped;verify rc=0;drift rc=0
⚠ 验证取数坑:① Grafana 的 admin 凭据在 secret grafana-admin(keys admin-user / admin-password),
不是 kube-prometheus-stack-grafana —— 用错会得到 401 password-auth.failed;
② dashboard sidecar 写入文件后会主动 POST /api/admin/provisioning/dashboards/reload,
故写入即触发加载,不必等 updateIntervalSeconds;
③ Grafana 容器是精简镜像(无 sh / ls),不能进容器查 /tmp/dashboards,只能从 sidecar 日志或 API 侧取证;
④ GET /api/search?query=<关键字> 对中文标题匹配不可靠(实测 query=service 返回 []),
按 tag 或 uid 查询才稳。
UI 渲染验证(须人工,原因见 §9.2):
- https://grafana.rainchen.top/d/env-service-map → 切「业务服务」变量,确认「主机」变量选项随之收敛、
「主机资源」三块柱形出数、点柱形可跳 Kibana 且已按该主机过滤;
- 「服务目录」表内每行的「指标」「日志」链接可点通;
- 环境总览右上角出现「服务 / 作业 / 主机(统一入口)」。
10.5 回滚¶
| 回滚对象 | 备份位置 | 回滚动作 |
|---|---|---|
env-monitor-deploy/dashboards/overview.yaml |
backup/env-monitor-deploy/dashboards/overview.yaml.bak.20261002-132502 |
覆盖后 build-dashboards + deploy |
env-monitor-deploy/config/env-monitor.yaml |
backup/env-monitor-deploy/config/env-monitor.yaml.bak.20261002-132502 |
覆盖后 build-dashboards + deploy |
新增 dashboards/service-map.yaml、manifests/15-*.yaml、service-catalog.yaml 的 business_services 段 |
无(全新 / 纯增量) | 删除 service-map.yaml 与 manifests/15-*.yaml,config 去掉该条目后 build-dashboards + deploy;或 kubectl -n monitoring delete cm env-service-map-dashboard |
回滚触发判据(任一成立即回滚):① deploy 返回非 0 或 drift rc≠0;
② 新盘导致既有盘(环境总览 / 四领域盘)渲染异常或链接失效;③ 抓取目标 up 数 < 14。
11. 第四阶段:覆盖缺口补齐 + Kibana 侧业务服务归并(2026-10-02)¶
11.1 背景与目标¶
第三阶段人工 UI 复验通过后,用户指出两处遗留,本阶段补齐:
- 覆盖缺口:宿主
192.168.31.250(jobexternal-node-exporter,单数)与 4 台 K8s 节点 (jobnode-exporter)的指标没有hostname标签,统一入口盘覆盖不到它们; - Kibana 侧仍是进程粒度:
service.name取值是systemd/sshd/slurmctld,业务服务归并 此前只落在 Grafana 与服务目录,日志侧看不到「GitLab」「Slurm 调度」这样的业务视角。
完成状态:① 19 台主机(14 集群外 + 4 K8s 节点 + 1 宿主)指标均带 hostname;
② Kibana 分域视图出现「业务服务」控件与面板,历史 14 天数据同样生效。
11.2 关键技术结论(先读)¶
prometheus_deploy/values.yaml已不是现场基线:2026-10-02 实测,现场 values (helm get values)比该文件多 10 项 —— Alertmanager 的 SMTP/route/inhibit_rules (由 dell-r620-monitor 与 env-monitor-deploy 两个工程叠加)与grafana.nodeSelector: k8s-node-03。 按该工程 RUNBOOK §5.2 的-f values.yaml单文件升级会丢掉这 10 项(邮件路由失效、 Grafana 节点漂移)→ 本阶段改走--reuse-values -f <overlay>(helm map 深合并、list 整体替换)。 (2026-10-03 更新)该缺口已闭环:漂移实际已涨到 13 项(本阶段的节点 relabel 与组三 #12 的 grafana 内存同样只走 overlay),已全部回写进values.yaml(SMTP 授权码除外,凭据不入库), 见prometheus-baseline-align-20261003/docs/SOP.md;此后单文件升级安全。- 对象级预演是唯一可信判据:
helm upgrade --dry-run的输出与helm get manifest逐对象哈希比对。 本次差异 = 1 个目标对象(node-exporter ServiceMonitor)+ 已知 hook 噪音(admission Job/ClusterRole) - Grafana PVC 的
spec.volumeName(服务端绑定字段,非漂移)。注意 helm 输出头尾都有非 YAML 内容 (header 与 NOTES),直接yaml.safe_load_all会解析失败,需按# Source:/\n---裁切。 - Alertmanager 运行配置的取证路径:operator 生成的是
alertmanager-<release>-alertmanager-generated,键名是alertmanager.yaml.gz(gzip), 不是alertmanager.yaml(后者是用户提供的源配置)。用计数而非打印正文(内含 SMTP 授权码)。 - Kibana 侧业务服务用 runtime field 实现:写在
index-patternsaved object 的attributes.runtimeFieldMap(字符串化 JSON,kibana_views.py的字段子集比对会覆盖它)。 相比「Filebeat 写入新字段」:对历史数据立即生效、不改采集链、不重启;代价是查询时计算 (实测 24h 全量聚合约 4~6 秒)。 kubernetes.node.name在 K8s 侧有值(k8s-master-01、k8s-node-01~03),而host.name是 Filebeat Pod 名 —— 故主机面板的 Kibana 跳链改用 kuery:host.name:X or kubernetes.node.name:X, 一条链接同时命中集群外主机与 K8s 节点。- 归并脚本首版留下 12% 「未归类」:K8s 节点的系统日志有
service.name但既无kubernetes.namespace也无cluster(它们是节点级 journal/文件日志,不带 Pod 元数据)。 加兜底(两者皆空 → 「K8s 集群与节点」)后归零。
11.3 分步操作(变更点)¶
| # | 变更点 | 文件 | 下发 |
|---|---|---|---|
| 1 | data view 加 business_service runtime field(Painless,按 ns/cluster/service.name 归并 15 类) |
monitoring-p2-20261001/kibana/saved_objects/01-data-view.json |
main.py kibana |
| 2 | 新增「日志量 · 按业务服务」Lens 面板 | 同目录 14-viz-business-service.json(新增) |
同上 |
| 3 | 分域视图加「业务服务」控件 ctrl-biz + p12 面板 |
同目录 06-dashboard-domain-overview.json |
同上 |
| 4 | 4 台 K8s 节点补 hostname/cluster |
log-metrics-crosslink-20261002/prom-node-exporter-relabel-overlay.yaml(新增 overlay) |
--reuse-values -f <overlay>(见下) |
| 5 | 宿主补 hostname/cluster |
dell-r620-monitor-20260929/manifests/01-external-node-exporter.yaml |
kubectl apply -f 该文件(不要跑该工程完整 deploy,它会 helm upgrade 注入自己的 Alertmanager 路由) |
| 6 | 新盘扩到 19 台 | env-monitor-deploy/dashboards/service-map.yaml(svc 加 2 项、job 过滤放宽、跳链改 kuery)+ service-catalog.yaml 的 hosts_filter |
build-dashboards → deploy |
cd /home/rain/Documents/k8s_ins
# 1) Kibana 侧(幂等,先 dry-run)
cd monitoring-p2-20261001 && .venv/bin/python main.py kibana --dry-run && .venv/bin/python main.py kibana
# 2) K8s 节点 relabel(**不许用 -f values.yaml 单文件**)
cd .. && helm upgrade --install kube-prometheus-stack prometheus_deploy/charts/kube-prometheus-stack-91.4.1.tgz \
-n monitoring --reuse-values -f log-metrics-crosslink-20261002/prom-node-exporter-relabel-overlay.yaml \
--no-hooks --timeout 30m --wait
# 3) 宿主 relabel
kubectl apply -f dell-r620-monitor-20260929/manifests/01-external-node-exporter.yaml
# 4) 新盘
cd env-monitor-deploy && .venv/bin/python main.py build-dashboards && .venv/bin/python main.py deploy
11.4 验证(2026-10-02 实测)¶
# 标签覆盖:三类 job 全部带 hostname(4+1+14)
kubectl -n monitoring exec prometheus-kube-prometheus-stack-prometheus-0 -c prometheus -- \
promtool query instant http://localhost:9090 'count by (hostname,cluster)(up{job="node-exporter"})' # 4 台,cluster=k8s
kubectl -n monitoring exec prometheus-kube-prometheus-stack-prometheus-0 -c prometheus -- \
promtool query instant http://localhost:9090 'count by (hostname,cluster)(up{job="external-node-exporter"})' # dell-r620 / dell_r620
# 两侧幂等
# main.py kibana 复跑:全部 done、零变更;main.py deploy 复跑:变更执行 0 次
⚠ relabel 生效有延迟:ServiceMonitor 改动后需等 operator 重建抓取配置 + 一个抓取周期 (实测 K8s 节点约 45 秒、宿主约 90 秒才在 Prometheus 里看到新标签),验证时不要立即判定失败。
UI 复验(人工):Kibana 分域视图 →「业务服务」控件可选 15 类;「日志量 · 按业务服务」面板出数
(切换后明细表按业务服务过滤);Grafana env-service-map 的「业务服务」变量可选 7 项,
选「K8s 集群与节点」应出 4 台节点。
结案(2026-10-02):以上 UI 复验已由用户确认通过,第四阶段验收闭环; 「日志 ↔ 指标互跳」四阶段整体结案(无遗留动作)。
11.5 回滚¶
| 回滚对象 | 备份位置 | 回滚动作 |
|---|---|---|
01-data-view.json / 06-*.json |
backup/monitoring-p2-20261001/kibana/saved_objects/*.bak.20261002-135302 |
覆盖后 main.py kibana |
| K8s 节点 relabel | backup/prometheus_deploy/manifests/pre-upgrade-20261002-135634.yaml(现场 manifest) |
helm rollback kube-prometheus-stack 10 -n monitoring(或反向 upgrade 去掉 overlay 中的 relabelings) |
| 宿主 ServiceMonitor | backup/dell-r620-monitor-20260929/manifests/01-external-node-exporter.yaml.bak.20261002-135302 |
覆盖后 kubectl apply -f 该文件 |
| 新盘与目录 | backup/env-monitor-deploy/dashboards/service-map.yaml.bak.*、backup/log-metrics-crosslink-20261002/service-catalog.yaml.bak.* |
覆盖后 build-dashboards + deploy |
回滚触发判据(任一成立即回滚):① main.py kibana / deploy 返回非 0 或复检不过;
② Alertmanager 运行时配置丢失 email-p1/p2 或 smtp(api/v2/status 计数为 0);
③ Grafana nodeSelector 不再是 k8s-node-03;④ 抓取目标 up 数下降。
附录 A:交付物清单¶
| 文件 | 说明 |
|---|---|
SOP.md |
本文件(含第一阶段与第二阶段) |
backup/README.md + backup/ |
修订前备份与台账 |
service-catalog.yaml |
服务目录映射表(cluster / service.name → 指标侧大盘) |
build-vega-panel.py |
Kibana Vega 面板声明文件生成脚本(避免双层转义) |
(工程内)env-monitor-deploy/modules/k8s_ingest.py、manifests/01-*.tpl、dashboards/overview.yaml |
指标标签与大盘 links / data link |
(工程内)monitoring-p2-20261001/kibana/saved_objects/12-*.json、13-*.json、06-*.json |
Kibana 静态入口与 Vega 动态面板、仪表板挂载 |
env-monitor-deploy/dashboards/service-map.yaml(+ 生成物 manifests/15-env-service-map-dashboard.yaml) |
第三阶段:统一入口盘精简源与生成物(uid env-service-map) |
(工程内)env-monitor-deploy/config/env-monitor.yaml、dashboards/overview.yaml |
第三阶段:新盘注册与环境总览入口 link |
monitoring-p2-20261001/kibana/saved_objects/14-viz-business-service.json |
第四阶段:按业务服务聚合的 Lens 面板(依赖 data view 的 business_service runtime field) |
prom-node-exporter-relabel-overlay.yaml |
第四阶段:4 台 K8s 节点 node-exporter 的 relabel overlay(必须与现场 values 合并,不许单文件升级) |
附录 B:遗留(截至第四阶段)¶
- 服务维度:日志侧已在第四阶段用 Kibana runtime field
business_service归并(15 类); 指标侧仍无service.name对应字段,「服务 → 指标」是间接映射(集群外按hostname正则、 K8s 平台服务按kubernetes.namespace),不是精确字段对齐。 - 覆盖缺口已补齐(第四阶段):19 台(14 集群外 + 4 K8s 节点 + 1 宿主)指标均带
hostname。 ⚠ 新增主机或节点时必须同步补 relabel(集群外走env-monitor-deploy的nodes配置、 K8s 节点走prom-node-exporter-relabel-overlay.yaml、宿主走 dell-r620 的 ServiceMonitor), 否则新盘主机面板与服务维度会漏掉它。 prometheus_deploy/values.yaml与现场 values 存在 10 项漂移(Alertmanager 路由/抑制规则、 Grafana nodeSelector),故升级必须--reuse-values -f overlay;该文件何时重新对齐现场、 或改为 overlay 汇总属【待决策】。- 新盘 4 组面板与变量级联的渲染已由用户人工复验通过(2026-10-02,第三阶段);
第四阶段新增的「业务服务」控件 /
p12面板、扩到 19 台的主机面板亦已确认通过 (2026-10-02,见 11.4);互跳四阶段全部验收闭环,本主题已结案。 - Kibana 原生 drilldown 在 8.19 无公开 API、无法声明式下发;若后续版本开放
/api/dashboards, 可考虑改回原生 URL drilldown 以换取更好的交互体验。 - 服务目录映射表已建立,但指标侧没有
service.name对应字段,故未实现 「服务 → 具体指标job/role」的精确映射。
来源:
/home/rain/Documents/k8s_ins/log-metrics-crosslink-20261002/SOP.md| 最后更新:2026-10-03 01:03(由build/sync.py同步,请勿在站点侧修改)