Skip to content

K8s 多集群管理平台 · 系统设计文档 v2.1


文档信息

字段内容
文档版本v2.1
创建日期2026-07-31
作者平台架构组
状态待评审
变更摘要v2.0 → v2.1:新增性能优化方案(分页/缓存/字段裁剪/Watch增量)、应用负责人绑定与飞书告警通知机制

一、项目概述

1.1 平台定位

面向运维团队的 Kubernetes 多集群管理平台,以**"域(Zone)"为核心调度模型**,通过 Node Label + NodeAffinity 实现应用按业务属性自动调度到合适的节点池。平台内置 AI 智能体(Copilot),提供智能排障、调度推荐、异常检测、告警降噪等辅助能力。

1.2 目标用户

用户角色使用场景
运维工程师日常发布、排障、扩缩容、告警处理
域管理员管理指定域的节点、配额、应用
超级管理员集群注册、权限分配、审计审查

1.3 设计目标

目标量化指标
调度自动化应用发布时根据标签自动匹配域,无需人工选择节点
资源可视化按域实时查看 Request / Limit / Actual 三级水位,刷新间隔 ≤ 10s
安全隔离隐私域独立集群 + NetworkPolicy + 节点污点三重隔离
智能运维AI 辅助排障覆盖 6 大类故障,平均定位时间从 15min 降至 2min
性能体验应用列表万级数据秒开,详情页 < 2s 加载
告警精准告警直达应用负责人(飞书),MTTR 下降 40%
审计合规所有操作(含 AI 操作)全量审计,隐私域额外增强

二、架构设计

2.1 总体架构

┌──────────────────────────────────────────────────────────────────┐
│                        运维人员                                   │
│            Web UI (Vue3)  │  CLI (kubectl plugin)                │
├──────────────────────────────────────────────────────────────────┤
│  Frontend Layer                                                  │
│  ├── 全局看板(三级下钻)  ├── 应用管理  ├── 域管理                 │
│  ├── AI Copilot 侧边栏  ├── 洞察中心  ├── 排障知识库             │
│  └── 虚拟滚动列表 + WebSocket 增量                               │
├──────────────────────────────────────────────────────────────────┤
│  API / Orchestration Layer (Go + Gin)                            │
│  ├── Cluster Manager    ├── Auth/RBAC    ├── Scheduler Engine    │
│  ├── App Lifecycle      ├── Monitoring     ├── AI Orchestrator   │
│  │                                                     │        │
│  │   ├── Intent Parser   ├── Tool Dispatcher  ├── Context Builder│
│  │   ├── Memory Store    ├── Safety Guardrail  ├── Rules Engine  │
│  ├── Notification Router (飞书/邮件/Webhook)                      │
│  └─────────────────────────────────────────────────────────────┘│
├──────────────────────────────────────────────────────────────────┤
│  Cache Layer                                                     │
│  ├── L1: 本地内存 (sync.Map, TTL 5s)                            │
│  ├── L2: Redis (TTL 30s, 跨实例共享)                             │
│  └── L3: K8s API + Watch 增量                                   │
├──────────────────────────────────────────────────────────────────┤
│  Data Layer                                                      │
│  ├── PostgreSQL (业务数据 + AI对话 + 知识库 + 审计)               │
│  ├── VictoriaMetrics (指标聚合,跨集群查询)                       │
│  └── Loki / ES (日志聚合)                                        │
├──────────────────────────────────────────────────────────────────┤
│  Multi-Cluster Plane                                             │
│                                                                  │
│  ┌─────────────────┐    ┌─────────────────┐                     │
│  │  普通集群        │    │  隐私集群        │                     │
│  │  (Zone Labels)  │    │  (独立 ETCD)    │                     │
│  │                 │    │                 │                     │
│  │ ┌─────────────┐ │    │ ┌─────────────┐ │                     │
│  │ │ 核心业务域   │ │    │ │ 隐私安全域   │ │                     │
│  │ │ zone=core   │ │    │ │ zone=private│ │                     │
│  │ ├─────────────┤ │    │ │ +DenyAll NP │ │                     │
│  │ │ 消费型/默认  │ │    │ │ +Egress GW  │ │                     │
│  │ │ zone=default│ │    │ └─────────────┘ │                     │
│  │ ├─────────────┤ │    └─────────────────┘                     │
│  │ │ 任务跑批域   │ │                                            │
│  │ │ zone=batch  │ │                                            │
│  │ ├─────────────┤ │                                            │
│  │ │ 内存密集域   │ │                                            │
│  │ │ zone=memory │ │                                            │
│  │ ├─────────────┤ │                                            │
│  │ │ 通信域       │ │                                            │
│  │ │ zone=msg    │ │                                            │
│  │ ├─────────────┤ │                                            │
│  │ │ 异常观察域   │ │                                            │
│  │ │ zone=except │ │                                            │
│  │ └─────────────┘ │                                            │
│  └─────────────────┘                                            │
└──────────────────────────────────────────────────────────────────┘

2.2 部署架构

组件部署方式说明
平台 API Server物理机 / 虚拟机(systemd 管理)管控面独立,不依赖 K8s
PostgreSQL物理机 / 虚拟机主从复制 + 每日备份
Redis物理机 / 虚拟机L2 缓存 + Session 存储
VictoriaMetrics物理机 / 虚拟机单节点或集群模式
前端静态文件Nginx 托管构建产物 dist/
普通集群内的 Agent可选:DaemonSet本地指标采集转发
LLM 推理服务物理机 + GPU(Ollama / vLLM)私有化部署,模型如 Qwen2.5-72B
飞书应用飞书开放平台机器人 + 消息卡片

2.3 多集群通信

  • 平台持有各集群的 kubeconfig(存储在 PG 的 clusters 表,AES-256 加密)
  • API Server 通过 client-go 直连各集群的 Kubernetes API
  • 每个集群连接配置:APIServer 地址、CA 证书、ServiceAccount Token、超时时间、QPS 限制
  • 隐私集群的连接额外启用 审计代理(所有请求录屏 + 存证)

三、核心模型设计

3.1 域(Zone)模型

属性说明
域标识zone=<name> Node Label
调度方式NodeAffinity(硬亲和 or 软亲和 + 权重)
污点策略隐私域 NoSchedule;跑批域 spot;异常域 TTL
超卖比域级别预设,应用发布时自动填充 request/limit
ResourceQuota每个域独立配额,防止资源被撑爆
PodDisruptionBudget核心域 / 通信域必须保证最小可用副本
网络策略隐私域默认 Deny All + Egress 白名单
HPA 预设域级别默认扩缩容阈值

域类型定义表:

域类型Node Label超卖比调度策略网络隔离HPA 默认阈值节点规格
核心业务zone=core1:1硬亲和CPU 70%/30%high-cpu 独占
消费型/默认zone=default1:1.5硬亲和CPU 70%/30%standard
任务跑批zone=batch1:3软亲和 + 容忍 spot队列长度 / 空闲 5minpreemptible
内存密集zone=memory1:1硬亲和Mem 75%/40%high-mem
通信zone=msg1:1硬亲和CPU 70%/30%high-net
隐私安全zone=private1:1污点 + 容忍是 (Deny All)CPU 70%/30%加密节点
异常观察zone=exception1:2软亲和 + TTL不自动扩缩独立池

3.2 应用模型(CRD)

yaml
# AppDefinition CRD(平台自研,存储在 PG,同步渲染为 K8s 原生资源)
apiVersion: platform.example.com/v1
kind: AppDefinition
metadata:
  name: payment-service
  namespace: team-payment
spec:
  displayName: 支付服务
  team: payment
  zone:
    preferred: core
    fallback: default
  template: microservice-v2
  image: registry.example.com/payment:v2.4
  replicas: 3
  resources:
    requests:
      cpu: 500m
      memory: 1Gi
    limits:
      cpu: 1500m
      memory: 2Gi
  healthCheck:
    livenessPath: /health
    readinessPath: /ready
    initialDelaySeconds: 10
  hpa:
    minReplicas: 3
    maxReplicas: 50
    targetCPUUtilization: 70
  configRefs:
    - configMap: payment-config
    - secret: payment-secrets
  ports:
    - port: 8080
      protocol: TCP
  domain: payment.example.com
  owners:
    - type: user
      ref: user-uuid-xxx
      notifyChannels: ["feishu"]
      alertLevel: all
---
# AppRelease CRD(每次发布生成一个 Release 记录)
apiVersion: platform.example.com/v1
kind: AppRelease
metadata:
  name: payment-service-v2.4-20260131-1423
