22 KiB
tags, create time
| tags | create time | |||
|---|---|---|---|---|
|
2026-07-10 10:30 |
XINFRA PRD 优化决策记录
概述
本文档记录 requirements 各优化点的方案对比与决策依据,供团队同步使用。每个修改点均以 方案 A(原设计)vs 方案 B(最终选择) 的形式呈现。
所有优化的共同方向:让 PRD 精确描述"平台开发团队需要交付什么",把"依赖什么"和"不需要做什么"从需求列表中剥离出来。 这不是缩小项目范围——基础设施仍然会建、监控仍然会用、网络仍然会通——只是把不属于平台开发团队的工作归还给对应的团队,让 PRD 的读者对实际开发工作量有准确的预期。
1. 统一认证模型
方案 A:1:1:1 用户映射(原设计)
主系统自建用户表,维护 LDAP 账号 ↔ 主系统用户 ↔ 子系统用户的三者一一对应关系。主系统管身份(Authentication),子系统管授权(Authorization)。用户首次登录主系统时自动在子系统中创建对应账号,后续通过映射关系同步状态。
方案 B:LDAP SSO 跳转(最终选择)
主系统只做 LDAP SSO 跳板 + 导航入口。用户通过主系统门户选择目标子系统后,系统通过 LDAP 认证代入身份,直接跳转到子系统。各子系统直接对接企业 LDAP 做认证,权限仍由各子系统自行管理。
对比
| 维度 | 方案 A(1:1:1 映射) | 方案 B(SSO 跳转) |
|---|---|---|
| 主系统开发量 | 需自建用户注册/注销接口、用户表 CRUD、映射关系维护、子系统账号同步 Worker | 只需一个 LDAP 登录页 + 子系统跳转链接,无用户表 |
| 子系统改造量 | 每个子系统需新增"接收主系统同步账号"的 API,并处理账号冲突、状态覆盖等边界情况 | 零改造——Wayne / CloudDM / CacheCloud 均已原生支持 LDAP,直接配置即可 |
| 新增子系统成本 | 每接入一个子系统都要开发同步接口 + 映射逻辑 + 联调测试 | 子系统配置 LDAP 连接即完成接入,无额外开发 |
| 典型故障场景 | 用户在 LDAP 离职后,主系统映射表残留 → 子系统仍显示该用户;用户改名后三方数据不一致;子系统同步失败导致"主系统能登录但子系统报权限不存在" | 无映射层,LDAP 是唯一身份源,LDAP 账号失效后所有子系统自然无法登录 |
| 数据一致性 | 需定时对账三张用户表(LDAP / 主系统 / 子系统),发现漂移后人工或自动修复 | 天然一致——每次登录实时读 LDAP,无缓存映射 |
| 现有基础设施 | 需评估 Wayne / CloudDM / CacheCloud 是否暴露了账号管理 API 供主系统调用 | 三个子系统均已支持 LDAP Bind 认证,配置 LDAP Server 地址和 Base DN 即可 |
| 运维复杂度 | 多一个数据库表 + 一个同步服务需要监控和维护 | 无额外运维组件 |
决策理由
Wayne、CloudDM、CacheCloud 三者都原生支持 LDAP 认证——这不是需要开发的能力,而是各子系统开箱即用的配置项。在子系统已经能直接对接 LDAP 的前提下,主系统在中间再加一层用户映射,本质是在没有问题的地方制造问题。
方案 A 的真正代价不在于初次开发(建表 + 同步接口大约 1-2 周),而在于长期维护:每接入一个新子系统都要对接映射接口;用户在 LDAP 侧发生变更(离职、改名、部门调动)时需要一套同步机制保证三方一致;映射表本身也是一个需要备份、监控、排障的有状态组件。这些工作量会随着子系统数量线性增长。
方案 B 将 LDAP 作为唯一的身份源(Single Source of Truth),主系统只做跳转入口。这不仅消除了映射不同步的故障模式,也让"新增子系统"这件事从"开发同步接口 + 联调"降级为"配置 LDAP 连接"——一个运维操作,零开发成本。
2. 主系统面板范围
方案 A:统一 DashBoard(原设计)
主系统自建一个全功能面板,同时聚合四类数据:
| 面板模块 | 数据来源 | 技术实现 |
|---|---|---|
| 审计日志 | 子系统通过 HTTP Webhook 上报 | 自建接收 + 存储 + 查询 |
| 监控指标 | 通过 PromQL 查询 Prometheus | 需实现 PromQL 查询引擎 + 图表渲染 |
| 安全事件 | WAF 拦截事件 + 异常登录检测 | 需接入 WAF 日志流 + 登录行为分析 |
| 告警概览 | 各子系统告警汇总,按严重级别分组 | 需对接各子系统告警 API 或 Prometheus Alertmanager |
方案 B:审计面板 + Grafana 复用(最终选择)
主系统只自建审计日志聚合:
| 面板模块 | 处理方式 | 理由 |
|---|---|---|
| 审计日志 | 主系统自建(Webhook 接收 + 存储 + 按业务字段检索) | 结构化业务数据,Grafana 不擅长 |
| 监控指标 | 直接复用 Grafana Dashboard | Grafana + Prometheus 已原生支持 |
| 安全事件 | 在审计面板中作为审计日志的一个子类展示 | WAF 拦截事件本质也是"操作审计",无需独立模块 |
| 告警概览 | 直接复用 Grafana + Alertmanager | Grafana 已原生支持告警汇总和分组 |
对比
| 维度 | 方案 A(全自建) | 方案 B(审计 + Grafana) |
|---|---|---|
| 前端开发量 | 4 个面板模块(审计表格、监控图表、安全事件列表、告警卡片),每个需要独立的筛选器、图表组件、权限控制 | 1 个模块(审计日志查询页),监控/告警零前端开发 |
| 后端开发量 | 审计 Webhook 接收 + PromQL 查询代理 + Alertmanager API 代理 + 安全日志解析 + 4 套查询接口 | 审计 Webhook 接收 + 存储 + 查询,共 1 套接口 |
| 运维组件 | 需维护自建面板的数据库、缓存、前端静态资源 | 只需维护审计日志的存储(可复用主系统已有数据库) |
| 数据一致性 | 自建面板的监控数据与 Grafana 来自同一 Prometheus,但刷新间隔/聚合方式可能不同 → 用户看到两个"不一样的 CPU 使用率" | Grafana 是唯一监控源,不存在分歧 |
| Grafana 能力覆盖 | 监控指标展示(已支持)、告警汇总(已支持)、多数据源(已支持)、RBAC(已支持)——重复建设 | 100% 复用已有能力 |
| 审计日志特殊性 | — | 审计日志是结构化业务数据(操作人、操作类型、工单号、时间范围),需要按业务字段组合检索,Grafana 的 LogQL/SQL 面板不适合这类场景,确实需要自建 |
| 用户体验 | 用户在主系统看监控 → 发现异常 → 去 Grafana 看详情 → 两套系统数据对不上 → 困惑 | 用户在主系统看审计,去 Grafana 看监控,职责清晰不混淆 |
决策理由
方案 A 的核心问题是用自研代码重新实现了 Grafana 已经做好的事。具体来说:
- 监控指标面板:Prometheus → Grafana 的链路已经是行业标准,Grafana 原生支持 PromQL 查询、变量下钻、告警规则、多数据源聚合。自建一套 PromQL 查询引擎 + 图表渲染,开发量至少 2-3 周,且最终效果大概率不如 Grafana。
- 告警概览:Alertmanager 已经提供了按严重级别分组、静默、路由的能力,Grafana 的 Alerting 模块可以直接展示。自建等于维护两套告警查看入口。
- 安全事件:WAF 拦截事件本质上也是一种"操作审计"(某个 IP 在某个时间被拦截了某个请求),完全可以归入审计日志体系,按事件类型分类展示,不需要独立建一个安全事件模块。
审计日志是唯一 Grafana 做不好的部分。审计日志的典型查询是"张三在 7 月 10 号对 production 数据库执行了哪些操作",这需要按操作人、操作类型、目标资源、时间范围等业务字段做组合筛选——这是结构化数据检索的场景,Grafana 面向时序数据的设计不适合。因此主系统自建审计面板是合理的,但把监控和告警也自建就是重复劳动。
3. CI/CD 引擎选型
方案 A:双引擎架构(原设计)
PRD 标题为"双引擎架构",支持 GitLab CI 和另一引擎(如 Jenkins)。这意味着需要:
| 需要做的事 | 具体内容 |
|---|---|
| 抽象流水线 DSL | 设计一套统一的 Pipeline 配置格式,能翻译为 GitLab CI YAML 和 Jenkinsfile |
| 引擎适配层 | 分别对接 GitLab CI API 和 Jenkins API,处理两者的差异(认证方式、触发机制、状态回调格式、日志获取方式) |
| 统一查看界面 | 自建流水线状态页,聚合两个引擎的执行记录,因为 GitLab CI 的 Pipeline 页面只能看到自己的流水线 |
| 配置管理 | 同一套项目在两个引擎中的配置同步(变量、Secret、Runner 配置) |
方案 B:GitLab CI 单引擎(最终选择)
明确只用 GitLab CI 一个引擎。CI/CD 全部通过 .gitlab-ci.yml 定义,直接调用 GitLab CI API 触发 Pipeline。流水线执行状态和日志查看直接复用 GitLab CI 原生 Pipeline 页面,平台不自建查看界面。
对比
| 维度 | 方案 A(双引擎) | 方案 B(单引擎) |
|---|---|---|
| 开发工作量 | DSL 抽象层 + 两套 API 适配 + 统一查看界面 + 配置同步,预估 4-6 周 | 直接调用 GitLab CI REST API,复用 .gitlab-ci.yml,预估 1 周 |
| DSL 抽象复杂度 | 需要定义一套比 GitLab CI YAML 和 Jenkinsfile 更通用的格式,同时不能丢失任一引擎的特有功能(如 GitLab 的 rules: / Jenkins 的 parallel 语法差异) |
不需要抽象,直接用 .gitlab-ci.yml |
| 调试体验 | Pipeline 失败后需要先定位是 DSL 翻译层的 bug 还是引擎本身的 bug | 直接在 GitLab CI 页面看错误,无中间层 |
| 维护成本 | 两个引擎版本升级都可能破坏适配层(GitLab CI API breaking changes / Jenkins 插件兼容性) | 只跟进 GitLab CI 一个 |
| 统一查看界面 | 需自建前端页面,聚合两引擎执行记录 | 零开发——GitLab CI Pipeline 页面已原生支持 |
| 实际使用场景 | 公司内部只用 GitLab CI,Jenkins 无实际使用团队 | 与实际场景完全匹配 |
| 未来扩展性 | 提前抽象,但抽象边界很难预判(第二个引擎是什么?API 什么样?) | 需要时再抽象,此时已有 GitLab CI 的完整使用经验,抽象更准确 |
决策理由
方案 A 属于典型的为不存在的需求做过度设计。公司内部目前只使用 GitLab CI,没有任何团队在用 Jenkins 或其他引擎。在这种情况下,"双引擎"架构的实际效果是:花了 4-6 周开发一套 DSL 翻译层,其中 GitLab CI 那一半只相当于直接调用 API 的 1 周工作量,Jenkins 那一半在可预见的未来不会被使用。
更关键的是抽象时机问题。在只有一个引擎的使用经验时做抽象,几乎必然会在抽象边界上犯错——你不知道第二个引擎的 API 是什么样的,不知道它的 Pipeline 模型和 GitLab CI 有多大差异,不知道哪些概念可以统一、哪些必须分别处理。等到真正需要引入第二引擎时,大概率要重写抽象层。先做好一件事,等第二件来了再抽象,比提前猜错要省得多。
4. 基础设施类需求的归属
方案 A:WAF / 大内网 / Ansible 作为功能需求(原设计)
FR-6(Ansible 自动化部署)、FR-7(WAF 安全态势)、FR-8(大内网互联)与 Wayne、CloudDM、CacheCloud 并列,作为平台的 10 个功能需求之一,需排优先级、写验收标准、分配开发人员。
方案 B:归入基础设施依赖(最终选择)
将三者移至「基础设施依赖」章节,注明由基础设施团队负责,平台开发团队只需了解其约束(如"跨机房 Pod 通信延迟 < 2ms"),不负责实施。
对比
| 维度 | 方案 A(作为功能需求) | 方案 B(作为基础设施依赖) |
|---|---|---|
| PRD 中的呈现 | 与 Wayne、CloudDM 同级,共 10 个 FR,每个有编号、需求表、验收标准 | 独立章节,只描述约束和 SLA,不排开发优先级 |
| 读者理解 | 非技术读者(产品、管理层)会认为这 10 个 FR 都是平台团队要交付的 | 明确标注"非平台开发范围",避免职责混淆 |
| 排期影响 | 10 个 FR 需要排入同一份开发计划,团队压力和管理层预期都会膨胀 | 6 个 FR 排入开发计划,范围真实可控 |
| 验收责任 | 平台团队需要对 WAF 防护效果、网络延迟 SLA 负责,即使这些不由自己实施 | 基础设施团队负责验收,平台团队只负责"在基础设施就绪的前提下,平台功能正常" |
| 变更影响 | 网络架构调整时需要同时修改 PRD 的 FR-8 和基础设施团队自己的文档,容易不一致 | 基础设施团队独立维护自己的文档,PRD 只引用约束 |
| 实际执行者 | FR-6 的 Ansible Playbook 由 SRE 编写;FR-7 的 WAF 规则由安全团队配置;FR-8 的网络链路由网络团队搭建——没有一条是平台开发团队执行的 | 与实际执行者一致 |
决策理由
把 WAF、大内网、Ansible 列为功能需求,最直接的后果是管理层和协作方对平台团队的交付预期被错误放大。当 PRD 中列了 10 个 FR,而团队实际只能负责其中 6 个的开发,剩下 3 个要等基础设施团队就绪后"验收",这会在排期评审中造成困惑:"FR-7 WAF 的开发进度怎么样了?"——答案是"它不是我们开发的",但 PRD 的结构没有体现这一点。
更深层的问题是验收责任错位。如果 FR-7 作为功能需求,平台团队需要对"WAF 覆盖所有对外暴露的 HTTP/HTTPS 入口"这条验收标准负责。但 WAF 的部署和规则配置是安全团队的工作,平台团队既没有权限也没有能力去验收它。把验收标准挂在错误的团队名下,最终只会导致要么验收流于形式,要么平台团队替基础设施团队背锅。
方案 B 将三者移至「基础设施依赖」章节,明确传递一个信息:这些是平台运行的前提条件,由对应的团队负责交付,平台团队只关心它们的约束和 SLA。这让每个团队只对自己实际执行的工作负责。
5. RKE2 集群需求的粒度
方案 A:详细配置参数(原设计)
FR-1 包含 6 条需求,详细描述 RKE2 的技术配置:
| 需求编号 | 内容 | 信息类型 |
|---|---|---|
| FR-1.1 | 每个机房独立部署 RKE2,cluster-cidr(10.42.0.0/16),service-cidr(10.43.0.0/16) | 网络规划参数 |
| FR-1.2 | Canal(Calico + Flannel)CNI,kube-proxy iptables 模式 | 组件选型参数 |
| FR-1.3 | 支持 Air-gap 离线部署 | 能力约束 |
| FR-1.4 | 节点注册支持静态 Token 和 Bootstrap 证书签名两种模式 | 部署方式参数 |
| FR-1.5 | containerd 运行时,不依赖 Docker | 组件选型参数 |
| FR-1.6 | Systemd 服务管理方式部署 | 部署方式参数 |
方案 B:约束表格 + 引用 SOP(最终选择)
FR-1 精简为一张 4 行约束表格,只保留平台开发团队需要感知的信息:
| 约束项 | 说明 | 对平台团队的影响 |
|---|---|---|
| CNI 插件 | Canal(Calico + Flannel) | Wayne 通过 Client-Go 操作 K8s 对象时需知 CNI 行为 |
| 容器运行时 | containerd(不依赖 Docker) | 镜像构建和调试工具选型不依赖 Docker CLI |
| 离线部署 | 支持 Air-gap 环境 | 所有依赖包需预先下载,镜像推送到内网 Harbor |
| 集群规模 | 七机房各一套独立集群 | Wayne 需管理多集群连接 |
详细部署规范(网络 CIDR、节点注册模式、Systemd 配置等)引用运维 SOP 文档。
对比
| 维度 | 方案 A(详细参数) | 方案 B(约束 + SOP) |
|---|---|---|
| 信息定位 | 混合了"平台约束"和"运维配置"两类信息 | 只保留"平台约束",运维配置归 SOP |
| 读者适配 | 开发人员读到大量网络 CIDR 和节点注册模式参数——这些不影响他们写代码 | 开发人员只看到影响自己工作的 4 条约束 |
| 运维人员适配 | 运维需要的部署步骤散落在 PRD 的需求表中,无法独立查阅 | 集中在 SOP 文档,按操作场景组织("初始化集群"、"扩容节点"、"升级版本") |
| 变更影响面 | service-cidr 规划调整 → 需要走 PRD 评审流程修改 FR-1.1 | service-cidr 调整 → 只改 SOP 文档,PRD 无变动 |
| 信息权威性 | PRD 不是运维操作手册,放网络配置参数会导致"以 PRD 为准还是以 SOP 为准"的歧义 | SOP 是运维操作的单一权威来源,无歧义 |
| 文档体积 | FR-1 占 PRD 约 15% 篇幅 | FR-1 占 PRD 约 3% 篇幅 |
决策理由
PRD 和 SOP 服务于不同的读者和不同的生命周期:
- PRD 的读者:产品、开发、管理层。他们需要知道"平台依赖什么基础设施",以便理解技术约束和排期风险。
- SOP 的读者:SRE、运维。他们需要知道"具体怎么部署",包括每一步的命令、参数、验证方式。
方案 A 把这两类信息混在一起,导致两个问题:第一,开发人员在 PRD 中读到 cluster-cidr 和节点注册模式时,这些信息对他们写代码没有任何帮助,只是阅读噪音;第二,运维人员在 PRD 中找到的部署参数不完整(只有选型结论没有操作步骤),他们最终还是需要一份独立的 SOP 文档,等于维护了两个"半成品"。
方案 B 让 PRD 只承担它该承担的职责——告诉读者"RKE2 集群的这些约束会影响平台设计"——而把部署操作的完整细节交给 SOP。当运维团队调整网络规划或节点注册方式时,只需改 SOP,PRD 保持不变。职责清晰,维护成本最低。
6. 资源指标面板的覆盖范围
方案 A:多云 + 自建机房全自研(原设计)
FR-9 要求资源指标面板同时覆盖:
| 数据源 | 接入方式 | 复杂度 |
|---|---|---|
| AWS | Cost Explorer API + CUR(Cost and Usage Reports),按服务/账户/标签维度 | 高——API 有请求频率限制,账单数据 T+1 到 T+3 延迟,预留实例分摊需独立计算 |
| 阿里云 | 账单 API + BSS(Business Support System),按产品/实例/标签维度 | 高——账单格式与 AWS 完全不同,需独立适配 |
| 腾讯云 | 费用中心 API,按项目/资源/标签维度 | 高——第三套格式,又有自己的分账逻辑 |
| 自建机房 | Prometheus 节点指标 + SNMP 网络指标 | 低——数据已在 Prometheus 中 |
还需实现统一数据模型(将三家云厂商的不同账单结构归一化)、汇率换算、按部门/项目/机房聚合、月度趋势对比、闲置资源告警。
方案 B:初期只做自建机房(最终选择)
只覆盖自建机房的资源开销,数据源为 Prometheus 节点指标 + SNMP 网络指标,按 Namespace → Project → Department 路径归属。多云账单接入推至后续迭代。
对比
| 维度 | 方案 A(多云 + 自建) | 方案 B(只做自建) |
|---|---|---|
| 数据源适配工作量 | 3 套云 API 适配(认证、分页、账单格式解析)+ 1 套 Prometheus 查询 | 1 套 Prometheus 查询 |
| 数据标准化 | 需建统一数据模型,将 AWS CUR / 阿里云 BSS / 腾讯云费用中心的账单字段归一化(服务名映射、计费单位统一、分账标签对齐) | Prometheus 指标格式天然统一,只需按 K8s Namespace 做归属映射 |
| 数据延迟 | AWS T+1~T+3,阿里云 T+1,腾讯云 T+1,需处理"部分云数据已到、部分未到"的中间态 | Prometheus 实时采集,分钟级延迟 |
| 预留/节省计划 | AWS Reserved Instance / Savings Plan、阿里云预留实例券等需按摊销方式计算实际成本,每家逻辑不同 | 无此问题——自建机房无预留实例概念 |
| 前端展示 | 需支持"云厂商"维度的筛选和对比 | 只有机房维度,前端逻辑简单 |
| 交付周期 | 多云适配 + 数据标准化 + 前端展示,预估 4-6 周 | Prometheus 查询 + 归属映射 + 前端展示,预估 1-2 周 |
| 实际痛点 | 多云账单多数团队已有各自查看方式(AWS Console / 阿里云控制台),统一面板是锦上添花 | 自建机房开销目前是真正的管理盲区——没有统一归集,各团队不知道自己的物理机用了多少电、多少带宽 |
决策理由
方案 A 的核心风险不在于技术难度,而在于投入产出比极低。对接多云 Billing API 的工作量不亚于一个独立产品线:
仅 AWS 一家,Cost Explorer API 就有按 Service / Account / Tag / Region 等多种维度的查询方式,账单数据有 T+1 到 T+3 的延迟,Reserved Instance 和 Savings Plan 需要按摊销方式计算实际成本(不是简单的月度费用除以 30 天)。阿里云和腾讯云各有一套完全不同的账单结构和分账逻辑。三家云厂商的"服务名"都不统一(AWS 叫 EC2,阿里云叫 ECS,腾讯云叫 CVM),需要建一层服务名映射才能做跨云对比。这些都是脏活累活,但对用户的价值有限——每个云厂商自己的控制台已经提供了详细的账单查看能力。
自建机房的资源开销则完全不同:Prometheus 节点指标已经存在(CPU / 内存 / 磁盘 / 网络),数据格式统一,只需建一层 K8s Namespace → Project → Department 的归属映射就能产出价值。这是目前真正"没人管"的管理盲区——没有统一归集,各团队不清楚自己的物理机资源利用率和开销。
先解决最痛的盲区,多云账单留到二期。二期启动时,一期已经积累的"部门/项目归属映射"可以直接复用于多云场景,不需要推倒重来。
总结
以上 6 个优化点可以归纳为两类决策逻辑:
| 决策逻辑 | 涉及的优化点 | 核心原则 |
|---|---|---|
| 砍掉不必要的自研 | #1 认证模型、#2 DashBoard、#3 CI/CD 引擎 | 开源工具已有的能力不重复造轮子 |
| 厘清职责边界 | #4 基础设施归属、#5 RKE2 粒度、#6 资源面板范围 | 只写平台团队实际要交付的内容 |