From e829c9577a644cf1774f5e7e3e815caa4c40dab0 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Mon, 14 Sep 2026 21:49:09 +0800 Subject: [PATCH 01/14] =?UTF-8?q?docs(design):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=BE=AE=E6=9C=8D=E5=8A=A1=E5=8F=AF=E8=A7=82=E6=B5=8B=E6=80=A7?= =?UTF-8?q?=E5=BB=BA=E8=AE=BE=E6=8A=80=E6=9C=AF=E8=AE=BE=E8=AE=A1=EF=BC=88?= =?UTF-8?q?#1938=20/=20=E5=AD=90=E4=BB=BB=E5=8A=A1=20#2061=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spec 契约 + 四语言 SDK 之外的第三份交付物:面向评审的技术设计稿。 - §3 整体架构:范围分层 / 部署与流程 / 底座选型 / community 贯穿维度 - §4 详细设计:契约层、四语言 SDK 接入模式(Go/Java/Python 各一示例)、 部署侧字段注入、底座与观测消费侧、中心指标集群选型与形态 - §5 工作量预估、§6 风险与待确认(含 R7 部署口径明细)、附录 关键结论:指标侧改为自建中心 Prometheus(弃用 AOM 多账号聚合,官方确认 不支持跨 Region),17 集群 Agent remote_write 汇聚,统一大盘 + 统一告警; 日志侧复用现有 LTS 每集群 1 条流,大盘并入自建 Grafana。 Co-Authored-By: Claude Code --- ...00\346\234\257\350\256\276\350\256\241.md" | 1029 +++++++++++++++++ 1 file changed, 1029 insertions(+) create mode 100644 "docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" new file mode 100644 index 0000000..58765a9 --- /dev/null +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -0,0 +1,1029 @@ +# 微服务可观测性建设技术设计 + +> 需求:[opensourceways/backlog#1938](https://github.com/opensourceways/backlog/issues/1938) +> 子任务 A(SDK 与试点):[#2061](https://github.com/opensourceways/backlog/issues/2061) · B(底座与大屏告警):[#2062](https://github.com/opensourceways/backlog/issues/2062) · C(全量铺开与验收):[#2063](https://github.com/opensourceways/backlog/issues/2063) +> 契约与 SDK 实现仓:[opensourceways/obs-sdk](https://github.com/opensourceways/obs-sdk) + +--- + +## 1. 背景 + +### 1.1 问题 + +基础设施团队维护的重点微服务缺乏统一可观测能力,故障定位靠人工登录机器翻日志,排障链路长、效率低,服务健康度不可见。 + +各社区另缺一个**统一的服务健康度大盘**(形态可对齐 [GitHub Status](https://www.githubstatus.com/)):社区用户与运维无法一眼看到整体与各组件(如评审机器人、账号、CLA 等)是否正常、异常落在哪一段? + +### 1.2 覆盖范围 + +以 2025-05-01 ~ 2025-07-31 三个月有 PR 合入的活跃服务为全集,剔除纯配置/部署仓、umbrella 大仓、框架库/工具仓、前端 website 仓后,保留 **15 个大仓 / 26 个微服务子仓 / 390 个合入 PR**。 + +语言分布不统一:Go 7 · Java 6 · Python 8(+3 待评估)· Node 1 · 编排仓 1。 + +### 1.3 现状基线 + +| 能力 | 现状 | 结论 | +| --- | --- | --- | +| 硬件级指标(CPU/内存/磁盘/网络) | 已由华为云 CCE 云原生监控插件(node-exporter / kube-state-metrics)+ icagent 上报控制台 | **复用,不建设** | +| 日志采集管道 | log-agent 插件(fluent-bit / otel-collector)已部署,全局规则 `default-stdout`(`allContainers: true`)采集所有 ns 容器 stdout | **复用,不建设** | +| 日志内容 | 已进 LTS 可全文检索,但**无结构化裸文本、无统一业务字段**(service / level / request_id 不保证、命名不统一) | **建设点:结构化 + 字段统一** | +| 业务指标 | 26 个微服务均未暴露 / 接入 `/metrics`;Prometheus 仅采系统组件 | **建设点:从零接入** | +| 告警 | 无 PrometheusRule、无 Alertmanager | **建设点:从零接入** | +| 监控大盘(对内指标视图) | 无业务级大盘 | **建设点:从零接入** | +| 服务健康度大盘(对外状态视图) | 无,各社区无统一入口,整体/组件级健康度不可见 | **建设点:从零接入** | + +### 1.4 关键约束 + +1. **多语言**:4 种语言、框架不统一(Gin / Spring Boot / Django / FastAPI / Flask / 上游开源项目),不能用单一语言的方案覆盖。 +2. **多社区、多 Region**:26 服务 prod 跨 **4 个 Region**(香港 / 北京一 / 北京四 / 贵阳二,约 17 个集群)。同一逻辑服务可能按社区拆成多套独立部署(如 `robot-universal-review` 在 **10 个社区 / 7 个集群**各有一套),需要能按社区维度切片查看健康度。 +3. **不能自研 instrumentation**:各语言日志/指标生态成熟,自研只会带来维护负担与生态割裂。 + +--- + +## 2. 目标 + +### 2.1 建设目标 + +| # | 目标 | 对应验收标准 | +| --- | --- | --- | +| G1 | 26 个微服务暴露 `/metrics`(QPS / 错误率 / 业务自定义指标)并接入 Prometheus | 验收 2 | +| G2 | 26 个微服务日志统一输出**结构化 JSON**(含 service / level / community / request_id 等契约字段)到 stdout,经现有 log-agent 进 LTS,支持按 service / level / community / request_id 检索 | 验收 3 | +| G3 | 建立业务级监控大盘,重点服务健康度集中可见,**支持按 community 维度过滤/分组** | 验收 4 | +| G4 | 关键服务配置告警规则(高错误率 / 宕机 / 资源超阈值)并打通通知到负责人 | 验收 5 | +| G5 | 硬件级指标复用云上,不重复建设 | 验收 1 | + +### 2.2 设计原则(方案阶段已定) + +1. **薄封装,不自研 instrumentation**。每语言 1 个薄 SDK,内部引用各语言官方库(Go→`client_golang`、Python→`prometheus-client`、Java→`micrometer`+Actuator、Node→`prom-client`),SDK 只做装配:中间件挂载 + 通用字段注入 + 命名对齐 + 一行初始化。 +2. **契约先行**。跨语言统一的日志 schema、通用字段、指标命名规范收敛到单一仓库的 `spec/` 目录,是唯一事实来源;四语言实现与 spec 不一致时以 spec 为准。 +3. **log 与 metrics 同仓不同 package**,不拆成两个库。 +4. **单仓 monorepo**:`opensourceways/obs-sdk`,顶层 `spec/` + `go/ python/ java/ node/`,各语言子目录自管版本。 +5. **首期只做 log + metrics,不含 trace**。`trace_id` / `span_id` 作为**预留注入位**存在(字段可写可透传、有值才输出),二期接入 OTel 时零日志格式返工。 +6. **Go SDK 独立成库,不放进 robot-framework-lib** —— 后者是机器人领域框架,SDK 需领域中立以服务 24 个非机器人服务。 + +--- + +## 3. 整体架构 + +### 3.1 范围与分层视图 + +基础设施可观测建设整体分**三块** + +```mermaid +flowchart TB + subgraph L1["① 范围"] + direction LR + A1["【服务】微服务
26 个微服务子仓 · 4 种语言"] + A2["【资源】昇腾 CI 资源
昇腾 NPU 算力 · CI 节点"] + A3["【其他】账号等"] + end + + subgraph L2["② 采集"] + direction LR + B1["obs-sdk(本项目产出)"] + B2["探测 CronJob + Agent"] + B3["(待补充)"] + end + + subgraph L3["③ 存储(日志 · Region 级自持 / 指标 · 汇聚到独立中心)"] + C1["日志 · LTS 各 Region 日志流
指标 · 各集群 Agent remote_write → 独立中心 Prometheus"] + end + + subgraph L4["④ 汇聚(只读分析路径)"] + D1["日志 · Grafana + LTS 数据源(访问层汇聚 · 不搬数据)
指标 · 中心 Prometheus 天然汇聚(无需额外聚合层)"] + end + + subgraph L5["⑤ 视图(只读分析路径)"] + F1["统一大盘 · 自建 Grafana ×1(指标 + 日志)
服务健康度 · 按 community 昇腾资源水位 账号 / 配额"] + end + + subgraph L6["⑥ 告警(从 ③ 分叉)"] + direction LR + E1["日志 · LTS 告警规则
各 Region 本地、逐流配置(17 条)"] + E2["指标 · 中心 Alertmanager
一条规则覆盖全部集群(不经 SMN)"] + E3["SMN 主题 · 每 Region 一个(仅日志告警)
订阅端统一 → 邮件 / 短信 / 企微 / 钉钉 / Webhook"] + end + + A1 --> B1 + A2 --> B2 + A3 --> B3 + B1 --> C1 + B2 --> C1 + B3 --> C1 + + C1 --> D1 + D1 --> F1 + + C1 --> E1 + C1 --> E2 + E1 --> E3 + + classDef scope stroke:#d9534f,stroke-width:2px + class A1,B1 scope +``` + + +**本方案在底座上的四点定位**: + +1. **日志 —— 复用,不新建**:继续用各集群**现有的日志流**(CCE 云原生日志采集插件为每集群建的 `k8s-log-*` 组),本方案只改**日志的内容格式**(结构化 JSON + 契约字段),**不动采集管道**。 +2. **指标 —— 新建**:26 个服务目前均未暴露 `/metrics`,需从零接入;存储侧**自建 Prometheus 实例**(独立中心集群,见 §4.7),不走华为云托管。 +3. **大盘 —— 自建 Grafana**:**一个**实例同时挂中心 Prometheus(指标)+ 17 个日志数据源(日志),见 §4.7.6 / §4.7.8。 +4. **已有现成闭环可参照**:**昇腾 CI 资源块**已跑通 **多集群 CronJob + Agent 上报 → 中心 Prometheus 存储 → Alertmanager 告警 → 邮件接收** 的完整链路,本方案的**指标侧与之同构**(见 §4.7.1)。⚠️ 该闭环**不含大盘**(资源块 Grafana 未启用,用的是外部 DataStat 看板),故第 3 点的自建 Grafana 属**本方案新增**,不能当作资源块已验证的能力。 + +### 3.2 部署与流程视图 + +```mermaid +flowchart TB + subgraph L1["① 部署 · 服务 × 集群 × Region
26 仓 / 4 种语言(同一服务按社区拆成多套)→ 17 个集群 / 4 个 Region"] + direction LR + subgraph RG2["beijing4"] + direction TB + C21["集群1
评审机器人 · CLA"] + C22["集群2
账号"] + C23["集群3
评审机器人 · 账号"] + end + subgraph RG3["guiyang2"] + direction TB + C31["集群1
评审机器人 · CLA · 账号"] + end + subgraph RG4["hongkong"] + direction TB + C41["集群1
账号 · CLA · 评审机器人"] + end + subgraph RG1["beijing1"] + direction TB + C11["集群1
账号"] + end + end + + subgraph L2["② 存储 · 日志每集群 1 条流(各 Region 自持)/ 指标汇聚到 1 个中心集群"] + direction LR + M1["日志
集群1 · 集群2 … 集群17
→ 17 条流"] + M2["指标
Agent 模式 · 本地不存
→ remote_write"] + end + + subgraph L3["③ 大盘 / 监控 —— 两侧形态完全不同"] + direction LR + subgraph KI["指标侧"] + direction TB + KI1["大盘
中心 Grafana ×1"] + KI2["监控告警
中心 Alertmanager ×1
一条规则覆盖全部集群"] + end + subgraph KL["日志侧"] + direction TB + KL1["大盘
Grafana 挂 17 个日志数据源"] + KL2["监控告警
各 Region 本地 LTS ×4 → SMN ×4"] + end + end + + RG1 --> M1 + RG2 --> M1 + RG3 --> M1 + RG4 --> M1 + + RG1 --> M2 + RG2 --> M2 + RG3 --> M2 + RG4 --> M2 + + M1 --> KL + M2 --> KI +``` + +本项目的部署形态可先记住三个数:**26 个微服务子仓(4 种语言)→ 17 个 CCE 集群(4 个 Region)→ 上报 17 条日志流 + 1 个中心指标集群**。 + +第一个数会**放大**:**26 仓 ≠ 26 个部署实例**,同一逻辑服务按社区拆成多套——`robot-universal-review` 一个仓就有 **16 套部署**(生产 10 社区 / 7 集群),所以实际 Pod 实例数远多于 26。 + +**两侧的上报粒度完全不同**:日志侧**每集群 1 个日志组**(共 17 个,各 Region 自持,见 §4.6);指标侧**17 个集群的 Agent `remote_write` 汇聚到 1 个独立中心 Prometheus**(见 §4.7)。告警路径自存储层分叉:**指标告警在中心 Alertmanager 统一(一条规则覆盖全部集群)**,**日志告警仍逐 Region 本地 LTS 配置 → SMN**(LTS 无跨流查询,见 §4.6)。**该结构与 §3.1 一致,本图不重复展开。** + +**服务侧的接入形态**(每个 Pod 内): + +```mermaid +flowchart LR + APP["微服务进程
(SDK 已 Init)"] + APP -->|"obs-sdk 日志 · 单行扁平 JSON"| OUT["stdout"] + APP -->|"obs-sdk 指标 · Prometheus 文本"| MET["GET /metrics"] + OUT --> LA["log-agent
(节点 DaemonSet)"] + LA --> LTS["LTS"] + MET --> SM["ServiceMonitor"] + SM --> PROM["Prometheus Agent
(--agent,本地只抓不存)"] + PROM -->|"remote_write"| CTR["中心 Prometheus
(独立中心集群)"] +``` + + +### 3.3 底座选型(方案阶段已确认) + +| 能力 | 选型 | 说明 | +| --- | --- | --- | +| 日志存储 | **LTS**——**日志组按集群划分:每集群 1 个 `k8s-log-{集群ID}`,共 17 个** | 不自建 ES;容器日志写入 `stdout-{集群ID}` 日志流。**各 Region 自持,无跨日志组检索能力**(该限制决定了下方的日志告警形态) | +| 指标存储 | **自建中心 Prometheus**(kube-prometheus-stack):17 集群 Agent(`--agent`,只抓不存)`remote_write` 汇聚到**1 个中心实例** | 不自研 SDK,**但自建底座**——理由与形态见 **§4.7**。原「AOM Prometheus for CCE」路线**已弃用**(官方确认多实例聚合不支持跨 Region) | +| 日志大盘 | **自建 Grafana(同一实例)挂 LTS 日志数据源 ×17** | 与指标大盘同屏、**跨账号免多登**(§4.7.8)。✅ **接入日志流已确认可行**(2026-09-14 华为云,前提是流已结构化) | +| 指标大盘 | **自建 Grafana(1 个实例)挂中心 Prometheus**。**独立 Deployment、与中心 Prometheus 同集群**(§4.7.6) | 替代原「AOM 托管 Grafana ×4」——一个实例即可覆盖全部 17 集群(§4.7.8)。**只做看板,不进告警链路**(见下行注释) | +| 日志告警 | **各 Region 本地 LTS 内逐流配置(17 条)**,出口经 SMN 统一到订阅端 | 因 LTS **无跨流查询**,一条规则无法绑定多个日志流,**明确接受「无跨集群联合告警」**。**SMN 仅日志告警仍用**(Region 级资源),「统一」落在各 Region 主题**订阅同一接收端**,而非同一主题 | +| 指标告警 | **统一在中心 Alertmanager**(一条规则覆盖全部 17 集群) | 指标侧不再逐 Region 各配;`group_by: [cluster, alertname]` 区分来源 | + +**为什么指标告警统一、日志告警仍散**——两条链路能力不同,不是取舍不一致: + +1. **指标侧已统一**:数据经 `remote_write` 汇入中心 Prometheus,**告警规则天然覆盖全部 17 集群**,一条规则即可(`group_by: [cluster, alertname]` 区分来源)。这是自建中心相对 AOM 路线的主要收益之一(§4.7.3); +2. **日志侧统一不了**:LTS **没有跨日志组 / 流的检索能力**,一条告警规则无法绑定多个日志流——该限制已与华为云团队确认。因此日志规则只能**逐流在本地 LTS 内配置(17 条)**,且**跨集群联合条件写不出来**(如「某服务在所有社区的某类失败总数」); +3. **日志告警出口仍是 SMN**:**SMN 主题是 Region 级资源**(URN 形如 `urn:smn:::`),故「统一」不在同一个主题,而在**各 Region 主题订阅同一接收端**(邮件组 / 统一 webhook 接收服务)。 + +### 3.4 贯穿维度:community + +`community` 是本次建设的**核心维度**——支撑「按社区查看单服务健康度」。它在日志字段与指标 label 上语义一致,采用**双层注入**: + +| 层 | 场景 | 取值来源 | 日志表现 | 指标表现 | +| --- | --- | --- | --- | --- | +| **部署级默认**(静态) | 服务按社区拆实例(每实例只服务一个社区) | Init 注入:`OBS_COMMUNITY` 环境变量或显式参数 | 进程内所有日志的常驻字段 | 所有时间序列的常驻 const label | +| **请求级覆盖**(动态) | 中心化单实例服务多社区(靠路由/鉴权识别归属) | 请求上下文,由 SDK 从 context 读取 | 该请求关联日志的字段值 | 该请求打点的 series 的 label 值 | + +--- + +## 4. 详细设计 + +### 4.1 契约层(`spec/`) + +契约层是本次建设的**技术核心**:它把「多语言输出形态一致」这件事从「靠人自觉」变成「有据可查、可校验」。 + +#### 4.1.1 日志格式(`spec/log-format.md`) + +**输出形态**:每行一条日志,单行 JSON(不 pretty、不换行),UTF-8 写 stdout。 + +**顶层字段与顺序**: + +| 字段 | 必填 | 说明 | +| --- | --- | --- | +| `time` | 是 | RFC 3339 UTC,**固定毫秒精度(3 位小数)**,以 `Z` 结尾 | +| `level` | 是 | 小写枚举 `debug` / `info` / `warn` / `error` | +| `msg` | 是 | 人类可读的**常量短语** | +| `service` | 是 | 服务名(= service.yaml 的服务名) | +| `env` | 是 | `prod` / `test` / `preview` / `staging` | +| `instance` | 是 | 实例标识(k8s pod 名 / hostname) | +| `community` | 是 | 社区标识(部署级默认 + 请求级覆盖) | +| `request_id` | 否 | 单请求关联 ID | +| `trace_id` | 否(预留) | 二期 trace 接入前恒空/省略 | +| `span_id` | 否(预留) | 二期 trace 接入前恒空/省略 | +| `logger` | 否 | 调用位置 `文件:行号`(调试定位) | +| `error` | 否 | 错误信息;有异常上下文的语言可含完整 traceback | +| 其余 | 否 | 业务字段**平铺在顶层**,`snake_case`,禁止嵌套对象 | + +**两条关键传参约束**: + +1. **`msg` 必须是常量短语,禁止 printf 风格**(`log.Errorf("failed for user %s", uid)` 违规)。所有可查询维度通过 kv 传入:`log.ErrorContext(ctx, "get account failed", "user_id", uid, "error", err)`。 + *理由*:`msg` 一旦嵌值,同一事件每行都不同 → LTS 无法按 `msg` 聚合计数,日志告警规则**静默失效**;改文案即破坏已配置的检索。四语言 SDK **只提供 kv 形式,无 printf 变体**。 +2. **业务字段扁平**,不允许嵌套对象。嵌套会给 LTS 侧字段提取带来歧义。 + +> `error` 字段**不适合聚合**(取值逐次不同,Python 等语言还含 traceback)。按错误类型聚合请用 `msg` 常量 + 业务字段(如 `error_code`)。 + +#### 4.1.2 通用字段(`spec/common-fields.md`) + +7 个通用字段的来源与注入优先级: + +| 字段 | 注入层级 | 静态/动态 | 环境变量 | 内置默认 | +| --- | --- | --- | --- | --- | +| `service` | Init(进程级) | 静态 | `OBS_SERVICE` | `unknown` | +| `env` | Init(进程级) | 静态 | `OBS_ENV` | `unknown` | +| `instance` | Init(进程级) | 静态 | `OBS_INSTANCE` | **hostname** | +| `community` | Init + 请求上下文 | 双态 | `OBS_COMMUNITY` | `unknown` | +| `request_id` | 请求上下文 | 动态 | — | 无 | +| `trace_id` | 请求上下文(预留) | 动态/预留 | — | 无 | +| `span_id` | 请求上下文(预留) | 动态/预留 | — | 无 | + +取值优先级:**SDK Init 显式参数 > 部署环境变量 > 内置默认**。 +变量名统一 `OBS_*` 前缀,四语言读同一套变量名,保证部署模板(helm values)不因语言而异。 + +**`request_id` 注入策略**:可信入站头(如 `X-Request-Id`,**在服务已校验可信时**)> 中间件自动生成(UUID)> 无。出站调用应向下游传播,保证全链路同 ID。 + +#### 4.1.3 指标格式(`spec/metrics-format.md`) + +- **命名**:全小写 `snake_case`,单位后缀遵循 Prometheus 约定(`_total` / `_seconds` / `_bytes`)。 + - 业务指标强制前缀 `_`(服务短名)。例:`review_http_requests_total`。 + - 共享中间件公共指标用 SDK 保留前缀 **`obs_`**(不按 service 名开头——同一条 series 已带 `service` label,查询按 label 过滤)。例:`obs_http_server_requests_total`。 +- **通用 label 集**(每条 series 必须带):`service` / `env` / `instance` / `community`。 + - 前三个是 const label;**`community` 是唯一可动态的公共 label**。 +- **community 双层注入的指标实现**:对需要区分社区的指标,注册时把 `community` 声明为**普通可变 label**(service/env/instance 仍作 const label),打点时由 SDK 从上下文取覆盖值。**注册一次,单社区场景填默认值、多社区场景填覆盖值,两用。** +- **高基数禁令**:`request_id` / `trace_id` / `span_id` / PR number / commit sha 等**禁止**作 label,会撑爆时序基数。 +- **暴露**:每服务一个 `/metrics` 端点,HTTP `GET`,Prometheus text format。 + +#### 4.1.4 community 枚举(`spec/community-values.md`) + +18 个社区:`Ascend · BoostKit · CANN · Common · HiFloat · HPCKit · Infrastructure · Merlin · MindSpore · openEuler · OpenFuyao · openGauss · OpenJiuwen · openLookeng · OpenPangu · OpenUBMC · UnifiedBus · Xihe`。 +权威来源是 `infrastructure` 仓 `service.yaml` 的 `communities` 段,随上游刷新。 + +--- + +### 4.2 四语言 SDK + +#### 4.2.1 语言 × 能力矩阵 + +| 能力 | Go(`go/`) | Python(`python/`) | Java(`java/`) | Node(`node/`) | +| --- | --- | --- | --- | --- | +| 模块/包名 | `github.com/opensourceways/obs-sdk/go` | `obs-sdk-python` | `obs-sdk-java` | `obs-sdk-node` | +| log 底层 | stdlib `log/slog` + 自研 Handler | stdlib `logging` + 自定 JSON Formatter | logback + logstash JSON encoder | 自定 JSON serializer | +| metrics 底层 | `client_golang` | `prometheus-client` | `micrometer` + Prometheus registry | `prom-client` | +| Init | `log.Init(cfg)` / `metrics.New(cfg)` | `log.init(...)` / `metrics.init(...)` | `ObsLogging.init(cfg)` / `ObsMetrics.of(cfg)` | `log.init(opts)` / `new Metrics(opts)` | +| 请求上下文 | `sdkctx`(`context.Context`) | `_context`(contextvars) | `RequestContext`(MDC + ThreadLocal) | `context`(AsyncLocalStorage) | +| 中间件 | `middleware`(net/http)+ `ginmw`(gin) | `fastapi_wrap` / `flask_middleware` / `DjangoMiddleware` | `ObsFilter`(Servlet Filter) | `makeMiddleware`(express) | +| 服务端指标 | `obs_http_server_*`(中间件) | 同上 | 走 Actuator + Micrometer 官方 server instrumentation(不重复埋点) | `obs_http_server_*`(中间件) | +| UT 数量 | 31 | 15 | 19 | 10 | +| 已发版 | ✅ `go/v1.0.0` | ❌ 版本号 `0.1.0`,未打 tag | ❌ 版本号 `0.1.0`,未打 tag | ❌ 版本号 `0.1.0`,未打 tag | +| CI | `go vet` + `go test` | `pytest`(Py3.10) | `mvn test`(JDK 17) | `npm test`(Node 20) | + +#### 4.2.2 Go SDK 设计要点 + +```go +// 启动时 Init 一次,之后全进程用包级函数(形状对齐 kratos v3,无需在每个调用点绑定 logger) +obslog.Init(obslog.Config{Service: "review", Community: "openeuler"}) + +// 日志:msg 常量 + kv 交替(禁止 printf) +obslog.Info("job done", "event", "release", "issue", "2061") +obslog.ErrorContext(ctx, "get account failed", "user_id", uid, "error", err) // ctx 里请求字段自动附加 + +// 指标:注册一次;community label 自动排首位,取请求覆盖或回退默认 +m := obsmetrics.New(obsmetrics.Config{Service: "review"}) +built := m.NewCounterVec("built_releases", "发布的构建数", "kind") +built.IncWithContext(ctx, "tag") + +// 中间件 +h := obshttpmw.New(obshttpmw.Options{Metrics: m, ResolveCommunity: fn}).Then(myHandler) +``` + +关键实现选择: +- **自定义 slog Handler** 而非第三方库:直接控制字段、顺序、时间格式,且无需引入额外依赖。 +- **手工构造 `slog.Record` 并控制 `runtime.Callers` skip**,让 `logger` 字段指向业务调用点而非 SDK 内部包装函数。 +- 包级 API 形状对齐主流生态(`log/slog`、kratos v3),降低接入心智负担。 + +#### 4.2.3 Java SDK 设计要点 + +Java 侧有一个**非显然的坑**,必须在接入文档里强调: + +> 日志 JSON 输出**必须**用 `java/examples/logback-json.xml`,它只挂 SDK 的 `ObsJsonProvider`。**不要退回 encoder 自带的 provider** —— `` 只能输出大写、字段名不可配、且不配 `` 会整条丢弃 throwable。 + +即:Java 的字段名/顺序/时间格式/级别小写/异常堆栈**由 SDK 的 provider 保证**,不能靠 logstash encoder 的配置凑。 + +Java 的**服务端指标不重复埋点**——走 Spring Boot Actuator + Micrometer 官方 server instrumentation,把 `m.meterRegistry()` 暴露成 bean 由 Actuator 托管。 + +#### 4.2.4 已知实现问题(需修复) + +| 问题 | 影响 | 位置 | +| --- | --- | --- | +| Java `fromEnvironment()` **无任何兜底**:只读 `OBS_*`,未设置时为 `null`,而 provider 对空值「省略该键」 | `service` / `env` / `instance` / `community` 四个**必填**字段在未注入环境变量时**整个 Key 不出现**,违反契约。Go / Python / Node 均回退到 `unknown`(`instance` 回退 hostname) | `java/.../ObsSdkConfig.java:41` | +| Python / Node / Java 未打 tag | 消费方无法按版本引用 | 各语言子目录 | + +--- + +### 4.3 服务接入模式(按语言) + +#### 4.3.1 Go 服务(7 个) + +`app-cla-server` / `cve-sa-backend` / `cve-manager-ng` / `robot-universal-label` / `review` / `repo-watcher` / `welcome` + +```go +obslog.Init(obslog.Config{Service: ""}) +m := obsmetrics.New(obsmetrics.Config{Service: ""}) + +// HTTP 服务端:gin 用 ginmw,net/http 用 obshttpmw.New(...).Then(handler) +r.Use(ginmw.Middleware(ginmw.Options{Metrics: m})) +r.GET("/metrics", gin.WrapH(m.Handler())) + +// 指标:基础名注册,community label 由 SDK 自动补、排首位 +prHandled := m.NewCounterVec("pr_handled", "处理的 PR 事件数", "action") + +// 请求内:community 在可信判定点解析后覆盖,request_id 注入 +ctx = sdkctx.WithCommunity(ctx, "openEuler") +ctx = sdkctx.WithRequestID(ctx, "req-123") +obslog.InfoContext(ctx, "handle request", "repo", repo) +prHandled.IncWithContext(ctx, "opened") +``` + +#### 4.3.2 Java 服务(6 个) + +`EasySearch` / `EasySearchImport` / `om-webserver` / `certification-server` / `easysoftware-autoupgrade` / `APIMagic`,均 Spring Boot 3.x: + +```java +ObsSdkConfig cfg = ObsSdkConfig.fromEnvironment(); // 读 OBS_* +ObsLogging.init(cfg); // 部署级字段写入 MDC +ObsMetrics m = ObsMetrics.of(cfg); // meterRegistry() 暴露为 bean,交 Actuator 托管 + +log.info("job done"); // SLF4J 输出走 logback-json.xml(挂 ObsJsonProvider) + +// 请求内:可信判定点解析 community 后 push +try (RequestContext.Scope s = RequestContext.push("openEuler", "req-123", null)) { + m.counter("pr_handled", "处理的 PR 事件数", "action").inc("opened"); +} +``` + +`logback-json.xml` 见 [java/examples/logback-json.xml](../java/examples/logback-json.xml);`/metrics` 由 Actuator 暴露(打开 `prometheus` endpoint),不重复埋服务端指标。 + +#### 4.3.3 Python 服务(11 个) + +```python +from obs_sdk import log, metrics, _context +from obs_sdk.middleware import fastapi_wrap # Flask: flask_middleware;Django: DjangoMiddleware + +log.init(service="") # env/community 由 SDK 读 OBS_*,进程内幂等 +metrics.init(service="") +fastapi_wrap(app, resolver=resolve_community) # 注入 request_id + 可信判定点解析 community + 记 obs_http_server_* + +logger = log.get_logger(__name__) +logger.info("job done", extra={"event": "release", "issue": "2061"}) + +with _context.bind(community="openEuler", request_id="req-123"): + metrics.counter("pr_handled", "处理的 PR 事件数", ["action"]).inc(1, action="opened") +``` + +`/metrics` 暴露:`return Response(content=metrics.generate_text(), media_type=metrics.content_type())`。 + +适配器按框架分三类:Django×3(meeting-center / meeting-platform / app-meeting-server)、FastAPI×4(oss-map / robot-issue-manage / hotopic-data-clean / om-dataarts)、Flask×1(forum-reply-robot)。**另 3 个非标准框架无现成适配器,需单独方案**:mailman(GNU Mailman)、copr_docker(Fedora COPR)、hotopic-mining(脚本/包型)。 + +#### 4.3.4 Node 服务(1 个) + +`etherpad-lite` 是**上游开源项目**(Etherpad,Express + Socket.IO)。接入需注意与上游代码保持可合并性,改造面要尽量小。 + +#### 4.3.5 不直接接入 + +`meeting-server` 是编排/部署型子仓(Shell + Go Template),由旗下子服务(app-meeting-server / meeting-center / meeting-platform)覆盖。 + +--- + +### 4.5 部署侧字段注入 + +日志/指标要带上 `env` 和 `community`,必须由部署侧注入(pod 内无免费信号可推): + +- `instance` **不用注入** —— SDK 默认取 hostname(k8s 下 = pod 名)。 +- `service` **不用注入** —— 编译期常量,代码 `Init` 里写死。 +- **`env` / `community` 必须注入** —— 无法从 pod 名、namespace、节点名、镜像 tag 推导。 + - namespace 推不出:`openEuler` 的 prod-02 与 test 都叫 `robot-openeuler`;`OpenUBMC` 的 prod 与 test 都叫 `robot-openubmc`。 + - 集群名推不出:它是 ArgoCD 规范名,**pod 内无法自省**。 + +**注入方式**:在 `Open-Infra-Ops/helm-chart-value` 各部署目录的 `values.yaml` 里,给对应 deployment 加: + +```yaml + env: + - name: OBS_ENV + value: prod + - name: OBS_COMMUNITY + value: ascend +``` + +(chart 已支持 env 透传,同文件 `sync-bot` 在用同款写法。) + +**值域口径**: +- `community` **统一小写**(依据 `spec/community-values.md`;四语言 SDK 都不做大小写归一,注入值即最终形态)。 +- `env` 需 `prod*` → `prod` 的映射(service.yaml 里存在 `prod-github`、`prod-02` 等,不在契约枚举内)。 + +**范围(以 `robot-universal-review` 为例)**:需改 **12 个部署目录**(不是 10 个——Common 与 Ascend 各有两套部署,同社区同值)。生成脚本要**按部署目录迭代,不能按社区迭代**。 + +> **备选方案(已否决)**:从 `(cluster, namespace)` 二元组反推 community。实测该组合对这 4 个机器人服务零冲突,但全域 375 个组合中已有 10 个跨社区(如 `ascend-guiyang-prod-cluster/ascend` 同时跑 Ascend 与 CANN),且 cluster 名 pod 拿不到。 +> **结论**:`(cluster, namespace)` 只作**校验**用途(断言注入值与映射仓一致),不作取值来源。 + +--- + +### 4.6 底座与观测消费侧 + +| 组件 | 设计 | +| --- | --- | +| **日志采集** | 复用 CCE 云原生日志采集插件(log-agent,基于 fluent-bit,节点 DaemonSet)。集群级 `default-stdout` 策略已覆盖**全 ns 全容器 stdout**,铺开**无需新增采集策略**——服务只要写 stdout 就进 LTS。 | +| **日志存储/检索** | LTS(各 Region 自持)。结构化后支持按 `service` / `level` / `community` / `request_id` 检索与聚合。**方案已定见 §4.6「【已定 · 2026-09-11】日志汇聚方案」**:拓扑为**每集群 1 个默认流 + Grafana 多数据源汇聚**,**采集范围先不收窄**(全量落流),结构化解析**只针对 obs-sdk 契约格式配 JSON 规则**,噪音在**查询侧**按 `service` / `community` 字段过滤。**统一检索入口走访问层汇聚**——Grafana + LTS-Grafana 数据源多源拼装,**不搬数据、保留 SQL**;**跨账号由自建 Grafana 解决**(LTS 数据源用 AK/SK 认证,一个实例可挂多套凭证,见 §4.7.8),**不再需要 LTS 多账号日志汇聚中心**。 | +| **指标采集** | 各集群 **Prometheus Agent**(`--agent`,本地只抓不存,ServiceMonitor 选目标 + `/metrics` 端口)→ `remote_write` | +| **指标存储** | **1 个独立中心 Prometheus 集群**(kube-prometheus-stack,`replicas: 2` + 反亲和,本地 30d)。**已弃用**「AOM Prometheus ×4 Region + 多账号聚合」路线——详见 **§4.7** | +| **大盘** | **已决:自建 Grafana ×1**(独立 Deployment,与中心 Prometheus 同集群),同时挂**中心 Prometheus(指标)+ LTS 数据源 ×17(日志)**——详见 **§4.7.6 / §4.7.8**。大盘内容:服务健康度(QPS / 错误率 / 延迟 / 资源)+ 日志检索,支持按 `community` 过滤/分组。**"看"与"告警"解耦**——大盘只影响可见性,采集 / 存储 / 告警均不依赖它。✅ **硬依赖已确认(2026-09-14,华为云团队)**:自建 Grafana 可接入各集群日志流,**前提是流已配置结构化**。**剩余唯一卡点是结构化解析本身**(§4.6 (a0)(i)) | +| **告警** | **指标:统一在中心 Alertmanager**——数据已汇聚,一条规则覆盖全部 17 集群(`group_by: [cluster, alertname]`),不经 SMN。**日志:仍为各 Region 本地 LTS 逐流配置(17 条)**,出口经各 Region SMN 主题 → 同一接收端(LTS 无跨流查询,**明确接受「无跨集群联合告警」**)。**告警从 ③ 存储分叉,不依赖 ④⑤**(见 §3.3)。 | + +**日志采集管道的约束(影响接入与验收口径)**: + +| 约束 | 影响 | +| --- | --- | +| containerd 运行时下**容器 stdout 的多行配置不生效** | 契约的「**单行**扁平 JSON」是硬约束而非风格偏好——多行日志会在 LTS 里被拆成互不相关的多条 | +| 单条日志 **≤ 512 KB**;单节点约 **10000 条/秒** | Python / Java 契约允许 `error` 字段带完整 traceback,超长堆栈需截断 | +| stdout 为**非持久化存储** | 轮转清历史、Pod 终止回收、节点磁盘压力自动清理均可能丢日志——**日志是排障手段,不作审计/账本**,需在接入文档中明示 | +| 容器存活 **< 1 分钟可能采不到** | 短命 Job / 一次性任务的日志有丢失风险 | +| 每集群最多 **100 条**采集策略;变更 **1–3 分钟**生效 | 靠 `default-stdout` 一条策略覆盖全部服务,**不应为单服务新增策略** | +| **日志流名称全局唯一**(不能跨日志组重名) | 插件默认名 `stdout-{集群ID}` 天然唯一、无冲突;**若将来自定义日志流名,需自带唯一性前缀**,否则跨集群建不出来 | +| 日志组按集群划分(`k8s-log-{集群ID}`,每集群 1 个) | 跨集群检索需在**多个日志组间**查询;LTS 的汇聚 / 检索入口要按日志组粒度设计,**不能假设「一个 Region 一个日志组」** | +| **LTS 无「跨日志组检索」**——搜索 / 快速查询 API 均以 `groups/{group_id}/topics/{topic_id}` 限定**单一组 / 流** | **17 个日志组不会自动汇成一个检索入口**,必须显式选一条汇聚路径,见下行 | + +**日志汇聚:17 个集群日志组怎么收成一个检索入口** + +LTS **没有「跨日志组检索」能力**——搜索、快速查询及其列表的 API 全部以 `groups/{group_id}/topics/{topic_id}` 限定在**单个日志组 / 日志流**内,控制台也是逐组进入详情页。因此 **17 个 `k8s-log-{集群ID}` 不会自动汇成一个入口**。 + +> **【已定 · 2026-09-11】日志汇聚方案** +> +> 经多轮现网实测与推演,日志侧收敛为下述形态。**本节以下内容(术语辨析、官方口径表、A/B/C/D 选项)是决策过程,不是方案本身。** +> +> | 维度 | 决定 | 理由 / 代价 | +> | --- | --- | --- | +> | **大盘前端** | **【2026-09-14 更新】自建 Grafana ×1**(独立 Deployment,与中心 Prometheus 同集群),同时挂**中心 Prometheus + LTS 数据源 ×17** | **原选「AOM 托管 Grafana ×4」的前提已失效**——指标侧改为自建中心后(§4.7),"避免自建"这条理由不再成立。自建还能一次解决**跨账号免多登**(AK/SK 按数据源各带一套)+ **日志指标同屏**,见 §4.7.8。✅ **硬依赖已确认(2026-09-14,华为云团队)**:自建 Grafana 可接入各集群日志流,**前提是流已配置结构化**。**剩余唯一卡点是结构化解析本身**(§4.6 (a0)(i)) | +> | **拓扑** | **每集群 1 个默认流**(`stdout-{集群ID}`)不变,Grafana 多数据源汇聚,**不搬数据** | 即原"路径 ① / 选项 C"。**D 已否决**,见下方否决记录 | +> | **采集范围** | **先不收窄**(保持 `default-stdout` 全量) | 用**配额与存储**换取**零运维复杂度**:新服务自动纳入、**无采集窗口期**、不维护 ns 白名单、**sidecar 不再需要插件支持"按容器名排除"**。代价是基础设施 / 第三方日志一并落流(容量已量化,余量一到两个数量级,暂不成问题) | +> | **结构化解析** | 只针对 **obs-sdk 契约格式**配 **JSON 规则** | 非 JSON 行(基础设施文本 / ANSI 着色文本 / Envoy access log)解析失败后**原样保留**,不污染结构化字段 | +> | **噪音过滤** | **在查询侧做**,不在采集侧 | 面板查询统一带 `WHERE service = '...'`:logrus 行与第三方 JSON 因**缺 `service` 字段**被自然排除;sidecar 与基础设施日志因**无结构化字段**被自然排除 | +> | **告警** | **日志:LTS 原生,逐流配置(17 条)**;**【2026-09-14 更新】指标:统一在中心 Alertmanager,一条规则覆盖全部 17 集群** | **日志侧明确接受「无跨集群联合告警」**——LTS 无跨日志流查询,17 条规则之间无法汇总(例如"某服务在所有社区的某类失败总数"这类**跨集群联合条件写不出来**);换来的是**通知链路完全不变**(仍走各 Region 的 SMN → 统一订阅端),且**无需设计"Grafana 告警 → 接回 SMN"**那套适配。**指标侧无此限制**——数据已汇聚到中心,告警天然统一,这是自建中心相对 AOM 路线的主要收益(§4.7.3) | +> +> **面板筛选策略**: +> +> | 面板 | `community` | `service` | 理由 | +> | --- | --- | --- | --- | +> | 日志 · 明细/排障 | **必选(多选,至少 1)** | **必选(多选,至少 1)** | 排除误伤(全量采集下本 Region 日志流里混有基础设施 / sidecar / 第三方日志);两字段合用 ≈ **精确定位到一个部署**。**必须多选**——单选会堵死"互调服务联合排查" | +> | 日志 · 聚合/对比 | 默认全选 | 默认全选 | 跨社区横向对比(如"某服务在所有社区的表现")是真实需求,且结果集小 | +> | 指标 | **默认全选,不强制** | — | **中心 Prometheus 存储已聚合**(全部 17 集群汇入同一实例),不筛选无查询放大问题;`community` 是低基数 label,`sum by (community)` 成本可忽略。**必选会禁掉横向对比,而横向对比恰是指标大盘最有价值之处**。担心误读时在面板标题显示当前筛选值即可 | +> +> > 两侧策略不同不是随意的不一致——**「必选筛选」本质是给"日志存储物理分裂成 17 个流"打的补丁**;指标侧存储本就聚合,不需要这个药。 +> +> **⚠️ 已知代价(需明确接受,不是意外)**: +> 1. **`robot-framework-lib` 的 121 处 logrus 打点(client 88 / config 14 / interrupts 11 / framework 6 / utils 2)在大盘上不可见**——其字段集无 `community` / `service`,被必选筛选条件排除; +> 2. **配额 / 存储不设防**——全量落流; +> 3. **聚合/对比面板要打 17 个数据源**,加载慢,任一失败则面板残缺。 +> +> **本方案仍需验证的前置项**(按优先级): +> 1. **(a0)(i) 全量流上能否配结构化解析**——**⚠️【2026-09-14 升级为唯一卡点】** 自建 Grafana 接入日志流已确认可行(见 4.7.8),**其前提正是"流已结构化",故本项现在是日志大盘链路上唯一未解的门槛**。配不了则日志大盘整个不成立(但**指标大盘与全部指标链路不受影响**——两者已解耦); +> 2. ~~**`hws-lts-grafana-datasource-plugin` 能否装进自建 Grafana**~~ → ✅ **【已确认 · 2026-09-14,与华为云团队沟通】** **自建 Grafana 可以接入各集群日志流**,前提是**日志流已配置结构化**。**此项已消解**——代价不再是"退回 LTS 控制台",**日志大盘确定落在自建 Grafana**。⚠️ **卡点转移到第 1 项(结构化解析)**,它是现在**唯一**的门槛; +> 3. **多账号的实际情况**——到底几个账号、如何在组织内管理;决定**自建 Grafana 里要配几套 LTS 数据源的 AK/SK**(一个实例即可承载多套,见 §4.7.8),也决定**回退到 LTS 控制台时要登录几个账号**。 +> +> ~~跨 Region 网络((a1)(a2)(a3) 三选一)~~ **【2026-09-14 重新需要】**——原判断「每 Region 一个实例、跨 Region 网络问题自动消失」**仅对日志大盘成立**;**指标侧改为自建中心后(§4.7),跨 Region 网络是无论如何都要打通的**(§4.7.5 第 3 项,本方案**新的硬门槛**),日志侧**复用同一条即可**,不构成额外开销。下方 (a1)/(a2)/(a3) 仍然适用。 +> +> **否决记录**: +> - **方案 D(按 Region 汇聚为 1 流)**——依赖太多、不确定性大。两个硬前提均未验证:**(e) 多集群能否共用同一日志流**(官方无任何记载);**结构化解析按流配置**意味着 D 把 Region 内所有集群的**接入进度与解析配置绑死**(任何集群输出有差异即污染整个 Region 的流,且迁移期必然有差异)。另有三项确定代价:爆炸半径从 1 个集群放大到整个 Region、单流 **500 请求/秒**被多集群写入叠加、失去 CCE 控制台按 ns / 工作负载 / 容器查询的能力。 +> - **自建日志前端**(把 LTS 多流引出来自绘页面)——见上表"大盘前端"行。 +> - ~~**自建统一 Grafana**(1 个实例同时覆盖日志 + 指标)~~ —— **【2026-09-14 已采纳,否决撤回】** +> 原否决理由是「要付跨 Region 网络 + 自行运维」。**指标侧改为自建中心后(§4.7),这两项成本已经为指标付过了**,日志接进来是**边际成本近乎为零**(多配 17 个数据源)。现方案:**自建 Grafana ×1 同时承载指标 + 日志**,见 §4.7.6 / §4.7.8。 + +**先厘清术语**——「集中日志流」是官方词,指的是**每集群**,不是跨集群: + +| 官方术语 | 含义 | 粒度 | +| --- | --- | --- | +| **采集到集中日志流** | 用默认 `k8s-log-{集群ID}` + `stdout-{集群ID}`,**同集群内所有容器的 stdout 汇到一个流** | **每集群 1 流 —— 即本项目今天的形态** | +| **采集到自定义日志流** | 自选日志组 + 日志流,可让不同工作负载进不同的流 | 可细分到工作负载 | + +> **⚠️ 一个必须先纠正的前提**:官方对「采集到集中日志流」的缺点原文是「**不同工作负载的日志结构不一样**,采集到一个日志流后无法配置结构化解析,无法使用 SQL 可视化分析」。该缺点**在本项目当前形态下已经成立,与是否跨集群汇聚无关**——现有 `default-stdout` 策略是 `allContainers: true` + 全部命名空间,`stdout-{集群ID}` 里混着多类负载,是彻底的异构流,结构化解析本来就配不上。 + +> **⚠️ 实测补充(2026-09-11,来自现网 `stdout` 流的抽样)**:抽样 10 条**全部**是**日志基础设施自身**的日志,**没有一条业务服务日志**。 +> **补充(同日,另一集群)**:该 10 条样本**不代表全貌**——在集群 `openeuler-hk-cce-x86` 中检到了货真价实的业务服务日志(`repo-watcher` / ns `robot-github-openeuler`),说明**业务日志确实在流里**,第一批抽样撞上的是采集器刷屏窗口。**同时,业务日志是 `robot-framework-lib` 的 logrus JSON,不是 obs-sdk 契约格式**——落库后同一流内并存两套格式(细节见待验证项 (a0-1b)),这直接影响下面的"收窄后即同构"判断:**收窄只解决"业务 vs 基础设施"的同构,不解决"logrus 行 vs obs-sdk 行"的同构**。 +> +> **⚠️ 流内格式清单(2026-09-11 实测,至此已确认四种)**——这是"结构化解析配不上"最直接的证据,也是评估**结构化解析工作量的基线**: +> +> | # | 来源 | 格式 | 时间基准 | +> | --- | --- | --- | --- | +> | 1 | `fluentd-*` / `log-agent-fluent-bit-*` | 基础设施文本 | 本地 | +> | 2 | `repo-watcher`(机器人服务,走 robot-framework-lib) | **logrus JSON** | UTC **秒精度** | +> | 3 | `cve-manager`(普通 Gin 服务) | **ANSI 着色文本**(`[1;34m[I][0m [hook.go:146]`) | 本地 CST | +> | 4 | `istio-proxy`(ASM sidecar,**同 Pod 另一容器**) | **Envoy access log** | UTC 毫秒 | +> +> 第 3 种把 ANSI 转义码写进了日志——**是给终端看的 logger,不是给日志系统看的**,正是本设计要消除的形态。第 4 种由 `allContainers: true` 带入,**按 ns 收窄挡不住**,见待验证项 (a0-1d)。 +> - `fluentd-*`(平台自建、写 ES 的那套)——多条 `[out_es] failed to write data into buffer by buffer overflow action=:throw_exception`、`suppressed same stacktrace`; +> - `log-agent-fluent-bit-*`(CCE 插件采集器本身)——`Get the pod list from kubelet failed: failed to unmarshal podlist`。 +> +> `content` 字段格式横跨 Ruby fluentd 文本、**带 ANSI 转义码**(`[1;31m[E][0m`)的 Go 日志、k8s 容器日志路径 tag(`..._monitoring_otel-collector-...log`)——**没有任何单一 JSON 规则能吃下这些**,是对"结构化解析配不上"的直接实证。 +> +> **由此多出一个此前未识别的风险——采集链路的正反馈放大**:采集器自身出问题(buffer overflow / 限流 / pod 列表抓取失败)→ 吐更多错误日志 → 这些日志**又走同一条采集链路** → 采集器压力更大。即"**故障越严重、日志越多、越可能触发『可能丢日志』的软阈值**"。在选项 D(Region 共用一个流)下该效应还会**跨集群传导**。 + +**第一步:把采集范围收窄**(与汇聚无关,无论最后怎么选都要做) + +CCE 插件的日志采集策略支持按命名空间限定范围(插件版本 **1.6.1+**): + +```yaml +# 容器标准输出类策略 +allContainers: true +namespaces: ["robot-openeuler", "robot-openubmc", ...] # 空数组 = 全部命名空间(现状) +# excludePodLabels 可排除特定 Pod,需插件 1.7.4+ +``` + +收窄后,流内容在「**业务日志 vs 基础设施日志**」这一维度上同构了——**但这只是同构的一半**。 + +> **⚠️ 更正(2026-09-11,基于现网证据)**:此前此处写的是"契约保证 26 个服务输出同一套 JSON 字段",**该表述不成立**。现网检到的业务日志是 **`robot-framework-lib` 的 logrus JSON**(`component/error/file/func/level/msg/time`),`level: fatal`、`time` 秒精度、无 `service/env/instance/community/request_id`——**与 obs-sdk 契约行不同构**。 +> 且**不是过渡期现象**:框架那 121 处 logrus 打点会长期保留,**两套格式的共存是稳态而非临时**。 +> **因此"收窄 → 即可配结构化解析 → 即可 SQL 聚合"这条链,中间还缺一环**:得先明确 LTS 侧对这两套格式怎么处理(分别配解析?还是在云端做字段归一化?还是只对 obs-sdk 行做索引、logrus 行仅全文检索?)。这一点未定之前,**"结构化解析配得上"仍不成立**,只是从"多类负载混流"变成了"两类 JSON 混流"——后者好治得多,但仍需显式处理。 + +**第二步:选汇聚粒度** + +| 路径 | 做法 | 代价 / 前提 | +| --- | --- | --- | +| **① 不汇聚(每集群 1 流)+ Grafana 多数据源** | 各集群上报到**自己的**日志流;装华为云 **LTS-Grafana 插件**(`hws-lts-grafana-datasource-plugin`),**一个数据源绑一个日志流 ID**,面板侧用 Grafana 的 Mixed 数据源一次查多个流——**统一检索入口在 Grafana 侧拼出来,不搬数据** | ① **数据源数 = 日志流数(17)**,配置量与使用体验都不轻;② 数据源 `Endpoint` 按 Region 选 → 跨 Region 至少 **4 套**,**Grafana 需网络可达 4 个 Region 的 LTS 端点**;③ 插件需 **Grafana ≥ 9.0**,且要先在 LTS 控制台**开通「可视化」功能**;④ 数据源要求日志流**已配置结构化** | +| **② 按 Region 汇聚(每 Region 1 流)+ Grafana** | 各集群的采集策略**都指向同一个**日志组 + 日志流(如 `obs-{region}` / `obs-app-stdout`)→ 每 Region 1 流 | ① Grafana 侧降到 **4 个数据源、4 个查询目标**,明显清爽;② **官方无「多集群共用同一日志流」的配置说明**——下拉框里"看起来能选",**属未验证**;③ 失去按集群隔离;④ 单流 **100 MB/s** 上限(4 路分摊) | +| **③ 按 Region 汇聚 + 多账号日志汇聚中心** | 走 Organizations,把各日志流**复制**到聚合账号 | ~~依赖 Organizations;跨 Region 是否成立未确证~~ **【已不需要】** 跨账号已由**自建 Grafana 的 AK/SK 多数据源**解决(§4.7.8),**不再需要日志汇聚中心**;复制方案的"存储翻倍"代价也随之避免 | +| **④ 不汇聚、也不上 Grafana** | 接受 17 个日志组,控制台逐组进 | 没有统一检索入口,跨 Region 只能人工切换 —— **不建议** | + +> **⚠️ 时序上有个陷阱**:Grafana 的 LTS 数据源要求绑定的日志流**已配置结构化**,所以**所有路径都以"按 namespace 收敛采集"为共同前提**,没有"不动采集"的选项。 + +#### 官方口径:集中日志流 vs 自定义日志流 + +LTS/CCE 文档对「接入时选哪种采集方式」给了一张明确的权衡表,**倾向是"集中日志流"**: + +| 采集方式 | 优点 | 缺点 | +| --- | --- | --- | +| **采集到集中日志流**(插件默认) | 在 CCE 界面可按命名空间 / 工作负载 / 容器名**直接查**对应日志 | 不同工作负载日志结构不一样 → **无法配置结构化解析、无法用 SQL 可视化分析**;单流 **100 MB/s**,大流量有瓶颈 | +| **采集到自定义日志流** | 可配置结构化解析、可用 SQL;多流写入速率**线性扩增**,大流量无瓶颈 | **CCE 界面无法**按命名空间 / 工作负载 / 容器名直接查 | + +官方的判据是:**"主要靠 CCE 界面翻日志、流量不大" → 集中日志流;"需要结构化解析 / SQL 分析 / 大流量" → 自定义日志流**。本项目属于后者(日志要聚合告警 → 要 SQL)。 + +> **⚠️ 但官方这张表漏了第三个选项**:它隐含假设「集中日志流 = 全部命名空间全部容器」,而**采集范围其实独立可调**(即上面的第一步)。于是: + +(下表用 **A/B/C/D** 编号,与上面那条"汇聚粒度"表的 ①②③④ 是两回事,别串) + +| 选项 | 流 | 采集范围 | 流内容同构? | CCE 界面按 ns/负载查? | Grafana 数据源 | +| --- | --- | --- | --- | --- | --- | +| 现状 | 默认 `stdout-{集群ID}` | 全部 ns | ❌ | ✅ | — | +| **A** 集中日志流(官方推荐) | 默认 `stdout-{集群ID}` | 全部 ns | ❌ | ✅ | 17 | +| **B** 自定义日志流(官方备选) | 自选,按工作负载拆 | 自定 | ✅ | ❌ | 17+ | +| **C** 默认流 + 收窄 ns(**建议先试**) | 默认 `stdout-{集群ID}` | `namespaces: [...]` | ✅ | ✅ | 17 | +| **D** 自定义流 + 按 Region 共享 | 各集群同一个流 | 各自收窄 | ✅ | ❌ | **4** | + +**选项 C 两头都要**:流只含我们的服务 → 同构 → 结构化解析能配;同时保住 CCE 界面按 ns / 工作负载 / 容器名查看的能力(官方说自定义流会丢掉的那个)。 + +> **与指标链路的同构性(支持 D 的一个独立论据)**:~~AOM 侧已定"**每 Region 1 个实例**,Region 内集群都接进同一个"~~。**⚠️【2026-09-14 该论据的前提已失效】**——指标侧改为**自建中心 1 个实例**(§4.7)后,"每 Region 1 个"不再成立,D 与指标链路的同构关系**反而不如从前**(指标是 1 个中心,D 是 4 个流,仍不同构)。**D 已否决的结论不变**,此段仅作历史记录。原对比: + +| | 指标(已定) | 日志 · 选项 C | 日志 · 选项 D | +| --- | --- | --- | --- | +| 服务端收敛点 | AOM Prometheus 实例 | LTS 日志流(每集群 1 个) | LTS 日志流(每 Region 1 个) | +| 存储对象数 | **4** | **17** | **4** | +| Grafana 数据源 | 4 | 17 | 4 | +| 告警规则集数 | 4 | 17 | 4 | + +设计反复强调的是"日志与指标同一层级、同为 Region 级"(§3.3 整张表都按此对齐)。**C 会在日志侧开一个特例,D 保持结构一致**——这与"数据源数量少"是两个不同方向的理由,但同向支持 D。 + +> **⚠️ 但有一处真实不对称,且对 D 不利**:**收敛点的失败语义不同**。 +> - **指标侧**:Prometheus 写入带缓冲与重试(Agent 侧 WAL),且**未见 Prometheus 有"超过 X 会丢指标"的表述**; +> - **日志侧**:LTS 官方**明确写了**单流超 100 MB/s「**可能导致日志丢失**」,**无补发语义**。 +> +> 后果:**D 把"单个流被限流/写爆"的爆炸半径,从 1 个集群放大到该 Region 的全部集群**。指标侧不存在这个放大。 +> +> **但按本项目场景量化后,这个放大基本不构成风险**(见待验证项 11(a5)):契约真实示例行实测 info **289 B** / error **386 B**,100 MB/s ≈ **27–36 万条/秒**;机器人 / CLA 属事件驱动,每 Region 合计 1 万条/秒仅 **2.76 MB/s(占上限 2.76%)**,余量一到两个数量级。**所以选 D 的风险不在量,而在"多集群能否共用同一流"((e))与下面的请求数上限。** + +> **另一处隐藏差异**:**日志流不只是存储容器,还是结构化解析的配置单位**(指标实例里靠 label 区分,加服务不用动配置)。故 D = "一个 Region 一套解析规则",配一次全 Region 生效(比 C 的 17 次强);但**若将来某服务需要单独解析规则,D 下做不到,得拆流并重新分配采集目标**。C 则保留单集群独立调整的余地。 + +> **⚠️ C 的疑点必须实测**:官方说集中日志流「无法配置结构化解析」,但它给的理由是「**不同工作负载日志结构不一样**」——C 恰好把这个前提消掉了。所以关键问题是:**那是技术上的硬禁止,还是"配了也没意义"的忠告?** 本文倾向后者不成立(云端结构化解析是对日志流配的,理论上不挑流的来源),**但这是推断,不能当结论**。**C 通了就选 C,不通退 D。** + +> **官方对日志组另有规划建议**:一个日志组对应一个**项目 / 业务**,把该项目下多个应用的日志流放进同一组(日志组不存数据、只是分类容器)。若照此办,可建 `obs-sdk` 日志组、把各集群的 `stdout-{集群ID}` 流都放进去(**1 组 × 17 流**,流名不用改)。**但这只让管理边界整齐,不产生统一检索入口**——检索仍逐流,属纯整理动作。另:官方建议**不同日志类型(stdout / event / audit)用不同日志流**,别混。 + +> **⚠️ 与 §3.3 告警选型的连锁反应**:§3.3 把「日志聚合告警依赖 LTS 的 SQL 统计类型」当作**把日志规则留在 LTS 的理由**。该理由依赖 SQL 可用,SQL 又依赖「结构化解析配得上」,后者再依赖「采集范围已按 namespace 收敛」。**若试点期这一步验证不通过,§3.3 的日志告警选型需整体重谈**——优先级高于汇聚粒度本身。 + +**容量与结构化解析的准确数字(上一版有出入)**: + +- **100 MB/s 是软限制**(官方标 `Not mandatory`):超过不是拒绝写入,而是**不保证 QoS / 可能丢日志**。另有单日志流 **500 次/秒**写入次数上限、日志组 1000 次/秒。⚠️ 旧版文档写的是 **5 MB/s + 25K 条/秒**——该数字随版本变化大,**容量规划须按各 Region 实际版本文档核**。 +- **一个日志流只能配一种结构化方式**(ICAgent 结构化 **或** 云端结构化,切换**必须先删除**原配置)。 +- **结构化配置修改后仅对新写入生效**,历史数据不按新规则重新解析。 +- 云端结构化解析**消耗 LTS 算力,官方称未来按日志量收取「日志加工流量费」**。 +- 自定义日志流下 **CCE 界面不再能按 ns / 工作负载 / 容器名直接查**(官方明示缺点)。 + +> **附带发现(可能影响 §3.3 告警选型,此处仅记录)**:LTS-Grafana 插件除仪表盘外还**支持 Grafana 自身的告警功能**。这意味着"日志告警"多了一条候选路径(Grafana 侧统一配规则,而非逐 Region 各配一套 LTS 规则)。 +> +> **【2026-09-14 已决:不采用】**——**日志告警仍走华为云 LTS 原生、逐流配置**。采用 Grafana Alerting 会把告警依赖压到 Grafana 的可用性上,**与 §4.7.6「Grafana 只做看板、不进告警链路」的故障域解耦原则相悖**(Grafana 一旦进告警链路,其 HA 就从"可选"变成"必须")。**待逐流维护真的成为负担时再评估。** + +**黑盒拨测:白盒埋点覆盖不了的那一半** + +本文 §4.2–§4.3 的 SDK 埋点是**白盒**——服务自己吐「我做了什么」。它天然看不见**服务进程之外**的东西。以下类别只能靠**外部主动探测**(黑盒)覆盖,需在铺开时另行补,不在本 SDK 范围内: + +| 类别 | 例子 | 为什么埋点覆盖不了 | +| --- | --- | --- | +| 外部依赖可达性 | 依赖的 GitCode / GitHub API 通不通、下游服务在不在 | 请求发生在服务进程之外 | +| 凭据可用性 | 能否从 Vault 读到 token、凭据是否临期 | 读取动作在启动期,且失败即进程退出,无日志可依 | +| 端到端可用性 | 服务整体还能不能正常响应一个真实请求 | 服务内指标全绿但外部路由/网关挂了,埋点看不出来 | + +资源块已有的**探测 CronJob + Pushgateway** 基建可直接复用:CronJob 跑探测脚本 → push 到 Pushgateway → Prometheus 抓取 → `ProbeStale` 规则抓「指标过期」。**两个关键点**: + +1. **`ProbeStale` 是必备的**。拨测有内生盲区——探测脚本自己挂了,指标不再更新,而「指标不再更新」看起来和「一切正常」一样。必须有一条规则专门抓指标过期。 +2. **push 失败要重试后显式失败**。参考资源块做法:重试 6 次 × 45 秒吸收网络抖动,全失败则 Job 退出非零,让失败本身可被发现。 + +> **⚠️ 【2026-09-14】本节多项已因「指标侧改为自建中心」(§4.7)而消解**——完整消解清单见 §4.7.4。下方以 ~~删除线~~ + 【消解】/【不适用】标注。 + +**待验证项(建议在试点阶段并行验证)**: + +1. ~~ServiceMonitor 在 4 个 Region 的实际可用性~~ → **【更新】** 改为「各集群 Agent → 中心的采集链路与网络可达性」,即 §4.7.9 第 1 项——**新的唯一硬门槛**; +2. ~~自定义指标采样点计费量级~~ → **【不适用】** 自建方案无采样点计费,改为**容量与磁盘成本核算**(§4.7.9 第 2 项); +3. ~~聚合实例上统一告警规则跨 Region 选择 / 通知是否符合预期~~ → **【消解】** 告警统一在中心 Alertmanager,**不存在跨 Region 规则问题**; +4. log-agent 在测试/生产集群的插件与 `default-stdout` 配置是否与预览集群一致(**不确认则验收标准 3 悬空**); +5. ~~**跨 Region 汇聚是否成立(日志与指标两侧均未验证)**~~ → **【消解】** 指标侧:`remote_write` 本身就是跨 Region 的,**无需"聚合能力",该问题不存在**;日志侧:仍走逐流 + Grafana 多数据源,本就不依赖汇聚能力。 + ⚠️ 本文此前的表述「已验证指标侧的多区域聚合实例」**不成立**——AOM 该能力的官方名称是「多**账号**聚合」,不是「多**区域**」聚合。 +6. ~~**AOM 侧日志告警是否支持 SQL 统计类型**~~ → **【不适用】** 指标告警已不再经过 AOM(改中心 Alertmanager),**AOM 告警中心整体不再使用**;日志告警仍在 LTS 内,SQL 统计能力**本就在用**,不构成待验证项。§3.3 中"把日志规则留在 LTS 的代价"一节已随之删除。 +7. ~~**统一大盘能否走 AOM「多账号虚拟聚合实例」**~~ → **【消解】** 大盘改为**自建 Grafana 直连中心 Prometheus**,**完全不依赖 AOM 聚合能力**。以下推演保留备查。 + - **结论先行**:**大盘不严格依赖聚合账号**——出统一大盘有三条路,依赖程度递减:Grafana 直接配多个 Prometheus 数据源(**完全不依赖聚合实例**)> 多账号**虚拟**聚合实例(服务端联邦查询,不落库)> 多账号聚合实例(真落库)。**虚拟聚合实例足以承载大盘**,其官方定位原文即「实现不同账号下 Prometheus 实例的**统一查询和统一告警**」。 + - **(a) 告警是可商榷项**:最佳实践中确有「配置监控告警」步骤,故告警并非不可用;但该样例针对**云服务指标**,而 obs-sdk 产出的是**自定义普罗指标**——文档明确「账号接入」功能**不适用于自定义普罗指标**。因此「**自定义指标 + 虚拟聚合实例 + 告警**」这一组合的**原文步骤未找到**,属待实测。落地建议:**大盘走虚拟实例可行;告警先落真聚合实例**,或实测虚拟实例能否承载。 + - **(b) 容量上限**:**单实例最多聚合 5 个 Prometheus 实例**——当前 4 Region 刚好卡在上限内、**无余量**,新增 Region 即超限;且**不支持嵌套聚合**(不能聚合虚拟聚合实例)。 + - **(c) 无本地存储**:虚拟实例**不存储、不支持指标写入**,告警评估只能靠查询时联邦,**实际时延与稳定性未经生产验证**。 +8. ~~**必须先确认 Organizations / OU 前提**~~ → **【消解】** 自建中心方案**不涉及华为云多账号机制**(`remote_write` 只需网络可达 + 鉴权,与账号归属无关),**该前提整个不再需要**。以下推演保留备查。原内容:AOM 与 LTS 的多账号能力均要求:已创建组织、已将对应服务设为可信服务、由管理账号或委托管理员配置;且 **AOM 仅支持接入 OU 下的成员账号**,组织与成员账号关系变更时**不会自动同步**。**若 17 个集群涉及的账号不在同一组织 / OU 下,第 ④ 层汇聚路线整体不成立**——需在试点阶段最优先确认。**影响面已收敛至「统一大盘」**:存储为 Region 级、告警从存储分叉,二者均不受牵连。 +9. **SMN 主题的 Region 级约束与「统一接收端」方案**【2026-09-14:**仅日志告警适用**,指标告警已走中心 Alertmanager】——主题 URN 含区域名(`urn:smn:::`),LTS / AOM 创建通知规则时只能选**本 Region** 主题,故「同一个 SMN 主题」跨 Region **不成立**。需确认:(a) 每 Region 各建一个主题、订阅同一接收端是否满足现有运维习惯(告警收敛、值班轮转);(b) SMN「订阅用户」的**跨区域统一管理仅支持国内站点**,香港 Region 是否适用;(c) 接收端统一走邮件组还是自建 webhook 接收服务。 +10. ~~**AOM Prometheus 单实例可接入的集群数上限**~~ → **【不适用】** 已不用 AOM。自建中心的容量约束改为 **Prometheus 单实例的 series 承载与磁盘**(§4.7.9 第 2 项)。原内容保留备查:已确认「1 个实例可接多个集群」(在实例的「集成中心 → 接入集群」逐个「一键安装」,非自动),故按 4 个实例走;但官方未给出单实例可接入集群数的上限。 +11. **LTS 日志汇聚走哪条路(决定统一日志检索入口是否成立)**——LTS **无跨日志组检索**,17 个 `k8s-log-{集群ID}` 不会自动成统一入口。 + - **(a0) 【最高优先级】全量默认流上能否配结构化解析**——见 §4.6「【已定】日志汇聚方案」:**已决定不收窄采集范围**,故本项不再以"按 namespace 收敛"为前提,而是验证**在异构全量流上配 JSON 结构化解析**是否可行(官方原文对其持负面口径,理由是"不同工作负载日志结构不一样")。需实测三问: + (i) **配置动作本身是否被禁止**(硬门槛——配不了则整个"已定方案"不成立,须退回自定义日志流); + (ii) **非 JSON 行解析失败后是保留原样还是被丢弃**(影响配额,不影响大盘); + (iii) **合法 JSON 但字段集不同的行**(logrus / 第三方)解析成什么(只要不产生 `service` 字段即无害,查询侧会自然排除)。 + 原"按 namespace 收窄"路线**未被否决、仅暂缓**:若 (i) 为"配不了",退路是①改自定义日志流(配得上解析,代价是失去 CCE 控制台查询)或②恢复按 ns 收窄;两条退路都**不影响服务侧**。 + - **(a0-1) 【已确认】业务服务日志确实在 LTS 里**——2026-09-11 在集群 `openeuler-hk-cce-x86`(香港 Region,`clusterId=1efda3f6-0cab-11ed-9c17-0255ac101f29`)的 `stdout` 流中检到 `repo-watcher` 的业务日志(`nameSpace: robot-github-openeuler`)。**采集接入这一环是通的,后续讨论成立。** + - 同一条数据**实证了「每集群一个日志组」**:字段 `__host_group__: k8s-log-1efda3f6-0cab-11ed-9c17-0255ac101f29` 与同批次的 `clusterId` **完全一致**; + - 也实证了**按 namespace 收窄是可行的**——但 **⚠️ 不能用前缀规则**:业务日志的 ns 既有 `robot-github-openeuler`(机器人服务),也有 `cve-manager`(**ns 名 = 服务名**)。与基础设施 ns(`monitoring` 等)可分,但**必须按服务清单逐个枚举**,写 `robot-*` 会漏掉 `cve-manager` 这一整类。 + - **(a0-1b) 【新发现·消费侧】同一流内会并存两套日志格式**——检到的 `repo-watcher` 日志是 **`robot-framework-lib` 的 logrus JSON**,不是 obs-sdk 输出。两处与契约冲突,会直接落到 LTS 的检索 / 聚合 / 告警规则上: + - **`level: fatal`** —— **不在契约枚举** `debug/info/warn/error` 内(§4.1.1 只对 fatal 做了"不强制"的开放表述); + - **`time: 2026-09-11T08:18:07Z`** —— **秒精度、无毫秒**,违反契约"固定毫秒精度"(§4.1.1); + - 字段名是 `component / error / file / func / level / msg / time`,**没有** `service / env / instance / community / request_id`。 + **接入 obs-sdk 后,同一个流里将并存"框架 logrus 行"与"obs-sdk 行"**——这是**消费侧的真实代价**,此前只在生产侧讨论过。**待定:告警规则与大盘查询是否接受同时兼容 `fatal` 与秒/毫秒两种时间格式**,或需在 LTS 侧做归一化。 + - **(a0-1c) 【需确认】stdout 与 stderr 是否都被采集**——该条业务日志的 `pathFile` 是 **`/stderr.log`**(logrus 的 error/fatal 默认写 stderr),而基础设施日志那批是 `stdout.log`。**若采集策略只覆盖 stdout,则 error / fatal 级日志会整体缺失**——而告警最依赖的恰是这两级。需确认 `default-stdout` 策略对 stderr 的覆盖情况。 + - **(a0-1d) 【新发现·采集侧】`allContainers: true` 会把注入 Sidecar 一起采进来**——2026-09-11 在 ns `cve-manager` 的样本中,3 条里 **2 条是 `containerName: istio-proxy`**(ASM sidecar,镜像 `asm/proxyv2`)的 **Envoy access log**,只有 1 条是业务容器 `cve-manager`。影响三处: + 1. **按 namespace 收窄挡不住 sidecar**——sidecar 与业务容器**同 Pod 同 ns**,ns 白名单对它无效;需确认插件是否支持**按容器名排除**(`namespaces` 只管 ns,`excludePodLabels` 只管 Pod label,二者都够不着"排除 Pod 内某个容器"); + 2. **日志量被乘性放大,此前估算偏低**——Envoy access log **每请求至少 1 条**(样本中为 `inbound`;若 outbound 亦开启则 2 条)。§4.6 容量结论(每 Region 2.76 MB/s)**只算了业务日志,未含 sidecar**,机器人 / CLA 这类 webhook 驱动、请求集中的场景需重估; + 3. **时间基准不一致**——同一条流内 istio-proxy 输出 **UTC**(`2026-09-11T09:59:30.943Z`),而业务容器输出**本地时间 CST**(`2026/09/11 17:59:30.943`,同一毫秒)。做时序分析前须先统一。 + 顺带:**是否保留 Envoy access log 需定夺**——HTTP 层可观测性有价值,但它与 SDK 中间件产出的 `obs_http_server_*` 指标高度重叠,且格式独立;若保留,`(a0-1b)` 的"两套格式"就要改成"N 套"。 + - **(a0-1e) 【需澄清】`cve-manager` 与清单里的 `cve-manager-ng` 是否同一服务**——§4.3.1 的 Go Gin 服务写的是 `cve-manager-ng`,现网 pod 的 `appName: cve-manager`、镜像 `openeuler/cve-manager:both_0910-311906`。若为两个服务,则「26 仓」清单本身要更新,铺开范围随之变。 + - **(a0-2) 【关键分叉】默认流上到底能不能配云端结构化解析**——决定选"默认流 + 收窄 ns"还是"自定义流": + - **能配**(本文倾向)→ 选**默认流 + 收窄 ns**:流同构、可 SQL、**同时保住 CCE 界面按 ns / 工作负载 / 容器名查看的能力**,且不用动接入方式; + - **配不上**(官方原文的措辞指向这个)→ 只能退**自定义日志流**,接受失去 CCE 界面那个查看能力。 + ⚠️ 官方「无法配置结构化解析」**给的理由是"不同工作负载日志结构不一样"**,收窄 ns 后该前提已消掉——**所以问题的实质是:这是技术硬禁止,还是"配了没意义"的忠告?** 本文的回答是推断,**必须实测**。 + - (a) **【2026-09-14 重新适用】Grafana 实例能否同时可达各 Region 的 LTS 端点**——~~原为"1 个统一 Grafana"方案的硬前提,曾因"改为每 Region 1 个实例"而不再需要~~;**现因大盘改回自建 Grafana ×1(§4.7.8)而重新成为前置项**。⚠️ **性质已变**:指标侧**无论如何**都要打通「各集群 → 中心」的跨 Region 网络(§4.7.5 第 3 项),日志侧**复用同一条网络**,不再是一笔额外开销——这也是自建 Grafana 这次能通过的原因之一。以下三条路线仍然适用: + - **(a1) LTS 公网 Endpoint + AK/SK**——零网络改造,只要 Grafana 出网即可;**但需确认 4 个 Region(尤其香港)都有可用的公网 Endpoint,且安全合规允许出公网**(本文未能查到 `ap-southeast-1` 的具体端点地址); + - **(a2) 云连接 CC 打通 4 个 Region 的 VPC**——走内网更安全,**但按带宽计费**。⚠️ **VPC 对等连接不支持跨 Region**(仅同 Region 内 VPC 互连),跨 Region 只能走 CC 或 CC + 企业路由器。**【2026-09-14】这条同时是指标链路的候选路径**(§4.7.5 第 3 项)——**一次打通,指标与日志两侧共用**; + - **(a3) 放弃跨 Region,改为每 Region 各 1 个 Grafana(共 4 个)**——无跨 Region 网络需求,代价是 4 个入口。**"统一"可另做**:入口反代聚合成一个 URL + 用同一份 dashboard JSON(GitOps 下发)保证 4 处口径一致——**统一来自"同一份配置",不必来自"同一个进程"**。 + - **(a4) 【2026-09-14 已推翻】Grafana 数量 = 4 → 改为 1(自建)**。~~原决:每 Region 1 个 AOM 托管实例,不承担告警。~~ **推翻原因**:指标侧改为自建中心后(§4.7),「避免跨 Region 网络与自建运维」这条理由失效——**这两项成本已经为指标付过了**;且自建还能解决**跨账号免多登 + 日志指标同屏**(§4.7.8)。**「Grafana 不承担告警」这点沿用**,故故障域仍与告警解耦——单点只影响"看"。**原「单点问题随之消失」的结论改为**:单点风险由「中心 Grafana 的 HA」承接(§4.7.6)。 + - **(a5) 【已决】汇聚粒度取 17 流(选项 C)还是 4 流(选项 D)**——**已选 C(每集群 1 默认流 + Grafana 汇聚),D 已否决**,见 §4.6「【已定】日志汇聚方案」的否决记录。以下推演保留作为决策依据: + 原两论据**同向支持 D**,但有一条代价指向 C: + - **论据一(省事)**:**一个 Grafana 数据源绑一个 `Log StreamId`**。C = **17 个数据源**且每个面板要挂多个查询目标;D = **4 个数据源**,明显清爽; + - **论据二(结构一致)**:**D 与指标链路同构**——AOM 侧是"每 Region 1 实例",D 与之在**存储对象数 / 数据源数 / 告警规则集数**三项上全部对齐(都是 4);C 会在日志侧开 17 的特例; + - **⚠️ 指向 C 的代价**:**收敛点的失败语义不对称**——指标侧写入带缓冲重试且**未见 Prometheus 有"超限丢指标"表述**;日志侧官方**明说**单流超 100 MB/s「可能导致日志丢失」、**无补发**。**D 会把"单流写爆"的爆炸半径从 1 个集群放大到该 Region 全部集群。** + **容量已量化,结论:容量不是 D 的门槛**。按契约真实示例行实测(info **289 B** / error **386 B**),**100 MB/s ≈ 27–36 万条/秒**。机器人 / CLA 是**事件驱动**服务,按每 Region 合计 1 万条/秒算仅 **2.76 MB/s(占上限 2.76%)**——**有一到两个数量级余量**。打满 100 MB/s 需要 ~36 万条/秒,折「每请求 5 条日志」即 **7.2 万请求/秒持续不断**,对这类服务不现实。 + **因此 D 的真正门槛不是量,而是 (e)「多集群能否共用同一日志流」这条未验证项**(与数据量无关),外加下面 (a6) 的请求数上限。仍需实测确认写入速率,但**验证目的是拿到真实数字而非筛掉 D**。另注意 C/D 都要改采集策略(见 a0),差别只在目标流选哪个。 + - **(a6) 【D 独有,与数据量无关】单日志流 500 次/秒的 API 请求数上限**——官方上限是**日志流级 500 次/秒**(日志组级 1000 次/秒)。选项 D 下 **17 个集群的 log-agent 都往同一个流写,各集群的 flush 请求数是叠加的**:若每个集群约 1 次/秒 flush 则 17 次/秒(无压力),但 flush 频率、批量大小需确认。**这是一条与日志大小无关的约束**——即使日志很小、MB/s 远低于上限,也可能先撞这条。选项 C 下每流只有 1 个集群写入,不存在叠加。 + - (b) **LTS-Grafana 插件的可用性**:LTS 控制台的「可视化」功能能否开通、插件对 Grafana 版本的要求(≥ 9.0)、以及**一个数据源绑一个日志流 ID** 带来的实际配置量可否脚本化; + - (c) **结构化解析的运维成本**:**一个日志流只能配一种结构化方式**(切换要先删原配置)、**改配置不回溯**(只对新写入生效)——契约字段若变更,17 处(或 4 处)都要重配且历史数据不可分析,需评估能否 API 批量下发; + - (e) **多集群能否共用同一日志流**(按 Region 汇聚路径)——官方**无**此配置说明,仅「采集到自定义日志流」的下拉框似可手动选到同一目标,属未验证; + - (f) **各 Region 实际版本文档里的写入上限**——本文查到的 100 MB/s 是软限制,**旧版文档写的是 5 MB/s + 25K 条/秒**,差异极大,**容量规划不能引用本文数字**,须按各 Region 实际版本核。 + +--- + +### 4.7 中心指标集群:选型与形态 + +> **【已定 · 2026-09-14】指标侧改为「自建中心 Prometheus 集群」,弃用 AOM Prometheus for CCE + 多账号聚合。** +> +> 该决定**推翻了 §3.3 此前「不采用资源块自建栈」的结论**。**日志侧采集/存储方案不变**(仍为每集群 1 个 LTS 流,见 §4.6「【已定】日志汇聚方案」),但**大盘归属随之调整**——日志大盘一并并入自建 Grafana,见下「日志大盘的归属更新」。 + +#### 4.7.1 先例:资源块已跑通同一形态 + +昇腾 CI 在 [ascend-ci-deployment/monitoring](https://github.com/opensourceways/ascend-ci-deployment) 的自建栈,**实测形态**如下(非推演): + +| 组件 | 实测配置 | +| --- | --- | +| **中心 Prometheus** | kube-prometheus-stack,`replicas: 1`、`retention: 15d`、100Gi EVS、`scrapeInterval: 60s`、`enableRemoteWriteReceiver: true`,位于 `infra-monitoring` ns | +| **暴露方式** | Service `type: LoadBalancer` + ELB → **公网 `113.44.182.82:9090`**,`http://` **明文** + Basic Auth(`agent` / `password_file`) | +| **各集群 Agent** | 本地只抓不存(`--agent`),`remote_write` 到上述**同一 URL**。贵阳 `guiyang-001`/`guiyang-006`、香港 `hk-001` 的 configmap **逐字相同**,只差 `cluster` 标签 | +| **中心 Grafana** | 13.0.1,`replicas: 1`,10Gi PVC。**`grafana.enabled: false`——独立 Deployment**,与中心 Prometheus **同集群同 ns、复用同一 ELB**(`elb.id: 8625d057…`,端口分开);数据源**只有 1 个**(指向中心 Prometheus 的 svc) | +| **Alertmanager** | chart 自带,`replicas: 1`,QQ SMTP 邮件;路由 `group_by: [cluster, alertname]`——**说明告警已在全局视图上运行,一条规则覆盖所有集群** | +| **长期存储** | 中心再 `remote_write`,但**只 keep `custom_npu_.*`** → VictoriaMetrics(`vminsert.infra-monitoring.svc:8480`) | + +> **跨 Region 是怎么打通的**:**一个中心 Prometheus 挂在公网 IP 上,各集群 Agent 通过 `remote_write` 直接写它。** 不走云连接 CC、不走 VPC 对等、不做多实例聚合。`enableRemoteWriteReceiver: true` 即为此而开。 + +#### 4.7.2 目标拓扑 + +```text +17 个 CCE 集群(4 Region) + └─ Prometheus Agent(--agent,本地只抓不存) + │ remote_write(生产须 TLS + 鉴权) + ▼ + 【中心集群 · 独立】──────────────────────────┐ + ├─ 中心 Prometheus(replicas: 2 + 反亲和) │ 指标链路 + │ └─ Alertmanager(告警统一在此) │ + └─ Grafana(独立 Deployment,仅看板) ┘ + ├─ 数据源 ×1:中心 Prometheus + └─ 数据源 ×17:LTS 日志流(可选,见 4.7.5) +``` + +#### 4.7.3 与 AOM 路线的对比 + +| 维度 | AOM Prometheus for CCE(原路线) | 自建中心 Prometheus(现路线) | +| --- | --- | --- | +| **跨 Region 统一大盘** | ❌ 官方已确认**多实例聚合不支持跨 Region** | ✅ 天然成立(就是**一个**实例) | +| **跨 Region 统一告警** | ❌ 需逐 Region 各配一套(4 套规则) | ✅ **一条规则覆盖全部集群** | +| **Organizations / OU 前提** | **强依赖**(多账号聚合要求同组织 / OU) | ✅ **完全不依赖**——`remote_write` 只需网络可达 + 鉴权 | +| **跨账号** | 走华为云多账号机制 | ✅ 每个 Agent 各带一套凭证即可,**与账号归属无关** | +| **单实例集群数上限** | 官方未给出,17 集群分配有风险 | ✅ 无此约束(仅受 Prometheus 自身容量限制) | +| **运维** | 云托管,**零运维** | ❌ **自行运维**(HA / 容量 / 升级 / 备份) | +| **网络** | 零改造 | ❌ **需打通各集群 → 中心**并解决合规 | +| **成本** | 按采样点计费 | 自建集群底座 + 存储 + **跨 Region 流量费** | + +**取舍**:用**运维与网络成本**,换**统一大盘、统一告警、以及摆脱 Organizations / OU 前提**。 + +#### 4.7.4 由此消解的前置项(重要) + +原 AOM 路线上卡住的若干条,在自建方案下**不再成立**: + +| 原前置项 | 状态 | +| --- | --- | +| §4.6 待验证项 5 —— 跨 Region 汇聚是否成立 | **消解**:`remote_write` 本身就是跨 Region 的,无需"聚合能力" | +| §4.6 待验证项 7 —— 统一大盘能否走多账号虚拟聚合实例 | **消解**:依赖消失 | +| §4.6 待验证项 8 —— Organizations / OU 前提 | **消解**:自建方案不涉及华为云多账号机制 | +| §4.6 待验证项 10 —— AOM 单实例可接入集群数上限 | **不适用** | +| §6 风险 R10 —— 第 ④ 层汇聚两条前提未确证 | **风险消失** | + +> 这一条是本次决策最大的收益:**原路线把"统一大盘"押在华为云两套未确证的机制上(Organizations / OU + 跨 Region),自建方案把这两条前提整个移除了。** + +#### 4.7.5 中心集群的形态规划(四项) + +1. **HA**:中心 Prometheus **`replicas: 2` + pod 反亲和**(资源块当前为 `1`,其 values 注释已写明"正式上线时恢复 `replicas: 2`")。**它是单点,挂了全网指标断线。** +2. **存储**:**一期用本地存储(30d),不上 VictoriaMetrics**——见 4.7.7。 +3. **网络**:⚠️ **生产不能照搬资源块的公网明文 HTTP**。各集群 Agent → 中心这条链路必须解决:(a) 传输加密(至少 HTTPS);(b) 合规(生产指标数据出公网需确认);(c) 带宽与成本。候选路径:**云连接 CC**(按带宽计费、不过公网)/ **专线** / **HTTPS + 公网 EIP**。 +4. **安全**:`enableRemoteWriteReceiver: true` + 公网端口 = **拿到 basic auth 就能往中心写任意指标**。生产至少要做:强凭据 + 轮换、源 IP 白名单 / 安全组收敛、只放行 `/api/v1/write`。**独立集群的好处正是把风险面收敛到这一个集群上。** + +#### 4.7.6 Grafana 形态:独立 Deployment,与中心 Prometheus 同集群 + +**照搬资源块的形态:Grafana 独立于 chart(`grafana.enabled: false`),与中心 Prometheus 同集群、同 ns。** + +| 理由 | 说明 | +| --- | --- | +| **"独立"的价值在生命周期解耦,不在物理位置** | 独立 Deployment 已让 Grafana 的升级 / 重启 / 回滚不碰 Prometheus,反之亦然——这是真正需要的隔离 | +| **同集群走集群内 svc 查询** | `prometheus-kube-prometheus-prometheus.infra-monitoring.svc:9090`,零网络成本、零延迟。Grafana 是查询密集型无状态服务,离 Prometheus 越近越好 | +| **故障域本来就解耦** | 关键在**告警用 Alertmanager、不用 Grafana Alerting**——Grafana 挂了只是看不了图,**告警不受影响** | +| **单开一个集群只为 Grafana 不划算** | 多一份集群底座成本,还**新增一条跨集群链路**(Grafana → Prometheus) | + +**例外**:Grafana 要对外开放给多租户、或有独立安全域要求时,才值得独立集群——**那是安全需求,不是可用性需求**。 + +**两点可照抄**:Grafana PVC 只要 **10Gi**(dashboard 走 ConfigMap provisioning,PVC 只存状态);**和 Prometheus 复用同一个 ELB、端口分开**,省一个 ELB。 + +#### 4.7.7 VictoriaMetrics:一期不上 + +资源块里 VM 的角色**不是"全量长期存储",而是"少数需要长期趋势的指标的冷存储"**(只接 `custom_npu_.*`)。据此: + +| 保留期要求 | 建议 | +| --- | --- | +| **≤ 30d** | 中心 Prometheus 本地存储够用,**不上 VM**。预留 `remoteWrite` 配置位(改一行的事) | +| **> 30d** | 上 VM,但**只 keep 需要长期的指标**,不要全量转发 | + +**容量粗算**(`磁盘 ≈ 保留秒数 × 每秒样本数 × 1.7 B`,按 `scrapeInterval: 60s`): + +| active series | 日增 | 30d 占用 | +| --- | --- | --- | +| 20 万 | ≈ 0.5 GB/天 | ≈ 15 GB | +| 200 万 | ≈ 4.9 GB/天 | ≈ 147 GB | + +**series 数是这里唯一的未知量**,取决于 26 个服务的指标设计——**尤其不要把高基数塞进 label**(§4.1.3 铁律:`request_id` / `trace_id` / `span_id` 禁止当 label)。 + +> **建议**:一期先不配 VM,中心 Prometheus 本地存 30d,**跑一两个月看真实 series 增长再定**,避免过早引入一个额外组件。 +> +> ⚠️ **若必须上 VM,注意一个坑**:中心 Prometheus 上 `replicas: 2` 后,**两个副本会各写一份相同数据到 VM**,必须在 vminsert / vmselect 侧配 `-dedup.minScrapeInterval` 去重,否则**数据翻倍、查询结果异常**。VM 自身的 HA(vminsert / vmselect / vmstorage)也要一并考虑。 + +#### 4.7.8 日志大盘的归属更新 + +本决策**改变了 §4.6「日志汇聚方案」中"大盘前端"的前提**——原方案选 AOM 托管 Grafana ×4 的两个理由之一是"避免自建",而**指标侧已经要自建了,该理由不再成立**。 + +| | AOM 托管 Grafana ×4(原) | 自建 Grafana ×1(现) | +| --- | --- | --- | +| **多账号** | 账号级资源,N 个账号要**登录 N 次** | 一个 Grafana 挂 N 套 AK/SK,**不用多登** ✅ | +| **日志 + 指标同屏** | ✗ 日志在 LTS,需插件才连得上 | ✓ 同屏 | +| **指标数据源** | 只能连本账号本 Region AOM | 挂中心 Prometheus | +| **实例数** | 4 个 | 1 个 | +| **运维** | 云托管,零运维 | 自行运维(已有资源块模板) | + +> **LTS 插件用 AK/SK 认证,每个数据源可带自己的一套凭证**——所以一个自建 Grafana 就能横跨 N 个华为云账号,把 17 个日志流全挂上。**AOM 托管 Grafana 做不到这点**(它是账号级资源)。这恰好解决了此前"多账号登录麻烦"的痛点。 + +> ### ✅ 【已确认 · 2026-09-14】自建 Grafana 可接入各集群日志流 +> +> **与华为云团队沟通确认**:**自建 Grafana 可以接入各集群的日志流**——**前提是日志流已配置结构化解析**。 +> +> 这解开了本方案此前的**最后一个硬依赖**(原为「`hws-lts-grafana-datasource-plugin` 能否装进自建 Grafana」,且对资源块在用的 13.0.1 的兼容性无任何背书)。**至此,日志大盘链路上的唯一卡点就是「结构化解析」本身**——直接指向 §4.6 待验证项 **(a0)(i)**: +> +> ```text +> 日志大盘能否落地 = 自建 Grafana 接入 ✅(已确认) AND 流已结构化 ❓(唯一卡点) +> ``` + +**告警归属不变(同日确认)**:**日志告警仍走华为云 LTS 原生、逐流配置(17 条)**,**不迁到 Grafana Alerting**——Grafana **只做看板**,与 4.7.6「Grafana 不进告警链路」一致,**故障域保持解耦**(Grafana 挂了不影响告警)。若将来要用 Grafana Alerting 跨 17 数据源做一条规则,则**必须同步把 Grafana 的 HA 做起来**。 + +#### 4.7.9 本方案仍需验证的前置项 + +| # | 项 | 影响 | +| --- | --- | --- | +| 1 | **各集群 → 中心集群的网络与合规**(CC / 专线 / 公网 HTTPS 三选一) | **本方案的唯一硬门槛**,不成立则整个中心方案不成立 | +| 2 | **中心集群的容量与压测**:17 集群 × 26 服务的真实 series 量、30d 保留所需磁盘、单实例能否承载 | 决定存储规格与 VM 是否必要 | +| 3 | **HA 验证**:`replicas: 2` + 反亲和下的去重与告警行为 | 中心是单点,必须 | +| 4 | **安全加固**:TLS、凭据轮换、源 IP 白名单 | 生产合规 | +| 5 | ~~`hws-lts-grafana-datasource-plugin` 对 Grafana 13 的兼容性~~ → ✅ **【已确认 · 2026-09-14】** 华为云确认**自建 Grafana 可接入各集群日志流**,前提是**流已配置结构化** | **已消解**。⚠️ 但**结构化解析随之成为日志大盘链路上唯一的卡点**(§4.6 (a0)(i) 升级为**最高优先级**) | + +--- + +## 5. 工作量预估 + +> **口径说明**:以下为**粗估**,单位人天,含开发 + 自测 + 联调,不含需求评审与排期等待。 +> 单价基于试点实测数据校准前的一般经验;**建议在子任务 A 的试点完成后回填真实数据再修正 C 的估算**。 + +### 5.1 子任务 A —— SDK 建设与试点接入(#2061) + +| 项 | 状态 | 剩余人天 | +| --- | --- | --- | +| 契约层 `spec/`(4 份文档) | ✅ 已完成 | 0 | +| obs-sdk-go(log / metrics / sdkctx / middleware+ginmw,31 UT) | ✅ 已完成,已发 `go/v1.0.0` | 0.5 | +| obs-sdk-python(15 UT) | ✅ 代码完成 | 0.5(打 tag + 安装验证) | +| obs-sdk-java(19 UT) | ✅ 代码完成,**存在无兜底缺陷** | 1.5(缺陷修复 + UT + 打 tag) | +| obs-sdk-node(10 UT) | ✅ 代码完成 | 0.5(打 tag) | +| 试点接入:`robot-universal-review` 日志([#2161](https://github.com/opensourceways/backlog/issues/2161)) | 📋 已开 issue | 1.5 | +| 试点接入:`robot-universal-review` 指标([#2162](https://github.com/opensourceways/backlog/issues/2162)) | 📋 已开 issue | 1.5 | +| 部署侧 `OBS_*` 注入(helm-chart-value,12 个目录) | 📋 待办 | 2~3(含跨团队确认) | +| **小计** | | **8~9.5** | + +### 5.2 子任务 B —— 底座搭建与大盘告警(#2062) + +| 项 | 人天 | +| --- | --- | +| 中心 Prometheus 集群搭建(kube-prometheus-stack + HA + 存储 + Alertmanager) | 5~8 | +| 各集群 Prometheus Agent 铺开(17 集群)+ 采集链路验证 | 4~6 | +| **跨 Region 网络打通**(CC / 专线 / 公网 HTTPS 三选一)+ 安全加固 | 3~6 | +| 自建 Grafana 部署(独立 Deployment + 持久化 + 入口) | 2~3 | +| Grafana 大盘(服务健康度 + community 维度 + 日志检索面板) | 6~9 | +| 中心 Alertmanager 指标告警规则 + LTS 日志告警(17 条)+ SMN 通知 | 4~6 | +| 容量与成本核算(series 量 / 磁盘 / 跨 Region 流量) | 1~2 | +| **小计** | **25~40** | + +> **⚠️ 【2026-09-14】本节已随指标路线改为自建中心而重估**(原 17~27 人天基于 AOM 托管路线)。**成本上升是真实的**——自建多出「中心集群搭建」「Agent 铺开」「跨 Region 网络」「安全加固」四项,而省掉的只有「采样点计费评估」一项。**这是换取统一大盘 + 统一告警所付的显式代价**(§4.7.3)。 + +### 5.3 子任务 C —— 26 仓全量铺开与验收(#2063) + +按语言与框架的改造复杂度分档: + +| 服务分组 | 数量 | 单价(人天) | 小计 | +| --- | --- | --- | --- | +| Go · 机器人服务(robot-universal-label / repo-watcher / welcome + 试点已做的 review) | 3 | 1~1.5 | 3~4.5 | +| Go · 普通 Gin(app-cla-server / cve-sa-backend / cve-manager-ng) | 3 | 0.5~1 | 1.5~3 | +| Java · Spring Boot(Actuator 原生路径) | 6 | 1~1.5 | 6~9 | +| Python · Django + DRF | 3 | 1~1.5 | 3~4.5 | +| Python · FastAPI | 4 | 0.5~1 | 2~4 | +| Python · Flask | 1 | 0.5~1 | 0.5~1 | +| Python · **非标准框架待评估**(mailman / copr_docker / hotopic-mining) | 3 | 3~5 | 9~15 | +| Node · etherpad-lite(上游开源,需保持可合并) | 1 | 2~3 | 2~3 | +| 编排仓 meeting-server(由子服务覆盖) | 1 | 0 | 0 | +| 逐服务验收核对(字段 / label / 大盘) | — | — | 3~5 | +| **小计** | **26** | | **30.5~49** | + +### 5.4 汇总 + +| 子任务 | 人天 | 对应 issue | +| --- | --- | --- | +| A · SDK 建设与试点接入 | 8~9.5 | #2061 | +| B · 底座搭建与大盘告警 | 25~40 | #2062 | +| C · 26 仓全量铺开与验收 | 30.5~49 | #2063 | +| **合计** | **63.5~98.5** | 约 **3.1~4.8 人月** | + +**估算的最大不确定性**在 C 的「非标准框架待评估」三项(9~15 人天)与 Java 组(6~9 人天)。建议: +1. 试点完成后用实测数据回填单价; +2. 三项非标准框架服务(mailman / copr_docker / hotopic-mining)与 Node 的 etherpad-lite **先做技术验证再报价**,避免按经验值低估; +3. 「26 仓」中 `hotopic-data-clean` / `hotopic-mining` 的 prod 目前挂在 **test 集群**(`infra-hk-test-cluster-001`),`oss-map` / `om-dataarts` 在 service.md 无 prod 部署记录 —— **这 4 个是否纳入本次铺开需先澄清**,否则 C 的范围可能变动。 + +--- + +## 6. 风险与待确认 + +| # | 项 | 影响 | 处置 | +| --- | --- | --- | --- | +| R1 | ~~**15 天存储窗口**:AOM 指标默认存 15 天(超期按量计费)~~ → **【2026-09-14 转换】** 自建中心 Prometheus **保留期可自定**(建议 30d),不再受 15 天约束(§4.7.7) | ~~故障回溯窗口可能不足~~ **风险消除**;但**磁盘容量成为新的约束** | 按 §4.7.7 公式核算 series 量 → 定保留期与磁盘规格;>30d 需求再上 VictoriaMetrics | +| R2 | ~~ServiceMonitor 在 4 Region 的可用性~~ → **【转换】各集群 Agent → 中心集群的采集链路与网络可达性**未经生产验证 | 指标可能采不上——**且这次没有云托管兜底** | 试点阶段**逐集群**验证 Agent 与 `remote_write` 连通性;网络方案见 §4.7.5 第 3 项 | +| R3 | ~~自定义指标采样点计费量级未知~~ → **【转换】自建中心的容量与成本**:series 量、磁盘、**跨 Region 流量费**三项均未测算 | 26 仓铺开成本不可控(原为按量计费,现为**自建资源 + 出网流量**) | 试点阶段实测 17 集群真实 series 量后外推(§4.7.7 已给容量公式);跨 Region 流量按所选网络方案(CC 按带宽 / 公网按流量)分别核算 | +| R4 | log-agent 在生产集群的配置是否与预览集群一致未确认 | 结构化日志可能采不到字段 | 铺开前抽查生产集群插件配置 | +| R5 | **Java SDK 无兜底**,未注入环境变量时 4 个必填字段整个缺失 | 违反契约,Java 服务日志字段不全 | 单独立项修复(加 hostname / `unknown` 兜底 + 补 UT,断言落在真实 JSON 输出上) | +| R6 | Python / Node / Java 未打 tag,Java 进私服路径未验证 | 消费方无法按版本引用 | 随各语言首次接入服务时一并处理 | +| R7 | **#1938 覆盖范围表的机器人部分与实际部署不符** | 影响 community 取值与大盘分维度 | 见下 | +| R8 | Java SDK 的 logstash-logback-encoder / jackson-core 在 SDK 内为 `provided` | 接入服务运行时必须自带,否则日志不可用 | 接入文档中明确要求,或改为传递依赖 | +| R9 | 请求级 community 的安全约束(禁止裸读 URL/Header) | 误用会导致 community 被外部可控 | 代码 review 检查点 + 接入文档强调 | +| R10 | ~~**第 ④ 层汇聚的两条前提均未确证**:Organizations / OU 归属、跨 Region 是否成立~~ → **【2026-09-14 消解】** 自建中心**不涉及华为云多账号机制**,两条前提整个不再需要(§4.7.4) | ~~汇聚层整体不成立,失去统一大盘~~ **风险消除** | 无需处置 | +| R11 | ~~**告警规则逐 Region 各配一份**(4 Region × 日志/指标 ≈ 8 套)~~ → **【2026-09-14 收敛为日志单侧】**:**指标告警已在中心统一为 1 套**;**日志仍为 4 Region × 逐流 17 条**,SMN 主题亦每 Region 一个 | 阈值 / 规则变更需多点同步,易产生配置漂移;跨 Region 无单一配置入口 | 规则**模板化 / IaC 生成**(脚本或 Terraform 统一产出后下发各 Region),避免手工逐 Region 修改;接入文档中固化规则清单。**指标侧已无此问题** | +| R12 | **【新增 · 2026-09-14】跨 Region 网络与安全合规**:各集群 → 中心集群的链路是本方案的**唯一硬门槛**(§4.7.5 第 3 项 / §4.7.9 第 1 项) | 不成立则**整个指标自建方案不成立**——比 R10 更严重(R10 只损失大盘,本项损失**全部指标**) | 试点阶段**最优先**确定网络方案(CC / 专线 / 公网 HTTPS);同步做传输加密与源 IP 收敛。⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090`) | + +### R7 明细:`robot-universal-review` 的部署口径 + +实测 `infrastructure` 仓 `service.yaml`,该服务的**生产部署是 10 个社区 / 7 个集群**(不是一一对应,`infra-cn4-x86-common-cluster` 一台跑 3 个社区)。 + +而 #1938 覆盖范围表中该服务列了 7 个集群,与实测有**两处出入**: + +1. **多算了 `mindspore-cn-north-4-x86-cluster`** —— 该集群上的 `deployment-keeper-approve-v2` 的「镜像构建源码仓」列被误填为 `robot-universal-review`(`:74` 的 `robot-universal-keeper-approve` 同样误填),疑为映射表生成时的数据问题; +2. **漏了 `openeuler-cn-north4-x86-cluster`** —— openEuler 社区的实际 prod-02 部署。 + +另外 `service.yaml` 中 openEuler 的 `prod` 那条记录是**残缺记录**(集群/命名空间/ArgoCD 应用三列全空,部署仓还指向已迁移的旧仓 `opensourceways/helm-chart-value`),实际生效的是 `prod-02`。 + +**建议**:请映射表维护方校正 R7 相关行;铺开时若按「一行一条部署」生成配置,需显式跳过该残缺记录。 + +--- + +## 附录 + +### A. 相关链接 + +| 项 | 链接 | +| --- | --- | +| SDK 仓 | https://github.com/opensourceways/obs-sdk | +| 契约层 | [spec/](../spec/README.md) | +| Go 用法 | [go/README.md](../go/README.md) | +| Python 用法 | [python/README.md](../python/README.md) | +| Java 用法 | [java/README.md](../java/README.md) | +| Node 用法 | [node/README.md](../node/README.md) | +| 服务与社区映射 | https://github.com/opensourceways/infrastructure/blob/main/service.yaml | +| 试点日志 issue | [#2161](https://github.com/opensourceways/backlog/issues/2161) | +| 试点指标 issue | [#2162](https://github.com/opensourceways/backlog/issues/2162) | + +### B. 术语 + +| 术语 | 含义 | +| --- | --- | +| **community** | 社区标识(openEuler / Ascend / MindSpore 等 18 个),本次建设的核心切片维度 | +| **部署级 vs 请求级** | 字段/label 的两种取值来源:前者是 Init 一次注入的进程常量,后者是每请求从 context 覆盖 | +| **契约层** | `spec/` 目录,四语言输出格式的唯一权威定义 | +| **薄封装** | SDK 不自研 instrumentation,只做官方库的装配与字段注入 | +| **高基数** | 取值近乎唯一(request_id、trace_id、PR number 等),不能作 metrics label | +| **log-agent** | CCE 云原生日志采集插件的旧名,基于 fluent-bit + OTel,以 DaemonSet 部署在每个节点 | +| **default-stdout** | 该插件下的集群级日志采集策略名,内容为「全 ns 全容器 stdout」,业务日志进 LTS 的通道 | +| **聚合账号** | 汇聚方账号——是**跨账号**(基于 Organizations)而非「跨区域」。原设计通过 LTS 多账号日志汇聚中心 / AOM 多账号聚合实例承接各 Region 上报的日志与指标。**【2026-09-14】该路线已弃用**:指标侧改为**自建中心 Prometheus**(§4.7,不涉及华为云多账号机制);日志侧跨账号由**自建 Grafana 的 AK/SK 多数据源**解决(§4.7.8)。**本术语保留备查** | +| **中心指标集群** | 【2026-09-14 新增】独立部署的 Prometheus 中心集群,17 个集群的 Agent 经 `remote_write` 汇入,承载**统一指标大盘与统一告警**。形态参考资源块 `ascend-ci-deployment/monitoring`,**但独立部署、不复用其实例**(§4.7) | +| **Prometheus Agent** | `--agent` 模式,本地只抓取不存储,通过 `remote_write` 把数据推给中心——**汇聚发生在存储时,不是查询时** | +| **remote_write** | Prometheus 的远程写协议,本方案跨 Region 汇聚指标的**唯一机制**。⚠️ 资源块当前走**公网明文 HTTP**,生产不得照搬(§4.7.5) | +| **SMN** | 消息通知服务,告警的通知出口。**SMN 是 Region 级资源**;**【2026-09-14】现在仅日志告警使用**——指标告警已统一在中心 Alertmanager,不经 SMN | From 3398b13ac2705a22b599e9274c1be7383f3ed673 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 10:51:54 +0800 Subject: [PATCH 02/14] =?UTF-8?q?docs(design):=20=C2=A74.6/=C2=A74.7=20?= =?UTF-8?q?=E9=87=8D=E5=86=99=E4=B8=BA=E6=97=A5=E5=BF=97=E9=93=BE=E8=B7=AF?= =?UTF-8?q?=E4=B8=8E=E6=8C=87=E6=A0=87=E9=93=BE=E8=B7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按「结论 + 关键理由 + 关键数字」精简重写,删除决策过程与被推翻的历史: - §4.6 日志链路:日志采集 / 日志存储 / 日志告警 / 日志大盘 - §4.7 指标链路:指标采集 / 指标存储 / 指标告警 / 指标大盘 / 社区大盘 - 新增 §4.7.5 社区大盘(对外健康度状态页,与内部指标大盘对比,白盒 SDK + 黑盒拨测) - 9 条待验证项迁入 §6,新增风险行 R13–R21 - 15 处指向旧子节号的交叉引用重映射;412 行精简至 206 行 Co-Authored-By: Claude Code --- ...00\346\234\257\350\256\276\350\256\241.md" | 457 +++++------------- 1 file changed, 128 insertions(+), 329 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 58765a9..455b1d8 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -127,8 +127,8 @@ flowchart TB 1. **日志 —— 复用,不新建**:继续用各集群**现有的日志流**(CCE 云原生日志采集插件为每集群建的 `k8s-log-*` 组),本方案只改**日志的内容格式**(结构化 JSON + 契约字段),**不动采集管道**。 2. **指标 —— 新建**:26 个服务目前均未暴露 `/metrics`,需从零接入;存储侧**自建 Prometheus 实例**(独立中心集群,见 §4.7),不走华为云托管。 -3. **大盘 —— 自建 Grafana**:**一个**实例同时挂中心 Prometheus(指标)+ 17 个日志数据源(日志),见 §4.7.6 / §4.7.8。 -4. **已有现成闭环可参照**:**昇腾 CI 资源块**已跑通 **多集群 CronJob + Agent 上报 → 中心 Prometheus 存储 → Alertmanager 告警 → 邮件接收** 的完整链路,本方案的**指标侧与之同构**(见 §4.7.1)。⚠️ 该闭环**不含大盘**(资源块 Grafana 未启用,用的是外部 DataStat 看板),故第 3 点的自建 Grafana 属**本方案新增**,不能当作资源块已验证的能力。 +3. **大盘 —— 自建 Grafana**:**一个**实例同时挂中心 Prometheus(指标)+ 17 个日志数据源(日志),见 §4.7.4 / §4.6.4。 +4. **已有现成闭环可参照**:**昇腾 CI 资源块**已跑通 **多集群 CronJob + Agent 上报 → 中心 Prometheus 存储 → Alertmanager 告警 → 邮件接收** 的完整链路,本方案的**指标侧与之同构**(见 §4.7.2)。⚠️ 该闭环**不含大盘**(资源块 Grafana 未启用,用的是外部 DataStat 看板),故第 3 点的自建 Grafana 属**本方案新增**,不能当作资源块已验证的能力。 ### 3.2 部署与流程视图 @@ -217,8 +217,8 @@ flowchart LR | --- | --- | --- | | 日志存储 | **LTS**——**日志组按集群划分:每集群 1 个 `k8s-log-{集群ID}`,共 17 个** | 不自建 ES;容器日志写入 `stdout-{集群ID}` 日志流。**各 Region 自持,无跨日志组检索能力**(该限制决定了下方的日志告警形态) | | 指标存储 | **自建中心 Prometheus**(kube-prometheus-stack):17 集群 Agent(`--agent`,只抓不存)`remote_write` 汇聚到**1 个中心实例** | 不自研 SDK,**但自建底座**——理由与形态见 **§4.7**。原「AOM Prometheus for CCE」路线**已弃用**(官方确认多实例聚合不支持跨 Region) | -| 日志大盘 | **自建 Grafana(同一实例)挂 LTS 日志数据源 ×17** | 与指标大盘同屏、**跨账号免多登**(§4.7.8)。✅ **接入日志流已确认可行**(2026-09-14 华为云,前提是流已结构化) | -| 指标大盘 | **自建 Grafana(1 个实例)挂中心 Prometheus**。**独立 Deployment、与中心 Prometheus 同集群**(§4.7.6) | 替代原「AOM 托管 Grafana ×4」——一个实例即可覆盖全部 17 集群(§4.7.8)。**只做看板,不进告警链路**(见下行注释) | +| 日志大盘 | **自建 Grafana(同一实例)挂 LTS 日志数据源 ×17** | 与指标大盘同屏、**跨账号免多登**(§4.6.4)。✅ **接入日志流已确认可行**(2026-09-14 华为云,前提是流已结构化) | +| 指标大盘 | **自建 Grafana(1 个实例)挂中心 Prometheus**。**独立 Deployment、与中心 Prometheus 同集群**(§4.7.4) | 替代原「AOM 托管 Grafana ×4」——一个实例即可覆盖全部 17 集群(§4.7.4 / §4.6.4)。**只做看板,不进告警链路**(见下行注释) | | 日志告警 | **各 Region 本地 LTS 内逐流配置(17 条)**,出口经 SMN 统一到订阅端 | 因 LTS **无跨流查询**,一条规则无法绑定多个日志流,**明确接受「无跨集群联合告警」**。**SMN 仅日志告警仍用**(Region 级资源),「统一」落在各 Region 主题**订阅同一接收端**,而非同一主题 | | 指标告警 | **统一在中心 Alertmanager**(一条规则覆盖全部 17 集群) | 指标侧不再逐 Region 各配;`group_by: [cluster, alertname]` 区分来源 | @@ -474,317 +474,141 @@ with _context.bind(community="openEuler", request_id="req-123"): **范围(以 `robot-universal-review` 为例)**:需改 **12 个部署目录**(不是 10 个——Common 与 Ascend 各有两套部署,同社区同值)。生成脚本要**按部署目录迭代,不能按社区迭代**。 -> **备选方案(已否决)**:从 `(cluster, namespace)` 二元组反推 community。实测该组合对这 4 个机器人服务零冲突,但全域 375 个组合中已有 10 个跨社区(如 `ascend-guiyang-prod-cluster/ascend` 同时跑 Ascend 与 CANN),且 cluster 名 pod 拿不到。 -> **结论**:`(cluster, namespace)` 只作**校验**用途(断言注入值与映射仓一致),不作取值来源。 --- -### 4.6 底座与观测消费侧 +### 4.6 日志链路 -| 组件 | 设计 | -| --- | --- | -| **日志采集** | 复用 CCE 云原生日志采集插件(log-agent,基于 fluent-bit,节点 DaemonSet)。集群级 `default-stdout` 策略已覆盖**全 ns 全容器 stdout**,铺开**无需新增采集策略**——服务只要写 stdout 就进 LTS。 | -| **日志存储/检索** | LTS(各 Region 自持)。结构化后支持按 `service` / `level` / `community` / `request_id` 检索与聚合。**方案已定见 §4.6「【已定 · 2026-09-11】日志汇聚方案」**:拓扑为**每集群 1 个默认流 + Grafana 多数据源汇聚**,**采集范围先不收窄**(全量落流),结构化解析**只针对 obs-sdk 契约格式配 JSON 规则**,噪音在**查询侧**按 `service` / `community` 字段过滤。**统一检索入口走访问层汇聚**——Grafana + LTS-Grafana 数据源多源拼装,**不搬数据、保留 SQL**;**跨账号由自建 Grafana 解决**(LTS 数据源用 AK/SK 认证,一个实例可挂多套凭证,见 §4.7.8),**不再需要 LTS 多账号日志汇聚中心**。 | -| **指标采集** | 各集群 **Prometheus Agent**(`--agent`,本地只抓不存,ServiceMonitor 选目标 + `/metrics` 端口)→ `remote_write` | -| **指标存储** | **1 个独立中心 Prometheus 集群**(kube-prometheus-stack,`replicas: 2` + 反亲和,本地 30d)。**已弃用**「AOM Prometheus ×4 Region + 多账号聚合」路线——详见 **§4.7** | -| **大盘** | **已决:自建 Grafana ×1**(独立 Deployment,与中心 Prometheus 同集群),同时挂**中心 Prometheus(指标)+ LTS 数据源 ×17(日志)**——详见 **§4.7.6 / §4.7.8**。大盘内容:服务健康度(QPS / 错误率 / 延迟 / 资源)+ 日志检索,支持按 `community` 过滤/分组。**"看"与"告警"解耦**——大盘只影响可见性,采集 / 存储 / 告警均不依赖它。✅ **硬依赖已确认(2026-09-14,华为云团队)**:自建 Grafana 可接入各集群日志流,**前提是流已配置结构化**。**剩余唯一卡点是结构化解析本身**(§4.6 (a0)(i)) | -| **告警** | **指标:统一在中心 Alertmanager**——数据已汇聚,一条规则覆盖全部 17 集群(`group_by: [cluster, alertname]`),不经 SMN。**日志:仍为各 Region 本地 LTS 逐流配置(17 条)**,出口经各 Region SMN 主题 → 同一接收端(LTS 无跨流查询,**明确接受「无跨集群联合告警」**)。**告警从 ③ 存储分叉,不依赖 ④⑤**(见 §3.3)。 | +日志侧**复用现有底座,不新建**:采集管道沿用 CCE 云原生日志采集插件,存储沿用 LTS。本方案只改**日志的内容格式**(结构化 JSON + 契约字段),不动采集管道。 + +#### 4.6.1 日志采集 + +**形态**:复用 CCE 云原生日志采集插件(`log-agent`,基于 fluent-bit,节点 DaemonSet)。集群级 `default-stdout` 策略已覆盖**全 ns 全容器 stdout**,铺开**无需新增采集策略**——服务只要写 stdout 就进 LTS。 -**日志采集管道的约束(影响接入与验收口径)**: +**采集范围先不收窄**(保持全量),噪音在**查询侧**按 `service` / `community` 字段过滤。用配额与存储换零运维复杂度:新服务自动纳入、**无采集窗口期**、不维护 ns 白名单。 + +**采集管道的硬约束**(直接影响接入与验收口径): | 约束 | 影响 | | --- | --- | | containerd 运行时下**容器 stdout 的多行配置不生效** | 契约的「**单行**扁平 JSON」是硬约束而非风格偏好——多行日志会在 LTS 里被拆成互不相关的多条 | | 单条日志 **≤ 512 KB**;单节点约 **10000 条/秒** | Python / Java 契约允许 `error` 字段带完整 traceback,超长堆栈需截断 | -| stdout 为**非持久化存储** | 轮转清历史、Pod 终止回收、节点磁盘压力自动清理均可能丢日志——**日志是排障手段,不作审计/账本**,需在接入文档中明示 | +| stdout 为**非持久化存储** | 轮转清历史、Pod 终止回收、节点磁盘压力自动清理均可能丢日志——**日志是排障手段,不作审计 / 账本**,需在接入文档中明示 | | 容器存活 **< 1 分钟可能采不到** | 短命 Job / 一次性任务的日志有丢失风险 | | 每集群最多 **100 条**采集策略;变更 **1–3 分钟**生效 | 靠 `default-stdout` 一条策略覆盖全部服务,**不应为单服务新增策略** | | **日志流名称全局唯一**(不能跨日志组重名) | 插件默认名 `stdout-{集群ID}` 天然唯一、无冲突;**若将来自定义日志流名,需自带唯一性前缀**,否则跨集群建不出来 | -| 日志组按集群划分(`k8s-log-{集群ID}`,每集群 1 个) | 跨集群检索需在**多个日志组间**查询;LTS 的汇聚 / 检索入口要按日志组粒度设计,**不能假设「一个 Region 一个日志组」** | -| **LTS 无「跨日志组检索」**——搜索 / 快速查询 API 均以 `groups/{group_id}/topics/{topic_id}` 限定**单一组 / 流** | **17 个日志组不会自动汇成一个检索入口**,必须显式选一条汇聚路径,见下行 | - -**日志汇聚:17 个集群日志组怎么收成一个检索入口** -LTS **没有「跨日志组检索」能力**——搜索、快速查询及其列表的 API 全部以 `groups/{group_id}/topics/{topic_id}` 限定在**单个日志组 / 日志流**内,控制台也是逐组进入详情页。因此 **17 个 `k8s-log-{集群ID}` 不会自动汇成一个入口**。 +**实测:全量流内混着四类格式**(2026-09-11 现网抽样)——这是「结构化解析只能针对契约格式配」的直接依据,也是评估解析工作量的基线: -> **【已定 · 2026-09-11】日志汇聚方案** -> -> 经多轮现网实测与推演,日志侧收敛为下述形态。**本节以下内容(术语辨析、官方口径表、A/B/C/D 选项)是决策过程,不是方案本身。** -> -> | 维度 | 决定 | 理由 / 代价 | -> | --- | --- | --- | -> | **大盘前端** | **【2026-09-14 更新】自建 Grafana ×1**(独立 Deployment,与中心 Prometheus 同集群),同时挂**中心 Prometheus + LTS 数据源 ×17** | **原选「AOM 托管 Grafana ×4」的前提已失效**——指标侧改为自建中心后(§4.7),"避免自建"这条理由不再成立。自建还能一次解决**跨账号免多登**(AK/SK 按数据源各带一套)+ **日志指标同屏**,见 §4.7.8。✅ **硬依赖已确认(2026-09-14,华为云团队)**:自建 Grafana 可接入各集群日志流,**前提是流已配置结构化**。**剩余唯一卡点是结构化解析本身**(§4.6 (a0)(i)) | -> | **拓扑** | **每集群 1 个默认流**(`stdout-{集群ID}`)不变,Grafana 多数据源汇聚,**不搬数据** | 即原"路径 ① / 选项 C"。**D 已否决**,见下方否决记录 | -> | **采集范围** | **先不收窄**(保持 `default-stdout` 全量) | 用**配额与存储**换取**零运维复杂度**:新服务自动纳入、**无采集窗口期**、不维护 ns 白名单、**sidecar 不再需要插件支持"按容器名排除"**。代价是基础设施 / 第三方日志一并落流(容量已量化,余量一到两个数量级,暂不成问题) | -> | **结构化解析** | 只针对 **obs-sdk 契约格式**配 **JSON 规则** | 非 JSON 行(基础设施文本 / ANSI 着色文本 / Envoy access log)解析失败后**原样保留**,不污染结构化字段 | -> | **噪音过滤** | **在查询侧做**,不在采集侧 | 面板查询统一带 `WHERE service = '...'`:logrus 行与第三方 JSON 因**缺 `service` 字段**被自然排除;sidecar 与基础设施日志因**无结构化字段**被自然排除 | -> | **告警** | **日志:LTS 原生,逐流配置(17 条)**;**【2026-09-14 更新】指标:统一在中心 Alertmanager,一条规则覆盖全部 17 集群** | **日志侧明确接受「无跨集群联合告警」**——LTS 无跨日志流查询,17 条规则之间无法汇总(例如"某服务在所有社区的某类失败总数"这类**跨集群联合条件写不出来**);换来的是**通知链路完全不变**(仍走各 Region 的 SMN → 统一订阅端),且**无需设计"Grafana 告警 → 接回 SMN"**那套适配。**指标侧无此限制**——数据已汇聚到中心,告警天然统一,这是自建中心相对 AOM 路线的主要收益(§4.7.3) | -> -> **面板筛选策略**: -> -> | 面板 | `community` | `service` | 理由 | -> | --- | --- | --- | --- | -> | 日志 · 明细/排障 | **必选(多选,至少 1)** | **必选(多选,至少 1)** | 排除误伤(全量采集下本 Region 日志流里混有基础设施 / sidecar / 第三方日志);两字段合用 ≈ **精确定位到一个部署**。**必须多选**——单选会堵死"互调服务联合排查" | -> | 日志 · 聚合/对比 | 默认全选 | 默认全选 | 跨社区横向对比(如"某服务在所有社区的表现")是真实需求,且结果集小 | -> | 指标 | **默认全选,不强制** | — | **中心 Prometheus 存储已聚合**(全部 17 集群汇入同一实例),不筛选无查询放大问题;`community` 是低基数 label,`sum by (community)` 成本可忽略。**必选会禁掉横向对比,而横向对比恰是指标大盘最有价值之处**。担心误读时在面板标题显示当前筛选值即可 | -> -> > 两侧策略不同不是随意的不一致——**「必选筛选」本质是给"日志存储物理分裂成 17 个流"打的补丁**;指标侧存储本就聚合,不需要这个药。 -> -> **⚠️ 已知代价(需明确接受,不是意外)**: -> 1. **`robot-framework-lib` 的 121 处 logrus 打点(client 88 / config 14 / interrupts 11 / framework 6 / utils 2)在大盘上不可见**——其字段集无 `community` / `service`,被必选筛选条件排除; -> 2. **配额 / 存储不设防**——全量落流; -> 3. **聚合/对比面板要打 17 个数据源**,加载慢,任一失败则面板残缺。 -> -> **本方案仍需验证的前置项**(按优先级): -> 1. **(a0)(i) 全量流上能否配结构化解析**——**⚠️【2026-09-14 升级为唯一卡点】** 自建 Grafana 接入日志流已确认可行(见 4.7.8),**其前提正是"流已结构化",故本项现在是日志大盘链路上唯一未解的门槛**。配不了则日志大盘整个不成立(但**指标大盘与全部指标链路不受影响**——两者已解耦); -> 2. ~~**`hws-lts-grafana-datasource-plugin` 能否装进自建 Grafana**~~ → ✅ **【已确认 · 2026-09-14,与华为云团队沟通】** **自建 Grafana 可以接入各集群日志流**,前提是**日志流已配置结构化**。**此项已消解**——代价不再是"退回 LTS 控制台",**日志大盘确定落在自建 Grafana**。⚠️ **卡点转移到第 1 项(结构化解析)**,它是现在**唯一**的门槛; -> 3. **多账号的实际情况**——到底几个账号、如何在组织内管理;决定**自建 Grafana 里要配几套 LTS 数据源的 AK/SK**(一个实例即可承载多套,见 §4.7.8),也决定**回退到 LTS 控制台时要登录几个账号**。 -> -> ~~跨 Region 网络((a1)(a2)(a3) 三选一)~~ **【2026-09-14 重新需要】**——原判断「每 Region 一个实例、跨 Region 网络问题自动消失」**仅对日志大盘成立**;**指标侧改为自建中心后(§4.7),跨 Region 网络是无论如何都要打通的**(§4.7.5 第 3 项,本方案**新的硬门槛**),日志侧**复用同一条即可**,不构成额外开销。下方 (a1)/(a2)/(a3) 仍然适用。 -> -> **否决记录**: -> - **方案 D(按 Region 汇聚为 1 流)**——依赖太多、不确定性大。两个硬前提均未验证:**(e) 多集群能否共用同一日志流**(官方无任何记载);**结构化解析按流配置**意味着 D 把 Region 内所有集群的**接入进度与解析配置绑死**(任何集群输出有差异即污染整个 Region 的流,且迁移期必然有差异)。另有三项确定代价:爆炸半径从 1 个集群放大到整个 Region、单流 **500 请求/秒**被多集群写入叠加、失去 CCE 控制台按 ns / 工作负载 / 容器查询的能力。 -> - **自建日志前端**(把 LTS 多流引出来自绘页面)——见上表"大盘前端"行。 -> - ~~**自建统一 Grafana**(1 个实例同时覆盖日志 + 指标)~~ —— **【2026-09-14 已采纳,否决撤回】** -> 原否决理由是「要付跨 Region 网络 + 自行运维」。**指标侧改为自建中心后(§4.7),这两项成本已经为指标付过了**,日志接进来是**边际成本近乎为零**(多配 17 个数据源)。现方案:**自建 Grafana ×1 同时承载指标 + 日志**,见 §4.7.6 / §4.7.8。 +| # | 来源 | 格式 | 时间基准 | +| --- | --- | --- | --- | +| 1 | `fluentd-*` / `log-agent-fluent-bit-*` | 基础设施文本 | 本地 | +| 2 | `repo-watcher`(机器人服务) | **logrus JSON** | UTC **秒精度** | +| 3 | `cve-manager`(Gin 服务) | **ANSI 着色文本**(`[1;34m[I][0m [hook.go:146]`) | 本地 CST | +| 4 | `istio-proxy`(ASM sidecar,**同 Pod 另一容器**) | **Envoy access log** | UTC 毫秒 | -**先厘清术语**——「集中日志流」是官方词,指的是**每集群**,不是跨集群: +第 3 种把 ANSI 转义码写进了日志——**是给终端看的 logger,不是给日志系统看的**,正是本设计要消除的形态。第 4 种由 `allContainers: true` 带入,**按 ns 收窄挡不住**(sidecar 与业务容器同 Pod 同 ns)。 -| 官方术语 | 含义 | 粒度 | -| --- | --- | --- | -| **采集到集中日志流** | 用默认 `k8s-log-{集群ID}` + `stdout-{集群ID}`,**同集群内所有容器的 stdout 汇到一个流** | **每集群 1 流 —— 即本项目今天的形态** | -| **采集到自定义日志流** | 自选日志组 + 日志流,可让不同工作负载进不同的流 | 可细分到工作负载 | +**两个采集侧待确认项**(详见 §6):`stdout` 与 `stderr` 是否都被采集(logrus 的 error / fatal 默认写 stderr,若只采 stdout 则告警最依赖的两级整体缺失);sidecar 日志是否保留(Envoy access log 每请求至少 1 条,会使日志量成倍放大,且其 UTC 时间基准与本地 CST 的业务日志不一致)。 -> **⚠️ 一个必须先纠正的前提**:官方对「采集到集中日志流」的缺点原文是「**不同工作负载的日志结构不一样**,采集到一个日志流后无法配置结构化解析,无法使用 SQL 可视化分析」。该缺点**在本项目当前形态下已经成立,与是否跨集群汇聚无关**——现有 `default-stdout` 策略是 `allContainers: true` + 全部命名空间,`stdout-{集群ID}` 里混着多类负载,是彻底的异构流,结构化解析本来就配不上。 +#### 4.6.2 日志存储 -> **⚠️ 实测补充(2026-09-11,来自现网 `stdout` 流的抽样)**:抽样 10 条**全部**是**日志基础设施自身**的日志,**没有一条业务服务日志**。 -> **补充(同日,另一集群)**:该 10 条样本**不代表全貌**——在集群 `openeuler-hk-cce-x86` 中检到了货真价实的业务服务日志(`repo-watcher` / ns `robot-github-openeuler`),说明**业务日志确实在流里**,第一批抽样撞上的是采集器刷屏窗口。**同时,业务日志是 `robot-framework-lib` 的 logrus JSON,不是 obs-sdk 契约格式**——落库后同一流内并存两套格式(细节见待验证项 (a0-1b)),这直接影响下面的"收窄后即同构"判断:**收窄只解决"业务 vs 基础设施"的同构,不解决"logrus 行 vs obs-sdk 行"的同构**。 -> -> **⚠️ 流内格式清单(2026-09-11 实测,至此已确认四种)**——这是"结构化解析配不上"最直接的证据,也是评估**结构化解析工作量的基线**: -> -> | # | 来源 | 格式 | 时间基准 | -> | --- | --- | --- | --- | -> | 1 | `fluentd-*` / `log-agent-fluent-bit-*` | 基础设施文本 | 本地 | -> | 2 | `repo-watcher`(机器人服务,走 robot-framework-lib) | **logrus JSON** | UTC **秒精度** | -> | 3 | `cve-manager`(普通 Gin 服务) | **ANSI 着色文本**(`[1;34m[I][0m [hook.go:146]`) | 本地 CST | -> | 4 | `istio-proxy`(ASM sidecar,**同 Pod 另一容器**) | **Envoy access log** | UTC 毫秒 | -> -> 第 3 种把 ANSI 转义码写进了日志——**是给终端看的 logger,不是给日志系统看的**,正是本设计要消除的形态。第 4 种由 `allContainers: true` 带入,**按 ns 收窄挡不住**,见待验证项 (a0-1d)。 -> - `fluentd-*`(平台自建、写 ES 的那套)——多条 `[out_es] failed to write data into buffer by buffer overflow action=:throw_exception`、`suppressed same stacktrace`; -> - `log-agent-fluent-bit-*`(CCE 插件采集器本身)——`Get the pod list from kubelet failed: failed to unmarshal podlist`。 -> -> `content` 字段格式横跨 Ruby fluentd 文本、**带 ANSI 转义码**(`[1;31m[E][0m`)的 Go 日志、k8s 容器日志路径 tag(`..._monitoring_otel-collector-...log`)——**没有任何单一 JSON 规则能吃下这些**,是对"结构化解析配不上"的直接实证。 -> -> **由此多出一个此前未识别的风险——采集链路的正反馈放大**:采集器自身出问题(buffer overflow / 限流 / pod 列表抓取失败)→ 吐更多错误日志 → 这些日志**又走同一条采集链路** → 采集器压力更大。即"**故障越严重、日志越多、越可能触发『可能丢日志』的软阈值**"。在选项 D(Region 共用一个流)下该效应还会**跨集群传导**。 +**形态:LTS,各 Region 自持**,不自建 ES。日志组按集群划分,每集群 1 个 `k8s-log-{集群ID}`,容器日志写入 `stdout-{集群ID}` 流——**共 17 组 / 17 流**。 -**第一步:把采集范围收窄**(与汇聚无关,无论最后怎么选都要做) +**⚠️ LTS 无「跨日志组检索」**:搜索、快速查询及其列表的 API 全部以 `groups/{group_id}/topics/{topic_id}` 限定在**单个日志组 / 流**内,控制台也是逐组进入详情页。因此 **17 个 `k8s-log-{集群ID}` 不会自动汇成一个检索入口**,统一入口只能靠 Grafana 多数据源拼装(§4.6.4)。 -CCE 插件的日志采集策略支持按命名空间限定范围(插件版本 **1.6.1+**): +**结构化解析**:只针对 **obs-sdk 契约格式**配 **JSON 规则**。非 JSON 行(基础设施文本 / ANSI 着色文本 / Envoy access log)解析失败后**原样保留**,不污染结构化字段。 -```yaml -# 容器标准输出类策略 -allContainers: true -namespaces: ["robot-openeuler", "robot-openubmc", ...] # 空数组 = 全部命名空间(现状) -# excludePodLabels 可排除特定 Pod,需插件 1.7.4+ -``` +**容量口径**:单流 **100 MB/s** 为**软限制**(官方标 `Not mandatory`,超限不是拒绝写入,而是**不保证 QoS / 可能丢日志**,且**无补发语义**);另有单流 **500 次/秒**写入次数上限。⚠️ 该数字随版本变化大(旧版文档写的是 5 MB/s + 25K 条/秒),**容量规划须按各 Region 实际版本文档核,不要引用本文数字**。 -收窄后,流内容在「**业务日志 vs 基础设施日志**」这一维度上同构了——**但这只是同构的一半**。 +**其他约束**:一个日志流只能配**一种**结构化方式(ICAgent 结构化**或**云端结构化,切换**必须先删除**原配置);**结构化配置修改只对新写入生效**,历史数据不按新规则重新解析;云端结构化解析**消耗 LTS 算力**,官方称未来按日志量收取「日志加工流量费」。 -> **⚠️ 更正(2026-09-11,基于现网证据)**:此前此处写的是"契约保证 26 个服务输出同一套 JSON 字段",**该表述不成立**。现网检到的业务日志是 **`robot-framework-lib` 的 logrus JSON**(`component/error/file/func/level/msg/time`),`level: fatal`、`time` 秒精度、无 `service/env/instance/community/request_id`——**与 obs-sdk 契约行不同构**。 -> 且**不是过渡期现象**:框架那 121 处 logrus 打点会长期保留,**两套格式的共存是稳态而非临时**。 -> **因此"收窄 → 即可配结构化解析 → 即可 SQL 聚合"这条链,中间还缺一环**:得先明确 LTS 侧对这两套格式怎么处理(分别配解析?还是在云端做字段归一化?还是只对 obs-sdk 行做索引、logrus 行仅全文检索?)。这一点未定之前,**"结构化解析配得上"仍不成立**,只是从"多类负载混流"变成了"两类 JSON 混流"——后者好治得多,但仍需显式处理。 +#### 4.6.3 日志告警 -**第二步:选汇聚粒度** +**形态:仍走华为云 LTS 原生,各 Region 逐流配置(17 条)**,出口经**各 Region 的 SMN 主题** → 同一接收端(邮件组 / 统一 webhook 接收服务)。 -| 路径 | 做法 | 代价 / 前提 | -| --- | --- | --- | -| **① 不汇聚(每集群 1 流)+ Grafana 多数据源** | 各集群上报到**自己的**日志流;装华为云 **LTS-Grafana 插件**(`hws-lts-grafana-datasource-plugin`),**一个数据源绑一个日志流 ID**,面板侧用 Grafana 的 Mixed 数据源一次查多个流——**统一检索入口在 Grafana 侧拼出来,不搬数据** | ① **数据源数 = 日志流数(17)**,配置量与使用体验都不轻;② 数据源 `Endpoint` 按 Region 选 → 跨 Region 至少 **4 套**,**Grafana 需网络可达 4 个 Region 的 LTS 端点**;③ 插件需 **Grafana ≥ 9.0**,且要先在 LTS 控制台**开通「可视化」功能**;④ 数据源要求日志流**已配置结构化** | -| **② 按 Region 汇聚(每 Region 1 流)+ Grafana** | 各集群的采集策略**都指向同一个**日志组 + 日志流(如 `obs-{region}` / `obs-app-stdout`)→ 每 Region 1 流 | ① Grafana 侧降到 **4 个数据源、4 个查询目标**,明显清爽;② **官方无「多集群共用同一日志流」的配置说明**——下拉框里"看起来能选",**属未验证**;③ 失去按集群隔离;④ 单流 **100 MB/s** 上限(4 路分摊) | -| **③ 按 Region 汇聚 + 多账号日志汇聚中心** | 走 Organizations,把各日志流**复制**到聚合账号 | ~~依赖 Organizations;跨 Region 是否成立未确证~~ **【已不需要】** 跨账号已由**自建 Grafana 的 AK/SK 多数据源**解决(§4.7.8),**不再需要日志汇聚中心**;复制方案的"存储翻倍"代价也随之避免 | -| **④ 不汇聚、也不上 Grafana** | 接受 17 个日志组,控制台逐组进 | 没有统一检索入口,跨 Region 只能人工切换 —— **不建议** | +**为什么统一不了**:LTS **没有跨日志组 / 流的检索能力**,一条告警规则无法绑定多个日志流——该限制已与华为云团队确认。因此**明确接受「无跨集群联合告警」**:像「某服务在所有社区的某类失败总数」这类跨集群联合条件**写不出来**。 -> **⚠️ 时序上有个陷阱**:Grafana 的 LTS 数据源要求绑定的日志流**已配置结构化**,所以**所有路径都以"按 namespace 收敛采集"为共同前提**,没有"不动采集"的选项。 +**SMN 是 Region 级资源**(URN 形如 `urn:smn:::`),故「统一」不在同一个主题,而在**各 Region 主题订阅同一接收端**。 -#### 官方口径:集中日志流 vs 自定义日志流 +**不迁到 Grafana Alerting**:LTS-Grafana 插件虽支持 Grafana 自身的告警功能,但采用它会让 **Grafana 进入告警链路**,与 §4.7.4「Grafana 只做看板、故障域解耦」相悖——Grafana 一旦进告警链路,其 HA 就从「可选」变成「必须」。**待逐流维护真的成为负担时再评估。** -LTS/CCE 文档对「接入时选哪种采集方式」给了一张明确的权衡表,**倾向是"集中日志流"**: +> **⚠️ 前置依赖**:日志聚合告警依赖 LTS 的 **SQL 统计类型**,而 SQL 依赖**结构化解析配得上**(§4.6.2)。**若试点期这一步验证不通过,本节的日志告警选型需整体重谈**——优先级高于其他事项。 -| 采集方式 | 优点 | 缺点 | -| --- | --- | --- | -| **采集到集中日志流**(插件默认) | 在 CCE 界面可按命名空间 / 工作负载 / 容器名**直接查**对应日志 | 不同工作负载日志结构不一样 → **无法配置结构化解析、无法用 SQL 可视化分析**;单流 **100 MB/s**,大流量有瓶颈 | -| **采集到自定义日志流** | 可配置结构化解析、可用 SQL;多流写入速率**线性扩增**,大流量无瓶颈 | **CCE 界面无法**按命名空间 / 工作负载 / 容器名直接查 | +#### 4.6.4 日志大盘 -官方的判据是:**"主要靠 CCE 界面翻日志、流量不大" → 集中日志流;"需要结构化解析 / SQL 分析 / 大流量" → 自定义日志流**。本项目属于后者(日志要聚合告警 → 要 SQL)。 +**形态:并入自建 Grafana(1 个实例),挂 LTS 数据源 ×17**(每个数据源绑一个日志流 ID,各带一套 AK/SK 凭证)。 -> **⚠️ 但官方这张表漏了第三个选项**:它隐含假设「集中日志流 = 全部命名空间全部容器」,而**采集范围其实独立可调**(即上面的第一步)。于是: +> ✅ **硬依赖已确认(2026-09-14,华为云团队)**:**自建 Grafana 可以接入各集群的日志流**,**前提是日志流已配置结构化解析**。 +> 至此日志大盘链路上的**唯一卡点就是「结构化解析」本身**: +> +> ```text +> 日志大盘能否落地 = 自建 Grafana 接入 ✅(已确认) AND 流已结构化 ❓(唯一卡点) +> ``` -(下表用 **A/B/C/D** 编号,与上面那条"汇聚粒度"表的 ①②③④ 是两回事,别串) +**为什么用自建 Grafana 而不是 AOM 托管 Grafana ×4**:LTS 插件用 **AK/SK 认证,每个数据源可带自己的一套凭证**,所以**一个实例就能横跨 N 个华为云账号**、把 17 个日志流全挂上,**免多登**;而 AOM 托管 Grafana 是**账号级资源**,N 个账号要登录 N 次。且指标侧本就要自建 Grafana(§4.7.4),日志接进来是**边际成本近乎为零**(多配 17 个数据源)。 -| 选项 | 流 | 采集范围 | 流内容同构? | CCE 界面按 ns/负载查? | Grafana 数据源 | -| --- | --- | --- | --- | --- | --- | -| 现状 | 默认 `stdout-{集群ID}` | 全部 ns | ❌ | ✅ | — | -| **A** 集中日志流(官方推荐) | 默认 `stdout-{集群ID}` | 全部 ns | ❌ | ✅ | 17 | -| **B** 自定义日志流(官方备选) | 自选,按工作负载拆 | 自定 | ✅ | ❌ | 17+ | -| **C** 默认流 + 收窄 ns(**建议先试**) | 默认 `stdout-{集群ID}` | `namespaces: [...]` | ✅ | ✅ | 17 | -| **D** 自定义流 + 按 Region 共享 | 各集群同一个流 | 各自收窄 | ✅ | ❌ | **4** | +**面板筛选策略**: -**选项 C 两头都要**:流只含我们的服务 → 同构 → 结构化解析能配;同时保住 CCE 界面按 ns / 工作负载 / 容器名查看的能力(官方说自定义流会丢掉的那个)。 +| 面板 | `community` | `service` | 理由 | +| --- | --- | --- | --- | +| 明细 / 排障 | **必选(多选,至少 1)** | **必选(多选,至少 1)** | 排除误伤(全量采集下流里混有基础设施 / sidecar / 第三方日志);两字段合用 ≈ **精确定位到一个部署**。**必须多选**——单选会堵死「互调服务联合排查」 | +| 聚合 / 对比 | 默认全选 | 默认全选 | 跨社区横向对比(如「某服务在所有社区的表现」)是真实需求,且结果集小 | -> **与指标链路的同构性(支持 D 的一个独立论据)**:~~AOM 侧已定"**每 Region 1 个实例**,Region 内集群都接进同一个"~~。**⚠️【2026-09-14 该论据的前提已失效】**——指标侧改为**自建中心 1 个实例**(§4.7)后,"每 Region 1 个"不再成立,D 与指标链路的同构关系**反而不如从前**(指标是 1 个中心,D 是 4 个流,仍不同构)。**D 已否决的结论不变**,此段仅作历史记录。原对比: +> **为什么日志侧必选、指标侧不强制**:**「必选筛选」本质是给「日志存储物理分裂成 17 个流」打的补丁**;指标侧存储本就聚合(§4.7.4),不需要这个药。 -| | 指标(已定) | 日志 · 选项 C | 日志 · 选项 D | -| --- | --- | --- | --- | -| 服务端收敛点 | AOM Prometheus 实例 | LTS 日志流(每集群 1 个) | LTS 日志流(每 Region 1 个) | -| 存储对象数 | **4** | **17** | **4** | -| Grafana 数据源 | 4 | 17 | 4 | -| 告警规则集数 | 4 | 17 | 4 | +**已知代价(需明确接受,不是意外)**: -设计反复强调的是"日志与指标同一层级、同为 Region 级"(§3.3 整张表都按此对齐)。**C 会在日志侧开一个特例,D 保持结构一致**——这与"数据源数量少"是两个不同方向的理由,但同向支持 D。 +1. **`robot-framework-lib` 的 121 处 logrus 打点(client 88 / config 14 / interrupts 11 / framework 6 / utils 2)在大盘上不可见**——其字段集无 `community` / `service`,被必选筛选条件排除; +2. **配额 / 存储不设防**——全量落流; +3. **聚合 / 对比面板要打 17 个数据源**,加载慢,任一失败则面板残缺。 -> **⚠️ 但有一处真实不对称,且对 D 不利**:**收敛点的失败语义不同**。 -> - **指标侧**:Prometheus 写入带缓冲与重试(Agent 侧 WAL),且**未见 Prometheus 有"超过 X 会丢指标"的表述**; -> - **日志侧**:LTS 官方**明确写了**单流超 100 MB/s「**可能导致日志丢失**」,**无补发语义**。 -> -> 后果:**D 把"单个流被限流/写爆"的爆炸半径,从 1 个集群放大到该 Region 的全部集群**。指标侧不存在这个放大。 -> -> **但按本项目场景量化后,这个放大基本不构成风险**(见待验证项 11(a5)):契约真实示例行实测 info **289 B** / error **386 B**,100 MB/s ≈ **27–36 万条/秒**;机器人 / CLA 属事件驱动,每 Region 合计 1 万条/秒仅 **2.76 MB/s(占上限 2.76%)**,余量一到两个数量级。**所以选 D 的风险不在量,而在"多集群能否共用同一流"((e))与下面的请求数上限。** +--- -> **另一处隐藏差异**:**日志流不只是存储容器,还是结构化解析的配置单位**(指标实例里靠 label 区分,加服务不用动配置)。故 D = "一个 Region 一套解析规则",配一次全 Region 生效(比 C 的 17 次强);但**若将来某服务需要单独解析规则,D 下做不到,得拆流并重新分配采集目标**。C 则保留单集群独立调整的余地。 +### 4.7 指标链路 -> **⚠️ C 的疑点必须实测**:官方说集中日志流「无法配置结构化解析」,但它给的理由是「**不同工作负载日志结构不一样**」——C 恰好把这个前提消掉了。所以关键问题是:**那是技术上的硬禁止,还是"配了也没意义"的忠告?** 本文倾向后者不成立(云端结构化解析是对日志流配的,理论上不挑流的来源),**但这是推断,不能当结论**。**C 通了就选 C,不通退 D。** +指标侧**与日志侧相反:底座新建**。26 个服务目前均未暴露 `/metrics`,存储侧自建 Prometheus 实例,不走华为云托管。 -> **官方对日志组另有规划建议**:一个日志组对应一个**项目 / 业务**,把该项目下多个应用的日志流放进同一组(日志组不存数据、只是分类容器)。若照此办,可建 `obs-sdk` 日志组、把各集群的 `stdout-{集群ID}` 流都放进去(**1 组 × 17 流**,流名不用改)。**但这只让管理边界整齐,不产生统一检索入口**——检索仍逐流,属纯整理动作。另:官方建议**不同日志类型(stdout / event / audit)用不同日志流**,别混。 +核心结论:**弃用「AOM Prometheus for CCE + 多账号聚合」路线,改为「自建中心 Prometheus 集群」**——原路线经官方确认**不支持跨 Region 聚合**,拿不到统一大盘与统一告警。 -> **⚠️ 与 §3.3 告警选型的连锁反应**:§3.3 把「日志聚合告警依赖 LTS 的 SQL 统计类型」当作**把日志规则留在 LTS 的理由**。该理由依赖 SQL 可用,SQL 又依赖「结构化解析配得上」,后者再依赖「采集范围已按 namespace 收敛」。**若试点期这一步验证不通过,§3.3 的日志告警选型需整体重谈**——优先级高于汇聚粒度本身。 +#### 4.7.1 指标采集 -**容量与结构化解析的准确数字(上一版有出入)**: +**形态**:各集群部署 **Prometheus Agent**(`--agent`,**本地只抓不存**,本地只有 WAL),以 ServiceMonitor 选目标、抓各服务 `/metrics`,再 `remote_write` 到中心。形态照搬资源块(见 §4.7.2),但**独立部署、不复用其实例**——资源块 Agent 覆盖的是 CI 集群,与服务块 prod 集群基本不重叠;资源块的价值是**形态先例与配置模板**。 -- **100 MB/s 是软限制**(官方标 `Not mandatory`):超过不是拒绝写入,而是**不保证 QoS / 可能丢日志**。另有单日志流 **500 次/秒**写入次数上限、日志组 1000 次/秒。⚠️ 旧版文档写的是 **5 MB/s + 25K 条/秒**——该数字随版本变化大,**容量规划须按各 Region 实际版本文档核**。 -- **一个日志流只能配一种结构化方式**(ICAgent 结构化 **或** 云端结构化,切换**必须先删除**原配置)。 -- **结构化配置修改后仅对新写入生效**,历史数据不按新规则重新解析。 -- 云端结构化解析**消耗 LTS 算力,官方称未来按日志量收取「日志加工流量费」**。 -- 自定义日志流下 **CCE 界面不再能按 ns / 工作负载 / 容器名直接查**(官方明示缺点)。 +**⚠️ 跨 Region 链路是本方案的唯一硬门槛**(各集群 Agent → 中心): -> **附带发现(可能影响 §3.3 告警选型,此处仅记录)**:LTS-Grafana 插件除仪表盘外还**支持 Grafana 自身的告警功能**。这意味着"日志告警"多了一条候选路径(Grafana 侧统一配规则,而非逐 Region 各配一套 LTS 规则)。 -> -> **【2026-09-14 已决:不采用】**——**日志告警仍走华为云 LTS 原生、逐流配置**。采用 Grafana Alerting 会把告警依赖压到 Grafana 的可用性上,**与 §4.7.6「Grafana 只做看板、不进告警链路」的故障域解耦原则相悖**(Grafana 一旦进告警链路,其 HA 就从"可选"变成"必须")。**待逐流维护真的成为负担时再评估。** +- 必须解决:(a) 传输加密(至少 HTTPS);(b) 合规(生产指标数据出公网需确认);(c) 带宽与成本。 +- 候选路径:**云连接 CC**(按带宽计费、不过公网)/ **专线** / **HTTPS + 公网 EIP**。 +- ⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090` + Basic Auth)。**该链路不成立则整个中心方案不成立。** **黑盒拨测:白盒埋点覆盖不了的那一半** -本文 §4.2–§4.3 的 SDK 埋点是**白盒**——服务自己吐「我做了什么」。它天然看不见**服务进程之外**的东西。以下类别只能靠**外部主动探测**(黑盒)覆盖,需在铺开时另行补,不在本 SDK 范围内: +§4.2–§4.3 的 SDK 埋点是**白盒**——服务自己吐「我做了什么」,天然看不见**服务进程之外**的东西。以下类别只能靠**外部主动探测**覆盖,需在铺开时另行补,不在本 SDK 范围内: | 类别 | 例子 | 为什么埋点覆盖不了 | | --- | --- | --- | | 外部依赖可达性 | 依赖的 GitCode / GitHub API 通不通、下游服务在不在 | 请求发生在服务进程之外 | | 凭据可用性 | 能否从 Vault 读到 token、凭据是否临期 | 读取动作在启动期,且失败即进程退出,无日志可依 | -| 端到端可用性 | 服务整体还能不能正常响应一个真实请求 | 服务内指标全绿但外部路由/网关挂了,埋点看不出来 | +| 端到端可用性 | 服务整体还能不能正常响应一个真实请求 | 服务内指标全绿但外部路由 / 网关挂了,埋点看不出来 | 资源块已有的**探测 CronJob + Pushgateway** 基建可直接复用:CronJob 跑探测脚本 → push 到 Pushgateway → Prometheus 抓取 → `ProbeStale` 规则抓「指标过期」。**两个关键点**: 1. **`ProbeStale` 是必备的**。拨测有内生盲区——探测脚本自己挂了,指标不再更新,而「指标不再更新」看起来和「一切正常」一样。必须有一条规则专门抓指标过期。 2. **push 失败要重试后显式失败**。参考资源块做法:重试 6 次 × 45 秒吸收网络抖动,全失败则 Job 退出非零,让失败本身可被发现。 -> **⚠️ 【2026-09-14】本节多项已因「指标侧改为自建中心」(§4.7)而消解**——完整消解清单见 §4.7.4。下方以 ~~删除线~~ + 【消解】/【不适用】标注。 - -**待验证项(建议在试点阶段并行验证)**: - -1. ~~ServiceMonitor 在 4 个 Region 的实际可用性~~ → **【更新】** 改为「各集群 Agent → 中心的采集链路与网络可达性」,即 §4.7.9 第 1 项——**新的唯一硬门槛**; -2. ~~自定义指标采样点计费量级~~ → **【不适用】** 自建方案无采样点计费,改为**容量与磁盘成本核算**(§4.7.9 第 2 项); -3. ~~聚合实例上统一告警规则跨 Region 选择 / 通知是否符合预期~~ → **【消解】** 告警统一在中心 Alertmanager,**不存在跨 Region 规则问题**; -4. log-agent 在测试/生产集群的插件与 `default-stdout` 配置是否与预览集群一致(**不确认则验收标准 3 悬空**); -5. ~~**跨 Region 汇聚是否成立(日志与指标两侧均未验证)**~~ → **【消解】** 指标侧:`remote_write` 本身就是跨 Region 的,**无需"聚合能力",该问题不存在**;日志侧:仍走逐流 + Grafana 多数据源,本就不依赖汇聚能力。 - ⚠️ 本文此前的表述「已验证指标侧的多区域聚合实例」**不成立**——AOM 该能力的官方名称是「多**账号**聚合」,不是「多**区域**」聚合。 -6. ~~**AOM 侧日志告警是否支持 SQL 统计类型**~~ → **【不适用】** 指标告警已不再经过 AOM(改中心 Alertmanager),**AOM 告警中心整体不再使用**;日志告警仍在 LTS 内,SQL 统计能力**本就在用**,不构成待验证项。§3.3 中"把日志规则留在 LTS 的代价"一节已随之删除。 -7. ~~**统一大盘能否走 AOM「多账号虚拟聚合实例」**~~ → **【消解】** 大盘改为**自建 Grafana 直连中心 Prometheus**,**完全不依赖 AOM 聚合能力**。以下推演保留备查。 - - **结论先行**:**大盘不严格依赖聚合账号**——出统一大盘有三条路,依赖程度递减:Grafana 直接配多个 Prometheus 数据源(**完全不依赖聚合实例**)> 多账号**虚拟**聚合实例(服务端联邦查询,不落库)> 多账号聚合实例(真落库)。**虚拟聚合实例足以承载大盘**,其官方定位原文即「实现不同账号下 Prometheus 实例的**统一查询和统一告警**」。 - - **(a) 告警是可商榷项**:最佳实践中确有「配置监控告警」步骤,故告警并非不可用;但该样例针对**云服务指标**,而 obs-sdk 产出的是**自定义普罗指标**——文档明确「账号接入」功能**不适用于自定义普罗指标**。因此「**自定义指标 + 虚拟聚合实例 + 告警**」这一组合的**原文步骤未找到**,属待实测。落地建议:**大盘走虚拟实例可行;告警先落真聚合实例**,或实测虚拟实例能否承载。 - - **(b) 容量上限**:**单实例最多聚合 5 个 Prometheus 实例**——当前 4 Region 刚好卡在上限内、**无余量**,新增 Region 即超限;且**不支持嵌套聚合**(不能聚合虚拟聚合实例)。 - - **(c) 无本地存储**:虚拟实例**不存储、不支持指标写入**,告警评估只能靠查询时联邦,**实际时延与稳定性未经生产验证**。 -8. ~~**必须先确认 Organizations / OU 前提**~~ → **【消解】** 自建中心方案**不涉及华为云多账号机制**(`remote_write` 只需网络可达 + 鉴权,与账号归属无关),**该前提整个不再需要**。以下推演保留备查。原内容:AOM 与 LTS 的多账号能力均要求:已创建组织、已将对应服务设为可信服务、由管理账号或委托管理员配置;且 **AOM 仅支持接入 OU 下的成员账号**,组织与成员账号关系变更时**不会自动同步**。**若 17 个集群涉及的账号不在同一组织 / OU 下,第 ④ 层汇聚路线整体不成立**——需在试点阶段最优先确认。**影响面已收敛至「统一大盘」**:存储为 Region 级、告警从存储分叉,二者均不受牵连。 -9. **SMN 主题的 Region 级约束与「统一接收端」方案**【2026-09-14:**仅日志告警适用**,指标告警已走中心 Alertmanager】——主题 URN 含区域名(`urn:smn:::`),LTS / AOM 创建通知规则时只能选**本 Region** 主题,故「同一个 SMN 主题」跨 Region **不成立**。需确认:(a) 每 Region 各建一个主题、订阅同一接收端是否满足现有运维习惯(告警收敛、值班轮转);(b) SMN「订阅用户」的**跨区域统一管理仅支持国内站点**,香港 Region 是否适用;(c) 接收端统一走邮件组还是自建 webhook 接收服务。 -10. ~~**AOM Prometheus 单实例可接入的集群数上限**~~ → **【不适用】** 已不用 AOM。自建中心的容量约束改为 **Prometheus 单实例的 series 承载与磁盘**(§4.7.9 第 2 项)。原内容保留备查:已确认「1 个实例可接多个集群」(在实例的「集成中心 → 接入集群」逐个「一键安装」,非自动),故按 4 个实例走;但官方未给出单实例可接入集群数的上限。 -11. **LTS 日志汇聚走哪条路(决定统一日志检索入口是否成立)**——LTS **无跨日志组检索**,17 个 `k8s-log-{集群ID}` 不会自动成统一入口。 - - **(a0) 【最高优先级】全量默认流上能否配结构化解析**——见 §4.6「【已定】日志汇聚方案」:**已决定不收窄采集范围**,故本项不再以"按 namespace 收敛"为前提,而是验证**在异构全量流上配 JSON 结构化解析**是否可行(官方原文对其持负面口径,理由是"不同工作负载日志结构不一样")。需实测三问: - (i) **配置动作本身是否被禁止**(硬门槛——配不了则整个"已定方案"不成立,须退回自定义日志流); - (ii) **非 JSON 行解析失败后是保留原样还是被丢弃**(影响配额,不影响大盘); - (iii) **合法 JSON 但字段集不同的行**(logrus / 第三方)解析成什么(只要不产生 `service` 字段即无害,查询侧会自然排除)。 - 原"按 namespace 收窄"路线**未被否决、仅暂缓**:若 (i) 为"配不了",退路是①改自定义日志流(配得上解析,代价是失去 CCE 控制台查询)或②恢复按 ns 收窄;两条退路都**不影响服务侧**。 - - **(a0-1) 【已确认】业务服务日志确实在 LTS 里**——2026-09-11 在集群 `openeuler-hk-cce-x86`(香港 Region,`clusterId=1efda3f6-0cab-11ed-9c17-0255ac101f29`)的 `stdout` 流中检到 `repo-watcher` 的业务日志(`nameSpace: robot-github-openeuler`)。**采集接入这一环是通的,后续讨论成立。** - - 同一条数据**实证了「每集群一个日志组」**:字段 `__host_group__: k8s-log-1efda3f6-0cab-11ed-9c17-0255ac101f29` 与同批次的 `clusterId` **完全一致**; - - 也实证了**按 namespace 收窄是可行的**——但 **⚠️ 不能用前缀规则**:业务日志的 ns 既有 `robot-github-openeuler`(机器人服务),也有 `cve-manager`(**ns 名 = 服务名**)。与基础设施 ns(`monitoring` 等)可分,但**必须按服务清单逐个枚举**,写 `robot-*` 会漏掉 `cve-manager` 这一整类。 - - **(a0-1b) 【新发现·消费侧】同一流内会并存两套日志格式**——检到的 `repo-watcher` 日志是 **`robot-framework-lib` 的 logrus JSON**,不是 obs-sdk 输出。两处与契约冲突,会直接落到 LTS 的检索 / 聚合 / 告警规则上: - - **`level: fatal`** —— **不在契约枚举** `debug/info/warn/error` 内(§4.1.1 只对 fatal 做了"不强制"的开放表述); - - **`time: 2026-09-11T08:18:07Z`** —— **秒精度、无毫秒**,违反契约"固定毫秒精度"(§4.1.1); - - 字段名是 `component / error / file / func / level / msg / time`,**没有** `service / env / instance / community / request_id`。 - **接入 obs-sdk 后,同一个流里将并存"框架 logrus 行"与"obs-sdk 行"**——这是**消费侧的真实代价**,此前只在生产侧讨论过。**待定:告警规则与大盘查询是否接受同时兼容 `fatal` 与秒/毫秒两种时间格式**,或需在 LTS 侧做归一化。 - - **(a0-1c) 【需确认】stdout 与 stderr 是否都被采集**——该条业务日志的 `pathFile` 是 **`/stderr.log`**(logrus 的 error/fatal 默认写 stderr),而基础设施日志那批是 `stdout.log`。**若采集策略只覆盖 stdout,则 error / fatal 级日志会整体缺失**——而告警最依赖的恰是这两级。需确认 `default-stdout` 策略对 stderr 的覆盖情况。 - - **(a0-1d) 【新发现·采集侧】`allContainers: true` 会把注入 Sidecar 一起采进来**——2026-09-11 在 ns `cve-manager` 的样本中,3 条里 **2 条是 `containerName: istio-proxy`**(ASM sidecar,镜像 `asm/proxyv2`)的 **Envoy access log**,只有 1 条是业务容器 `cve-manager`。影响三处: - 1. **按 namespace 收窄挡不住 sidecar**——sidecar 与业务容器**同 Pod 同 ns**,ns 白名单对它无效;需确认插件是否支持**按容器名排除**(`namespaces` 只管 ns,`excludePodLabels` 只管 Pod label,二者都够不着"排除 Pod 内某个容器"); - 2. **日志量被乘性放大,此前估算偏低**——Envoy access log **每请求至少 1 条**(样本中为 `inbound`;若 outbound 亦开启则 2 条)。§4.6 容量结论(每 Region 2.76 MB/s)**只算了业务日志,未含 sidecar**,机器人 / CLA 这类 webhook 驱动、请求集中的场景需重估; - 3. **时间基准不一致**——同一条流内 istio-proxy 输出 **UTC**(`2026-09-11T09:59:30.943Z`),而业务容器输出**本地时间 CST**(`2026/09/11 17:59:30.943`,同一毫秒)。做时序分析前须先统一。 - 顺带:**是否保留 Envoy access log 需定夺**——HTTP 层可观测性有价值,但它与 SDK 中间件产出的 `obs_http_server_*` 指标高度重叠,且格式独立;若保留,`(a0-1b)` 的"两套格式"就要改成"N 套"。 - - **(a0-1e) 【需澄清】`cve-manager` 与清单里的 `cve-manager-ng` 是否同一服务**——§4.3.1 的 Go Gin 服务写的是 `cve-manager-ng`,现网 pod 的 `appName: cve-manager`、镜像 `openeuler/cve-manager:both_0910-311906`。若为两个服务,则「26 仓」清单本身要更新,铺开范围随之变。 - - **(a0-2) 【关键分叉】默认流上到底能不能配云端结构化解析**——决定选"默认流 + 收窄 ns"还是"自定义流": - - **能配**(本文倾向)→ 选**默认流 + 收窄 ns**:流同构、可 SQL、**同时保住 CCE 界面按 ns / 工作负载 / 容器名查看的能力**,且不用动接入方式; - - **配不上**(官方原文的措辞指向这个)→ 只能退**自定义日志流**,接受失去 CCE 界面那个查看能力。 - ⚠️ 官方「无法配置结构化解析」**给的理由是"不同工作负载日志结构不一样"**,收窄 ns 后该前提已消掉——**所以问题的实质是:这是技术硬禁止,还是"配了没意义"的忠告?** 本文的回答是推断,**必须实测**。 - - (a) **【2026-09-14 重新适用】Grafana 实例能否同时可达各 Region 的 LTS 端点**——~~原为"1 个统一 Grafana"方案的硬前提,曾因"改为每 Region 1 个实例"而不再需要~~;**现因大盘改回自建 Grafana ×1(§4.7.8)而重新成为前置项**。⚠️ **性质已变**:指标侧**无论如何**都要打通「各集群 → 中心」的跨 Region 网络(§4.7.5 第 3 项),日志侧**复用同一条网络**,不再是一笔额外开销——这也是自建 Grafana 这次能通过的原因之一。以下三条路线仍然适用: - - **(a1) LTS 公网 Endpoint + AK/SK**——零网络改造,只要 Grafana 出网即可;**但需确认 4 个 Region(尤其香港)都有可用的公网 Endpoint,且安全合规允许出公网**(本文未能查到 `ap-southeast-1` 的具体端点地址); - - **(a2) 云连接 CC 打通 4 个 Region 的 VPC**——走内网更安全,**但按带宽计费**。⚠️ **VPC 对等连接不支持跨 Region**(仅同 Region 内 VPC 互连),跨 Region 只能走 CC 或 CC + 企业路由器。**【2026-09-14】这条同时是指标链路的候选路径**(§4.7.5 第 3 项)——**一次打通,指标与日志两侧共用**; - - **(a3) 放弃跨 Region,改为每 Region 各 1 个 Grafana(共 4 个)**——无跨 Region 网络需求,代价是 4 个入口。**"统一"可另做**:入口反代聚合成一个 URL + 用同一份 dashboard JSON(GitOps 下发)保证 4 处口径一致——**统一来自"同一份配置",不必来自"同一个进程"**。 - - **(a4) 【2026-09-14 已推翻】Grafana 数量 = 4 → 改为 1(自建)**。~~原决:每 Region 1 个 AOM 托管实例,不承担告警。~~ **推翻原因**:指标侧改为自建中心后(§4.7),「避免跨 Region 网络与自建运维」这条理由失效——**这两项成本已经为指标付过了**;且自建还能解决**跨账号免多登 + 日志指标同屏**(§4.7.8)。**「Grafana 不承担告警」这点沿用**,故故障域仍与告警解耦——单点只影响"看"。**原「单点问题随之消失」的结论改为**:单点风险由「中心 Grafana 的 HA」承接(§4.7.6)。 - - **(a5) 【已决】汇聚粒度取 17 流(选项 C)还是 4 流(选项 D)**——**已选 C(每集群 1 默认流 + Grafana 汇聚),D 已否决**,见 §4.6「【已定】日志汇聚方案」的否决记录。以下推演保留作为决策依据: - 原两论据**同向支持 D**,但有一条代价指向 C: - - **论据一(省事)**:**一个 Grafana 数据源绑一个 `Log StreamId`**。C = **17 个数据源**且每个面板要挂多个查询目标;D = **4 个数据源**,明显清爽; - - **论据二(结构一致)**:**D 与指标链路同构**——AOM 侧是"每 Region 1 实例",D 与之在**存储对象数 / 数据源数 / 告警规则集数**三项上全部对齐(都是 4);C 会在日志侧开 17 的特例; - - **⚠️ 指向 C 的代价**:**收敛点的失败语义不对称**——指标侧写入带缓冲重试且**未见 Prometheus 有"超限丢指标"表述**;日志侧官方**明说**单流超 100 MB/s「可能导致日志丢失」、**无补发**。**D 会把"单流写爆"的爆炸半径从 1 个集群放大到该 Region 全部集群。** - **容量已量化,结论:容量不是 D 的门槛**。按契约真实示例行实测(info **289 B** / error **386 B**),**100 MB/s ≈ 27–36 万条/秒**。机器人 / CLA 是**事件驱动**服务,按每 Region 合计 1 万条/秒算仅 **2.76 MB/s(占上限 2.76%)**——**有一到两个数量级余量**。打满 100 MB/s 需要 ~36 万条/秒,折「每请求 5 条日志」即 **7.2 万请求/秒持续不断**,对这类服务不现实。 - **因此 D 的真正门槛不是量,而是 (e)「多集群能否共用同一日志流」这条未验证项**(与数据量无关),外加下面 (a6) 的请求数上限。仍需实测确认写入速率,但**验证目的是拿到真实数字而非筛掉 D**。另注意 C/D 都要改采集策略(见 a0),差别只在目标流选哪个。 - - **(a6) 【D 独有,与数据量无关】单日志流 500 次/秒的 API 请求数上限**——官方上限是**日志流级 500 次/秒**(日志组级 1000 次/秒)。选项 D 下 **17 个集群的 log-agent 都往同一个流写,各集群的 flush 请求数是叠加的**:若每个集群约 1 次/秒 flush 则 17 次/秒(无压力),但 flush 频率、批量大小需确认。**这是一条与日志大小无关的约束**——即使日志很小、MB/s 远低于上限,也可能先撞这条。选项 C 下每流只有 1 个集群写入,不存在叠加。 - - (b) **LTS-Grafana 插件的可用性**:LTS 控制台的「可视化」功能能否开通、插件对 Grafana 版本的要求(≥ 9.0)、以及**一个数据源绑一个日志流 ID** 带来的实际配置量可否脚本化; - - (c) **结构化解析的运维成本**:**一个日志流只能配一种结构化方式**(切换要先删原配置)、**改配置不回溯**(只对新写入生效)——契约字段若变更,17 处(或 4 处)都要重配且历史数据不可分析,需评估能否 API 批量下发; - - (e) **多集群能否共用同一日志流**(按 Region 汇聚路径)——官方**无**此配置说明,仅「采集到自定义日志流」的下拉框似可手动选到同一目标,属未验证; - - (f) **各 Region 实际版本文档里的写入上限**——本文查到的 100 MB/s 是软限制,**旧版文档写的是 5 MB/s + 25K 条/秒**,差异极大,**容量规划不能引用本文数字**,须按各 Region 实际版本核。 +#### 4.7.2 指标存储 ---- +**形态:1 个独立中心 Prometheus 集群**(kube-prometheus-stack,放独立中心集群)。17 个集群的 Agent 经 `remote_write` 汇入同一实例,`enableRemoteWriteReceiver: true`。 -### 4.7 中心指标集群:选型与形态 - -> **【已定 · 2026-09-14】指标侧改为「自建中心 Prometheus 集群」,弃用 AOM Prometheus for CCE + 多账号聚合。** -> -> 该决定**推翻了 §3.3 此前「不采用资源块自建栈」的结论**。**日志侧采集/存储方案不变**(仍为每集群 1 个 LTS 流,见 §4.6「【已定】日志汇聚方案」),但**大盘归属随之调整**——日志大盘一并并入自建 Grafana,见下「日志大盘的归属更新」。 - -#### 4.7.1 先例:资源块已跑通同一形态 - -昇腾 CI 在 [ascend-ci-deployment/monitoring](https://github.com/opensourceways/ascend-ci-deployment) 的自建栈,**实测形态**如下(非推演): - -| 组件 | 实测配置 | +| 项 | 决定 | | --- | --- | -| **中心 Prometheus** | kube-prometheus-stack,`replicas: 1`、`retention: 15d`、100Gi EVS、`scrapeInterval: 60s`、`enableRemoteWriteReceiver: true`,位于 `infra-monitoring` ns | -| **暴露方式** | Service `type: LoadBalancer` + ELB → **公网 `113.44.182.82:9090`**,`http://` **明文** + Basic Auth(`agent` / `password_file`) | -| **各集群 Agent** | 本地只抓不存(`--agent`),`remote_write` 到上述**同一 URL**。贵阳 `guiyang-001`/`guiyang-006`、香港 `hk-001` 的 configmap **逐字相同**,只差 `cluster` 标签 | -| **中心 Grafana** | 13.0.1,`replicas: 1`,10Gi PVC。**`grafana.enabled: false`——独立 Deployment**,与中心 Prometheus **同集群同 ns、复用同一 ELB**(`elb.id: 8625d057…`,端口分开);数据源**只有 1 个**(指向中心 Prometheus 的 svc) | -| **Alertmanager** | chart 自带,`replicas: 1`,QQ SMTP 邮件;路由 `group_by: [cluster, alertname]`——**说明告警已在全局视图上运行,一条规则覆盖所有集群** | -| **长期存储** | 中心再 `remote_write`,但**只 keep `custom_npu_.*`** → VictoriaMetrics(`vminsert.infra-monitoring.svc:8480`) | - -> **跨 Region 是怎么打通的**:**一个中心 Prometheus 挂在公网 IP 上,各集群 Agent 通过 `remote_write` 直接写它。** 不走云连接 CC、不走 VPC 对等、不做多实例聚合。`enableRemoteWriteReceiver: true` 即为此而开。 - -#### 4.7.2 目标拓扑 - -```text -17 个 CCE 集群(4 Region) - └─ Prometheus Agent(--agent,本地只抓不存) - │ remote_write(生产须 TLS + 鉴权) - ▼ - 【中心集群 · 独立】──────────────────────────┐ - ├─ 中心 Prometheus(replicas: 2 + 反亲和) │ 指标链路 - │ └─ Alertmanager(告警统一在此) │ - └─ Grafana(独立 Deployment,仅看板) ┘ - ├─ 数据源 ×1:中心 Prometheus - └─ 数据源 ×17:LTS 日志流(可选,见 4.7.5) -``` +| **HA** | `replicas: 2` + pod 反亲和(资源块当前为 `1`,其 values 注释已写明「正式上线时恢复 `replicas: 2`」)。**它是单点,挂了全网指标断线** | +| **保留期** | 一期**本地存储 30d,不上 VictoriaMetrics**——先跑一两个月看真实 series 增长再定,避免过早引入额外组件 | +| **安全** | `enableRemoteWriteReceiver: true` + 公网端口 = **拿到 basic auth 就能往中心写任意指标**。生产至少要做:强凭据 + 轮换、源 IP 白名单 / 安全组收敛、只放行 `/api/v1/write`。**独立集群的好处正是把风险面收敛到这一个集群上** | + +**形态先例**:昇腾 CI 资源块在 [ascend-ci-deployment/monitoring](https://github.com/opensourceways/ascend-ci-deployment) 已跑通同一形态(中心 Prometheus + Alertmanager + 各集群 Agent `remote_write`),**本方案指标侧与之同构**。两处**不可照搬**:资源块走**公网明文 HTTP + Basic Auth**(见 §4.7.1);其 Grafana **未启用**(用的是外部 DataStat 看板),故本方案的自建 Grafana 属新增能力。 -#### 4.7.3 与 AOM 路线的对比 +**为什么弃用 AOM 路线**: | 维度 | AOM Prometheus for CCE(原路线) | 自建中心 Prometheus(现路线) | | --- | --- | --- | @@ -799,99 +623,65 @@ LTS/CCE 文档对「接入时选哪种采集方式」给了一张明确的权衡 **取舍**:用**运维与网络成本**,换**统一大盘、统一告警、以及摆脱 Organizations / OU 前提**。 -#### 4.7.4 由此消解的前置项(重要) +**容量粗算**(`磁盘 ≈ 保留秒数 × 每秒样本数 × 1.7 B`,按 `scrapeInterval: 60s`): + +| active series | 日增 | 30d 占用 | +| --- | --- | --- | +| 20 万 | ≈ 0.5 GB/天 | ≈ 15 GB | +| 200 万 | ≈ 4.9 GB/天 | ≈ 147 GB | -原 AOM 路线上卡住的若干条,在自建方案下**不再成立**: +**series 数是这里唯一的未知量**,取决于 26 个服务的指标设计——**尤其不要把高基数塞进 label**(§4.1.3 铁律:`request_id` / `trace_id` / `span_id` 禁止当 label)。 -| 原前置项 | 状态 | -| --- | --- | -| §4.6 待验证项 5 —— 跨 Region 汇聚是否成立 | **消解**:`remote_write` 本身就是跨 Region 的,无需"聚合能力" | -| §4.6 待验证项 7 —— 统一大盘能否走多账号虚拟聚合实例 | **消解**:依赖消失 | -| §4.6 待验证项 8 —— Organizations / OU 前提 | **消解**:自建方案不涉及华为云多账号机制 | -| §4.6 待验证项 10 —— AOM 单实例可接入集群数上限 | **不适用** | -| §6 风险 R10 —— 第 ④ 层汇聚两条前提未确证 | **风险消失** | +> ⚠️ **若将来必须上 VictoriaMetrics**:资源块里 VM 的角色**不是「全量长期存储」,而是「少数需要长期趋势的指标的冷存储」**(只接 `custom_npu_.*`),照此办即可(保留期 > 30d 才上)。**一个坑**:中心 Prometheus `replicas: 2` 后,**两个副本会各写一份相同数据到 VM**,必须在 vminsert / vmselect 侧配 `-dedup.minScrapeInterval` 去重,否则**数据翻倍、查询结果异常**。 -> 这一条是本次决策最大的收益:**原路线把"统一大盘"押在华为云两套未确证的机制上(Organizations / OU + 跨 Region),自建方案把这两条前提整个移除了。** +#### 4.7.3 指标告警 -#### 4.7.5 中心集群的形态规划(四项) +**形态:统一在中心 Alertmanager**——数据已经汇聚,**一条规则覆盖全部 17 集群**,用 `group_by: [cluster, alertname]` 区分来源。**不经 SMN**(SMN 仅日志告警仍用)。 -1. **HA**:中心 Prometheus **`replicas: 2` + pod 反亲和**(资源块当前为 `1`,其 values 注释已写明"正式上线时恢复 `replicas: 2`")。**它是单点,挂了全网指标断线。** -2. **存储**:**一期用本地存储(30d),不上 VictoriaMetrics**——见 4.7.7。 -3. **网络**:⚠️ **生产不能照搬资源块的公网明文 HTTP**。各集群 Agent → 中心这条链路必须解决:(a) 传输加密(至少 HTTPS);(b) 合规(生产指标数据出公网需确认);(c) 带宽与成本。候选路径:**云连接 CC**(按带宽计费、不过公网)/ **专线** / **HTTPS + 公网 EIP**。 -4. **安全**:`enableRemoteWriteReceiver: true` + 公网端口 = **拿到 basic auth 就能往中心写任意指标**。生产至少要做:强凭据 + 轮换、源 IP 白名单 / 安全组收敛、只放行 `/api/v1/write`。**独立集群的好处正是把风险面收敛到这一个集群上。** +这是自建中心相对 AOM 路线的**主要收益之一**:原路线需逐 Region 各配一套,阈值与规则变更要多点同步、易产生配置漂移。 -#### 4.7.6 Grafana 形态:独立 Deployment,与中心 Prometheus 同集群 +#### 4.7.4 指标大盘 -**照搬资源块的形态:Grafana 独立于 chart(`grafana.enabled: false`),与中心 Prometheus 同集群、同 ns。** +**形态:自建 Grafana(1 个实例)挂中心 Prometheus**,**独立 Deployment、与中心 Prometheus 同集群同 ns**。 -| 理由 | 说明 | +| 设计点 | 说明 | | --- | --- | -| **"独立"的价值在生命周期解耦,不在物理位置** | 独立 Deployment 已让 Grafana 的升级 / 重启 / 回滚不碰 Prometheus,反之亦然——这是真正需要的隔离 | +| **「独立」的价值在生命周期解耦,不在物理位置** | 独立 Deployment 已让 Grafana 的升级 / 重启 / 回滚不碰 Prometheus,反之亦然——这是真正需要的隔离 | | **同集群走集群内 svc 查询** | `prometheus-kube-prometheus-prometheus.infra-monitoring.svc:9090`,零网络成本、零延迟。Grafana 是查询密集型无状态服务,离 Prometheus 越近越好 | -| **故障域本来就解耦** | 关键在**告警用 Alertmanager、不用 Grafana Alerting**——Grafana 挂了只是看不了图,**告警不受影响** | -| **单开一个集群只为 Grafana 不划算** | 多一份集群底座成本,还**新增一条跨集群链路**(Grafana → Prometheus) | - -**例外**:Grafana 要对外开放给多租户、或有独立安全域要求时,才值得独立集群——**那是安全需求,不是可用性需求**。 +| **故障域与告警解耦** | 关键在**告警用 Alertmanager、不用 Grafana Alerting**——Grafana 挂了只是看不了图,**告警不受影响** | +| **不单开一个集群** | 多一份集群底座成本,还**新增一条跨集群链路**(Grafana → Prometheus) | -**两点可照抄**:Grafana PVC 只要 **10Gi**(dashboard 走 ConfigMap provisioning,PVC 只存状态);**和 Prometheus 复用同一个 ELB、端口分开**,省一个 ELB。 +**两点可照抄资源块**:Grafana PVC 只要 **10Gi**(dashboard 走 ConfigMap provisioning,PVC 只存状态);**和 Prometheus 复用同一个 ELB、端口分开**,省一个 ELB。 -#### 4.7.7 VictoriaMetrics:一期不上 +**面板筛选策略**:`community` **默认全选、不强制**——中心 Prometheus 存储已聚合(全部 17 集群汇入同一实例),不筛选无查询放大问题;`community` 是低基数 label,`sum by (community)` 成本可忽略。**必选会禁掉横向对比,而横向对比恰是指标大盘最有价值之处**;担心误读时在面板标题显示当前筛选值即可。 -资源块里 VM 的角色**不是"全量长期存储",而是"少数需要长期趋势的指标的冷存储"**(只接 `custom_npu_.*`)。据此: +**大盘内容**:服务健康度(QPS / 错误率 / 延迟 / 资源)+ 日志检索(与 §4.6.4 同屏,跨账号免多登),支持按 `community` 过滤 / 分组。**「看」与「告警」解耦**——大盘只影响可见性,采集 / 存储 / 告警均不依赖它。 -| 保留期要求 | 建议 | -| --- | --- | -| **≤ 30d** | 中心 Prometheus 本地存储够用,**不上 VM**。预留 `remoteWrite` 配置位(改一行的事) | -| **> 30d** | 上 VM,但**只 keep 需要长期的指标**,不要全量转发 | +#### 4.7.5 社区大盘 -**容量粗算**(`磁盘 ≈ 保留秒数 × 每秒样本数 × 1.7 B`,按 `scrapeInterval: 60s`): +这是**与内部指标大盘并列的另一个视图**,本方案需同时给出: -| active series | 日增 | 30d 占用 | +| | 指标大盘(§4.7.4) | 社区大盘(本节) | | --- | --- | --- | -| 20 万 | ≈ 0.5 GB/天 | ≈ 15 GB | -| 200 万 | ≈ 4.9 GB/天 | ≈ 147 GB | +| **读者** | 运维 / 研发 | 社区用户 | +| **回答的问题** | **为什么坏**(QPS / 错误率 / 延迟 / 资源) | **哪块坏了**(组件是否正常、异常落在哪一段) | +| **形态** | Grafana 面板 | GitHub Status 形态的状态页 | +| **粒度** | 服务 × community × 集群 | **按社区聚合的组件级健康度** | -**series 数是这里唯一的未知量**,取决于 26 个服务的指标设计——**尤其不要把高基数塞进 label**(§4.1.3 铁律:`request_id` / `trace_id` / `span_id` 禁止当 label)。 +**目标**:一眼看到**整体与各组件**(从重点微服务中挑选,如评审机器人、账号、CLA 等)是否正常、异常落在哪一段,替代当前「靠零散告警与人肉打听拼凑判断」。 -> **建议**:一期先不配 VM,中心 Prometheus 本地存 30d,**跑一两个月看真实 series 增长再定**,避免过早引入一个额外组件。 -> -> ⚠️ **若必须上 VM,注意一个坑**:中心 Prometheus 上 `replicas: 2` 后,**两个副本会各写一份相同数据到 VM**,必须在 vminsert / vmselect 侧配 `-dedup.minScrapeInterval` 去重,否则**数据翻倍、查询结果异常**。VM 自身的 HA(vminsert / vmselect / vmstorage)也要一并考虑。 +**数据来源**: -#### 4.7.8 日志大盘的归属更新 +- **白盒**:§4.2–§4.3 的 SDK 指标(服务自报的 QPS / 错误率); +- **黑盒**:§4.7.1 的探测 CronJob 指标——**端到端可用性这类「服务内指标全绿、但外部路由 / 网关挂了」的情况只有拨测能发现**,而它恰好最直接回答「这个组件还能不能用」。 -本决策**改变了 §4.6「日志汇聚方案」中"大盘前端"的前提**——原方案选 AOM 托管 Grafana ×4 的两个理由之一是"避免自建",而**指标侧已经要自建了,该理由不再成立**。 +**与 Grafana 解耦**:状态页是**对外**入口,不应把内部 Grafana 直接暴露出去(多租户、安全域、可用性要求都不同)。落地形态(静态页 + 定时拉取 / 轻量服务)另议。 -| | AOM 托管 Grafana ×4(原) | 自建 Grafana ×1(现) | -| --- | --- | --- | -| **多账号** | 账号级资源,N 个账号要**登录 N 次** | 一个 Grafana 挂 N 套 AK/SK,**不用多登** ✅ | -| **日志 + 指标同屏** | ✗ 日志在 LTS,需插件才连得上 | ✓ 同屏 | -| **指标数据源** | 只能连本账号本 Region AOM | 挂中心 Prometheus | -| **实例数** | 4 个 | 1 个 | -| **运维** | 云托管,零运维 | 自行运维(已有资源块模板) | - -> **LTS 插件用 AK/SK 认证,每个数据源可带自己的一套凭证**——所以一个自建 Grafana 就能横跨 N 个华为云账号,把 17 个日志流全挂上。**AOM 托管 Grafana 做不到这点**(它是账号级资源)。这恰好解决了此前"多账号登录麻烦"的痛点。 +**待定**: -> ### ✅ 【已确认 · 2026-09-14】自建 Grafana 可接入各集群日志流 -> -> **与华为云团队沟通确认**:**自建 Grafana 可以接入各集群的日志流**——**前提是日志流已配置结构化解析**。 -> -> 这解开了本方案此前的**最后一个硬依赖**(原为「`hws-lts-grafana-datasource-plugin` 能否装进自建 Grafana」,且对资源块在用的 13.0.1 的兼容性无任何背书)。**至此,日志大盘链路上的唯一卡点就是「结构化解析」本身**——直接指向 §4.6 待验证项 **(a0)(i)**: -> -> ```text -> 日志大盘能否落地 = 自建 Grafana 接入 ✅(已确认) AND 流已结构化 ❓(唯一卡点) -> ``` - -**告警归属不变(同日确认)**:**日志告警仍走华为云 LTS 原生、逐流配置(17 条)**,**不迁到 Grafana Alerting**——Grafana **只做看板**,与 4.7.6「Grafana 不进告警链路」一致,**故障域保持解耦**(Grafana 挂了不影响告警)。若将来要用 Grafana Alerting 跨 17 数据源做一条规则,则**必须同步把 Grafana 的 HA 做起来**。 - -#### 4.7.9 本方案仍需验证的前置项 - -| # | 项 | 影响 | -| --- | --- | --- | -| 1 | **各集群 → 中心集群的网络与合规**(CC / 专线 / 公网 HTTPS 三选一) | **本方案的唯一硬门槛**,不成立则整个中心方案不成立 | -| 2 | **中心集群的容量与压测**:17 集群 × 26 服务的真实 series 量、30d 保留所需磁盘、单实例能否承载 | 决定存储规格与 VM 是否必要 | -| 3 | **HA 验证**:`replicas: 2` + 反亲和下的去重与告警行为 | 中心是单点,必须 | -| 4 | **安全加固**:TLS、凭据轮换、源 IP 白名单 | 生产合规 | -| 5 | ~~`hws-lts-grafana-datasource-plugin` 对 Grafana 13 的兼容性~~ → ✅ **【已确认 · 2026-09-14】** 华为云确认**自建 Grafana 可接入各集群日志流**,前提是**流已配置结构化** | **已消解**。⚠️ 但**结构化解析随之成为日志大盘链路上唯一的卡点**(§4.6 (a0)(i) 升级为**最高优先级**) | +1. **组件级健康的判定口径**——几个指标、什么阈值算「异常」,需与各社区运维对齐; +2. **异常事件的发布流程**——谁改状态、是否人工确认;状态页的价值在可信,不能纯靠自动抖动; +3. **是否纳入本期交付范围**——§1.1 已把它列为要解决的问题,而 §2.1 的 G1–G5 尚未覆盖它,需明确。 --- @@ -927,7 +717,7 @@ LTS/CCE 文档对「接入时选哪种采集方式」给了一张明确的权衡 | 容量与成本核算(series 量 / 磁盘 / 跨 Region 流量) | 1~2 | | **小计** | **25~40** | -> **⚠️ 【2026-09-14】本节已随指标路线改为自建中心而重估**(原 17~27 人天基于 AOM 托管路线)。**成本上升是真实的**——自建多出「中心集群搭建」「Agent 铺开」「跨 Region 网络」「安全加固」四项,而省掉的只有「采样点计费评估」一项。**这是换取统一大盘 + 统一告警所付的显式代价**(§4.7.3)。 +> **⚠️ 【2026-09-14】本节已随指标路线改为自建中心而重估**(原 17~27 人天基于 AOM 托管路线)。**成本上升是真实的**——自建多出「中心集群搭建」「Agent 铺开」「跨 Region 网络」「安全加固」四项,而省掉的只有「采样点计费评估」一项。**这是换取统一大盘 + 统一告警所付的显式代价**(§4.7.2)。 ### 5.3 子任务 C —— 26 仓全量铺开与验收(#2063) @@ -967,18 +757,27 @@ LTS/CCE 文档对「接入时选哪种采集方式」给了一张明确的权衡 | # | 项 | 影响 | 处置 | | --- | --- | --- | --- | -| R1 | ~~**15 天存储窗口**:AOM 指标默认存 15 天(超期按量计费)~~ → **【2026-09-14 转换】** 自建中心 Prometheus **保留期可自定**(建议 30d),不再受 15 天约束(§4.7.7) | ~~故障回溯窗口可能不足~~ **风险消除**;但**磁盘容量成为新的约束** | 按 §4.7.7 公式核算 series 量 → 定保留期与磁盘规格;>30d 需求再上 VictoriaMetrics | -| R2 | ~~ServiceMonitor 在 4 Region 的可用性~~ → **【转换】各集群 Agent → 中心集群的采集链路与网络可达性**未经生产验证 | 指标可能采不上——**且这次没有云托管兜底** | 试点阶段**逐集群**验证 Agent 与 `remote_write` 连通性;网络方案见 §4.7.5 第 3 项 | -| R3 | ~~自定义指标采样点计费量级未知~~ → **【转换】自建中心的容量与成本**:series 量、磁盘、**跨 Region 流量费**三项均未测算 | 26 仓铺开成本不可控(原为按量计费,现为**自建资源 + 出网流量**) | 试点阶段实测 17 集群真实 series 量后外推(§4.7.7 已给容量公式);跨 Region 流量按所选网络方案(CC 按带宽 / 公网按流量)分别核算 | +| R1 | ~~**15 天存储窗口**:AOM 指标默认存 15 天(超期按量计费)~~ → **【2026-09-14 转换】** 自建中心 Prometheus **保留期可自定**(建议 30d),不再受 15 天约束(§4.7.2) | ~~故障回溯窗口可能不足~~ **风险消除**;但**磁盘容量成为新的约束** | 按 §4.7.2 公式核算 series 量 → 定保留期与磁盘规格;>30d 需求再上 VictoriaMetrics | +| R2 | ~~ServiceMonitor 在 4 Region 的可用性~~ → **【转换】各集群 Agent → 中心集群的采集链路与网络可达性**未经生产验证 | 指标可能采不上——**且这次没有云托管兜底** | 试点阶段**逐集群**验证 Agent 与 `remote_write` 连通性;网络方案见 §4.7.1 | +| R3 | ~~自定义指标采样点计费量级未知~~ → **【转换】自建中心的容量与成本**:series 量、磁盘、**跨 Region 流量费**三项均未测算 | 26 仓铺开成本不可控(原为按量计费,现为**自建资源 + 出网流量**) | 试点阶段实测 17 集群真实 series 量后外推(§4.7.2 已给容量公式);跨 Region 流量按所选网络方案(CC 按带宽 / 公网按流量)分别核算 | | R4 | log-agent 在生产集群的配置是否与预览集群一致未确认 | 结构化日志可能采不到字段 | 铺开前抽查生产集群插件配置 | | R5 | **Java SDK 无兜底**,未注入环境变量时 4 个必填字段整个缺失 | 违反契约,Java 服务日志字段不全 | 单独立项修复(加 hostname / `unknown` 兜底 + 补 UT,断言落在真实 JSON 输出上) | | R6 | Python / Node / Java 未打 tag,Java 进私服路径未验证 | 消费方无法按版本引用 | 随各语言首次接入服务时一并处理 | | R7 | **#1938 覆盖范围表的机器人部分与实际部署不符** | 影响 community 取值与大盘分维度 | 见下 | | R8 | Java SDK 的 logstash-logback-encoder / jackson-core 在 SDK 内为 `provided` | 接入服务运行时必须自带,否则日志不可用 | 接入文档中明确要求,或改为传递依赖 | | R9 | 请求级 community 的安全约束(禁止裸读 URL/Header) | 误用会导致 community 被外部可控 | 代码 review 检查点 + 接入文档强调 | -| R10 | ~~**第 ④ 层汇聚的两条前提均未确证**:Organizations / OU 归属、跨 Region 是否成立~~ → **【2026-09-14 消解】** 自建中心**不涉及华为云多账号机制**,两条前提整个不再需要(§4.7.4) | ~~汇聚层整体不成立,失去统一大盘~~ **风险消除** | 无需处置 | +| R10 | ~~**第 ④ 层汇聚的两条前提均未确证**:Organizations / OU 归属、跨 Region 是否成立~~ → **【2026-09-14 消解】** 自建中心**不涉及华为云多账号机制**,两条前提整个不再需要(§4.7.2) | ~~汇聚层整体不成立,失去统一大盘~~ **风险消除** | 无需处置 | | R11 | ~~**告警规则逐 Region 各配一份**(4 Region × 日志/指标 ≈ 8 套)~~ → **【2026-09-14 收敛为日志单侧】**:**指标告警已在中心统一为 1 套**;**日志仍为 4 Region × 逐流 17 条**,SMN 主题亦每 Region 一个 | 阈值 / 规则变更需多点同步,易产生配置漂移;跨 Region 无单一配置入口 | 规则**模板化 / IaC 生成**(脚本或 Terraform 统一产出后下发各 Region),避免手工逐 Region 修改;接入文档中固化规则清单。**指标侧已无此问题** | -| R12 | **【新增 · 2026-09-14】跨 Region 网络与安全合规**:各集群 → 中心集群的链路是本方案的**唯一硬门槛**(§4.7.5 第 3 项 / §4.7.9 第 1 项) | 不成立则**整个指标自建方案不成立**——比 R10 更严重(R10 只损失大盘,本项损失**全部指标**) | 试点阶段**最优先**确定网络方案(CC / 专线 / 公网 HTTPS);同步做传输加密与源 IP 收敛。⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090`) | +| R12 | **【新增 · 2026-09-14】跨 Region 网络与安全合规**:各集群 → 中心集群的链路是本方案的**唯一硬门槛**(§4.7.1) | 不成立则**整个指标自建方案不成立**——比 R10 更严重(R10 只损失大盘,本项损失**全部指标**) | 试点阶段**最优先**确定网络方案(CC / 专线 / 公网 HTTPS);同步做传输加密与源 IP 收敛。⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090`) | +| R13 | **【日志侧唯一卡点】全量默认流上能否配置云端结构化解析**(§4.6.2) | 配不上则**日志大盘与日志聚合告警整体不成立**(指标侧不受影响,两者已解耦)。退路:改自定义日志流(失去 CCE 控制台按 ns / 负载查询)或恢复按 ns 收窄 | **最高优先级**,试点期第一步。实测三问:① 配置动作本身是否被禁止(硬门槛);② 非 JSON 行解析失败后是保留原样还是被丢弃;③ 合法 JSON 但字段集不同的行(logrus / 第三方)解析成什么(只要不产生 `service` 字段即无害) | +| R14 | **同一日志流内并存两套格式**:obs-sdk 契约行与 `robot-framework-lib` 的 logrus JSON(后者无 `service` / `env` / `community`,且 `level: fatal`、`time` 秒精度均与契约冲突)(§4.6.1) | LTS 侧的检索 / 聚合 / 告警规则要同时兼容两种格式;且**不是过渡期现象**——框架那 121 处打点会长期保留,两套格式的共存是稳态 | 明确 LTS 侧怎么处理这两套(分别配解析?云端做字段归一化?只对 obs-sdk 行做索引、logrus 行仅全文检索?)。**这一点未定之前,「结构化解析配得上」仍不成立** | +| R15 | **stdout 与 stderr 是否都被采集**未确认——现网检到的业务日志 `pathFile` 是 `/stderr.log`(logrus 的 error / fatal 默认写 stderr)(§4.6.1) | 若采集策略只覆盖 stdout,则 **error / fatal 级日志整体缺失**——而告警最依赖的恰是这两级 | 试点期确认 `default-stdout` 策略对 stderr 的覆盖情况 | +| R16 | **`allContainers: true` 会把注入的 Sidecar 一并采进来**——现网样本中 `istio-proxy` 的 Envoy access log 占 2/3,且**按 ns 收窄挡不住**(与业务容器同 Pod 同 ns)(§4.6.1) | 三处:① 日志量被乘性放大(每请求至少 1 条),此前容量估算只算了业务日志;② 时间基准不一致(sidecar 走 UTC、业务容器走本地 CST);③ 是否保留 Envoy access log 需定夺——它与 SDK 的 `obs_http_server_*` 高度重叠 | 确认插件是否支持**按容器名排除**(`namespaces` 只管 ns、`excludePodLabels` 只管 Pod label,二者都够不着「排除 Pod 内某个容器」);据此重估日志量 | +| R17 | 「26 仓」清单可能变化:现网 pod 的 `appName: cve-manager`,而清单里写的是 `cve-manager-ng`(§4.3.1) | 若为两个服务,铺开范围随之变 | 澄清二者是否同一服务;一并确认 §5.4 列出的 4 个部署口径存疑的服务是否纳入本次铺开 | +| R18 | **各 Region 实际版本文档里的 LTS 写入上限未核**——本文的 100 MB/s 是软限制,旧版文档写的是 5 MB/s + 25K 条/秒,差异极大(§4.6.2) | 容量规划若引用本文数字会严重偏差 | **按各 Region 实际版本文档核,不要沿用本文数字** | +| R19 | **SMN 的 Region 级约束下「统一接收端」方案待确认**:主题 URN 含区域名(`urn:smn:::`),跨 Region 只能各建主题(§4.6.3) | 影响告警收敛与值班轮转 | 确认 ① 每 Region 各建主题 + 订阅同一接收端是否满足现有运维习惯;② SMN 订阅用户的跨区域统一管理(仅国内站点支持)香港是否适用;③ 接收端走邮件组还是自建 webhook 接收服务 | +| R20 | **中心集群的 HA 未验证**:`replicas: 2` + pod 反亲和下的去重与告警行为(§4.7.2) | 中心是单点,挂了全网指标断线 | 试点期验证。若将来上 VictoriaMetrics,必须同时配 `-dedup.minScrapeInterval`,否则两个副本各写一份、**数据翻倍** | +| R21 | **社区大盘(§4.7.5)的判定口径与发布流程未定** | 影响对外可视性;纯自动抖动会损害状态页的可信度 | 与各社区运维对齐「组件级健康」用哪几个指标、什么阈值算异常;确定谁改状态、是否人工确认;并明确是否纳入本期交付范围 | ### R7 明细:`robot-universal-review` 的部署口径 @@ -1022,8 +821,8 @@ LTS/CCE 文档对「接入时选哪种采集方式」给了一张明确的权衡 | **高基数** | 取值近乎唯一(request_id、trace_id、PR number 等),不能作 metrics label | | **log-agent** | CCE 云原生日志采集插件的旧名,基于 fluent-bit + OTel,以 DaemonSet 部署在每个节点 | | **default-stdout** | 该插件下的集群级日志采集策略名,内容为「全 ns 全容器 stdout」,业务日志进 LTS 的通道 | -| **聚合账号** | 汇聚方账号——是**跨账号**(基于 Organizations)而非「跨区域」。原设计通过 LTS 多账号日志汇聚中心 / AOM 多账号聚合实例承接各 Region 上报的日志与指标。**【2026-09-14】该路线已弃用**:指标侧改为**自建中心 Prometheus**(§4.7,不涉及华为云多账号机制);日志侧跨账号由**自建 Grafana 的 AK/SK 多数据源**解决(§4.7.8)。**本术语保留备查** | +| **聚合账号** | 汇聚方账号——是**跨账号**(基于 Organizations)而非「跨区域」。原设计通过 LTS 多账号日志汇聚中心 / AOM 多账号聚合实例承接各 Region 上报的日志与指标。**【2026-09-14】该路线已弃用**:指标侧改为**自建中心 Prometheus**(§4.7,不涉及华为云多账号机制);日志侧跨账号由**自建 Grafana 的 AK/SK 多数据源**解决(§4.6.4)。**本术语保留备查** | | **中心指标集群** | 【2026-09-14 新增】独立部署的 Prometheus 中心集群,17 个集群的 Agent 经 `remote_write` 汇入,承载**统一指标大盘与统一告警**。形态参考资源块 `ascend-ci-deployment/monitoring`,**但独立部署、不复用其实例**(§4.7) | | **Prometheus Agent** | `--agent` 模式,本地只抓取不存储,通过 `remote_write` 把数据推给中心——**汇聚发生在存储时,不是查询时** | -| **remote_write** | Prometheus 的远程写协议,本方案跨 Region 汇聚指标的**唯一机制**。⚠️ 资源块当前走**公网明文 HTTP**,生产不得照搬(§4.7.5) | +| **remote_write** | Prometheus 的远程写协议,本方案跨 Region 汇聚指标的**唯一机制**。⚠️ 资源块当前走**公网明文 HTTP**,生产不得照搬(§4.7.1) | | **SMN** | 消息通知服务,告警的通知出口。**SMN 是 Region 级资源**;**【2026-09-14】现在仅日志告警使用**——指标告警已统一在中心 Alertmanager,不经 SMN | From df945c266d840c89827d39a971cb862ba1c952aa Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 16:44:51 +0800 Subject: [PATCH 03/14] =?UTF-8?q?docs(design):=20=E8=A1=A5=E5=85=85=20?= =?UTF-8?q?=C2=A74.8=20=E5=85=B8=E5=9E=8B=E5=9C=BA=E6=99=AF=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=A4=84=E7=90=86=E8=B7=AF=E5=BE=84=EF=BC=88?= =?UTF-8?q?=E7=94=A8=E6=88=B7/=E7=A0=94=E5=8F=91=E5=8F=8C=E8=A7=86?= =?UTF-8?q?=E8=A7=92=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 §4.8,给出两个端到端场景: - §4.8.1 用户视角:MindSpore 评审机器人不响应 —— 贡献者查社区健康度大盘 即可判断「是机器人侧问题」而非自己 PR 的问题,不必盲猜或逐个私聊研发; 点明该场景必须靠 §4.7.1 黑盒拨测(服务内指标可能全绿) - §4.8.2 研发视角:CLA 签署失败 —— 告警(带 cluster)→ 指标大盘确认是服务 异常而非流量问题 → 同屏日志检索定位到数据库 → 带证据转运维 → 自动消警; 附「本场景覆盖了 §4.6 / §4.7 哪几条链路」映射表 - §4.8.3 两个场景在发现 / 定位 / 协作三个维度的共同变化 场景标注为目标态,依赖项回指 §6 R13(结构化解析)与 R21(社区大盘交付范围)。 同时收敛 §4.6.1 日志采集: - 采集侧「硬约束表」与「实测四类格式表」收敛为官方日志读写限制文档外链 (该组数字随 LTS 版本变动大,外链比转述更稳) - 随之修正 §6 R14 的引用:其证据来自被收敛的实测表,现改指 §4.6.2 结构化解析口径 Co-Authored-By: Claude Code --- ...00\346\234\257\350\256\276\350\256\241.md" | 103 +++++++++++++----- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 455b1d8..75f3b15 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -485,31 +485,7 @@ with _context.bind(community="openEuler", request_id="req-123"): **形态**:复用 CCE 云原生日志采集插件(`log-agent`,基于 fluent-bit,节点 DaemonSet)。集群级 `default-stdout` 策略已覆盖**全 ns 全容器 stdout**,铺开**无需新增采集策略**——服务只要写 stdout 就进 LTS。 -**采集范围先不收窄**(保持全量),噪音在**查询侧**按 `service` / `community` 字段过滤。用配额与存储换零运维复杂度:新服务自动纳入、**无采集窗口期**、不维护 ns 白名单。 - -**采集管道的硬约束**(直接影响接入与验收口径): - -| 约束 | 影响 | -| --- | --- | -| containerd 运行时下**容器 stdout 的多行配置不生效** | 契约的「**单行**扁平 JSON」是硬约束而非风格偏好——多行日志会在 LTS 里被拆成互不相关的多条 | -| 单条日志 **≤ 512 KB**;单节点约 **10000 条/秒** | Python / Java 契约允许 `error` 字段带完整 traceback,超长堆栈需截断 | -| stdout 为**非持久化存储** | 轮转清历史、Pod 终止回收、节点磁盘压力自动清理均可能丢日志——**日志是排障手段,不作审计 / 账本**,需在接入文档中明示 | -| 容器存活 **< 1 分钟可能采不到** | 短命 Job / 一次性任务的日志有丢失风险 | -| 每集群最多 **100 条**采集策略;变更 **1–3 分钟**生效 | 靠 `default-stdout` 一条策略覆盖全部服务,**不应为单服务新增策略** | -| **日志流名称全局唯一**(不能跨日志组重名) | 插件默认名 `stdout-{集群ID}` 天然唯一、无冲突;**若将来自定义日志流名,需自带唯一性前缀**,否则跨集群建不出来 | - -**实测:全量流内混着四类格式**(2026-09-11 现网抽样)——这是「结构化解析只能针对契约格式配」的直接依据,也是评估解析工作量的基线: - -| # | 来源 | 格式 | 时间基准 | -| --- | --- | --- | --- | -| 1 | `fluentd-*` / `log-agent-fluent-bit-*` | 基础设施文本 | 本地 | -| 2 | `repo-watcher`(机器人服务) | **logrus JSON** | UTC **秒精度** | -| 3 | `cve-manager`(Gin 服务) | **ANSI 着色文本**(`[1;34m[I][0m [hook.go:146]`) | 本地 CST | -| 4 | `istio-proxy`(ASM sidecar,**同 Pod 另一容器**) | **Envoy access log** | UTC 毫秒 | - -第 3 种把 ANSI 转义码写进了日志——**是给终端看的 logger,不是给日志系统看的**,正是本设计要消除的形态。第 4 种由 `allContainers: true` 带入,**按 ns 收窄挡不住**(sidecar 与业务容器同 Pod 同 ns)。 - -**两个采集侧待确认项**(详见 §6):`stdout` 与 `stderr` 是否都被采集(logrus 的 error / fatal 默认写 stderr,若只采 stdout 则告警最依赖的两级整体缺失);sidecar 日志是否保留(Envoy access log 每请求至少 1 条,会使日志量成倍放大,且其 UTC 时间基准与本地 CST 的业务日志不一致)。 +日志读写限制:https://support.huaweicloud.com/productdesc-lts/lts-0718.html #### 4.6.2 日志存储 @@ -685,6 +661,81 @@ with _context.bind(community="openEuler", request_id="req-123"): --- +### 4.8 典型场景的问题处理路径 + +本节给出**两个端到端场景**——一个从**用户**出发,一个从**研发**出发——串起 §4.6 日志链路与 §4.7 指标链路,说明这套建设落地后**「问题怎么被发现、怎么被定位」**与今天有什么不同。 + +> 两个场景描述的是**目标态**。凡依赖「日志流已配结构化解析」的环节,均受 §6 R13 制约——该前提不成立时,日志检索与日志告警路径需按 §4.6.2 / §4.6.3 重谈。场景一额外依赖 §4.7.5 社区大盘落地(其交付范围待定,见 §4.7.5 待定第 3 项 / §6 R21)。 + +#### 4.8.1 用户视角:MindSpore 社区的评审机器人不响应 + +**场景**:贡献者向 MindSpore 社区提交 PR,机器人评审迟迟没有响应。 + +**今天**(§1.1 描述的问题):贡献者**无法区分**三种可能——机器人挂了、PR 还在排队、还是自己的提交方式有问题。唯一的办法是到社区群里问,或**逐个私聊研发**「机器人是不是又挂了」;研发同样没有全局视图,被问到了才去登机器翻日志。 + +**建设后**: + +| 步骤 | 动作 | 用到的建设成果 | +| --- | --- | --- | +| 1 | 打开**社区健康度大盘** | §4.7.5 社区大盘(对外状态页) | +| 2 | 看到 **MindSpore 社区的「评审机器人」组件异常**,同屏其余组件正常 | 按社区聚合的**组件级**健康度 | +| 3 | 得出结论:**是机器人侧的问题,不是自己 PR 的问题**;同时看到异常落在哪一个社区 | 状态页回答的是「**哪块坏了**」,而非「为什么坏」 | +| 4 | 按状态页指引等待或上报,**不再逐个联系研发** | — | + +**为什么用户视角必须靠黑盒**:这个场景里服务**进程内的指标可能全绿**——问题出在外部路由 / 网关 / 凭据,§4.2–§4.3 的白盒埋点天然看不见这一层,**只有 §4.7.1 的探测 CronJob 能发现**。这正是社区大盘要**同时**接白盒与黑盒两类数据的原因(§4.7.5)。 + +**收益**:把「用户盲猜 + 骚扰研发」变成「用户自助查询状态页」;研发也从「是不是挂了」这类问询中解放出来。 + +#### 4.8.2 研发视角:CLA 签署失败 + +**场景**:`app-cla-server`(§4.3.1)出现 CLA 签署失败率上升。 + +**今天**:只能等**用户来报障**(「签不了 CLA」)。研发拿到的是一个模糊现象,需要登机器**逐个实例 grep 日志**,且很难判断问题落在**自己的代码**还是**下游数据库**。 + +```mermaid +flowchart LR + alert["① 告警:CLA 失败率超阈值
(自带 cluster / alertname)"] + dash["② 指标大盘
失败率↑、QPS 正常
→ 定位到服务"] + log["③ 日志检索(同屏)
connection refused
→ 定位到数据库"] + ops["④ 联系运维
带集群 / 社区 / 错误原文"] + recover["⑤ 服务恢复
告警自动消解"] + + alert --> dash --> log --> ops --> recover +``` + +| 步骤 | 动作 | 用到的建设成果 | +| --- | --- | --- | +| 1 | 收到 **CLA 失败率告警**(邮件 / 统一 webhook),告警自带 `cluster` / `alertname` 标签 | §4.7.3 中心 Alertmanager,`group_by: [cluster, alertname]` | +| 2 | 打开**指标大盘**,按 `service=app-cla-server` + `community=<受影响社区>` 筛选 | §4.7.4 指标大盘(G3:支持按 community 过滤 / 分组) | +| 3 | 看到**失败率曲线抬升、QPS 与延迟正常** → 排除流量突增与上游调用,**确认是服务自身异常** | §4.2–§4.3 SDK 埋点的业务指标 | +| 4 | 同屏切到**日志检索**,沿用同一组筛选条件,看到 `error: get account from db: connection refused` → **确认故障在数据库,而非代码逻辑** | §4.6.4 日志大盘(Grafana 同实例挂 LTS ×17,免多登) | +| 5 | 带着「哪个集群 / 哪个社区 / 什么错误原文」**直接联系运维**处理 DB | — | +| 6 | 运维处理后**失败率回落、告警自动消解**,无需人工消警 | §4.7.3 告警基于实时汇聚的指标 | + +**关键在第 3→4 步**:这是今天耗时最长、也最靠人肉的一段。建设后它变成**同一个 Grafana 界面内的连续下钻**——用指标定位「是哪个服务」,用日志定位「是什么原因」,且**跨社区 / 跨集群无需切换登录**(§4.6.4 的 AK/SK 多数据源)。 + +**本场景对 §4.6 / §4.7 的覆盖**: + +| 链路 | 在本场景中的作用 | +| --- | --- | +| §4.7.1 指标采集 | 服务指标上报到中心 | +| §4.7.3 指标告警 | 失败率超阈值触发,且带 `cluster` 定位来源 | +| §4.7.4 指标大盘 | 确认「是服务异常、不是流量问题」 | +| §4.6.4 日志大盘 | 确认「异常在数据库、不是代码」 | +| §4.6.2 日志存储(结构化解析) | 日志能按 `service` / `community` 检索的**前提**(⚠️ 受 R13 制约) | + +#### 4.8.3 两个场景的共同变化 + +| 维度 | 今天 | 建设后 | +| --- | --- | --- | +| **发现** | 等用户报障、靠人肉打听 | 告警主动推送 + 看板随时可查 | +| **定位** | 登机器逐个实例翻日志 | 大盘 → 日志**同屏下钻** | +| **协作** | 靠口头描述现象,信息在传递中衰减 | 带 label 与日志原文的**定位结论**,可直接转交运维 | + +三个维度的共同指向是同一个东西:**把「不可见的系统」变成「可查证的系统」**——用户不必猜,研发不必翻,跨团队协作不必靠复述。 + +--- + ## 5. 工作量预估 > **口径说明**:以下为**粗估**,单位人天,含开发 + 自测 + 联调,不含需求评审与排期等待。 @@ -770,7 +821,7 @@ with _context.bind(community="openEuler", request_id="req-123"): | R11 | ~~**告警规则逐 Region 各配一份**(4 Region × 日志/指标 ≈ 8 套)~~ → **【2026-09-14 收敛为日志单侧】**:**指标告警已在中心统一为 1 套**;**日志仍为 4 Region × 逐流 17 条**,SMN 主题亦每 Region 一个 | 阈值 / 规则变更需多点同步,易产生配置漂移;跨 Region 无单一配置入口 | 规则**模板化 / IaC 生成**(脚本或 Terraform 统一产出后下发各 Region),避免手工逐 Region 修改;接入文档中固化规则清单。**指标侧已无此问题** | | R12 | **【新增 · 2026-09-14】跨 Region 网络与安全合规**:各集群 → 中心集群的链路是本方案的**唯一硬门槛**(§4.7.1) | 不成立则**整个指标自建方案不成立**——比 R10 更严重(R10 只损失大盘,本项损失**全部指标**) | 试点阶段**最优先**确定网络方案(CC / 专线 / 公网 HTTPS);同步做传输加密与源 IP 收敛。⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090`) | | R13 | **【日志侧唯一卡点】全量默认流上能否配置云端结构化解析**(§4.6.2) | 配不上则**日志大盘与日志聚合告警整体不成立**(指标侧不受影响,两者已解耦)。退路:改自定义日志流(失去 CCE 控制台按 ns / 负载查询)或恢复按 ns 收窄 | **最高优先级**,试点期第一步。实测三问:① 配置动作本身是否被禁止(硬门槛);② 非 JSON 行解析失败后是保留原样还是被丢弃;③ 合法 JSON 但字段集不同的行(logrus / 第三方)解析成什么(只要不产生 `service` 字段即无害) | -| R14 | **同一日志流内并存两套格式**:obs-sdk 契约行与 `robot-framework-lib` 的 logrus JSON(后者无 `service` / `env` / `community`,且 `level: fatal`、`time` 秒精度均与契约冲突)(§4.6.1) | LTS 侧的检索 / 聚合 / 告警规则要同时兼容两种格式;且**不是过渡期现象**——框架那 121 处打点会长期保留,两套格式的共存是稳态 | 明确 LTS 侧怎么处理这两套(分别配解析?云端做字段归一化?只对 obs-sdk 行做索引、logrus 行仅全文检索?)。**这一点未定之前,「结构化解析配得上」仍不成立** | +| R14 | **同一日志流内并存两套格式**:obs-sdk 契约行与 `robot-framework-lib` 的 logrus JSON(后者无 `service` / `env` / `community`,且 `level: fatal`、`time` 秒精度均与契约冲突)(§4.6.2) | LTS 侧的检索 / 聚合 / 告警规则要同时兼容两种格式;且**不是过渡期现象**——框架那 121 处打点会长期保留,两套格式的共存是稳态 | 明确 LTS 侧怎么处理这两套(分别配解析?云端做字段归一化?只对 obs-sdk 行做索引、logrus 行仅全文检索?)。**这一点未定之前,「结构化解析配得上」仍不成立** | | R15 | **stdout 与 stderr 是否都被采集**未确认——现网检到的业务日志 `pathFile` 是 `/stderr.log`(logrus 的 error / fatal 默认写 stderr)(§4.6.1) | 若采集策略只覆盖 stdout,则 **error / fatal 级日志整体缺失**——而告警最依赖的恰是这两级 | 试点期确认 `default-stdout` 策略对 stderr 的覆盖情况 | | R16 | **`allContainers: true` 会把注入的 Sidecar 一并采进来**——现网样本中 `istio-proxy` 的 Envoy access log 占 2/3,且**按 ns 收窄挡不住**(与业务容器同 Pod 同 ns)(§4.6.1) | 三处:① 日志量被乘性放大(每请求至少 1 条),此前容量估算只算了业务日志;② 时间基准不一致(sidecar 走 UTC、业务容器走本地 CST);③ 是否保留 Envoy access log 需定夺——它与 SDK 的 `obs_http_server_*` 高度重叠 | 确认插件是否支持**按容器名排除**(`namespaces` 只管 ns、`excludePodLabels` 只管 Pod label,二者都够不着「排除 Pod 内某个容器」);据此重估日志量 | | R17 | 「26 仓」清单可能变化:现网 pod 的 `appName: cve-manager`,而清单里写的是 `cve-manager-ng`(§4.3.1) | 若为两个服务,铺开范围随之变 | 澄清二者是否同一服务;一并确认 §5.4 列出的 4 个部署口径存疑的服务是否纳入本次铺开 | From b1b3fe4787570f44e53e39e33fb997829e54ff89 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 17:00:44 +0800 Subject: [PATCH 04/14] =?UTF-8?q?docs(design):=20=C2=A72.1=20=E5=BB=BA?= =?UTF-8?q?=E8=AE=BE=E7=9B=AE=E6=A0=87=E8=A1=A5=E5=85=85=E4=B8=A4=E4=B8=AA?= =?UTF-8?q?=E4=BB=A3=E8=A1=A8=E6=80=A7=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把 §4.8 的两个典型场景提炼为「视角 / 场景 / 目标态下」三行表,放在 G1–G5 目标表之后,让「目标达成后落到具体的人身上是什么样」在开篇即可见: - 用户视角:查社区健康度大盘即知是机器人侧异常,不盲猜、不打扰研发 - 研发视角:告警先于用户报障,大盘 → 日志同屏下钻定位到数据库 并标注用户视角依赖的 §4.7.5 社区大盘不在 G1–G5 之列、交付范围待定(§6 R21)。 Co-Authored-By: Claude Code --- ...6\346\212\200\346\234\257\350\256\276\350\256\241.md" | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 75f3b15..1573b46 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -52,6 +52,15 @@ | G4 | 关键服务配置告警规则(高错误率 / 宕机 / 资源超阈值)并打通通知到负责人 | 验收 5 | | G5 | 硬件级指标复用云上,不重复建设 | 验收 1 | +**目标达成后,落到具体的人身上是这样两件事**(完整处理路径见 §4.8.1 / §4.8.2): + +| 视角 | 场景 | 目标态下 | +| --- | --- | --- | +| **用户** | MindSpore 社区评审机器人不响应 | 查**社区健康度大盘**即知是机器人侧异常、落在哪一个社区——**不盲猜、不逐个私聊研发** | +| **研发** | CLA 签署失败(`app-cla-server`) | **告警先于用户报障**(自带 `cluster`)→ 指标大盘确认是服务自身异常 → 同屏日志检索定位到数据库 → 带证据转运维处理 | + +> ⚠️ 用户视角依赖 §4.7.5 社区健康度大盘,而它**不在 G1–G5 之列**(§1.1 已将其列为要解决的问题);是否纳入本期交付待定,见 §6 R21。 + ### 2.2 设计原则(方案阶段已定) 1. **薄封装,不自研 instrumentation**。每语言 1 个薄 SDK,内部引用各语言官方库(Go→`client_golang`、Python→`prometheus-client`、Java→`micrometer`+Actuator、Node→`prom-client`),SDK 只做装配:中间件挂载 + 通用字段注入 + 命名对齐 + 一行初始化。 From feaae137f53e85d440bcc416306d8963f7fc75bb Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 17:04:23 +0800 Subject: [PATCH 05/14] =?UTF-8?q?docs(design):=20=E7=A4=BE=E5=8C=BA?= =?UTF-8?q?=E5=81=A5=E5=BA=B7=E5=BA=A6=E5=A4=A7=E7=9B=98=E7=AB=8B=E4=B8=BA?= =?UTF-8?q?=20G6=20=E5=BB=BA=E8=AE=BE=E7=9B=AE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上游验收标准 1–5 未覆盖对外状态页,故 G6 标注为「本方案新增」,验收口径 需与需求方补充确认。跟随性一致性修复: - §2.1 新增 G6 目标行;用户视角场景的依赖改为挂 G6 - §4.7.5 待定第 3 项由「是否纳入本期交付范围」改为「验收口径」 - §4.8 场景一的依赖项改指 G6 - §5.2 增设 G6 工作量行(标记待估,不计入小计);§5.4 汇总标注未含 G6 注:本次提交同时带入作者手工精简移除的 §6 R21 一行,未在代码层面回滚。 Co-Authored-By: Claude Code --- ...12\200\346\234\257\350\256\276\350\256\241.md" | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 1573b46..246342b 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -51,6 +51,7 @@ | G3 | 建立业务级监控大盘,重点服务健康度集中可见,**支持按 community 维度过滤/分组** | 验收 4 | | G4 | 关键服务配置告警规则(高错误率 / 宕机 / 资源超阈值)并打通通知到负责人 | 验收 5 | | G5 | 硬件级指标复用云上,不重复建设 | 验收 1 | +| G6 | 建立**社区健康度大盘**(对外状态页),按社区聚合展示重点组件(评审机器人 / 账号 / CLA 等)的健康度 | **本方案新增**——上游验收标准 1–5 未覆盖对外状态页,口径待与需求方补充确认 | **目标达成后,落到具体的人身上是这样两件事**(完整处理路径见 §4.8.1 / §4.8.2): @@ -59,7 +60,7 @@ | **用户** | MindSpore 社区评审机器人不响应 | 查**社区健康度大盘**即知是机器人侧异常、落在哪一个社区——**不盲猜、不逐个私聊研发** | | **研发** | CLA 签署失败(`app-cla-server`) | **告警先于用户报障**(自带 `cluster`)→ 指标大盘确认是服务自身异常 → 同屏日志检索定位到数据库 → 带证据转运维处理 | -> ⚠️ 用户视角依赖 §4.7.5 社区健康度大盘,而它**不在 G1–G5 之列**(§1.1 已将其列为要解决的问题);是否纳入本期交付待定,见 §6 R21。 +> 用户视角依赖 **G6 社区健康度大盘**(§4.7.5)。该目标**超出上游验收标准 1–5**——§1.1 已把它列为要解决的问题,但上游验收项未覆盖对外状态页,验收口径需与需求方补充确认;其判定口径与发布流程仍待定(§4.7.5 待定)。 ### 2.2 设计原则(方案阶段已定) @@ -666,7 +667,7 @@ with _context.bind(community="openEuler", request_id="req-123"): 1. **组件级健康的判定口径**——几个指标、什么阈值算「异常」,需与各社区运维对齐; 2. **异常事件的发布流程**——谁改状态、是否人工确认;状态页的价值在可信,不能纯靠自动抖动; -3. **是否纳入本期交付范围**——§1.1 已把它列为要解决的问题,而 §2.1 的 G1–G5 尚未覆盖它,需明确。 +3. **验收口径**——已在本方案中列为 **G6**(§2.1),但**上游验收标准 1–5 未覆盖对外状态页**,需与需求方补充确认验收方式。 --- @@ -674,7 +675,7 @@ with _context.bind(community="openEuler", request_id="req-123"): 本节给出**两个端到端场景**——一个从**用户**出发,一个从**研发**出发——串起 §4.6 日志链路与 §4.7 指标链路,说明这套建设落地后**「问题怎么被发现、怎么被定位」**与今天有什么不同。 -> 两个场景描述的是**目标态**。凡依赖「日志流已配结构化解析」的环节,均受 §6 R13 制约——该前提不成立时,日志检索与日志告警路径需按 §4.6.2 / §4.6.3 重谈。场景一额外依赖 §4.7.5 社区大盘落地(其交付范围待定,见 §4.7.5 待定第 3 项 / §6 R21)。 +> 两个场景描述的是**目标态**。凡依赖「日志流已配结构化解析」的环节,均受 §6 R13 制约——该前提不成立时,日志检索与日志告警路径需按 §4.6.2 / §4.6.3 重谈。场景一额外依赖 §4.7.5 社区大盘(即 §2.1 的 **G6**,其判定口径与发布流程仍待定,见 §4.7.5 待定)。 #### 4.8.1 用户视角:MindSpore 社区的评审机器人不响应 @@ -775,7 +776,10 @@ flowchart LR | Grafana 大盘(服务健康度 + community 维度 + 日志检索面板) | 6~9 | | 中心 Alertmanager 指标告警规则 + LTS 日志告警(17 条)+ SMN 通知 | 4~6 | | 容量与成本核算(series 量 / 磁盘 / 跨 Region 流量) | 1~2 | -| **小计** | **25~40** | +| **社区健康度大盘(G6)**——数据聚合 + 状态页 + 发布流程 | ⌛ **待估**(未计入小计) | +| **小计** | **25~40**(未含 G6) | + +> ⚠️ **G6 社区健康度大盘的人天尚未估算**,未计入上表与 §5.4 合计。它是本方案新增的目标(上游验收标准 1–5 未覆盖),落地形态(静态页 + 定时拉取 / 轻量服务)与判定口径均未定(§4.7.5 待定),**待这两项确认后再单独估算**。 > **⚠️ 【2026-09-14】本节已随指标路线改为自建中心而重估**(原 17~27 人天基于 AOM 托管路线)。**成本上升是真实的**——自建多出「中心集群搭建」「Agent 铺开」「跨 Region 网络」「安全加固」四项,而省掉的只有「采样点计费评估」一项。**这是换取统一大盘 + 统一告警所付的显式代价**(§4.7.2)。 @@ -806,6 +810,8 @@ flowchart LR | C · 26 仓全量铺开与验收 | 30.5~49 | #2063 | | **合计** | **63.5~98.5** | 约 **3.1~4.8 人月** | +> ⚠️ 上表**未含 G6 社区健康度大盘**(人天待估,见 §5.2),故本方案的总工作量会高于此合计。 + **估算的最大不确定性**在 C 的「非标准框架待评估」三项(9~15 人天)与 Java 组(6~9 人天)。建议: 1. 试点完成后用实测数据回填单价; 2. 三项非标准框架服务(mailman / copr_docker / hotopic-mining)与 Node 的 etherpad-lite **先做技术验证再报价**,避免按经验值低估; @@ -837,7 +843,6 @@ flowchart LR | R18 | **各 Region 实际版本文档里的 LTS 写入上限未核**——本文的 100 MB/s 是软限制,旧版文档写的是 5 MB/s + 25K 条/秒,差异极大(§4.6.2) | 容量规划若引用本文数字会严重偏差 | **按各 Region 实际版本文档核,不要沿用本文数字** | | R19 | **SMN 的 Region 级约束下「统一接收端」方案待确认**:主题 URN 含区域名(`urn:smn:::`),跨 Region 只能各建主题(§4.6.3) | 影响告警收敛与值班轮转 | 确认 ① 每 Region 各建主题 + 订阅同一接收端是否满足现有运维习惯;② SMN 订阅用户的跨区域统一管理(仅国内站点支持)香港是否适用;③ 接收端走邮件组还是自建 webhook 接收服务 | | R20 | **中心集群的 HA 未验证**:`replicas: 2` + pod 反亲和下的去重与告警行为(§4.7.2) | 中心是单点,挂了全网指标断线 | 试点期验证。若将来上 VictoriaMetrics,必须同时配 `-dedup.minScrapeInterval`,否则两个副本各写一份、**数据翻倍** | -| R21 | **社区大盘(§4.7.5)的判定口径与发布流程未定** | 影响对外可视性;纯自动抖动会损害状态页的可信度 | 与各社区运维对齐「组件级健康」用哪几个指标、什么阈值算异常;确定谁改状态、是否人工确认;并明确是否纳入本期交付范围 | ### R7 明细:`robot-universal-review` 的部署口径 From 8bebbe69d6303f2d484c747c05cb63769627907b Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 17:06:21 +0800 Subject: [PATCH 06/14] =?UTF-8?q?docs(design):=20G6=20=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E9=AA=8C=E6=94=B6=E7=BC=96=E5=8F=B7=E5=86=99=E4=B8=BA=206?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上游 #1938 的验收标准为 1–5(子任务 #2063 亦按「5 条验收标准」逐条打勾), 社区健康度大盘排在 6,故写「验收 6(本方案新增)」并保留「本方案新增」限定, 避免读者误以为 #1938 中已存在第 6 条。§2.1 注与 §4.7.5 待定第 3 项同步写明。 Co-Authored-By: Claude Code --- ...\276\346\212\200\346\234\257\350\256\276\350\256\241.md" | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 246342b..0802e43 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -51,7 +51,7 @@ | G3 | 建立业务级监控大盘,重点服务健康度集中可见,**支持按 community 维度过滤/分组** | 验收 4 | | G4 | 关键服务配置告警规则(高错误率 / 宕机 / 资源超阈值)并打通通知到负责人 | 验收 5 | | G5 | 硬件级指标复用云上,不重复建设 | 验收 1 | -| G6 | 建立**社区健康度大盘**(对外状态页),按社区聚合展示重点组件(评审机器人 / 账号 / CLA 等)的健康度 | **本方案新增**——上游验收标准 1–5 未覆盖对外状态页,口径待与需求方补充确认 | +| G6 | 建立**社区健康度大盘**(对外状态页),按社区聚合展示重点组件(评审机器人 / 账号 / CLA 等)的健康度 | **验收 6(本方案新增)** | **目标达成后,落到具体的人身上是这样两件事**(完整处理路径见 §4.8.1 / §4.8.2): @@ -60,8 +60,6 @@ | **用户** | MindSpore 社区评审机器人不响应 | 查**社区健康度大盘**即知是机器人侧异常、落在哪一个社区——**不盲猜、不逐个私聊研发** | | **研发** | CLA 签署失败(`app-cla-server`) | **告警先于用户报障**(自带 `cluster`)→ 指标大盘确认是服务自身异常 → 同屏日志检索定位到数据库 → 带证据转运维处理 | -> 用户视角依赖 **G6 社区健康度大盘**(§4.7.5)。该目标**超出上游验收标准 1–5**——§1.1 已把它列为要解决的问题,但上游验收项未覆盖对外状态页,验收口径需与需求方补充确认;其判定口径与发布流程仍待定(§4.7.5 待定)。 - ### 2.2 设计原则(方案阶段已定) 1. **薄封装,不自研 instrumentation**。每语言 1 个薄 SDK,内部引用各语言官方库(Go→`client_golang`、Python→`prometheus-client`、Java→`micrometer`+Actuator、Node→`prom-client`),SDK 只做装配:中间件挂载 + 通用字段注入 + 命名对齐 + 一行初始化。 @@ -667,7 +665,7 @@ with _context.bind(community="openEuler", request_id="req-123"): 1. **组件级健康的判定口径**——几个指标、什么阈值算「异常」,需与各社区运维对齐; 2. **异常事件的发布流程**——谁改状态、是否人工确认;状态页的价值在可信,不能纯靠自动抖动; -3. **验收口径**——已在本方案中列为 **G6**(§2.1),但**上游验收标准 1–5 未覆盖对外状态页**,需与需求方补充确认验收方式。 +3. **验收口径**——已在本方案中列为 **G6 / 验收 6**(§2.1),但**上游 #1938 的验收标准 1–5 未覆盖对外状态页**,需与需求方补充确认验收方式。 --- From fe90062cfe07848a8eac8cd1f325354a7b4bdb9e Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 17:23:33 +0800 Subject: [PATCH 07/14] =?UTF-8?q?docs(design):=20=C2=A73.1=20=E5=A2=9E?= =?UTF-8?q?=E8=A1=A5=E6=98=87=E8=85=BE=20CI=20=E8=B5=84=E6=BA=90=E5=9D=97?= =?UTF-8?q?=E7=8E=B0=E6=9C=89=E6=9E=B6=E6=9E=84=E5=9B=BE=EF=BC=88=E5=BD=A2?= =?UTF-8?q?=E6=80=81=E5=85=88=E4=BE=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按 ascend-ci-deployment 仓 monitoring/ 与 argocd/clusters/ 的实际配置绘制 存量系统的逻辑架构,非本方案:多 Region(中心 beijing + 业务 12 集群 / 4 个 Region)、两条上报路径(Agent remote_write / CronJob push → Pushgateway)、 中心 Prometheus + Alertmanager + Pushgateway 三件套、告警邮件链路、看板。 同时记录两处与正文第 3、4 点的出入,待核对: - 仓库中 Grafana 已是完整定义(含 2 块 dashboard 与 ArgoCD Application), 与「资源块 Grafana 未启用」的说法冲突 - 「数据中台看板」在仓库中无任何引用,存在性待确认 Co-Authored-By: Claude Code --- ...00\346\234\257\350\256\276\350\256\241.md" | 80 ++++++++++++------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 0802e43..84651c3 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -138,6 +138,55 @@ flowchart TB 3. **大盘 —— 自建 Grafana**:**一个**实例同时挂中心 Prometheus(指标)+ 17 个日志数据源(日志),见 §4.7.4 / §4.6.4。 4. **已有现成闭环可参照**:**昇腾 CI 资源块**已跑通 **多集群 CronJob + Agent 上报 → 中心 Prometheus 存储 → Alertmanager 告警 → 邮件接收** 的完整链路,本方案的**指标侧与之同构**(见 §4.7.2)。⚠️ 该闭环**不含大盘**(资源块 Grafana 未启用,用的是外部 DataStat 看板),故第 3 点的自建 Grafana 属**本方案新增**,不能当作资源块已验证的能力。 +#### 3.1.1 形态先例:昇腾 CI 资源块**现有**架构 + +> ⚠️ 本图描述的是**已跑通的存量系统**(`ascend-ci-deployment` 仓 `monitoring/`),**不是本方案要建的东西**。本方案建成后的形态见 §3.2。 + +```mermaid +flowchart TB + subgraph BIZ["业务集群 ×12 · 跨 4 个 Region
cn-north-12 ×4 | guizhou 贵州 ×6 | hongkong 香港 ×1 | wulanchabu 乌兰察布 ×1"] + direction LR + AG["Prometheus Agent
--agent(本地只抓不存)
scrape kube-state-metrics / node-exporter"] + CJ["拨测 CronJob
github-probe · cloud-account · cert-expiry …
产出 Prometheus text 格式"] + end + + subgraph CTR["中心监控集群 · infra-cn4-x86-common-cluster(beijing)· ns infra-monitoring"] + direction TB + PGW["Pushgateway
LoadBalancer + 持久化"] + PROM["Prometheus
TSDB + PrometheusRule 评估
replicas 1 · 保留 15d · 100Gi"] + AM["Alertmanager
告警路由 + 邮件模板
replicas 1"] + end + + subgraph VIEW["视图(只读)"] + direction LR + GRAF["Grafana
数据源 = 中心 Prometheus"] + DS["数据中台看板
(外部系统)"] + end + + AG -->|"① remote_write"| PROM + CJ -->|"② HTTP push"| PGW + PGW -->|"scrape"| PROM + PROM -->|"规则触发"| AM + AM -->|"SMTP"| MAIL["运维团队
HTML 邮件"] + PROM --> GRAF + PROM --> DS +``` + +**两条上报路径**是本图的关键,也是本方案要复用的形态: + +| 路径 | 机制 | 数据来源 | +| --- | --- | --- | +| **① 采集** | 各集群 **Prometheus Agent**(`--agent`,本地只抓不存)`scrape` 后 `remote_write` 到中心 | 系统 / 基础设施指标(kube-state-metrics、node-exporter) | +| **② 拨测** | 各集群 **CronJob** 跑探测脚本,产出的指标 **push 到中心 Pushgateway**,再由中心 Prometheus `scrape` | 服务进程之外的东西:外部 API 可达性、云账号余额、证书有效期、共享盘 | + +**存量系统的量化口径**(2026-09-15 核对 `ascend-ci-deployment` 仓 `monitoring/` 与 `argocd/clusters/`): + +- **规模**:中心 **1 个**(`infra-cn4-x86-common-cluster`,`beijing`,ns `infra-monitoring`)+ 业务 **12 个 / 4 个 Region**(`cn-north-12` ×4、`guizhou` ×6、`hongkong` ×1、`wulanchabu` ×1)——**跨 Region 是既成事实,不是待验证假设**; +- **中心参数**:Prometheus `replicas: 1` / `retention: 15d` / `enableRemoteWriteReceiver: true` / 100Gi PVC;Alertmanager `replicas: 1`; +- **通知投递**:Alertmanager 经 **QQ 邮箱 SMTP** 发 HTML 邮件到运维团队。 + +> ⚠️ **待核对:资源块 Grafana 是否真的「未启用」**。上方第 4 点称「资源块 Grafana 未启用,用的是外部 DataStat 看板」,但 `ascend-ci-deployment` 仓中 Grafana **已是一套完整定义**——`monitoring/grafana/` 含 `deployment` / `service` / `pvc` / 数据源(中心 Prometheus)/ 2 块真实 dashboard(`CI-Network-Overview`、`Pod-Network-Traffic`),且 `argocd/clusters/infra-cn4-x86-common-cluster/monitoring-grafana.yaml` 有对应 ArgoCD Application(README 的 Application 清单未列它,属 README 陈旧)。**若 Grafana 实际已启用,第 3 点「自建 Grafana 属本方案新增」的立论需改写。** 另:「数据中台看板」在上述仓库中**无任何引用**,其存在性与数据来源需另行确认。 + ### 3.2 部署与流程视图 ```mermaid @@ -493,32 +542,24 @@ with _context.bind(community="openEuler", request_id="req-123"): **形态**:复用 CCE 云原生日志采集插件(`log-agent`,基于 fluent-bit,节点 DaemonSet)。集群级 `default-stdout` 策略已覆盖**全 ns 全容器 stdout**,铺开**无需新增采集策略**——服务只要写 stdout 就进 LTS。 -日志读写限制:https://support.huaweicloud.com/productdesc-lts/lts-0718.html - #### 4.6.2 日志存储 **形态:LTS,各 Region 自持**,不自建 ES。日志组按集群划分,每集群 1 个 `k8s-log-{集群ID}`,容器日志写入 `stdout-{集群ID}` 流——**共 17 组 / 17 流**。 -**⚠️ LTS 无「跨日志组检索」**:搜索、快速查询及其列表的 API 全部以 `groups/{group_id}/topics/{topic_id}` 限定在**单个日志组 / 流**内,控制台也是逐组进入详情页。因此 **17 个 `k8s-log-{集群ID}` 不会自动汇成一个检索入口**,统一入口只能靠 Grafana 多数据源拼装(§4.6.4)。 +**⚠️ LTS 无「跨日志组检索」**:搜索、快速查询及其列表的 API 全部以 `groups/{group_id}/topics/{topic_id}` 限定在**单个日志组 / 流**内,控制台也是逐组进入详情页。统一入口只能靠 Grafana 多数据源拼装。 -**结构化解析**:只针对 **obs-sdk 契约格式**配 **JSON 规则**。非 JSON 行(基础设施文本 / ANSI 着色文本 / Envoy access log)解析失败后**原样保留**,不污染结构化字段。 +**结构化解析**:只针对 **obs-sdk 契约格式**配 **JSON 规则**。 **容量口径**:单流 **100 MB/s** 为**软限制**(官方标 `Not mandatory`,超限不是拒绝写入,而是**不保证 QoS / 可能丢日志**,且**无补发语义**);另有单流 **500 次/秒**写入次数上限。⚠️ 该数字随版本变化大(旧版文档写的是 5 MB/s + 25K 条/秒),**容量规划须按各 Region 实际版本文档核,不要引用本文数字**。 **其他约束**:一个日志流只能配**一种**结构化方式(ICAgent 结构化**或**云端结构化,切换**必须先删除**原配置);**结构化配置修改只对新写入生效**,历史数据不按新规则重新解析;云端结构化解析**消耗 LTS 算力**,官方称未来按日志量收取「日志加工流量费」。 +日志读写限制:https://support.huaweicloud.com/productdesc-lts/lts-0718.html + #### 4.6.3 日志告警 **形态:仍走华为云 LTS 原生,各 Region 逐流配置(17 条)**,出口经**各 Region 的 SMN 主题** → 同一接收端(邮件组 / 统一 webhook 接收服务)。 -**为什么统一不了**:LTS **没有跨日志组 / 流的检索能力**,一条告警规则无法绑定多个日志流——该限制已与华为云团队确认。因此**明确接受「无跨集群联合告警」**:像「某服务在所有社区的某类失败总数」这类跨集群联合条件**写不出来**。 - -**SMN 是 Region 级资源**(URN 形如 `urn:smn:::`),故「统一」不在同一个主题,而在**各 Region 主题订阅同一接收端**。 - -**不迁到 Grafana Alerting**:LTS-Grafana 插件虽支持 Grafana 自身的告警功能,但采用它会让 **Grafana 进入告警链路**,与 §4.7.4「Grafana 只做看板、故障域解耦」相悖——Grafana 一旦进告警链路,其 HA 就从「可选」变成「必须」。**待逐流维护真的成为负担时再评估。** - -> **⚠️ 前置依赖**:日志聚合告警依赖 LTS 的 **SQL 统计类型**,而 SQL 依赖**结构化解析配得上**(§4.6.2)。**若试点期这一步验证不通过,本节的日志告警选型需整体重谈**——优先级高于其他事项。 - #### 4.6.4 日志大盘 **形态:并入自建 Grafana(1 个实例),挂 LTS 数据源 ×17**(每个数据源绑一个日志流 ID,各带一套 AK/SK 凭证)。 @@ -565,21 +606,6 @@ with _context.bind(community="openEuler", request_id="req-123"): - 候选路径:**云连接 CC**(按带宽计费、不过公网)/ **专线** / **HTTPS + 公网 EIP**。 - ⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090` + Basic Auth)。**该链路不成立则整个中心方案不成立。** -**黑盒拨测:白盒埋点覆盖不了的那一半** - -§4.2–§4.3 的 SDK 埋点是**白盒**——服务自己吐「我做了什么」,天然看不见**服务进程之外**的东西。以下类别只能靠**外部主动探测**覆盖,需在铺开时另行补,不在本 SDK 范围内: - -| 类别 | 例子 | 为什么埋点覆盖不了 | -| --- | --- | --- | -| 外部依赖可达性 | 依赖的 GitCode / GitHub API 通不通、下游服务在不在 | 请求发生在服务进程之外 | -| 凭据可用性 | 能否从 Vault 读到 token、凭据是否临期 | 读取动作在启动期,且失败即进程退出,无日志可依 | -| 端到端可用性 | 服务整体还能不能正常响应一个真实请求 | 服务内指标全绿但外部路由 / 网关挂了,埋点看不出来 | - -资源块已有的**探测 CronJob + Pushgateway** 基建可直接复用:CronJob 跑探测脚本 → push 到 Pushgateway → Prometheus 抓取 → `ProbeStale` 规则抓「指标过期」。**两个关键点**: - -1. **`ProbeStale` 是必备的**。拨测有内生盲区——探测脚本自己挂了,指标不再更新,而「指标不再更新」看起来和「一切正常」一样。必须有一条规则专门抓指标过期。 -2. **push 失败要重试后显式失败**。参考资源块做法:重试 6 次 × 45 秒吸收网络抖动,全失败则 Job 退出非零,让失败本身可被发现。 - #### 4.7.2 指标存储 **形态:1 个独立中心 Prometheus 集群**(kube-prometheus-stack,放独立中心集群)。17 个集群的 Agent 经 `remote_write` 汇入同一实例,`enableRemoteWriteReceiver: true`。 From 0e161d30d7222e761cd24c91d9530c7706b6bb47 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 17:31:31 +0800 Subject: [PATCH 08/14] =?UTF-8?q?docs(design):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E5=9D=97=E8=A7=86=E5=9B=BE=E6=8C=89=20Grafana=20=E5=AE=9A?= =?UTF-8?q?=E6=80=A7=EF=BC=8C=E4=BF=AE=E6=AD=A3=E7=9B=B8=E5=85=B3=E7=AB=8B?= =?UTF-8?q?=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 核实 ascend-ci-deployment 后确认资源块 Grafana 已是一套完整定义(含 2 块 dashboard 与 ArgoCD Application),此前「Grafana 未启用、用的是外部 DataStat 看板」的说法不成立,据此修正四处: - §3.1 第 4 点:闭环补上 Grafana 大盘,删去「不含大盘」的限定 - §3.1.1 图:视图层只保留 Grafana,去掉数据中台看板节点 - §3.1.1 注:改为「资源块 Grafana 与本方案的差别」——数据源从中心 Prometheus 扩展到再加 17 个 LTS 日志数据源,本方案独有工作量在此 - §4.7.2:不可照搬项由两处减为一处,只留公网明文 HTTP(TLS 方案在 kustomization.yaml 中被注释、标为 Phase 2) Co-Authored-By: Claude Code --- ...6\346\212\200\346\234\257\350\256\276\350\256\241.md" | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 84651c3..1812b7f 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -136,7 +136,7 @@ flowchart TB 1. **日志 —— 复用,不新建**:继续用各集群**现有的日志流**(CCE 云原生日志采集插件为每集群建的 `k8s-log-*` 组),本方案只改**日志的内容格式**(结构化 JSON + 契约字段),**不动采集管道**。 2. **指标 —— 新建**:26 个服务目前均未暴露 `/metrics`,需从零接入;存储侧**自建 Prometheus 实例**(独立中心集群,见 §4.7),不走华为云托管。 3. **大盘 —— 自建 Grafana**:**一个**实例同时挂中心 Prometheus(指标)+ 17 个日志数据源(日志),见 §4.7.4 / §4.6.4。 -4. **已有现成闭环可参照**:**昇腾 CI 资源块**已跑通 **多集群 CronJob + Agent 上报 → 中心 Prometheus 存储 → Alertmanager 告警 → 邮件接收** 的完整链路,本方案的**指标侧与之同构**(见 §4.7.2)。⚠️ 该闭环**不含大盘**(资源块 Grafana 未启用,用的是外部 DataStat 看板),故第 3 点的自建 Grafana 属**本方案新增**,不能当作资源块已验证的能力。 +4. **已有现成闭环可参照**:**昇腾 CI 资源块**已跑通 **多集群 CronJob + Agent 上报 → 中心 Prometheus 存储 → Grafana 大盘 + Alertmanager 告警 → 邮件接收** 的完整链路,本方案的**指标侧与之同构**(架构图见 §3.1.1,参数对照见 §4.7.2)。 #### 3.1.1 形态先例:昇腾 CI 资源块**现有**架构 @@ -158,9 +158,7 @@ flowchart TB end subgraph VIEW["视图(只读)"] - direction LR GRAF["Grafana
数据源 = 中心 Prometheus"] - DS["数据中台看板
(外部系统)"] end AG -->|"① remote_write"| PROM @@ -169,7 +167,6 @@ flowchart TB PROM -->|"规则触发"| AM AM -->|"SMTP"| MAIL["运维团队
HTML 邮件"] PROM --> GRAF - PROM --> DS ``` **两条上报路径**是本图的关键,也是本方案要复用的形态: @@ -185,7 +182,7 @@ flowchart TB - **中心参数**:Prometheus `replicas: 1` / `retention: 15d` / `enableRemoteWriteReceiver: true` / 100Gi PVC;Alertmanager `replicas: 1`; - **通知投递**:Alertmanager 经 **QQ 邮箱 SMTP** 发 HTML 邮件到运维团队。 -> ⚠️ **待核对:资源块 Grafana 是否真的「未启用」**。上方第 4 点称「资源块 Grafana 未启用,用的是外部 DataStat 看板」,但 `ascend-ci-deployment` 仓中 Grafana **已是一套完整定义**——`monitoring/grafana/` 含 `deployment` / `service` / `pvc` / 数据源(中心 Prometheus)/ 2 块真实 dashboard(`CI-Network-Overview`、`Pod-Network-Traffic`),且 `argocd/clusters/infra-cn4-x86-common-cluster/monitoring-grafana.yaml` 有对应 ArgoCD Application(README 的 Application 清单未列它,属 README 陈旧)。**若 Grafana 实际已启用,第 3 点「自建 Grafana 属本方案新增」的立论需改写。** 另:「数据中台看板」在上述仓库中**无任何引用**,其存在性与数据来源需另行确认。 +> **资源块 Grafana 与本方案的差别**:仓库中 `monitoring/grafana/` 是一套完整定义(`deployment` / `service` / `pvc` / 数据源 = 中心 Prometheus / 2 块 dashboard),**数据源只有中心 Prometheus**(系统与拨测指标)。本方案的 Grafana 除中心 Prometheus 外,还要额外挂 **17 个 LTS 日志数据源**(§4.6.4),且服务对象是**业务指标**(§4.7.4)——**形态可照抄,日志数据源的接入量是本方案独有的工作量**。 ### 3.2 部署与流程视图 @@ -616,7 +613,7 @@ with _context.bind(community="openEuler", request_id="req-123"): | **保留期** | 一期**本地存储 30d,不上 VictoriaMetrics**——先跑一两个月看真实 series 增长再定,避免过早引入额外组件 | | **安全** | `enableRemoteWriteReceiver: true` + 公网端口 = **拿到 basic auth 就能往中心写任意指标**。生产至少要做:强凭据 + 轮换、源 IP 白名单 / 安全组收敛、只放行 `/api/v1/write`。**独立集群的好处正是把风险面收敛到这一个集群上** | -**形态先例**:昇腾 CI 资源块在 [ascend-ci-deployment/monitoring](https://github.com/opensourceways/ascend-ci-deployment) 已跑通同一形态(中心 Prometheus + Alertmanager + 各集群 Agent `remote_write`),**本方案指标侧与之同构**。两处**不可照搬**:资源块走**公网明文 HTTP + Basic Auth**(见 §4.7.1);其 Grafana **未启用**(用的是外部 DataStat 看板),故本方案的自建 Grafana 属新增能力。 +**形态先例**:昇腾 CI 资源块在 [ascend-ci-deployment/monitoring](https://github.com/opensourceways/ascend-ci-deployment) 已跑通同一形态(中心 Prometheus + Alertmanager + 各集群 Agent `remote_write`),**本方案指标侧与之同构**(其架构图见 §3.1.1)。一处**不可照搬**:资源块走**公网明文 HTTP + Basic Auth**——其 TLS 方案(`prometheus-remote-write-certificate` / `-ingress`、`pushgateway-certificate` / `-ingress`)在 `kustomization.yaml` 中**被注释、标为 Phase 2**,待 cert-manager 就绪才启用。本方案必须自行解决传输加密(见 §4.7.1)。 **为什么弃用 AOM 路线**: From 4aec1af46a4ae4904db30c861a8822fb8d9989c5 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 17:34:28 +0800 Subject: [PATCH 09/14] =?UTF-8?q?docs(design):=20=E5=8E=BB=E6=8E=89=20?= =?UTF-8?q?=C2=A74.7.2=20=E7=9A=84=E3=80=8C=E5=BD=A2=E6=80=81=E5=85=88?= =?UTF-8?q?=E4=BE=8B=E3=80=8D=E6=AE=B5=E8=90=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 同一论点已由 §3.1 第 4 点、§3.1.1 图注、§4.7.1 的 ⚠️ 三处承载,§4.7.2 此处冗余。 注:本次提交同时带入作者手工精简移除的 §3.1.1「存量系统的量化口径」条目 与「资源块 Grafana 与本方案的差别」注,未作回滚。 Co-Authored-By: Claude Code --- ...346\212\200\346\234\257\350\256\276\350\256\241.md" | 10 ---------- 1 file changed, 10 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 1812b7f..ef967ce 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -176,14 +176,6 @@ flowchart TB | **① 采集** | 各集群 **Prometheus Agent**(`--agent`,本地只抓不存)`scrape` 后 `remote_write` 到中心 | 系统 / 基础设施指标(kube-state-metrics、node-exporter) | | **② 拨测** | 各集群 **CronJob** 跑探测脚本,产出的指标 **push 到中心 Pushgateway**,再由中心 Prometheus `scrape` | 服务进程之外的东西:外部 API 可达性、云账号余额、证书有效期、共享盘 | -**存量系统的量化口径**(2026-09-15 核对 `ascend-ci-deployment` 仓 `monitoring/` 与 `argocd/clusters/`): - -- **规模**:中心 **1 个**(`infra-cn4-x86-common-cluster`,`beijing`,ns `infra-monitoring`)+ 业务 **12 个 / 4 个 Region**(`cn-north-12` ×4、`guizhou` ×6、`hongkong` ×1、`wulanchabu` ×1)——**跨 Region 是既成事实,不是待验证假设**; -- **中心参数**:Prometheus `replicas: 1` / `retention: 15d` / `enableRemoteWriteReceiver: true` / 100Gi PVC;Alertmanager `replicas: 1`; -- **通知投递**:Alertmanager 经 **QQ 邮箱 SMTP** 发 HTML 邮件到运维团队。 - -> **资源块 Grafana 与本方案的差别**:仓库中 `monitoring/grafana/` 是一套完整定义(`deployment` / `service` / `pvc` / 数据源 = 中心 Prometheus / 2 块 dashboard),**数据源只有中心 Prometheus**(系统与拨测指标)。本方案的 Grafana 除中心 Prometheus 外,还要额外挂 **17 个 LTS 日志数据源**(§4.6.4),且服务对象是**业务指标**(§4.7.4)——**形态可照抄,日志数据源的接入量是本方案独有的工作量**。 - ### 3.2 部署与流程视图 ```mermaid @@ -613,8 +605,6 @@ with _context.bind(community="openEuler", request_id="req-123"): | **保留期** | 一期**本地存储 30d,不上 VictoriaMetrics**——先跑一两个月看真实 series 增长再定,避免过早引入额外组件 | | **安全** | `enableRemoteWriteReceiver: true` + 公网端口 = **拿到 basic auth 就能往中心写任意指标**。生产至少要做:强凭据 + 轮换、源 IP 白名单 / 安全组收敛、只放行 `/api/v1/write`。**独立集群的好处正是把风险面收敛到这一个集群上** | -**形态先例**:昇腾 CI 资源块在 [ascend-ci-deployment/monitoring](https://github.com/opensourceways/ascend-ci-deployment) 已跑通同一形态(中心 Prometheus + Alertmanager + 各集群 Agent `remote_write`),**本方案指标侧与之同构**(其架构图见 §3.1.1)。一处**不可照搬**:资源块走**公网明文 HTTP + Basic Auth**——其 TLS 方案(`prometheus-remote-write-certificate` / `-ingress`、`pushgateway-certificate` / `-ingress`)在 `kustomization.yaml` 中**被注释、标为 Phase 2**,待 cert-manager 就绪才启用。本方案必须自行解决传输加密(见 §4.7.1)。 - **为什么弃用 AOM 路线**: | 维度 | AOM Prometheus for CCE(原路线) | 自建中心 Prometheus(现路线) | From e0de371b269b8061c78d85c635d15c763fad4647 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 17:46:27 +0800 Subject: [PATCH 10/14] =?UTF-8?q?docs(design):=20=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E4=B8=8A=E6=B8=B8=20#1938=20=E6=96=B0=E5=A2=9E=E7=9A=84?= =?UTF-8?q?=E9=AA=8C=E6=94=B6=E6=A0=87=E5=87=86=E7=AC=AC=206=20=E6=9D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1938 正文「### 验收标准」由 5 条增至 6 条(新增「服务健康度大盘」), 文档随之把 G6 的「验收 6(本方案新增)」改为「验收 6」, 并把 §5.2 注中「上游验收标准 1–5 未覆盖」更新为已同步的事实。 注:本次提交同时带入作者手工精简移除的若干段落,未作回滚: §4.7.2 AOM 对比表 3 行与 VictoriaMetrics 去重提示、§4.7.5「数据来源」块与待定第 3 项。 Co-Authored-By: Claude Code --- ...\200\346\234\257\350\256\276\350\256\241.md" | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index ef967ce..13d7091 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -51,7 +51,7 @@ | G3 | 建立业务级监控大盘,重点服务健康度集中可见,**支持按 community 维度过滤/分组** | 验收 4 | | G4 | 关键服务配置告警规则(高错误率 / 宕机 / 资源超阈值)并打通通知到负责人 | 验收 5 | | G5 | 硬件级指标复用云上,不重复建设 | 验收 1 | -| G6 | 建立**社区健康度大盘**(对外状态页),按社区聚合展示重点组件(评审机器人 / 账号 / CLA 等)的健康度 | **验收 6(本方案新增)** | +| G6 | 建立**社区健康度大盘**(对外状态页),按社区聚合展示重点组件(评审机器人 / 账号 / CLA 等)的健康度 | **验收 6** | **目标达成后,落到具体的人身上是这样两件事**(完整处理路径见 §4.8.1 / §4.8.2): @@ -611,14 +611,11 @@ with _context.bind(community="openEuler", request_id="req-123"): | --- | --- | --- | | **跨 Region 统一大盘** | ❌ 官方已确认**多实例聚合不支持跨 Region** | ✅ 天然成立(就是**一个**实例) | | **跨 Region 统一告警** | ❌ 需逐 Region 各配一套(4 套规则) | ✅ **一条规则覆盖全部集群** | -| **Organizations / OU 前提** | **强依赖**(多账号聚合要求同组织 / OU) | ✅ **完全不依赖**——`remote_write` 只需网络可达 + 鉴权 | | **跨账号** | 走华为云多账号机制 | ✅ 每个 Agent 各带一套凭证即可,**与账号归属无关** | -| **单实例集群数上限** | 官方未给出,17 集群分配有风险 | ✅ 无此约束(仅受 Prometheus 自身容量限制) | | **运维** | 云托管,**零运维** | ❌ **自行运维**(HA / 容量 / 升级 / 备份) | | **网络** | 零改造 | ❌ **需打通各集群 → 中心**并解决合规 | -| **成本** | 按采样点计费 | 自建集群底座 + 存储 + **跨 Region 流量费** | -**取舍**:用**运维与网络成本**,换**统一大盘、统一告警、以及摆脱 Organizations / OU 前提**。 +**取舍**:用**运维与网络成本**,换**统一大盘、统一告警前提**。 **容量粗算**(`磁盘 ≈ 保留秒数 × 每秒样本数 × 1.7 B`,按 `scrapeInterval: 60s`): @@ -629,8 +626,6 @@ with _context.bind(community="openEuler", request_id="req-123"): **series 数是这里唯一的未知量**,取决于 26 个服务的指标设计——**尤其不要把高基数塞进 label**(§4.1.3 铁律:`request_id` / `trace_id` / `span_id` 禁止当 label)。 -> ⚠️ **若将来必须上 VictoriaMetrics**:资源块里 VM 的角色**不是「全量长期存储」,而是「少数需要长期趋势的指标的冷存储」**(只接 `custom_npu_.*`),照此办即可(保留期 > 30d 才上)。**一个坑**:中心 Prometheus `replicas: 2` 后,**两个副本会各写一份相同数据到 VM**,必须在 vminsert / vmselect 侧配 `-dedup.minScrapeInterval` 去重,否则**数据翻倍、查询结果异常**。 - #### 4.7.3 指标告警 **形态:统一在中心 Alertmanager**——数据已经汇聚,**一条规则覆盖全部 17 集群**,用 `group_by: [cluster, alertname]` 区分来源。**不经 SMN**(SMN 仅日志告警仍用)。 @@ -667,18 +662,12 @@ with _context.bind(community="openEuler", request_id="req-123"): **目标**:一眼看到**整体与各组件**(从重点微服务中挑选,如评审机器人、账号、CLA 等)是否正常、异常落在哪一段,替代当前「靠零散告警与人肉打听拼凑判断」。 -**数据来源**: - -- **白盒**:§4.2–§4.3 的 SDK 指标(服务自报的 QPS / 错误率); -- **黑盒**:§4.7.1 的探测 CronJob 指标——**端到端可用性这类「服务内指标全绿、但外部路由 / 网关挂了」的情况只有拨测能发现**,而它恰好最直接回答「这个组件还能不能用」。 - **与 Grafana 解耦**:状态页是**对外**入口,不应把内部 Grafana 直接暴露出去(多租户、安全域、可用性要求都不同)。落地形态(静态页 + 定时拉取 / 轻量服务)另议。 **待定**: 1. **组件级健康的判定口径**——几个指标、什么阈值算「异常」,需与各社区运维对齐; 2. **异常事件的发布流程**——谁改状态、是否人工确认;状态页的价值在可信,不能纯靠自动抖动; -3. **验收口径**——已在本方案中列为 **G6 / 验收 6**(§2.1),但**上游 #1938 的验收标准 1–5 未覆盖对外状态页**,需与需求方补充确认验收方式。 --- @@ -790,7 +779,7 @@ flowchart LR | **社区健康度大盘(G6)**——数据聚合 + 状态页 + 发布流程 | ⌛ **待估**(未计入小计) | | **小计** | **25~40**(未含 G6) | -> ⚠️ **G6 社区健康度大盘的人天尚未估算**,未计入上表与 §5.4 合计。它是本方案新增的目标(上游验收标准 1–5 未覆盖),落地形态(静态页 + 定时拉取 / 轻量服务)与判定口径均未定(§4.7.5 待定),**待这两项确认后再单独估算**。 +> ⚠️ **G6 社区健康度大盘的人天尚未估算**,未计入上表与 §5.4 合计。它原为本方案新增的目标,**2026-09-15 已同步为上游 [#1938](https://github.com/opensourceways/backlog/issues/1938) 的验收标准第 6 条**;落地形态(静态页 + 定时拉取 / 轻量服务)与判定口径均未定(§4.7.5 待定),**待这两项确认后再单独估算**。 > **⚠️ 【2026-09-14】本节已随指标路线改为自建中心而重估**(原 17~27 人天基于 AOM 托管路线)。**成本上升是真实的**——自建多出「中心集群搭建」「Agent 铺开」「跨 Region 网络」「安全加固」四项,而省掉的只有「采样点计费评估」一项。**这是换取统一大盘 + 统一告警所付的显式代价**(§4.7.2)。 From 6f441d58713f429a3edd989df315fe496c5d1695 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 18:00:20 +0800 Subject: [PATCH 11/14] =?UTF-8?q?docs(design):=20G6=20=E7=A4=BE=E5=8C=BA?= =?UTF-8?q?=E5=81=A5=E5=BA=B7=E5=BA=A6=E5=A4=A7=E7=9B=98=E8=AE=A1=E5=85=A5?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E9=87=8F=E9=A2=84=E4=BC=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §5.2 增列 G6 人天 7~12(判定口径 1~2 / 数据聚合 2~3 / 状态页与对外入口 3~5 / 发布流程 1~2),子任务 B 小计 25~40 → 32~52; §5.4 合计 63.5~98.5 → 70.5~110.5(约 3.5~5.5 人月),并去掉「未含 G6」的说明。 注:本次提交同时带入作者手工精简移除的 §4.7.5 待定第 2 项、§4.8 开篇说明、 §4.8.1「为什么必须靠黑盒」段与 §4.8.3 整节,未作回滚。 Co-Authored-By: Claude Code --- ...00\346\234\257\350\256\276\350\256\241.md" | 29 +++---------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 13d7091..6c138eb 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -667,7 +667,6 @@ with _context.bind(community="openEuler", request_id="req-123"): **待定**: 1. **组件级健康的判定口径**——几个指标、什么阈值算「异常」,需与各社区运维对齐; -2. **异常事件的发布流程**——谁改状态、是否人工确认;状态页的价值在可信,不能纯靠自动抖动; --- @@ -675,8 +674,6 @@ with _context.bind(community="openEuler", request_id="req-123"): 本节给出**两个端到端场景**——一个从**用户**出发,一个从**研发**出发——串起 §4.6 日志链路与 §4.7 指标链路,说明这套建设落地后**「问题怎么被发现、怎么被定位」**与今天有什么不同。 -> 两个场景描述的是**目标态**。凡依赖「日志流已配结构化解析」的环节,均受 §6 R13 制约——该前提不成立时,日志检索与日志告警路径需按 §4.6.2 / §4.6.3 重谈。场景一额外依赖 §4.7.5 社区大盘(即 §2.1 的 **G6**,其判定口径与发布流程仍待定,见 §4.7.5 待定)。 - #### 4.8.1 用户视角:MindSpore 社区的评审机器人不响应 **场景**:贡献者向 MindSpore 社区提交 PR,机器人评审迟迟没有响应。 @@ -692,8 +689,6 @@ with _context.bind(community="openEuler", request_id="req-123"): | 3 | 得出结论:**是机器人侧的问题,不是自己 PR 的问题**;同时看到异常落在哪一个社区 | 状态页回答的是「**哪块坏了**」,而非「为什么坏」 | | 4 | 按状态页指引等待或上报,**不再逐个联系研发** | — | -**为什么用户视角必须靠黑盒**:这个场景里服务**进程内的指标可能全绿**——问题出在外部路由 / 网关 / 凭据,§4.2–§4.3 的白盒埋点天然看不见这一层,**只有 §4.7.1 的探测 CronJob 能发现**。这正是社区大盘要**同时**接白盒与黑盒两类数据的原因(§4.7.5)。 - **收益**:把「用户盲猜 + 骚扰研发」变成「用户自助查询状态页」;研发也从「是不是挂了」这类问询中解放出来。 #### 4.8.2 研发视角:CLA 签署失败 @@ -734,16 +729,6 @@ flowchart LR | §4.6.4 日志大盘 | 确认「异常在数据库、不是代码」 | | §4.6.2 日志存储(结构化解析) | 日志能按 `service` / `community` 检索的**前提**(⚠️ 受 R13 制约) | -#### 4.8.3 两个场景的共同变化 - -| 维度 | 今天 | 建设后 | -| --- | --- | --- | -| **发现** | 等用户报障、靠人肉打听 | 告警主动推送 + 看板随时可查 | -| **定位** | 登机器逐个实例翻日志 | 大盘 → 日志**同屏下钻** | -| **协作** | 靠口头描述现象,信息在传递中衰减 | 带 label 与日志原文的**定位结论**,可直接转交运维 | - -三个维度的共同指向是同一个东西:**把「不可见的系统」变成「可查证的系统」**——用户不必猜,研发不必翻,跨团队协作不必靠复述。 - --- ## 5. 工作量预估 @@ -776,12 +761,8 @@ flowchart LR | Grafana 大盘(服务健康度 + community 维度 + 日志检索面板) | 6~9 | | 中心 Alertmanager 指标告警规则 + LTS 日志告警(17 条)+ SMN 通知 | 4~6 | | 容量与成本核算(series 量 / 磁盘 / 跨 Region 流量) | 1~2 | -| **社区健康度大盘(G6)**——数据聚合 + 状态页 + 发布流程 | ⌛ **待估**(未计入小计) | -| **小计** | **25~40**(未含 G6) | - -> ⚠️ **G6 社区健康度大盘的人天尚未估算**,未计入上表与 §5.4 合计。它原为本方案新增的目标,**2026-09-15 已同步为上游 [#1938](https://github.com/opensourceways/backlog/issues/1938) 的验收标准第 6 条**;落地形态(静态页 + 定时拉取 / 轻量服务)与判定口径均未定(§4.7.5 待定),**待这两项确认后再单独估算**。 - -> **⚠️ 【2026-09-14】本节已随指标路线改为自建中心而重估**(原 17~27 人天基于 AOM 托管路线)。**成本上升是真实的**——自建多出「中心集群搭建」「Agent 铺开」「跨 Region 网络」「安全加固」四项,而省掉的只有「采样点计费评估」一项。**这是换取统一大盘 + 统一告警所付的显式代价**(§4.7.2)。 +| **社区健康度大盘(G6)**——判定口径 + 数据聚合 + 状态页 + 发布流程 | 7~12 | +| **小计** | **32~52** | ### 5.3 子任务 C —— 26 仓全量铺开与验收(#2063) @@ -806,11 +787,9 @@ flowchart LR | 子任务 | 人天 | 对应 issue | | --- | --- | --- | | A · SDK 建设与试点接入 | 8~9.5 | #2061 | -| B · 底座搭建与大盘告警 | 25~40 | #2062 | +| B · 底座搭建与大盘告警 | 32~52 | #2062 | | C · 26 仓全量铺开与验收 | 30.5~49 | #2063 | -| **合计** | **63.5~98.5** | 约 **3.1~4.8 人月** | - -> ⚠️ 上表**未含 G6 社区健康度大盘**(人天待估,见 §5.2),故本方案的总工作量会高于此合计。 +| **合计** | **70.5~110.5** | 约 **3.5~5.5 人月** | **估算的最大不确定性**在 C 的「非标准框架待评估」三项(9~15 人天)与 Java 组(6~9 人天)。建议: 1. 试点完成后用实测数据回填单价; From 079d52826d6f4794f369e9bdf534b531a17625a7 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 18:49:51 +0800 Subject: [PATCH 12/14] =?UTF-8?q?docs(design):=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=C2=A74.8=20Prometheus=20=E6=90=AD=E5=BB=BA=20/=20=C2=A74.9=20G?= =?UTF-8?q?rafana=20=E7=9C=8B=E6=9D=BF=E6=90=AD=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - §4.8 中心集群与 Agent 搭建:kustomize + ArgoCD 目录组织、kube-prometheus-stack 关键 values(replicas 2 / retention 30d / enableRemoteWriteReceiver / out-of-order-ingestion / 100Gi csi-disk)、入口与安全、17 集群 Agent 的采集与 remote_write 配置、搭建顺序(先通网络再铺 Agent)。 - §4.9 Grafana 搭建:清单组成、数据源(中心 Prometheus + LTS ×17)、 dashboard 代码化(ConfigMap provisioning)、看板清单。 - 原 §4.8 及其子节后移为 §4.10 / §4.10.1 / §4.10.2,§2.1 的引用同步更新。 配置取值均取自 ascend-ci-deployment/monitoring 实测清单。 Co-Authored-By: Claude Code --- ...00\346\234\257\350\256\276\350\256\241.md" | 99 ++++++++++++++++++- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 6c138eb..0c0ca2c 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -53,7 +53,7 @@ | G5 | 硬件级指标复用云上,不重复建设 | 验收 1 | | G6 | 建立**社区健康度大盘**(对外状态页),按社区聚合展示重点组件(评审机器人 / 账号 / CLA 等)的健康度 | **验收 6** | -**目标达成后,落到具体的人身上是这样两件事**(完整处理路径见 §4.8.1 / §4.8.2): +**目标达成后,落到具体的人身上是这样两件事**(完整处理路径见 §4.10.1 / §4.10.2): | 视角 | 场景 | 目标态下 | | --- | --- | --- | @@ -670,11 +670,102 @@ with _context.bind(community="openEuler", request_id="req-123"): --- -### 4.8 典型场景的问题处理路径 +### 4.8 Prometheus 中心集群与 Agent 搭建 + +指标底座要搭**两处**:一处**中心**(1 个),一处**每个业务集群**(17 个)。都走 **kustomize + ArgoCD**——目录组织照抄资源块:`base/` 放公共清单,`config-for-<集群>/` 放该集群的 patch 与 Secret,一份 Application 对应一个集群。 + +#### 4.8.1 中心集群(1 处) + +**位置**:**独立中心集群**(新申请,不与任何业务集群复用),ns `infra-monitoring`——与 Alertmanager、Grafana(§4.9)同 ns,走集群内 DNS。 + +**组件**:一个 `kube-prometheus-stack` 出齐 Prometheus + Alertmanager + Operator,**关掉 chart 自带的其他组件**——`grafana.enabled: false`(Grafana 独立部署,§4.9)、`kubeStateMetrics` / `nodeExporter` / `kubeApiServer` / `kubelet` / `kubeControllerManager` / `kubeScheduler` / `kubeProxy` / `kubeEtcd` 全关(基础设施指标复用云上,§1.3 G5),`defaultRules` 里对应规则一并禁用。 + +| values 关键项 | 取值 | 理由 | +| --- | --- | --- | +| `prometheusSpec.replicas` | **2** + pod 反亲和 | 中心是单点,挂了全网指标断线(§4.7.2) | +| `retention` | **30d** | 一期本地存储,先看真实 series 增长再定;>30d 才考虑 VictoriaMetrics | +| `scrapeInterval` | 60s | 与 Agent 侧一致,§4.7.2 的容量公式按此口径 | +| `enableRemoteWriteReceiver` | **true** | 接收 17 集群 Agent 的写入 | +| `enableFeatures` / `tsdb.outOfOrderTimeWindow` | `out-of-order-ingestion` / `10m` | 跨 Region 写入乱序是常态,不开会丢点 | +| `storageSpec` | `storageClassName: csi-disk`、**100Gi** | 规格按 §4.7.2 公式核算后回填 | +| `service.type` | `LoadBalancer` + ELB ID | 对外入口,供各集群 Agent 写入 | + +**入口与安全**(§4.7.2 的安全项落到配置): + +- ⚠️ **不照搬资源块的公网明文 HTTP**——资源块当前是 `http://:9090` + Basic Auth,而其 TLS 清单(`prometheus-remote-write-certificate` / `-ingress`)在 `kustomization.yaml` 中**被注释、标为 Phase 2**。本方案**搭建时就要上 HTTPS**(§4.7.1),不留这个尾巴。 +- 凭据走 Secret 挂**文件**(`password_file`),不进 values 明文;配合源 IP 白名单 / 安全组收敛,**只放行 `/api/v1/write`**。 +- 把暴露面收敛到这一个集群,正是独立中心相对 AOM 的好处(§4.7.2)。 + +**PrometheusRule** 与 **Alertmanager 配置**(含邮件模板 / 接收人)也集中在中心定义,一条规则覆盖全部 17 集群,`group_by: [cluster, alertname]` 区分来源(§4.7.3)。 + +#### 4.8.2 各业务集群 Agent(17 处) + +**形态**:`prometheus --agent`(**本地只抓不存**,只有 WAL),`scrape` 完 `remote_write` 到中心。每个集群一套,用 `config-for-<集群>/` 打 patch 注入本集群的 `cluster` label 与写入凭据。 + +| 配置项 | 做法 | +| --- | --- | +| **采集目标** | ServiceMonitor 选各服务 `/metrics`(按 ns / label 选,**服务侧无需改配置**);基础设施指标仍复用云上,Agent 不重复抓 | +| **来源标注** | `cluster` label 是告警与大屏 `group_by` 的依据,在 Agent 侧统一打上 | +| **写入地址** | 中心 Prometheus 的写入端点,**HTTPS**(见 §4.8.1) | +| **鉴权** | `basic_auth` + `password_file` 挂 Secret,**每集群一套凭据**——跨账号场景各带各的,与账号归属无关(§4.7.2) | +| **写入瘦身** | 用 `write_relabel_configs` drop 无用 label(资源块的做法是 drop `container` / `container_id` / `uid`)——直接省中心磁盘与跨 Region 流量 | +| **资源限制** | 常驻但轻量,按集群规模给 requests / limits | + +**可照抄资源块**:`prometheus-agent-deployment.yaml`、`prometheus-agent-configmap.yaml`、RBAC / SA 清单,以及「`base/` + `config-for-*/`」的目录组织。**不可照抄**的只有写入地址与鉴权方式。 + +#### 4.8.3 搭建顺序 + +1. 中心集群起 `kube-prometheus-stack`(Prometheus + Alertmanager),开 `enableRemoteWriteReceiver`; +2. **先把跨 Region 网络打通再铺 Agent**——它是本方案唯一硬门槛(§4.7.1),链路不通则后面全白做; +3. 选 **1 个集群**试点 Agent:验证 `remote_write` 写入、`cluster` label、带宽与容量; +4. 批量铺 17 集群(脚本化生成 kustomize 目录 / ArgoCD Application); +5. 用实测 series 量**回填**中心磁盘规格与保留期(§4.7.2)。 + +--- + +### 4.9 Grafana 看板搭建 + +**形态**:**1 个** Grafana 实例,与中心 Prometheus **同集群同 ns**、**独立 Deployment**(§4.7.4)。一个实例同时挂**中心 Prometheus + 17 个 LTS 数据源**,指标大盘与日志大盘同屏(§4.6.4)。 + +#### 4.9.1 部署 + +清单组成照抄资源块 `monitoring/grafana/`,用 kustomize 管: + +| 清单 | 作用 | 资源块取值(可直接参照) | +| --- | --- | --- | +| `deployment.yaml` | 实例本体 | `replicas: 1`、`strategy: Recreate`(PVC 是 RWO)、`runAsNonRoot`、**镜像钉版本** | +| `pvc.yaml` | 只存 Grafana 自身状态 | **10Gi**——dashboard 走 ConfigMap provisioning,不占 PVC(§4.7.4) | +| `service.yaml` | 入口 | `LoadBalancer`,**复用中心 Prometheus 的那个 ELB、端口分开**,省一个 ELB | +| `grafana-datasource.yaml` | 数据源 provisioning | 见 §4.9.2 | +| `grafana-dashboard-provider.yaml` | dashboard 加载器 | 从 `/etc/grafana/dashboards/json` 读;`disableDeletion: true` + `editable: false` | +| admin Secret | 管理员密码 | Secret 注入,不进 values | + +#### 4.9.2 数据源 + +| 数据源 | 类型 | 接入方式 | +| --- | --- | --- | +| **中心 Prometheus** | prometheus | 集群内 DNS(`http://prometheus-kube-prometheus-prometheus.infra-monitoring.svc:9090`)、`access: proxy`、`isDefault: true`——零网络成本、零延迟(§4.7.4) | +| **LTS 日志流 ×17** | 华为云 LTS 插件 | **每个数据源绑一条日志流、各带一套 AK/SK**(§4.6.4)——正因为凭证是数据源级的,一个实例才能横跨 N 个账号、**免多登** | + +> ⚠️ LTS 侧的前提是**日志流已配结构化解析**(§4.6.2)——该前提不成立时,数据源挂上了也查不出结构化字段。 + +#### 4.9.3 看板 + +**dashboard 用代码管**:JSON 放 Git,经 `configMapGenerator` 生成 ConfigMap 挂进容器——**改看板 = 提 PR**,可 review、可回滚。资源块放了 2 块(`CI-Network-Overview` / `Pod-Network-Traffic`),本方案要做的: + +| 看板 | 内容 | 依据 | +| --- | --- | --- | +| **服务健康度大盘** | QPS / 错误率 / 延迟 / 资源,按 `community` 过滤 / 分组(默认全选、不强制) | §4.7.4 | +| **日志检索** | 与指标**同屏**;`community` / `service` **必选**筛选,排除基础设施 / sidecar / 第三方日志 | §4.6.4 | +| **聚合 / 对比** | 跨社区横向对比(默认全选) | §4.6.4 | + +**「看」与「告警」解耦**:Grafana 只做看板,**不进告警链路**——告警走中心 Alertmanager(§4.7.3),Grafana 挂了只是看不了图。 + +### 4.10 典型场景的问题处理路径 本节给出**两个端到端场景**——一个从**用户**出发,一个从**研发**出发——串起 §4.6 日志链路与 §4.7 指标链路,说明这套建设落地后**「问题怎么被发现、怎么被定位」**与今天有什么不同。 -#### 4.8.1 用户视角:MindSpore 社区的评审机器人不响应 +#### 4.10.1 用户视角:MindSpore 社区的评审机器人不响应 **场景**:贡献者向 MindSpore 社区提交 PR,机器人评审迟迟没有响应。 @@ -691,7 +782,7 @@ with _context.bind(community="openEuler", request_id="req-123"): **收益**:把「用户盲猜 + 骚扰研发」变成「用户自助查询状态页」;研发也从「是不是挂了」这类问询中解放出来。 -#### 4.8.2 研发视角:CLA 签署失败 +#### 4.10.2 研发视角:CLA 签署失败 **场景**:`app-cla-server`(§4.3.1)出现 CLA 签署失败率上升。 From 178a4e10009aaca917da34c46af0b673a5b75b0b Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 19:21:27 +0800 Subject: [PATCH 13/14] =?UTF-8?q?docs(design):=20=C2=A76=20=E9=A3=8E?= =?UTF-8?q?=E9=99=A9=E8=A1=A8=E6=94=B6=E6=95=9B=EF=BC=8CR12=20=E5=B9=B6?= =?UTF-8?q?=E5=85=A5=20R2=20=E5=B9=B6=E5=88=A0=E9=99=A4=2011=20=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - R12(跨 Region 网络与安全合规 = 唯一硬门槛)并入 R2,R2 由「采集链路可达性」 扩为「采集链路 + 网络可达性 + 安全合规」; - 删除 R4 / R9 / R10 / R11 / R12 / R13 / R15 / R16 / R17 / R18 / R19; - 保留 R1 / R2 / R3 / R5 / R6 / R7 / R8 / R14 / R20(编号保持不重排)。 §4.10.2 覆盖链路映射表中指向已删 R13 的引用,改为直接写明前提 「日志流已配结构化解析」。 Co-Authored-By: Claude Code --- ...12\200\346\234\257\350\256\276\350\256\241.md" | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index 0c0ca2c..a721674 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -818,7 +818,7 @@ flowchart LR | §4.7.3 指标告警 | 失败率超阈值触发,且带 `cluster` 定位来源 | | §4.7.4 指标大盘 | 确认「是服务异常、不是流量问题」 | | §4.6.4 日志大盘 | 确认「异常在数据库、不是代码」 | -| §4.6.2 日志存储(结构化解析) | 日志能按 `service` / `community` 检索的**前提**(⚠️ 受 R13 制约) | +| §4.6.2 日志存储(结构化解析) | 日志能按 `service` / `community` 检索的**前提**(⚠️ 前提:日志流已配结构化解析) | --- @@ -894,24 +894,13 @@ flowchart LR | # | 项 | 影响 | 处置 | | --- | --- | --- | --- | | R1 | ~~**15 天存储窗口**:AOM 指标默认存 15 天(超期按量计费)~~ → **【2026-09-14 转换】** 自建中心 Prometheus **保留期可自定**(建议 30d),不再受 15 天约束(§4.7.2) | ~~故障回溯窗口可能不足~~ **风险消除**;但**磁盘容量成为新的约束** | 按 §4.7.2 公式核算 series 量 → 定保留期与磁盘规格;>30d 需求再上 VictoriaMetrics | -| R2 | ~~ServiceMonitor 在 4 Region 的可用性~~ → **【转换】各集群 Agent → 中心集群的采集链路与网络可达性**未经生产验证 | 指标可能采不上——**且这次没有云托管兜底** | 试点阶段**逐集群**验证 Agent 与 `remote_write` 连通性;网络方案见 §4.7.1 | +| R2 | ~~ServiceMonitor 在 4 Region 的可用性~~ → **【转换 · 2026-09-14 扩容】各集群 Agent → 中心集群的采集链路、网络可达性与安全合规**未经生产验证,**这是本方案的唯一硬门槛**(§4.7.1) | 指标可能采不上——**且这次没有云托管兜底**;链路不成立则**整个指标自建方案不成立**(损失的是全部指标) | 试点阶段**最优先**确定网络方案(CC / 专线 / 公网 HTTPS)并**逐集群**验证 Agent 与 `remote_write` 连通性;同步做传输加密与源 IP 收敛。⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090`) | | R3 | ~~自定义指标采样点计费量级未知~~ → **【转换】自建中心的容量与成本**:series 量、磁盘、**跨 Region 流量费**三项均未测算 | 26 仓铺开成本不可控(原为按量计费,现为**自建资源 + 出网流量**) | 试点阶段实测 17 集群真实 series 量后外推(§4.7.2 已给容量公式);跨 Region 流量按所选网络方案(CC 按带宽 / 公网按流量)分别核算 | -| R4 | log-agent 在生产集群的配置是否与预览集群一致未确认 | 结构化日志可能采不到字段 | 铺开前抽查生产集群插件配置 | | R5 | **Java SDK 无兜底**,未注入环境变量时 4 个必填字段整个缺失 | 违反契约,Java 服务日志字段不全 | 单独立项修复(加 hostname / `unknown` 兜底 + 补 UT,断言落在真实 JSON 输出上) | | R6 | Python / Node / Java 未打 tag,Java 进私服路径未验证 | 消费方无法按版本引用 | 随各语言首次接入服务时一并处理 | | R7 | **#1938 覆盖范围表的机器人部分与实际部署不符** | 影响 community 取值与大盘分维度 | 见下 | | R8 | Java SDK 的 logstash-logback-encoder / jackson-core 在 SDK 内为 `provided` | 接入服务运行时必须自带,否则日志不可用 | 接入文档中明确要求,或改为传递依赖 | -| R9 | 请求级 community 的安全约束(禁止裸读 URL/Header) | 误用会导致 community 被外部可控 | 代码 review 检查点 + 接入文档强调 | -| R10 | ~~**第 ④ 层汇聚的两条前提均未确证**:Organizations / OU 归属、跨 Region 是否成立~~ → **【2026-09-14 消解】** 自建中心**不涉及华为云多账号机制**,两条前提整个不再需要(§4.7.2) | ~~汇聚层整体不成立,失去统一大盘~~ **风险消除** | 无需处置 | -| R11 | ~~**告警规则逐 Region 各配一份**(4 Region × 日志/指标 ≈ 8 套)~~ → **【2026-09-14 收敛为日志单侧】**:**指标告警已在中心统一为 1 套**;**日志仍为 4 Region × 逐流 17 条**,SMN 主题亦每 Region 一个 | 阈值 / 规则变更需多点同步,易产生配置漂移;跨 Region 无单一配置入口 | 规则**模板化 / IaC 生成**(脚本或 Terraform 统一产出后下发各 Region),避免手工逐 Region 修改;接入文档中固化规则清单。**指标侧已无此问题** | -| R12 | **【新增 · 2026-09-14】跨 Region 网络与安全合规**:各集群 → 中心集群的链路是本方案的**唯一硬门槛**(§4.7.1) | 不成立则**整个指标自建方案不成立**——比 R10 更严重(R10 只损失大盘,本项损失**全部指标**) | 试点阶段**最优先**确定网络方案(CC / 专线 / 公网 HTTPS);同步做传输加密与源 IP 收敛。⚠️ **不得照搬资源块的公网明文 HTTP**(`http://113.44.182.82:9090`) | -| R13 | **【日志侧唯一卡点】全量默认流上能否配置云端结构化解析**(§4.6.2) | 配不上则**日志大盘与日志聚合告警整体不成立**(指标侧不受影响,两者已解耦)。退路:改自定义日志流(失去 CCE 控制台按 ns / 负载查询)或恢复按 ns 收窄 | **最高优先级**,试点期第一步。实测三问:① 配置动作本身是否被禁止(硬门槛);② 非 JSON 行解析失败后是保留原样还是被丢弃;③ 合法 JSON 但字段集不同的行(logrus / 第三方)解析成什么(只要不产生 `service` 字段即无害) | | R14 | **同一日志流内并存两套格式**:obs-sdk 契约行与 `robot-framework-lib` 的 logrus JSON(后者无 `service` / `env` / `community`,且 `level: fatal`、`time` 秒精度均与契约冲突)(§4.6.2) | LTS 侧的检索 / 聚合 / 告警规则要同时兼容两种格式;且**不是过渡期现象**——框架那 121 处打点会长期保留,两套格式的共存是稳态 | 明确 LTS 侧怎么处理这两套(分别配解析?云端做字段归一化?只对 obs-sdk 行做索引、logrus 行仅全文检索?)。**这一点未定之前,「结构化解析配得上」仍不成立** | -| R15 | **stdout 与 stderr 是否都被采集**未确认——现网检到的业务日志 `pathFile` 是 `/stderr.log`(logrus 的 error / fatal 默认写 stderr)(§4.6.1) | 若采集策略只覆盖 stdout,则 **error / fatal 级日志整体缺失**——而告警最依赖的恰是这两级 | 试点期确认 `default-stdout` 策略对 stderr 的覆盖情况 | -| R16 | **`allContainers: true` 会把注入的 Sidecar 一并采进来**——现网样本中 `istio-proxy` 的 Envoy access log 占 2/3,且**按 ns 收窄挡不住**(与业务容器同 Pod 同 ns)(§4.6.1) | 三处:① 日志量被乘性放大(每请求至少 1 条),此前容量估算只算了业务日志;② 时间基准不一致(sidecar 走 UTC、业务容器走本地 CST);③ 是否保留 Envoy access log 需定夺——它与 SDK 的 `obs_http_server_*` 高度重叠 | 确认插件是否支持**按容器名排除**(`namespaces` 只管 ns、`excludePodLabels` 只管 Pod label,二者都够不着「排除 Pod 内某个容器」);据此重估日志量 | -| R17 | 「26 仓」清单可能变化:现网 pod 的 `appName: cve-manager`,而清单里写的是 `cve-manager-ng`(§4.3.1) | 若为两个服务,铺开范围随之变 | 澄清二者是否同一服务;一并确认 §5.4 列出的 4 个部署口径存疑的服务是否纳入本次铺开 | -| R18 | **各 Region 实际版本文档里的 LTS 写入上限未核**——本文的 100 MB/s 是软限制,旧版文档写的是 5 MB/s + 25K 条/秒,差异极大(§4.6.2) | 容量规划若引用本文数字会严重偏差 | **按各 Region 实际版本文档核,不要沿用本文数字** | -| R19 | **SMN 的 Region 级约束下「统一接收端」方案待确认**:主题 URN 含区域名(`urn:smn:::`),跨 Region 只能各建主题(§4.6.3) | 影响告警收敛与值班轮转 | 确认 ① 每 Region 各建主题 + 订阅同一接收端是否满足现有运维习惯;② SMN 订阅用户的跨区域统一管理(仅国内站点支持)香港是否适用;③ 接收端走邮件组还是自建 webhook 接收服务 | | R20 | **中心集群的 HA 未验证**:`replicas: 2` + pod 反亲和下的去重与告警行为(§4.7.2) | 中心是单点,挂了全网指标断线 | 试点期验证。若将来上 VictoriaMetrics,必须同时配 `-dedup.minScrapeInterval`,否则两个副本各写一份、**数据翻倍** | ### R7 明细:`robot-universal-review` 的部署口径 From 8a8583dec20942fd45adf63ff1e1fe391a75f1c5 Mon Sep 17 00:00:00 2001 From: TangJia025 <574451426@qq.com> Date: Tue, 15 Sep 2026 19:22:34 +0800 Subject: [PATCH 14/14] =?UTF-8?q?docs(design):=20=C2=A76=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=20R7=20=E5=8F=8A=E5=85=B6=E6=98=8E=E7=BB=86=E5=B0=8F?= =?UTF-8?q?=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除 R7「#1938 覆盖范围表的机器人部分与实际部署不符」一行,以及其下的 「### R7 明细:robot-universal-review 的部署口径」整节(含映射表的两处出入 与残缺记录说明)。编号保持不重排。 §1.4 中「robot-universal-review 在 10 个社区 / 7 个集群各有一套」的结论仍保留。 Co-Authored-By: Claude Code --- ...212\200\346\234\257\350\256\276\350\256\241.md" | 14 -------------- 1 file changed, 14 deletions(-) diff --git "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" index a721674..19f4526 100644 --- "a/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" +++ "b/docs/\345\276\256\346\234\215\345\212\241\345\217\257\350\247\202\346\265\213\346\200\247\345\273\272\350\256\276\346\212\200\346\234\257\350\256\276\350\256\241.md" @@ -898,24 +898,10 @@ flowchart LR | R3 | ~~自定义指标采样点计费量级未知~~ → **【转换】自建中心的容量与成本**:series 量、磁盘、**跨 Region 流量费**三项均未测算 | 26 仓铺开成本不可控(原为按量计费,现为**自建资源 + 出网流量**) | 试点阶段实测 17 集群真实 series 量后外推(§4.7.2 已给容量公式);跨 Region 流量按所选网络方案(CC 按带宽 / 公网按流量)分别核算 | | R5 | **Java SDK 无兜底**,未注入环境变量时 4 个必填字段整个缺失 | 违反契约,Java 服务日志字段不全 | 单独立项修复(加 hostname / `unknown` 兜底 + 补 UT,断言落在真实 JSON 输出上) | | R6 | Python / Node / Java 未打 tag,Java 进私服路径未验证 | 消费方无法按版本引用 | 随各语言首次接入服务时一并处理 | -| R7 | **#1938 覆盖范围表的机器人部分与实际部署不符** | 影响 community 取值与大盘分维度 | 见下 | | R8 | Java SDK 的 logstash-logback-encoder / jackson-core 在 SDK 内为 `provided` | 接入服务运行时必须自带,否则日志不可用 | 接入文档中明确要求,或改为传递依赖 | | R14 | **同一日志流内并存两套格式**:obs-sdk 契约行与 `robot-framework-lib` 的 logrus JSON(后者无 `service` / `env` / `community`,且 `level: fatal`、`time` 秒精度均与契约冲突)(§4.6.2) | LTS 侧的检索 / 聚合 / 告警规则要同时兼容两种格式;且**不是过渡期现象**——框架那 121 处打点会长期保留,两套格式的共存是稳态 | 明确 LTS 侧怎么处理这两套(分别配解析?云端做字段归一化?只对 obs-sdk 行做索引、logrus 行仅全文检索?)。**这一点未定之前,「结构化解析配得上」仍不成立** | | R20 | **中心集群的 HA 未验证**:`replicas: 2` + pod 反亲和下的去重与告警行为(§4.7.2) | 中心是单点,挂了全网指标断线 | 试点期验证。若将来上 VictoriaMetrics,必须同时配 `-dedup.minScrapeInterval`,否则两个副本各写一份、**数据翻倍** | -### R7 明细:`robot-universal-review` 的部署口径 - -实测 `infrastructure` 仓 `service.yaml`,该服务的**生产部署是 10 个社区 / 7 个集群**(不是一一对应,`infra-cn4-x86-common-cluster` 一台跑 3 个社区)。 - -而 #1938 覆盖范围表中该服务列了 7 个集群,与实测有**两处出入**: - -1. **多算了 `mindspore-cn-north-4-x86-cluster`** —— 该集群上的 `deployment-keeper-approve-v2` 的「镜像构建源码仓」列被误填为 `robot-universal-review`(`:74` 的 `robot-universal-keeper-approve` 同样误填),疑为映射表生成时的数据问题; -2. **漏了 `openeuler-cn-north4-x86-cluster`** —— openEuler 社区的实际 prod-02 部署。 - -另外 `service.yaml` 中 openEuler 的 `prod` 那条记录是**残缺记录**(集群/命名空间/ArgoCD 应用三列全空,部署仓还指向已迁移的旧仓 `opensourceways/helm-chart-value`),实际生效的是 `prod-02`。 - -**建议**:请映射表维护方校正 R7 相关行;铺开时若按「一行一条部署」生成配置,需显式跳过该残缺记录。 - --- ## 附录