spec:
  appDef: payment-service
  version: v2.4
  strategy: RollingUpdate
  status: Success
  deployedAt: "2026-07-31T14:23:00Z"
  deployedBy: zhangsan

3.3 Namespace 模型

Namespace = 业务团队隔离单元
├── 命名规则:team-<teamname>
├── 每个 NS 绑定一个团队 + 一个或多个域标签
├── 默认打标:app.zone=default(消费型域)
├── ResourceQuota 从所属域继承
└── NetworkPolicy 从所属域继承(隐私域 NS 额外限制)

3.4 标签治理体系

层级前缀示例谁设置能否修改
系统标签node.k8s.io/node.k8s.io/zone=core平台自动
业务标签app.team/ app.zone/app.team=payment平台从模板继承可覆盖
调度标签渲染产物nodeSelector / tolerations平台 Scheduler Engine
用户自定义custom/custom/env=stress用户

未打标应用处理:

  • 发布时自动注入 app.zone=default
  • 审计日志记录 auto_inject_zone
  • 看板标注 "⚠️ 未指定域"
  • 定期巡检报告列出默认域中的应用

四、功能模块详细设计

Module 1:集群管理

功能说明优先级
集群注册录入 kubeconfig(加密存储),平台连通性校验P0
集群健康检查定时探测 apiserver / etcd / nodes Ready 状态P0
节点同步定时拉取节点信息写入 node_infoP0
节点池管理按域对节点分组,支持打标 / 去标 / 驱逐P0
多集群切换前端全局集群选择器P0
集群删除校验无应用在使用后允许删除P1

Module 2:域管理

功能说明优先级
域 CRUD创建域 → 自动生成 ZonePolicy(超卖比 / HPA / Quota 默认值)P0
节点分配将节点划入某域(打 Label + 可选 Taint)P0
域资源水位实时计算域内 Request% / Limit% / Actual%P0
域扩缩容联动云厂商 API 调整节点池大小(Phase 2)P2
异常域 TTL到期自动缩容到 0,数据保留 N 天P1
隐私域网络策略创建时自动配置 NetworkPolicy Deny All + Egress 白名单P0

Module 3:应用全生命周期管理

功能说明优先级
应用创建从模板 / 镜像 / Git 仓库导入P0
负责人绑定创建/编辑时指定负责人(用户/团队),绑定通知渠道P0
配置管理ConfigMap / Secret 版本化管理,与应用 Release 绑定P1
发布RollingUpdate / Canary(Phase 2)/ Blue-Green(Phase 2)P0
回滚一键回退到任意历史 ReleaseP0
扩缩容手动调副本 + HPA 配置P0
域名/路由Ingress 自动创建,TLS 证书自动续期P1
日志查看聚合 Pod 日志(Loki/ES),支持关键词过滤P1
终端Web kubectl execP1
事件流K8s Events 时间线,持久化到 PGP1
发布风险评估AI 对比新旧版本 diff,评估风险等级P2
最小资源请求列表页只返回摘要字段(name/replicas/image/zone/status),详情按需加载P0

Module 4:智能看板

三级下钻:

层级内容刷新机制
L1 全局总览所有域卡片:节点数 / Pods / Request% / Limit% / Actual% / 饱和度WebSocket 增量推送
L2 域详情节点列表 + 应用 TopN + 资源水位时序图 (1h/24h/7d)10s 轮询 + WS 增量
L3 节点/应用详情Pod 级资源明细 + OOM 记录 + CPU Throttling5s 轮询

饱和度定义:

  • 饱和度 = max(Request%, Actual%)
  • 🟢 < 70% / 🟡 70%-85% / 🔴 > 85%
  • AI 异常检测标记(Isolation Forest 算法)

Module 5:监控 & 告警

层级内容采集方式
L1 基础设施Node / K8s 组件 / etcd / CoreDNSPrometheus + exporters
L2 应用黄金指标Rate / Errors / Duration / SaturationServiceMonitor
L3 业务自定义用户 Push 的 metrics自助 PrometheusRule

告警路由:

通知方式接收人
核心业务电话 + 飞书应用负责人 + 值班人
隐私安全电话 + 飞书 + 邮件安全组 + 应用负责人
任务跑批仅飞书团队群
默认/消费飞书应用负责人
异常观察飞书(降噪)申请人

AI 告警降噪: 同域 5min 内多条告警 → 聚合成一条根因分析。

Module 6:RBAC & 审计

三级角色:

角色权限范围
超级管理员所有集群、所有域、所有操作
域管理员指定域的读写 + 该域所在集群的只读
只读用户所有集群 / 域的读权限

审计日志:

  • 所有写操作记录:用户 / IP / 时间 / 操作对象 / 变更前后
  • AI 操作独立审计表(ai_tool_audit),记录意图 + 推理链 + 执行结果
  • 隐私域操作额外存证(不可篡改日志)

Module 7:AI 智能体(Copilot)

6 大能力域:

能力说明
智能调度推荐分析应用画像,推荐域 + 资源参数
智能标签治理漂移检测、命名建议、影响分析
看板智能洞察异常检测、根因定位、自然语言查询、容量预测
应用智能运维故障自愈、发布风险评估、智能回滚、配置优化
智能监控增强告警降噪聚合、根因分析、规则自动生成
通用助手自然语言 K8s 操作、知识问答、审计报告、成本分析

安全护栏(5 层):

  1. 权限继承(AI ≤ 当前用户)
  2. 危险操作拦截(DELETE / DRAIN / 修改 limit → 二次确认)
  3. 审计全记录
  4. 幻觉防护(RAG 强制引用源 + 数据类回答附带 PromQL 来源)
  5. 模型隔离(隐私域数据只走本地模型)

Module 8:AI 辅助排障(专项)

覆盖场景:

类别具体故障
应用异常CrashLoopBackOff / OOMKilled / ImagePullBackOff / 探针失败
性能劣化P99 飙升 / CPU throttle / 内存泄漏 / GC 频繁
调度失败Pending 资源不足 / 亲和性不满足 / taint 未容忍
网络问题Service 不通 / DNS 失败 / Ingress 502 / NetworkPolicy 误拦
存储问题PVC Pending / PV 只读 / 磁盘满 / inode 耗尽
平台组件etcd 延迟 / apiserver 超时 / CoreDNS 慢 / CNI 异常

排障工作流:

触发(手动/告警自动/对话)
  → 并行数据采集(Pod状态/Events/日志/指标/变更记录)
  → 规则引擎快速匹配(确定性故障)
  → LLM 深度推理(复杂/未知故障)
  → 结果呈现(根因+证据+修复建议+操作按钮)
  → 安全护栏校验
  → 执行修复(低风险自动/中风险确认/高风险审批)
  → 验证闭环(等待+N秒复查)
  → 知识沉淀(成功→知识库草稿→审核入库)

五、性能优化设计

5.1 问题定义

场景痛点不优化时的表现
应用列表万级 Deployment 全量拉取单次请求 30MB+,前端卡死
看板刷新轮询全量指标每 10s 一次重查询,DB 压力巨大
详情页加载所有 Pod + 日志 + 事件首屏 > 5s
告警风暴瞬间上千条通知通道被打爆

5.2 应用列表:分页 + 字段裁剪 + 虚拟滚动

5.2.1 后端:游标分页 + 稀疏输出

核心原则:永远不用全量 List,始终带 Limit + Continue + FieldSelector

接口返回字段数数据量估算用途
GET /api/v1/apps?fields=summary12 字段~2KB/条列表页(默认)
GET /api/v1/apps/:name?fields=basic~30 字段~8KB详情页概览
GET /api/v1/apps/:name?fields=full全部~50KB+YAML 编辑 / 高级配置

字段白名单机制:

  • 前端通过 ?fields=summary 指定输出级别
  • 后端校验字段白名单,拒绝非法字段(防止内部字段泄露)
  • summary 级别只返回:name / namespace / replicas / ready_replicas / image / zone / team / status / restarts / age / owner / alert_level
  • 不返回:spec.template.spec.containers 完整定义、volume 详情、env 列表等重字段

分页策略:K8s 原生 Continue Token(游标分页)

请求:GET /api/v1/apps?cluster_id=xxx&zone=core&page_size=20&fields=summary
响应:{
  "items": [...20条 SlimAppInfo...],
  "next_token": "eyJ2I...",   // K8s 原生 continue token
  "remaining": 234              // 剩余总数(K8s 返回 RemainingItemCount)
}

下次请求带 continue token 即可,无需 offset

优势:

  • 无 offset 性能衰减(万级数据第 100 页也不会变慢)
  • 与 K8s apiserver 的 List 机制天然对齐
  • 数据一致性好(基于 resourceVersion 的快照)

5.2.2 前端:虚拟滚动

技术选型说明
组件vue-virtual-scrollerRecycleScroller
原理只渲染可视区域行(约 15-20 行 DOM),滚动时复用
效果万级列表 DOM 节点恒定 < 50 个,60fps 流畅滚动
配合下拉到底 → 触发 loadMore → 携带 next_token 请求下一页

搜索/筛选策略:

  • 关键词搜索:前端输入 300ms 防抖后发送请求
  • 域筛选:切换域 → 重置列表 + 从头加载
  • 状态筛选:前端本地过滤(已加载的数据),不需要重新请求

5.2.3 并行查询优化

应用列表加载流程(并行):

主请求:GET /api/v1/apps?fields=summary&page_size=20

  ├── 并行1:List Deployments (LabelSelector=zone=core, Limit=20)
  ├── 并行2:List Pods (LabelSelector=app=xxx, 只取 status)  → 计算 Ready 数
  └── 并行3:查 Redis 缓存的应用摘要(owner / alert_level)

汇总 → SlimAppInfo[] → 返回前端

goroutine Pool 控制并发:

  • 单请求最多 10 个并行 goroutine
  • 超过则排队,防止 apiserver 被打爆
  • 超时控制:单 goroutine 超时 3s,超时返回降级数据

5.3 三级缓存架构

┌─────────────────────────────────────────────────────────┐
│  L1: API Server 本地内存缓存(最热数据,TTL 5s)         │
│  ├── Deployment 列表摘要(metadata only)→ sync.Map      │
│  ├── Node 资源水位 → atomic.Value                        │
│  ├── 域资源汇总(Request%/Limit%/Actual%)               │
│  └── 命中率: ~60%,延迟 < 1ms                           │
├─────────────────────────────────────────────────────────┤
│  L2: Redis 缓存(跨 API 实例共享,TTL 30s)              │
│  ├── 域资源汇总                                          │
│  ├── 应用列表摘要(SlimAppInfo[])                       │
│  ├── Pod 状态聚合                                        │
│  ├── 用户/负责人映射表                                   │
│  └── 命中率: ~30%,延迟 < 5ms                           │
├─────────────────────────────────────────────────────────┤
│  L3: 直连 K8s API(兜底)                               │
│  ├── 始终用 ?resourceVersion=xxx 做 watch 增量           │
│  ├── List 时带 Limit + Continue                         │
│  └── 延迟: 50ms ~ 2s(取决于 apiserver 负载)           │
└─────────────────────────────────────────────────────────┘

缓存键设计:

缓存键TTL内容失效策略
cache:deployments:{cluster}:{ns}:summary30sSlimAppInfo[] JSONWrite-through(Deployment 变更时主动失效)
cache:zone:{cluster}:{zone}:quota10s域资源水位Watch 事件触发失效
cache:node:{cluster}:{node}:allocatable60s节点可分配资源节点状态变更时失效
cache:owners:{cluster}:{app}5min应用负责人列表负责人变更时失效

Write-Through 失效:

  • Watch Deployment 变更事件 → 收到 ADDED / MODIFIED / DELETED → 立即删除对应缓存键
  • 下次请求自动从 K8s API 拉取并重新缓存
  • 保证缓存与 apiserver 最终一致

5.4 Watch 增量代替轮询

看板数据刷新策略:

数据类型刷新方式频率
应用列表WebSocket 增量推送(Watch → WS)事件驱动,亚秒级
域资源水位前端定时轮询(带 Redis 缓存)10s
节点详情前端定时轮询5s
告警列表WebSocket 推送事件驱动
AI 洞察轮询30s

WebSocket 连接管理:

前端建立 WS 连接:
  ws://platform.example.com/api/v1/ws/deployments?cluster_id=xxx&zone=core

后端 Watch K8s Deployment → 事件转换 → WS 推送:
  { "type": "ADDED", "app": "payment-service", "data": {...} }
  { "type": "MODIFIED", "app": "payment-service", "data": {...} }
  { "type": "DELETED", "app": "payment-service" }

前端收到增量 → 更新 Pinia store → Vue 响应式渲染
(不重新拉列表,只更新变化的行)

优势:

  • 看板实时性从 30s 轮询 → 亚秒级事件驱动
  • 减少 90% 的 HTTP 请求量
  • 服务器资源消耗更低(Watch 是长连接,比反复 List 轻量)

5.5 应用详情页:按需加载(Lazy Load)

详情页 Tab 结构:

┌──────────────────────────────────────────────────────┐
│  基本信息(首屏立即加载,fields=basic)               │
│  ├── 名称/镜像/副本数/状态/负责人                     │
│  └── 操作按钮(发布/回滚/扩缩/AI诊断)                │
├──────────────────────────────────────────────────────┤
│  [Pod列表] [日志] [事件] [监控] [配置] [YAML]         │
│                                                      │
│  每个 Tab 点击时才加载对应数据(懒加载)               │
│  ├── Pod列表:fields=summary(只返回 Pod 状态摘要)   │
│  ├── 日志:按需选择容器 + 时间范围                    │
│  ├── 事件:最近 50 条                                │
│  ├── 监控:Prometheus 查询(带时间范围)              │
│  ├── 配置:关联的 ConfigMap/Secret 列表               │
│  └── YAML:完整 Deployment YAML(仅高级用户需要)      │
└──────────────────────────────────────────────────────┘

首屏加载优化目标:

  • 基本信息:< 500ms(走 L1/L2 缓存)
  • 页面可交互:< 1s
  • 后续 Tab 点击:< 2s

5.6 告警风暴防护

策略说明
时间窗口合并同应用 5min 内多条告警合并为一条
AI 聚合同域 5min 内多条告警 → AI 分析根因 → 一条聚合告警
速率限制单应用每分钟最多发 3 条通知,超出丢弃并标记
静默期告警恢复后 10min 内不再发送同类型告警
负责人路由告警只发给应用绑定的负责人,不广播全员

六、应用负责人绑定 & 飞书告警通知设计

6.1 设计目标

目标说明
精准触达告警直接发给应用的负责人,而非广播到群
多负责人一个应用可绑定多个负责人(主备机制)
多渠道飞书(主)+ 邮件(备)+ Webhook(自定义)
级别控制负责人可选择接收全部 / 仅严重 / 不接收
降级策略无负责人时降级到域管理员 → 超级管理员

6.2 数据模型

app_owners(应用负责人绑定表)
├── id: UUID
├── cluster_id → clusters.id
├── namespace: VARCHAR(100)
├── app_name: VARCHAR(200)
├── owner_type: user / team / group
├── owner_id: → users.id / teams.id
├── notify_channels: ["feishu", "email", "webhook"]
├── alert_level: all / critical_only / none
└── UNIQUE(cluster_id, namespace, app_name, owner_id)

notification_targets(通知渠道配置)
├── id: UUID
├── type: feishu_webhook / feishu_user / email
├── identifier: webhook URL / email / open_id
├── display_name: VARCHAR(200)
├── extra: JSONB(如 { "chat_id": "oc_xxx" })
└── enabled: BOOLEAN

users(用户表扩展字段)
├── feishu_open_id: VARCHAR(100) UNIQUE
├── feishu_email: VARCHAR(200)
└── feishu_chat_id: VARCHAR(100)(个人群聊 ID)

6.3 负责人绑定流程

应用创建/编辑


填写基本信息(名称/镜像/域/资源)


┌──────────────────────────────────┐
│  负责人配置                       │
│                                   │
│  搜索用户/团队 → 添加到列表        │
│                                   │
│  每个负责人独立配置:              │
│  ├── 通知渠道(飞书 ✓ / 邮件 ✓)  │
│  └── 告警级别(全部 / 仅严重)     │
│                                   │
│  [搜索添加] [批量导入]             │
└──────────────────────────────────┘


保存 → 写入 app_owners 表 → 校验飞书 open_id 是否存在


如果负责人没有飞书 open_id → 发送邀请链接(首次绑定)

6.4 告警路由引擎

告警产生(Prometheus Alert → Alertmanager → 平台 Webhook)


解析告警 → 提取 cluster / namespace / app_name / severity


查找负责人(app_owners 表)

  ├── 找到负责人 → 按 alert_level 过滤
  │     ├── all → 全部告警都通知
  │     ├── critical_only → 仅 Critical 通知
  │     └── none → 跳过此人

  └── 未找到 → 降级到域管理员 → 再降级到超级管理员


按渠道分发通知
  ├── 飞书群机器人 Webhook → 发送卡片消息
  ├── 飞书个人消息 → 通过 open_id 发送
  ├── 邮件 → SMTP 发送
  └── Webhook → POST JSON 到自定义 URL


记录通知日志(谁 / 什么告警 / 什么渠道 / 是否成功)

6.5 飞书消息卡片设计

6.5.1 告警通知卡片

┌──────────────────────────────────────────────────┐
│ 🔴 Critical │ 核心域 payment-service 5xx 率异常   │
├──────────────────────────────────────────────────┤
│ **应用**: payment-service                        │
│ **集群**: prod-cluster-01                        │
│ **域**: core                                    │
│ **时间**: 2026-07-31 14:23:05                   │
│ **当前 5xx 率**: 8.3% (阈值 5%)                  │
│ **影响副本**: 3/5 pods                           │
│                                                  │
│ 🤖 **AI 初步分析**:                              │
│ 30分钟前发布 v2.4 后开始出现 5xx                 │
│ 置信度: 82%                                     │
├──────────────────────────────────────────────────┤
│  [📋 查看详情]  [🤖 AI 诊断]  [🔙 一键回滚]      │
└──────────────────────────────────────────────────┘

6.5.2 飞书卡片交互能力

按钮行为权限校验
📋 查看详情打开平台应用详情页需登录
🤖 AI 诊断跳转平台并执行 AI 诊断需该应用读权限
🔙 一键回滚跳转平台回滚确认页需该应用写权限
✅ 认领标记告警为"处理中"需该应用读权限
🔕 静默 1h该告警 1 小时内不再通知需该应用写权限

6.5.3 卡片消息类型选择

场景通知方式说明
应用有负责人飞书群机器人 Webhook发到团队群,所有人可见
紧急告警(Critical)飞书个人消息 + 群消息双重保障,确保看到
无负责人降级飞书群机器人 → 域管理员群兜底通知
隐私域告警飞书个人消息(加密卡片)不在群内讨论,防止信息泄露

6.6 飞书集成方案

6.6.1 集成架构

平台通知服务

  ├── 飞书开放平台 API
  │   ├── 发送群消息:POST /open-apis/bot/v2/hook/{webhook_key}
  │   ├── 发送个人消息:POST /open-apis/im/v1/messages
  │   ├── 获取用户信息:GET /open-apis/contact/v3/users/{open_id}
  │   └── 卡片交互回调:平台接收飞书 action 事件

  ├── 飞书应用配置
  │   ├── App ID / App Secret(AES-256 加密存储)
  │   ├── 权限范围:im:message / im:message.group_at_msg
  │   └── 事件订阅:im.message.receive_v1(接收卡片按钮点击)

  └── 个人消息 vs 群消息
      ├── 群消息:用 Bot Webhook URL(简单,无需用户授权)
      └── 个人消息:需获取用户 open_id(首次需用户授权绑定)

6.6.2 用户首次绑定飞书流程

平台用户管理页面


点击 "绑定飞书"


平台生成授权链接(飞书 OAuth2)


用户点击链接 → 跳转飞书授权页 → 确认授权


飞书回调平台 → 平台获取用户 open_id + email


写入 users 表(feishu_open_id / feishu_email)


绑定完成 → 后续可直接发个人消息

6.7 通知降级策略

Level 0: 应用负责人(飞书 + 邮件)
    │ 如果不存在或通知失败

Level 1: 域管理员(飞书群)
    │ 如果不存在或通知失败

Level 2: 超级管理员(飞书 + 邮件 + 电话)
    │ 如果不存在或通知失败

Level 3: 写入告警池(平台内可见)+ 日志记录

6.8 通知日志与效果追踪

字段说明
notification_idUUID
alert_id关联的告警 ID
target_typefeishu_webhook / feishu_user / email
target_identifier接收方标识
statussuccess / failed / timeout
sent_at发送时间
delivered_at飞书回调确认时间(如有)
clicked接收方是否点击了卡片按钮
click_action点击了哪个按钮(查看/回滚/认领)
error_msg失败原因

效果分析:

  • 统计每个负责人的"告警响应时间"(从发送到点击)
  • 识别"告警黑洞"(某些告警始终无人响应)
  • 优化负责人配置建议

七、数据库设计(完整 ER 关系)

clusters (1) ────< (N) zone_policies

clusters (1) ────< (N) namespaces ────┘

clusters (1) ────< (N) node_info      │

users (1) ────< (N) app_definitions ──┘

app_definitions (1) ──< (N) app_releases

users (1) ────< (N) audit_logs
users (1) ────< (N) ai_conversations (1) ──< (N) ai_messages
ai_conversations (1) ──< (N) ai_tool_audit

clusters (1) ────< (N) ai_insights
clusters (1) ────< (N) ai_diagnoses (1) ──< (1) ai_diagnosis_snapshots

users (1) ────< (N) ai_troubleshooting_kb

app_owners (N) ────> (1) users / teams
app_owners (N) ────> (1) app_definitions
notification_targets (1) ────< (N) notification_logs

7.1 完整建表 SQL

sql
-- ============================================
-- 集群表
-- ============================================
CREATE TABLE clusters (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name            VARCHAR(100) NOT NULL UNIQUE,
    api_server      VARCHAR(500) NOT NULL,
    kubeconfig_enc  TEXT NOT NULL,                    -- AES-256 加密
    ca_cert         TEXT,
    token_enc       TEXT,
    cluster_type    VARCHAR(20) NOT NULL DEFAULT 'normal', -- normal / private
    status          VARCHAR(20) NOT NULL DEFAULT 'unknown',
    version         VARCHAR(50),
    node_count      INT NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================
-- 域策略表
-- ============================================
CREATE TABLE zone_policies (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    zone_name       VARCHAR(50) NOT NULL,
    display_name    VARCHAR(100),
    oversell_ratio  DECIMAL(5,2) NOT NULL DEFAULT 1.0,
    request_limit_ratio DECIMAL(5,2) NOT NULL DEFAULT 1.0,
    hpa_min_replicas INT NOT NULL DEFAULT 1,
    hpa_max_replicas INT NOT NULL DEFAULT 10,
    hpa_cpu_threshold INT NOT NULL DEFAULT 70,
    hpa_mem_threshold INT,
    resource_quota  JSONB NOT NULL DEFAULT '{}',
    taint_key       VARCHAR(100),
    taint_effect    VARCHAR(50),
    network_policy  VARCHAR(20) DEFAULT 'allow',     -- allow / deny_all / custom
    egress_whitelist JSONB DEFAULT '[]',
    ttl_hours       INT,                              -- 异常域 TTL
    is_default      BOOLEAN NOT NULL DEFAULT FALSE,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(cluster_id, zone_name)
);

-- ============================================
-- Namespace 表
-- ============================================
CREATE TABLE namespaces (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    name            VARCHAR(100) NOT NULL,
    team            VARCHAR(100),
    zone            VARCHAR(50),
    labels          JSONB NOT NULL DEFAULT '{}',
    resource_quota  JSONB NOT NULL DEFAULT '{}',
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(cluster_id, name)
);

-- ============================================
-- 节点信息表
-- ============================================
CREATE TABLE node_info (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    node_name       VARCHAR(200) NOT NULL,
    zone            VARCHAR(50),
    labels          JSONB NOT NULL DEFAULT '{}',
    taints          JSONB NOT NULL DEFAULT '[]',
    allocatable_cpu INT NOT NULL DEFAULT 0,           -- millicores
    allocatable_mem BIGINT NOT NULL DEFAULT 0,         -- bytes
    capacity_cpu    INT NOT NULL DEFAULT 0,
    capacity_mem    BIGINT NOT NULL DEFAULT 0,
    instance_type   VARCHAR(100),
    lifecycle       VARCHAR(20) DEFAULT 'on-demand',  -- on-demand / spot
    conditions      JSONB NOT NULL DEFAULT '{}',
    status          VARCHAR(20) NOT NULL DEFAULT 'Unknown',
    synced_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(cluster_id, node_name)
);

-- ============================================
-- 用户表
-- ============================================
CREATE TABLE users (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username        VARCHAR(100) NOT NULL UNIQUE,
    display_name    VARCHAR(200),
    email           VARCHAR(200) UNIQUE,
    password_hash   VARCHAR(500),                      -- bcrypt
    role            VARCHAR(20) NOT NULL DEFAULT 'readonly', -- super_admin / zone_admin / readonly
    managed_zones   TEXT[] DEFAULT '{}',               -- 域管理员管理的域列表
    feishu_open_id  VARCHAR(100) UNIQUE,
    feishu_email    VARCHAR(200),
    feishu_chat_id  VARCHAR(100),
    enabled         BOOLEAN NOT NULL DEFAULT TRUE,
    last_login_at   TIMESTAMPTZ,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================
-- 应用定义表
-- ============================================
CREATE TABLE app_definitions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    namespace       VARCHAR(100) NOT NULL,
    name            VARCHAR(200) NOT NULL,
    display_name    VARCHAR(200),
    team            VARCHAR(100),
    zone_preferred  VARCHAR(50),
    zone_fallback   VARCHAR(50),
    template_ref    VARCHAR(100),
    image           VARCHAR(500),
    replicas        INT NOT NULL DEFAULT 1,
    resources       JSONB NOT NULL DEFAULT '{}',
    health_check    JSONB,
    hpa_config      JSONB,
    config_refs     JSONB DEFAULT '[]',
    ports           JSONB DEFAULT '[]',
    domain          VARCHAR(200),
    labels          JSONB DEFAULT '{}',
    status          VARCHAR(20) DEFAULT 'Unknown',
    created_by      UUID REFERENCES users(id),
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(cluster_id, namespace, name)
);

-- ============================================
-- 应用发布记录表
-- ============================================
CREATE TABLE app_releases (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    app_def_id      UUID NOT NULL REFERENCES app_definitions(id) ON DELETE CASCADE,
    version         VARCHAR(100) NOT NULL,
    strategy        VARCHAR(50) NOT NULL DEFAULT 'RollingUpdate',
    image           VARCHAR(500) NOT NULL,
    config_snapshot JSONB NOT NULL DEFAULT '{}',
    status          VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending/success/failed/rolled_back
    deployed_by     UUID REFERENCES users(id),
    deployed_at     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    finished_at     TIMESTAMPTZ,
    rollback_of     UUID REFERENCES app_releases(id),
    ai_risk_assessment JSONB,                          -- AI 发布风险评估结果
    UNIQUE(app_def_id, version, deployed_at)
);

-- ============================================
-- 应用负责人绑定表
-- ============================================
CREATE TABLE app_owners (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    namespace       VARCHAR(100) NOT NULL,
    app_name        VARCHAR(200) NOT NULL,
    owner_type      VARCHAR(20) NOT NULL DEFAULT 'user',   -- user / team
    owner_id        UUID NOT NULL,                         -- → users.id
    notify_channels JSONB NOT NULL DEFAULT '["feishu"]',
    alert_level     VARCHAR(20) NOT NULL DEFAULT 'all',    -- all / critical_only / none
    is_primary      BOOLEAN NOT NULL DEFAULT FALSE,        -- 是否主负责人
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(cluster_id, namespace, app_name, owner_id)
);

CREATE INDEX idx_app_owners_lookup ON app_owners(cluster_id, namespace, app_name);

-- ============================================
-- 通知渠道配置表
-- ============================================
CREATE TABLE notification_targets (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    type            VARCHAR(20) NOT NULL,                  -- feishu_webhook / feishu_user / email
    identifier      VARCHAR(500) NOT NULL,                 -- webhook URL / email / open_id
    display_name    VARCHAR(200),
    extra           JSONB,
    enabled         BOOLEAN NOT NULL DEFAULT TRUE,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(type, identifier)
);

-- ============================================
-- 通知日志表
-- ============================================
CREATE TABLE notification_logs (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    alert_id        UUID,
    app_owner_id    UUID REFERENCES app_owners(id),
    target_type     VARCHAR(20) NOT NULL,
    target_identifier VARCHAR(500) NOT NULL,
    status          VARCHAR(20) NOT NULL,                  -- success / failed / timeout
    sent_at         TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    delivered_at    TIMESTAMPTZ,
    clicked         BOOLEAN NOT NULL DEFAULT FALSE,
    click_action    VARCHAR(50),
    error_msg       TEXT
);

CREATE INDEX idx_notif_logs_alert ON notification_logs(alert_id);
CREATE INDEX idx_notif_logs_time ON notification_logs(sent_at DESC);

-- ============================================
-- 审计日志表(append-only)
-- ============================================
CREATE TABLE audit_logs (
    id              BIGSERIAL PRIMARY KEY,
    user_id         UUID REFERENCES users(id),
    username        VARCHAR(100),
    cluster_id      UUID REFERENCES clusters(id),
    namespace       VARCHAR(100),
    action          VARCHAR(100) NOT NULL,                 -- create / update / delete / scale / rollback
    resource_type   VARCHAR(50) NOT NULL,                 -- deployment / configmap / zone / cluster
    resource_name   VARCHAR(200),
    before_state    JSONB,
    after_state     JSONB,
    source_ip       INET,
    user_agent      VARCHAR(500),
    is_ai_operation BOOLEAN NOT NULL DEFAULT FALSE,
    ai_conversation_id UUID,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- 禁止 UPDATE/DELETE(append-only)
CREATE RULE audit_no_update AS ON UPDATE TO audit_logs DO INSTEAD NOTHING;
CREATE RULE audit_no_delete AS ON DELETE TO audit_logs DO INSTEAD NOTHING;
CREATE INDEX idx_audit_time ON audit_logs(created_at DESC);
CREATE INDEX idx_audit_user ON audit_logs(user_id, created_at DESC);
CREATE INDEX idx_audit_resource ON audit_logs(resource_type, resource_name);

-- ============================================
-- AI 对话会话表
-- ============================================
CREATE TABLE ai_conversations (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id         UUID NOT NULL REFERENCES users(id),
    cluster_id      UUID REFERENCES clusters(id),
    title           VARCHAR(255),
    summary         TEXT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================
-- AI 对话消息表
-- ============================================
CREATE TABLE ai_messages (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    conversation_id UUID NOT NULL REFERENCES ai_conversations(id) ON DELETE CASCADE,
    role            VARCHAR(20) NOT NULL,                  -- user / assistant / system / tool
    content         TEXT NOT NULL,
    tool_calls      JSONB,
    tool_results    JSONB,
    tokens_used     INT,
    latency_ms      INT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================
-- AI 知识库表(RAG)
-- ============================================
CREATE TABLE ai_knowledge_base (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    title           VARCHAR(255) NOT NULL,
    content         TEXT NOT NULL,
    source_type     VARCHAR(50) NOT NULL,                 -- runbook / sop / k8s_doc / custom
    source_ref      VARCHAR(500),
    embedding       VECTOR(1536),
    tags            TEXT[],
    created_by      UUID REFERENCES users(id),
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_kb_embedding ON ai_knowledge_base
    USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

-- ============================================
-- AI 洞察表
-- ============================================
CREATE TABLE ai_insights (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    insight_type    VARCHAR(50) NOT NULL,                 -- scheduling / anomaly / cost / security
    severity        VARCHAR(20) NOT NULL DEFAULT 'info',
    cluster_id      UUID REFERENCES clusters(id),
    zone            VARCHAR(50),
    namespace       VARCHAR(100),
    app_name        VARCHAR(200),
    title           VARCHAR(500) NOT NULL,
    description     TEXT NOT NULL,
    recommendation  TEXT,
    actions         JSONB,
    status          VARCHAR(20) NOT NULL DEFAULT 'open',  -- open / acknowledged / resolved / dismissed
    acknowledged_by UUID REFERENCES users(id),
    acknowledged_at TIMESTAMPTZ,
    expires_at      TIMESTAMPTZ,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================
-- AI 诊断记录表
-- ============================================
CREATE TABLE ai_diagnoses (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID NOT NULL REFERENCES clusters(id),
    namespace       VARCHAR(100) NOT NULL,
    app_name        VARCHAR(200) NOT NULL,
    trigger_type    VARCHAR(50) NOT NULL,                 -- manual / alert_auto / chat
    trigger_source  VARCHAR(500),
    root_cause      TEXT NOT NULL,
    confidence      INT NOT NULL CHECK (confidence >= 0 AND confidence <= 100),
    evidence        JSONB NOT NULL DEFAULT '[]',
    suggestions     JSONB NOT NULL DEFAULT '[]',
    status          VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending / fixed / ignored / escalated
    fixed_by        UUID REFERENCES users(id),
    fix_action      VARCHAR(100),
    feedback        VARCHAR(20),                         -- helpful / not_helpful
    feedback_note   TEXT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    resolved_at     TIMESTAMPTZ
);

-- ============================================
-- AI 诊断数据快照表
-- ============================================
CREATE TABLE ai_diagnosis_snapshots (
    diagnosis_id    UUID PRIMARY KEY REFERENCES ai_diagnoses(id) ON DELETE CASCADE,
    pod_status      JSONB,
    events          JSONB,
    metrics_summary JSONB,
    recent_logs     TEXT,
    recent_changes  JSONB
);

-- ============================================
-- AI 排障知识库表
-- ============================================
CREATE TABLE ai_troubleshooting_kb (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    symptom         VARCHAR(500) NOT NULL,
    root_cause      TEXT NOT NULL,
    diagnosis_steps TEXT NOT NULL,
    solution        TEXT NOT NULL,
    tech_stack      VARCHAR(100),
    zone            VARCHAR(50),
    hit_count       INT NOT NULL DEFAULT 0,
    success_count   INT NOT NULL DEFAULT 0,
    created_from    UUID REFERENCES ai_diagnoses(id),
    verified        BOOLEAN NOT NULL DEFAULT FALSE,
    created_by      UUID REFERENCES users(id),
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_ts_kb_symptom ON ai_troubleshooting_kb USING gin(to_tsvector('simple', symptom));

-- ============================================
-- AI 工具审计表
-- ============================================
CREATE TABLE ai_tool_audit (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id         UUID NOT NULL REFERENCES users(id),
    conversation_id UUID REFERENCES ai_conversations(id),
    tool_name       VARCHAR(100) NOT NULL,
    tool_input      JSONB NOT NULL,
    tool_output     JSONB,
    success         BOOLEAN NOT NULL,
    error_msg       TEXT,
    safety_check    JSONB,
    executed_at     TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================
-- 告警规则表
-- ============================================
CREATE TABLE alert_rules (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID REFERENCES clusters(id),
    zone            VARCHAR(50),
    name            VARCHAR(200) NOT NULL,
    expr            TEXT NOT NULL,                        -- PromQL
    duration        VARCHAR(20) NOT NULL DEFAULT '5m',
    severity        VARCHAR(20) NOT NULL DEFAULT 'warning',
    annotations     JSONB DEFAULT '{}',
    notify_channels JSONB DEFAULT '["feishu"]',
    enabled         BOOLEAN NOT NULL DEFAULT TRUE,
    created_by      UUID REFERENCES users(id),
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================
-- 告警事件表
-- ============================================
CREATE TABLE alert_events (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID REFERENCES clusters(id),
    zone            VARCHAR(50),
    namespace       VARCHAR(100),
    app_name        VARCHAR(200),
    alert_name      VARCHAR(200) NOT NULL,
    severity        VARCHAR(20) NOT NULL,
    summary         TEXT NOT NULL,
    description     TEXT,
    status          VARCHAR(20) NOT NULL DEFAULT 'firing', -- firing / resolved
    started_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    resolved_at     TIMESTAMPTZ,
    ai_aggregated   BOOLEAN NOT NULL DEFAULT FALSE,
    ai_root_cause   TEXT,
    ai_confidence   INT
);

CREATE INDEX idx_alert_events_active ON alert_events(cluster_id, status, started_at DESC);
CREATE INDEX idx_alert_events_app ON alert_events(cluster_id, namespace, app_name, started_at DESC);

-- ============================================
-- 标签字典表
-- ============================================
CREATE TABLE label_dictionary (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    category        VARCHAR(50) NOT NULL,                 -- system / business / scheduling / custom
    key             VARCHAR(100) NOT NULL,
    allowed_values  TEXT[] NOT NULL DEFAULT '{}',
    description     VARCHAR(500),
    is_required     BOOLEAN NOT NULL DEFAULT FALSE,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(category, key)
);

-- ============================================
-- 成本记录表
-- ============================================
CREATE TABLE cost_records (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    cluster_id      UUID REFERENCES clusters(id),
    zone            VARCHAR(50),
    namespace       VARCHAR(100),
    app_name        VARCHAR(200),
    resource_type   VARCHAR(20) NOT NULL,                 -- cpu / memory / storage / network
    consumed_amount DECIMAL(12,4) NOT NULL,
    unit_price      DECIMAL(10,4),
    cost_cny        DECIMAL(12,2),
    record_date     DATE NOT NULL,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_cost_records ON cost_records(cluster_id, zone, record_date DESC);

八、API 设计总览

8.1 路由总表

模块路由前缀主要端点
认证/api/v1/authPOST /login, GET /me, POST /refresh
用户/api/v1/usersCRUD + POST /:id/bind-feishu
集群/api/v1/clustersCRUD + GET /:id/health + GET /:id/nodes
/api/v1/zonesCRUD + GET /:id/nodes + GET /:id/quota
标签/api/v1/labelsGET /dictionary, POST /validate, GET /drift
应用/api/v1/appsCRUD + POST /:id/deploy + POST /:id/rollback
应用列表/api/v1/appsGET ?fields=summary&page_size=20&continue=xxx
应用负责人/api/v1/apps/:id/ownersGET / POST / DELETE
看板/api/v1/dashboardGET /global, GET /zones/:name, GET /nodes/:node
监控/api/v1/monitoringGET /metrics, GET /alerts, POST /alert-rules
通知/api/v1/notificationsGET /logs, POST /test, GET /targets
审计/api/v1/auditGET /logs, GET /export
WebSocket/api/v1/ws/deploymentsWS 增量推送
AI 对话/api/v1/ai/chatPOST (SSE 流式), GET /conversations
AI 诊断/api/v1/ai/diagnosisPOST /app, POST /pod, POST /alert, GET /history
AI 洞察/api/v1/ai/insightsGET, POST /:id/ack, POST /:id/dismiss
AI 知识库/api/v1/ai/knowledgeCRUD
AI 排障KB/api/v1/ai/troubleshootingCRUD + POST /:id/verify

8.2 关键接口规格

应用列表接口

GET /api/v1/apps

Query Parameters:
├── cluster_id     (required)  UUID    目标集群
├── zone           (optional)  string  按域筛选
├── namespace      (optional)  string  按命名空间筛选
├── keyword        (optional)  string  模糊匹配应用名
├── status         (optional)  string  Healthy / Degraded / Error
├── page_size      (optional)  int     每页数量,默认 20,最大 50
├── continue       (optional)  string K8s continue token(游标)
└── fields         (optional)  string  summary / basic / full(默认 summary)

Response (200 OK):
{
  "items": [
    {
      "name": "payment-service",
      "namespace": "team-payment",
      "replicas": 5,
      "ready_replicas": 3,
      "image": "registry.example.com/payment:v2.4",
      "zone": "core",
      "team": "payment",
      "status": "Degraded",
      "restarts": 12,
      "age": "3d2h",
      "owner": "张三",
      "alert_level": "all"
    }
  ],
  "next_token": "eyJ2Ijoi...",
  "remaining": 234
}

Error Responses:
├── 400  invalid field in fields parameter
├── 401  unauthorized
├── 403  cluster access denied
└── 504  k8s api timeout (after retry)

应用负责人接口

GET /api/v1/apps/:cluster_id/:namespace/:app_name/owners

Response:
{
  "owners": [
    {
      "id": "uuid-xxx",
      "owner_type": "user",
      "name": "张三",
      "email": "zhangsan@example.com",
      "notify_channels": ["feishu", "email"],
      "alert_level": "all",
      "is_primary": true,
      "feishu_bound": true
    }
  ]
}

POST /api/v1/apps/:cluster_id/:namespace/:app_name/owners
Request Body:
{
  "owner_type": "user",
  "owner_id": "uuid-xxx",
  "notify_channels": ["feishu"],
  "alert_level": "critical_only",
  "is_primary": false
}

DELETE /api/v1/apps/:cluster_id/:namespace/:app_name/owners/:owner_id

飞书绑定接口

POST /api/v1/users/:id/bind-feishu
Request Body:
{
  "auth_code": "string"  // 飞书 OAuth2 授权码
}
Response:
{
  "feishu_open_id": "ou_xxx",
  "feishu_email": "user@example.com",
  "bound": true
}

POST /api/v1/notifications/test
Request Body:
{
  "channel": "feishu",
  "target": "oc_xxx or open_id",
  "message": "测试告警通知"
}

九、AI 模块详细设计

9.1 AI Orchestrator 内部架构

User Input / System Trigger


┌─────────────────┐
│  Intent Parser   │ → 分类意图(诊断/查询/操作/分析)
└────────┬────────┘


┌─────────────────┐
│ Context Builder  │ → 组装上下文(集群/域/应用/时间范围/用户权限)
└────────┬────────┘


┌─────────────────┐
│ Tool Dispatcher  │ → 并行/串行调用 Tools
│                  │    ├── k8s_read (pods/events/logs/metrics)
│                  │    ├── k8s_write (scale/restart/patch)
│                  │    ├── platform_query (DB查询)
│                  │    └── knowledge_search (RAG)
└────────┬────────┘


┌─────────────────┐
│  Rules Engine   │ → 确定性规则先匹配(OOM/Pending/ImagePull等)
│                  │    命中 → 直接返回结果(不走LLM)
│                  │    未命中 → 进入 LLM 推理
└────────┬────────┘


┌─────────────────┐
│  LLM Client     │ → 构造 Prompt → 调用模型 → 解析输出
│                  │    本地 Ollama (默认) / 公有云API (兜底)
└────────┬────────┘


┌─────────────────┐
│ Safety Guardrail│ → 权限校验 / 危险操作拦截 / 输出审查
└────────┬────────┘


    Response / Action

9.2 LLM 接入策略

场景模型选择原因
排障诊断(含日志分析)本地 Qwen2.5-72B日志可能含敏感信息,不外传
告警降噪聚合本地 Qwen2.5-72B同上
调度推荐本地 Qwen2.5-14B轻量快速
知识问答(公开文档)公有云 API(可选)更快更准
隐私域任何操作仅本地模型合规红线

9.3 排障规则引擎(内置规则清单)

#规则名触发条件置信度
R01OOMKilledLastTerminationState.Reason == "OOMKilled"100%
R02ImagePullBackOffEvent Reason == FailedToPullImage100%
R03资源不足 PendingEvent Message contains "Insufficient cpu/memory"100%
R04Taint 未容忍Event Message contains "node(s) had taint"100%
R05就绪探针失败Event Reason == Unhealthy + Readiness95%
R06存活探针失败Event Reason == Unhealthy + Liveness95%
R075xx 飙升 + 近期发布ErrorRate>5% + Deploy 变更 <1h80%
R08磁盘压力Node Condition DiskPressure=True100%
R09内存泄漏嫌疑Mem Actual 连续 3h 单调增长75%
R10CPU ThrottleCPU Throttling > 50%85%

9.4 排障工作流详细设计

Step 1: 触发
├── 被动:用户点击 "AI 诊断" 按钮
├── 主动:平台收到关键告警时,后台自动触发
└── 对话:用户在 Copilot 中输入自然语言

Step 2: 数据采集(并行)
├── K8s 层:Pod status / Conditions / ContainerStatus
├── Events 层:最近 1h 内该应用的所有 Events
├── 日志层:最近 N 条容器日志(Loki/ES 查询)
├── 指标层:CPU/Mem/QPS/ErrorRate 时序(Prometheus + VM)
├── 变更层:最近 1h/24h 的 Deploy/ConfigMap/Secret 变更
└── 网络层:Service endpoints / DNS / NetworkPolicy(如适用)

Step 3: 因果推理
├── 规则引擎先做确定性匹配(快、零幻觉)
├── LLM 做复杂推理(日志语义理解、多信号关联)
└── 综合打分:根因假设 + 置信度(0-100%)

Step 4: 结果呈现
├── 根因结论(一句话)
├── 证据链(Events 原文 / 日志片段 / 指标截图)
├── 影响范围(多少 Pod / 多少用户受影响)
├── 修复建议(按推荐度排序,1 个最优 + 2 个备选)
└── 可执行操作按钮(一键执行 / 查看详情 / 忽略)

Step 5: 修复执行(安全护栏内)
├── 低风险操作:AI 可直接执行
├── 中风险操作:用户确认后执行
└── 高风险操作:需要二次审批

Step 6: 验证闭环
├── AI 等待 N 秒后自动复查指标
├── 如果恢复正常 → 标记 "已解决",记录到知识库
└── 如果未恢复 → 继续分析,或升级为人工介入

Step 7: 知识沉淀
├── 成功诊断 → 自动生成知识库草稿
├── 人工审核后正式入库
└── 下次同类问题命中知识库 → 直接给出方案(不调 LLM)

十、前端架构设计

10.1 页面结构

src/
├── views/
│   ├── dashboard/
│   │   ├── GlobalOverview.vue       # L1 全局看板
│   │   ├── ZoneDetail.vue           # L2 域详情
│   │   └── NodeDetail.vue           # L3 节点详情
│   ├── applications/
│   │   ├── AppList.vue              # 虚拟滚动列表
│   │   ├── AppDetail.vue            # 详情页(Tab 懒加载)
│   │   ├── AppForm.vue              # 创建/编辑表单
│   │   └── AppOwners.vue            # 负责人管理
│   ├── zones/
│   │   ├── ZoneList.vue
│   │   └── ZoneDetail.vue
│   ├── clusters/
│   │   ├── ClusterList.vue
│   │   └── ClusterDetail.vue
│   ├── monitoring/
│   │   ├── Alerts.vue
│   │   └── AlertRules.vue
│   ├── ai/
│   │   ├── CopilotSidebar.vue       # 全局 AI 侧边栏
│   │   ├── InsightCenter.vue        # AI 洞察中心
│   │   ├── KnowledgeBase.vue        # 知识库管理
│   │   └── AIDiagnosis.vue          # 诊断结果页
│   └── admin/
│       ├── Users.vue
│       ├── AuditLogs.vue
│       └── Settings.vue
├── components/
│   ├── common/
│   │   ├── ResourceBar.vue          # 三色资源条
│   │   ├── SaturationBadge.vue      # 饱和度标签
│   │   └── StatusDot.vue            # 状态指示灯
│   ├── app-list/
│   │   ├── VirtualAppList.vue       # 虚拟滚动列表容器
│   │   ├── AppRow.vue               # 单行应用摘要
│   │   └── AppFilters.vue           # 筛选栏
│   ├── ai/
│   │   ├── ChatMessage.vue          # 对话消息
│   │   ├── InsightCard.vue          # 洞察卡片
│   │   ├── ToolConfirmDialog.vue    # 危险操作确认
│   │   └── StreamText.vue           # 流式文字
│   └── notification/
│       └── FeishuBindDialog.vue     # 飞书绑定弹窗
├── stores/
│   ├── appStore.js                  # 应用列表(支持增量更新)
│   ├── clusterStore.js
│   ├── zoneStore.js
│   └── wsStore.js                  # WebSocket 管理
├── utils/
│   ├── ws.js                        # WebSocket 封装
│   ├── debounce.js
│   └── formatter.js
└── router/
    └── index.js

10.2 虚拟滚动列表实现要点

技术选型:vue-virtual-scroller (RecycleScroller)

关键参数:
├── item-size: 56px(固定行高,性能最优)
├── key-field: "name"(唯一标识)
├── page-mode: false(容器内滚动)
└── emit: scroll-end(触底加载更多)

数据加载策略:
├── 首次加载:page_size=20,fields=summary
├── 触底加载:page_size=20,continue=next_token
├── 筛选变更:重置列表 + 从头加载
├── WS 增量:收到 MODIFIED 事件 → 更新对应行(不重新拉取)
└── 缓存复用:切换域再切回 → 优先从 Pinia store 读取

搜索防抖:
├── 输入 300ms 无变化 → 发送请求
├── 请求进行中 → 新的输入排队,不并发
└── 响应返回 → 替换列表(非追加)

10.3 WebSocket 连接管理

连接生命周期:
├── 页面加载 → 建立 WS 连接(携带 cluster_id + zone 参数)
├── 切换集群/域 → 关闭旧连接 → 建立新连接
├── 连接断开 → 指数退避重连(1s → 2s → 4s → 最大 30s)
└── 页面卸载 → 主动关闭连接

消息类型:
├── DEPLOYMENT_ADDED → store.upsert()
├── DEPLOYMENT_MODIFIED → store.update()
├── DEPLOYMENT_DELETED → store.remove()
├── ALERT_FIRING → notificationStore.add()
├── ALERT_RESOLVED → notificationStore.remove()
└── AI_INSIGHT → insightStore.add()

十一、非功能性需求

维度要求验收方式
平台可用性99.9%(年度停机 < 8.76h)监控平台自身 uptime
API 响应列表页 < 1s(走缓存),详情 < 2s压测验证
并发支持50 并发运维在线操作压测:50 并发持续 10min
数据安全kubeconfig AES-256 加密;HTTPS 全站安全审计
可扩展性新增域类型只需配置 ZonePolicy文档验证
可观测性平台自身指标暴露 Prometheus 格式curl /metrics 验证
兼容性Kubernetes 1.24 ~ 1.30多版本测试
浏览器兼容Chrome 100+, Firefox 100+, Edge 100+手动验证
AI 响应规则命中 < 3s;LLM 诊断 < 30s;流式首字 < 2s计时验证
列表性能万级应用列表首屏 < 1s,滚动 60fpsChrome DevTools 性能分析

十二、实施路线图

Phase周期交付内容
0W1-W2Go 项目骨架 + PG 建表 + Vue3 初始化 + JWT 认证 + Redis 接入
1W3-W4集群注册/健康检查 + RBAC + 节点同步 + 标签字典
2W5-W6域管理 CRUD + 标签体系 + Scheduler Engine + 隐私域网络策略
3W7-W8应用管理(创建/发布/回滚/扩缩)+ 应用负责人绑定 + 飞书通知
4W9-W10智能看板 L1/L2/L3 + WebSocket 增量 + 虚拟滚动列表 + 三级缓存
5W11-W13监控 (Prometheus+VM) + 告警规则 + 飞书告警路由 + 通知降级
6W14-W16AI 基础:Orchestrator + Tools + Copilot UI + 安全护栏 L1-3
7W17-W19AI 进阶:排障规则引擎 + LLM 诊断 + 洞察中心 + 告警降噪
8W20-W22AI 深度:知识沉淀闭环 + 发布风险评估 + 自然语言操作
9W23-W24隐私域增强 + 成本分析 + 审计报表 + 全链路压测验收

十三、待定事项(Open Issues)

#问题决策状态
OI-01告警自动诊断的范围仅手动触发,不做自动诊断推送✅ 已确认
OI-02排障知识库是否对开发团队开放开放,开发可自助查阅知识库排查问题✅ 已确认
OI-03本地 LLM 的 GPU 资源配置需配置 GPU 节点,推荐单卡 A100 80G 或双卡 A6000 48G✅ 已确认
OI-04是否需要对接公司 LDAP/SSO对接 LDAP,Phase 1 即引入(不再延后到 Phase 2)✅ 已确认
OI-05飞书通知方式先 C(仅群机器人),Phase 2 加个人消息✅ 已确认
OI-06列表页默认排序规则按异常程度(Error 排最前)✅ 已确认

OI-01 决策影响说明(仅手动触发 AI 诊断)

告警触发时:
├── 平台照常采集告警并展示在告警列表
├── 不自动调用 AI 诊断
├── 在告警详情页和飞书卡片上显示 [🤖 AI 诊断] 按钮
├── 运维点击按钮后 → 触发诊断流程 → 结果展示
└── 好处:节省 LLM 算力;避免误判干扰;运维按需使用

例外:核心域 + Critical 级别告警 → 仍仅手动(不破例)

OI-02 决策影响说明(知识库对开发开放)

权限模型扩展:
├── 新增角色:developer(开发者)
├── developer 权限:
│   ├── 只读:AI 排障知识库(ai_troubleshooting_kb)
│   ├── 只读:应用基本信息(不含 Secret/ConfigMap 敏感值)
│   ├── 只读:应用日志(已脱敏)
│   └── 不可:发布/回滚/扩缩/删除等任何写操作

├── 知识库可见范围:
│   ├── verified = true 的知识(已审核)
│   └── 不包含内部排障中的草稿和未验证条目

└── 开发者自助排障流程:
    ├── 搜索症状关键词 → 命中知识库
    ├── 查看根因 + 排查步骤 + 解决方案
    ├── 如未命中 → 看到 "联系运维" 按钮
    └── 可评论/点赞知识条目(帮助运维优化内容)

OI-03 决策影响说明(GPU 资源配置)

推荐配置方案:

方案 A(推荐,高性能):
├── GPU:NVIDIA A100 80GB × 1
├── 模型:Qwen2.5-72B-Instruct(FP16 量化)
├── 推理框架:vLLM
├── 并发能力:~20 req/s
└── 适用:100+ 运维团队,高频 AI 使用

方案 B(经济型):
├── GPU:NVIDIA A6000 48GB × 2(NVLink)
├── 模型:Qwen2.5-32B-Instruct(FP16)
├── 推理框架:vLLM
├── 并发能力:~10 req/s
└── 适用:50 人以下团队

方案 C(轻量起步):
├── GPU:NVIDIA A100 80GB × 1
├── 模型:Qwen2.5-14B-Instruct(FP16)
├── 推理框架:Ollama
├── 并发能力:~15 req/s
└── 适用:MVP 阶段快速验证

部署建议:
├── GPU 节点独立部署(不在业务集群内)
├── 通过内网 IP + 端口访问(不暴露公网)
├── 模型文件存储在本地 SSD(NVMe,>500GB 可用空间)
├── 平台通过 HTTP 调用推理服务(OpenAI 兼容接口)
└── 健康检查:定时 ping /v1/models 端点

OI-04 决策影响说明(对接 LDAP)

LDAP 集成方案:

┌─────────────────────────────────────────────────────┐
│  用户登录流程(LDAP 模式)                         │
│                                                     │
│  用户输入用户名/密码                                 │
│       │                                             │
│       ▼                                             │
│  平台将凭证转发至 LDAP 服务器验证                   │
│       │                                             │
│  ┌────┴────┐                                      │
│  │ 验证成功 │ → 查询 LDAP 获取用户属性              │
│  └─────────┘   (displayName / email / groups)     │
│       │                                             │
│       ▼                                             │
│  本地 users 表 upsert(同步 LDAP 属性)              │
│       │                                             │
│       ▼                                             │
│  根据 LDAP group → 映射平台角色                     │
│  ┌─────────────────────────────────────────┐         │
│  │ cn=ops-admin    → super_admin          │         │
│  │ cn=ops-zone-xxx → zone_admin (zone=xxx)│         │
│  │ cn=developers    → developer (只读)    │         │
│  │ cn=ops-readonly  → readonly           │         │
│  └─────────────────────────────────────────┘         │
│       │                                             │
│       ▼                                             │
│  签发 JWT Token → 正常登录                           │
│                                                     │
│  验证失败 → 返回 401 + 错误提示                     │
└─────────────────────────────────────────────────────┘

配置项(config.yaml):
├── ldap.enabled: true
├── ldap.server: ldap://ldap.company.com:389
├── ldap.base_dn: "dc=company,dc=com"
├── ldap.bind_dn: "cn=platform,dc=company,dc=com"
├── ldap.bind_password_enc: "AES-256 加密"
├── ldap.user_filter: "(uid={username})"
├── ldap.group_filter: "(member={dn})"
├── ldap.group_mapping:
│   ├── "cn=ops-admin,dc=company,dc=com" → "super_admin"
│   ├── "cn=ops-zone-core,dc=company,dc=com" → "zone_admin:core"
│   ├── "cn=developers,dc=company,dc=com" → "developer"
│   └── "cn=ops-readonly,dc=company,dc=com" → "readonly"
└── ldap.sync_interval: "1h"(定时全量同步)

本地账号兜底:
├── 当 LDAP 不可用时(网络故障),允许本地 admin 账号登录
├── 本地 admin 密码定期强制更换(90 天)
└── LDAP 恢复后自动切回 LDAP 认证

附录

  • 附录 A:域类型详细参数对照表(见 3.1 节)
  • 附录 B:AI 排障规则引擎完整规则定义(见 9.3 节)
  • 附录 C:数据库完整 DDL(见第七章)
  • 附录 D:API OpenAPI 3.0 规范(独立文件)
  • 附录 E:飞书卡片消息 JSON Schema(独立文件)
  • 附录 F:性能优化 Checklist(见第五章 5.7 节)

附录 F:性能优化 Checklist

优化点实施方式预期收益验证方式
列表游标分页K8s Limit + Continue单次请求从 MB 级降到 KB 级网络面板查看传输大小
字段裁剪?fields=summary 只返回 12 字段单条记录从 ~50KB → ~2KB对比响应体大小
L1 本地缓存sync.Map + 5s TTL60% 请求 < 1msRedis 命中率监控
L2 Redis 缓存30s TTL 跨实例共享额外覆盖 30% 请求Redis INFO stats
Write-Through 失效Watch 事件触发缓存删除缓存与 apiserver 最终一致对比数据延迟 < 5s
WebSocket 增量Watch → WS 推送变更看板实时性从 30s → 亚秒级事件到渲染 < 500ms
虚拟滚动vue-virtual-scrollerDOM 节点恒定 < 50 个Chrome DevTools
并行查询goroutine pool (max 10)列表加载从 3s → 800ms后端日志计时
详情页懒加载Tab 点击时才加载首屏 < 500msLighthouse 评分
告警风暴防护时间窗口合并 + AI 聚合告警量下降 70%告警统计面板
负责人路由精准到人,不广播MTTR 下降 40%通知日志分析
数据库索引审计/告警/通知表加索引查询 P99 < 100msEXPLAIN ANALYZE