Repository Reading Site
全链路串联 — 用户旅程与系统流转
--- --- --- --- --- ---
全链路串联 — 用户旅程与系统流转
一、全局流转图
┌──────────────────────────────────────────────────────────────────────┐
│ │
│ 注册 ──→ 引导 ──→ 试用 ──→ 充值 ──→ 正式使用 │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ 用户模块 模型模块 计费模块 ┌──────────────────┐ │
│ (创建组织) (Playground) (充值) │ 日常使用 │ │
│ │ │ │
│ │ API 推理 ←──────┤ │
│ │ 数据管理 ←──────┤ │
│ │ 微调训练 ←──────┤ │
│ │ 模型部署 ←──────┤ │
│ │ 知识库 ←──────┤ │
│ │ 批量任务 ←──────┤ │
│ └───────┬──────────┘ │
│ │ │
│ ▼ │
│ 计费扣款 │
│ 用量统计 │
│ 账单生成 │
│ │
│ ────── 运维全程保障 ────── │
│ 监控 / 告警 / 扩缩容 / 成本 │
└──────────────────────────────────────────────────────────────────────┘
二、七条核心用户旅程
旅程 1: 开发者接入(从注册到第一次 API 调用)
时间线: 5 分钟
用户动作 触发的系统行为 涉及模块
─────────────────────────────────────────────────────────────────────
1. 打开官网,点"免费注册" — 用户模块
2. 输入邮箱+密码,注册 → 创建 User 记录 用户模块
→ 创建个人 Organization 用户模块
→ 绑定 Free 套餐 计费模块
→ 赠送 ¥10 体验额度 计费模块
→ Redis 写入初始余额 计费模块
→ 发送欢迎邮件 用户模块
3. 进入引导页,选"开发者" → 记录用户画像 用户模块
4. 引导试用 Playground → 打开 Playground 页面 模型模块
输入"你好",点发送 → 用赠送额度调用 Qwen2.5-7B 模型模块
→ API Gateway 认证(用session) 计费模块
→ 转发到推理共享池 模型模块
→ vLLM 推理生成回答 K8s/GPU
→ Token 计量,Redis 扣费 计费模块
→ 写 usage_log 计费模块
→ 返回回答 + usage 信息 模型模块
用户看到: 模型回复了!
5. 引导创建 API Key → 生成 sk-xxx 用户模块
→ SHA256 存入数据库 用户模块
→ 展示 Key (仅一次) 用户模块
→ 展示代码示例 模型模块
6. 用户复制代码到本地跑 → API 请求带 Bearer sk-xxx 用户模块
→ Gateway 验证 Key 计费模块
→ 限流检查 (Free: 10 RPM) 计费模块
→ 余额检查 计费模块
→ 推理 + 扣费 模型+计费
→ 返回结果
用户: "跑通了!"
结果: 5 分钟内完成 注册→试用→拿到Key→跑通代码
涉及: 用户模块 ↔ 计费模块 ↔ 模型模块 ↔ K8s 推理层
旅程 2: 企业客服团队微调专属模型
时间线: 1-2 天
用户动作 触发的系统行为 涉及模块
─────────────────────────────────────────────────────────────────────
前置: CTO 已注册并升级 Pro 套餐,邀请了 3 个开发者
1. 数据团队准备客服对话数据 — (线下) —
整理为 JSONL 格式
2. 上传数据集 → 分片上传到 S3/NFS 数据模块
"customer-service.jsonl" → 格式检测: JSONL 对话格式 数据模块
12,000 条 → 异步校验任务 (K8s Job): 数据模块
格式、Token统计、去重检测
→ 写入 datasets 表 数据模块
→ 存储计费开始 (3.2MB) 计费模块
3. 查看校验报告 → 读取校验结果 数据模块
发现 150 条重复 → 用户查看重复数据详情 数据模块
4. 执行去重 → 异步处理 Job 数据模块
得到 11,850 条 → 创建新版本 v2 数据模块
→ 旧版本保留 数据模块
5. 创建微调任务 → 进入 4 步向导 训练模块
Step1: 选 Qwen2.5-7B → 检查模型可用性 模型模块
Step2: 选数据集 v2 → 验证格式兼容 数据+训练
Step3: 标准方案 → 超参数自动填充 训练模块
Step4: 确认提交 → 预估费用 ¥2.50 计费模块
→ 检查余额 ≥ ¥2.50 计费模块
→ 预扣 ¥2.50 计费模块
→ 创建 TrainingJob CR 训练模块
→ Training Operator 检测 K8s
→ 检查 GPU 资源 运维/K8s
└ 有空闲 A10 → 创建 Job
└ 无空闲 → 入队等待
6. 等待训练 (30分钟) → K8s Job 运行: 训练模块
加载基座模型
加载数据集
LoRA 训练循环
每500步保存 Checkpoint → S3 训练模块
每步上报 loss → Prometheus 运维模块
→ 用户实时查看 loss 曲线 训练模块
→ GPU 利用率监控 运维模块
7. 训练完成通知 → Job 完成 训练模块
→ 上传模型到 S3 训练模块
→ 自动评估 (在验证集上) 训练模块
→ 结算费用: 预扣¥2.50 → 实际¥2.30 计费模块
退回 ¥0.20 计费模块
→ 邮件/站内通知 用户模块
→ 创建 ModelRegistry 记录 模型模块
8. 查看评估结果 → 基座 vs 微调对比 训练模块
eval_loss: 1.23 → 0.38 → 逐条回答对比 训练模块
"效果不错!"
9. 一键部署 → 创建 InferenceService CR 模型模块
→ Inference Operator 检测 K8s
→ 创建 Deployment (LoRA挂载) K8s
→ 创建 Service K8s
→ 等待 Pod Ready K8s
→ 更新 CR 状态: Serving 模型模块
→ 注册到 API Gateway 路由表 模型模块
→ 注册 ServiceMonitor 运维模块
10. 用 API Key 调用 → 和旅程1的第6步一样 模型+计费
model="acmecorp-cs-v3" 但路由到微调模型的推理实例
结果: 从上传数据到模型上线,全程在平台内完成
涉及: 所有 7 个模块全部参与
旅程 3: 一次 API 调用的完整链路
时间线: 200ms
这是平台最高频的操作,每秒可能发生数千次。
每一毫秒都要清楚发生了什么。
0ms 客户端发起 HTTPS 请求
POST /v1/chat/completions
Authorization: Bearer sk-a1b2...
{"model":"qwen2.5-7b", "messages":[...]}
│
1ms │ TLS 终结 (Ingress/Load Balancer)
│
2ms ▼ API Gateway 接收请求
│
3ms ├── 认证: 提取 Bearer Token
│ SHA256(sk-a1b2...) → 查 Redis 缓存
│ 命中 → 得到 {org_id, permissions, rate_limit}
│ 未命中 → 查 PostgreSQL → 写 Redis (TTL 5min)
│
4ms ├── 权限检查: permissions 包含 "chat.completions"?
│ allowed_models 包含 "qwen2.5-7b"?
│
5ms ├── 限流检查: Redis INCR rate:{org_id}:{minute}
│ 当前值 ≤ rate_limit? → 通过
│ 超出 → 返回 429 Too Many Requests
│
6ms ├── 余额检查: Redis GET org:{org_id}:balance
│ 余额 > 0? → 通过
│ 余额 ≤ 0 → 返回 402 Payment Required
│
7ms ├── 计算 prompt_tokens (tiktoken)
│ messages → tokenize → 502 tokens
│
8ms ├── 选择推理实例
│ model="qwen2.5-7b" → 查路由表
│ → qwen25-7b-shared.inference-shared.svc:8080
│ 负载均衡: 选一个最空闲的 Pod
│
10ms ▼ 转发到推理服务 (vLLM)
│
10- │ vLLM 推理:
15ms │ Prefill: 处理 502 个 input tokens (GPU 并行)
│
15- │ Decode: 逐个生成 output tokens
180ms │ 每生成一个 token:
│ 如果 stream=true → SSE 推送给客户端
│ 生成完毕: 198 tokens
│
180ms ▼ 推理完成,返回结果到 Gateway
│
181ms ├── 计算 completion_tokens: 198
│
182ms ├── 计算费用:
│ 502 × ¥2.0/1M + 198 × ¥6.0/1M = ¥0.00219
│
183ms ├── Redis 扣费 (Lua 原子脚本):
│ 检查余额 ≥ 219 (0.01分单位)
│ DECRBY org:{org_id}:balance 219
│
184ms ├── 异步写入消息队列:
│ {org_id, api_key_id, model, prompt_tokens:502,
│ completion_tokens:198, cost:0.00219, latency:180}
│
185ms ├── 记录 Prometheus 指标:
│ inference_requests_total{model,status} +1
│ inference_request_duration_seconds.Observe(0.180)
│ inference_tokens_total{type=input} +502
│ inference_tokens_total{type=output} +198
│
186ms ▼ 返回响应给客户端
{
"id": "chatcmpl-xxx",
"model": "qwen2.5-7b",
"choices": [{
"message": {"role":"assistant","content":"..."},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 502,
"completion_tokens": 198,
"total_tokens": 700
}
}
│
│ (异步,不影响响应)
▼
后台 消息队列消费者:
→ 批量 INSERT INTO usage_logs
→ 每分钟: Redis 余额 → PostgreSQL 同步
→ Grafana 实时展示 QPS/延迟/Token 曲线
旅程 4: 企业客户从试用到签约
时间线: 1-4 周
Week 1: 技术评估
├── CTO 注册 → Free 套餐 → Playground 试用
├── 开发者创建 Key → 集成到现有系统
├── 试用多个模型,对比效果
└── 赠送额度用完
系统: 余额告警 → 弹出充值引导
Week 2: 小规模使用
├── 充值 ¥500 → 继续测试
├── 上传业务数据 → 微调模型
├── 评估微调效果 → 满意
└── 日均调用增长到 5000 次
系统: Free 套餐 10 RPM 限流频繁触发
→ 弹出升级建议: "升级 Starter 获得 100 RPM"
Week 3: 正式采购
├── 升级 Pro 套餐 (¥999/月)
├── 邀请 5 个团队成员
├── 为不同项目创建不同 API Key
├── 设置月度预算告警 ¥5,000
└── 部署微调模型为推理服务
系统:
用户模块: 成员管理、Key 分发
计费模块: 套餐升级、自动续费
模型模块: 推理实例创建
运维模块: 监控告警配置
Week 4: 深度使用
├── 申请独享推理实例 (SLA 保证)
├── 设置 IP 白名单 (安全合规)
├── 配置 Webhook 接收用量告警
├── 财务申请开发票
└── 商务洽谈 Enterprise 年度合同
系统: 商务后台设置信用额度和专属折扣
旅程 5: RAG 知识库从搭建到使用
1. 创建知识库 → 选择 Embedding 模型 (BGE-M3) 数据模块
"产品帮助中心" → 创建知识库记录 数据模块
2. 上传文档 → PDF/Word 解析为文本 数据模块
45 篇帮助文档 → 分块 (chunk_size=512, overlap=50) 数据模块
3. 向量化 → 调用 BGE-M3 Embedding API 模型模块
1,230 个文档片段 → Token 计量,扣费 计费模块
→ 向量写入向量数据库 (pgvector) 数据模块
4. 测试检索 → 输入问题 数据模块
"退货流程是什么?" → Embedding 编码问题 模型模块
→ 向量相似度搜索 Top-K 数据模块
→ 返回相关文档片段 数据模块
5. 关联到对话模型 → 配置: qwen-7b + 知识库 模型模块
→ API 请求时自动:
1. Embedding 用户问题
2. 检索相关文档
3. 拼接到 prompt
4. 模型生成回答
→ 两次 API 调用 (Embedding + Chat) 计费模块
6. 更新文档 → 上传新文档 数据模块
新增 5 篇 → 增量向量化 模型模块
→ 旧文档删除的向量同步清理 数据模块
旅程 6: 训练任务失败与恢复
1. 提交训练任务 → 创建 TrainingJob CR 训练模块
→ 预扣费用 ¥12 计费模块
→ 分配 A10 GPU 运维/K8s
2. 训练运行中 → loss 曲线正常下降 训练模块
Step 500: checkpoint → 保存到 S3 训练模块
Step 800: GPU 节点宕机 → Pod 被驱逐 K8s
3. 系统自动恢复 → Operator 检测 Pod 失败 训练模块
→ 查找最近 checkpoint (step 500) 训练模块
→ 在新节点创建 Pod K8s
→ 从 step 500 恢复训练 训练模块
→ 用户看到: "训练已恢复" 训练模块
告警同时触发:
→ P0 告警: 节点宕机 运维模块
→ 电话通知值班人 运维模块
→ 值班人检查硬件 运维模块
4. 训练继续完成 → 正常完成 训练模块
→ 实际费用结算 (含恢复时间) 计费模块
→ 用户无感知 —
旅程 7: 模型版本迭代(v1 → v2 灰度切换)
1. 当前生产运行 v1 → InferenceService: cs-model-v1 模型模块
100% 流量 → v1 → 监控正常: P95=320ms 运维模块
2. 训练新版本 v2 → 更多数据 + 调整参数 训练模块
→ 评估: v2 比 v1 BLEU +15% 训练模块
3. 部署 v2 (不接流量) → 创建 InferenceService: cs-v2 模型模块
→ Operator 创建 Deployment K8s
→ Pod Ready,但 0% 流量 模型模块
4. 灰度 5% → API Gateway 路由规则: 模型模块
95% → v1, 5% → v2
→ 运维观察: 运维模块
v2 延迟/错误率/用户反馈
5. 观察 1 小时 → v2 指标正常 运维模块
无异常 → Grafana 对比面板: v1 vs v2 运维模块
6. 逐步放量 → 5% → 20% → 50% → 100% 模型模块
每步观察 30 分钟 → 自动回滚条件: 运维模块
如果 v2 的 5xx > v1 的 2 倍
→ 自动切回 v1 100%
7. 全量切换 → v1 缩容到 0 (保留,可回滚) 模型模块
→ v2 接管 100% 流量 模型模块
→ 更新 API 路由表 模型模块
→ 14 天后如果无回滚 → 清理 v1 模型模块
三、模块间调用关系
3.1 同步调用链路
每次 API 推理请求经过的模块(必须全部正常才能返回结果):
客户端
→ API Gateway
→ 用户模块 (Key 验证)
→ 计费模块 (限流 + 余额检查)
→ 模型模块 (路由选择)
→ K8s 推理 Pod (GPU 推理)
→ 计费模块 (Token 计量 + 扣费)
← 返回结果
任何一环故障:
Key 无效 → 401 Unauthorized
限流触发 → 429 Too Many Requests
余额不足 → 402 Payment Required
模型不可用 → 503 Service Unavailable
推理超时 → 504 Gateway Timeout
内部错误 → 500 Internal Server Error
3.2 异步事件流
事件总线 (消息队列 / K8s Watch)
─────────────────────────────
产生事件的模块: 消费事件的模块:
用户模块:
user.registered ──────────────────→ 计费: 赠送体验额度
member.invited ───────────────────→ 用户: 发送邮件
member.removed ───────────────────→ 用户: 吊销该成员所有 Key
计费模块:
balance.low ──────────────────────→ 用户: 发送余额告警
balance.zero ─────────────────────→ 模型: 暂停独享实例
subscription.upgraded ────────────→ 用户: 更新成员/Key 上限
subscription.expired ─────────────→ 模型: 降级服务
数据模块:
dataset.uploaded ─────────────────→ 数据: 异步校验任务
dataset.validated ────────────────→ 训练: 可用于训练
训练模块:
training.completed ───────────────→ 模型: 注册新模型版本
→ 计费: 结算训练费用
→ 用户: 通知
training.failed ──────────────────→ 计费: 退还预扣费用
→ 用户: 通知 + 失败原因
→ 运维: 如果是 GPU 故障则告警
模型模块:
model.deployed ───────────────────→ 运维: 注册监控
→ 计费: 开始计费 (独享实例)
model.offline ────────────────────→ 计费: 停止计费
→ 运维: 清理监控
运维模块:
alert.fired ──────────────────────→ 运维: 通知值班人
node.down ────────────────────────→ 训练: 受影响任务自动恢复
→ 模型: 受影响实例迁移
gpu.error ────────────────────────→ 训练: 迁移任务
→ 运维: 标记 GPU 不可用
3.3 数据依赖关系
哪个模块的数据被谁依赖:
用户模块 (organizations, users, api_keys):
→ 几乎所有模块都依赖(认证和租户隔离的基础)
计费模块 (balance, usage_logs, pricing):
→ API Gateway 依赖(限流和余额检查)
→ 模型模块依赖(独享实例计费)
→ 训练模块依赖(训练费用预估和结算)
数据模块 (datasets):
→ 训练模块依赖(训练数据来源)
→ 模型模块依赖(RAG 知识库向量数据)
模型模块 (models, inference_services):
→ API Gateway 依赖(路由表)
→ 训练模块依赖(基座模型选择)
训练模块 (training_jobs, checkpoints):
→ 模型模块依赖(训练产出的模型)
运维模块 (metrics, logs, alerts):
→ 计费模块依赖(成本数据)
→ 独立运行,不被业务模块直接依赖
依赖链:
用户 → 计费 → Gateway → 模型 → K8s
↑ ↑
训练 ← 数据 运维 (独立观测)
四、关键状态机
4.1 训练任务状态机
┌──────────┐
│ Created │ 用户提交
└────┬─────┘
│ 预扣费用成功
┌────▼─────┐
┌───│ Queued │ 等待 GPU
│ └────┬─────┘
GPU 一直没有│ │ GPU 分配成功
│ ┌────▼─────────┐
│ │ Initializing │ 下载模型/数据
│ └────┬─────────┘
│ │ 模型加载完成
│ ┌────▼─────┐
│ │ Training │ 训练中
│ └────┬─────┘
│ │ 训练完成
│ ┌────▼──────┐
│ │ Evaluating│ 自动评估
│ └────┬──────┘
│ │ 评估完成
│ ┌────▼──────┐
│ │ Completed │ → 结算费用/通知
│ └───────────┘
│
│ 任何阶段失败:
└──→┌────────┐
│ Failed │ → 退还预扣/通知/告警
└────────┘
用户取消:
┌──────────┐
│ Cancelled│ → 退还预扣 (扣已消耗)
└──────────┘
4.2 推理服务状态机
┌──────────┐
│ Pending │ CR 创建
└────┬─────┘
│ Operator 检测到
┌────▼──────┐
│ Deploying │ 创建 Deployment/Service
└────┬──────┘
│ Pod Ready
┌────▼──────┐
│ Serving │ 正常服务
└────┬──────┘
│
┌──────────┼──────────┐
│ │ │
版本更新 缩容到0 手动下线
│ │ │
┌────▼─────┐ │ ┌────▼─────┐
│ Updating │ │ │ Offline │
└────┬─────┘ │ └──────────┘
│ │
│ ┌────▼──────┐
│ │ Sleeping │ Serverless 模式
│ └────┬──────┘
│ │ 新请求到达
│ ┌────▼───────────┐
│ │ WakingUp │ 冷启动
│ └────┬───────────┘
│ │
└──────────┘→ Serving
4.3 组织账户状态机
┌──────────┐
│ Active │ 正常使用
└────┬─────┘
│
┌──────────┼──────────┐
│ │ │
余额归零 套餐过期 用户注销
│ │ │
┌────▼─────┐ │ ┌────▼─────────┐
│ Suspended│ │ │ Deactivating │
│ 暂停服务 │ │ │ 30天冷静期 │
└────┬─────┘ │ └────┬─────────┘
│ │ │
充值后恢复 续费后恢复 30天后
│ │ │
└──→ Active│ ┌────▼─────┐
│ │ Deleted │
└──→ Active │ 永久删除
└──────────┘
暂停状态下:
- API 调用被拒绝 (402)
- 独享实例暂停 (不计费)
- 数据保留 90 天
- 训练任务不可提交
- 控制台可登录 (只能充值/查看)
五、接口调用矩阵
谁调用谁
API User Billing Model Training Data K8s
GW Svc Svc Svc Svc Svc Operator
──────────────────────────────────────────────────────────────────────
API Gateway — 读Key 读余额 读路由 — — —
验证 限流检查
User Svc — — 创建账户 — — — —
Billing Svc — 读组织 — 读价格 结算费用 — —
信息
Model Svc — 读权限 查余额 — — 读数据 创建
集元数据 CRD
Training Svc — 读权限 预扣/ 读基座 — 读数据 创建
结算 模型 集 Job
Data Svc — 读权限 计存储 调 — — 创建
费 Embed Job
K8s Operator — — — 更新 更新 — CRUD
状态 状态 Deploy
Svc
HPA
六、技术串联方案
6.1 服务间通信
同步调用 (需要立即返回结果):
→ gRPC (内部服务间,高性能,强类型)
→ HTTP REST (API Gateway 对外)
异步事件 (不需要立即处理):
→ Redis Stream (轻量,用于 usage_log 写入)
→ NATS / RabbitMQ (复杂事件路由)
数据共享:
→ PostgreSQL (元数据,强一致)
→ Redis (缓存/限流/余额,高性能)
→ S3/NFS (文件存储,模型/数据集)
服务发现:
→ K8s Service (集群内)
→ CoreDNS (service-name.namespace.svc.cluster.local)
6.2 Gateway 路由表
API Gateway 是所有模块的统一入口:
路径 转发到 认证方式
───────────────────────────────────────────────────────────
/v1/chat/completions 推理服务 (动态路由) API Key
/v1/completions 推理服务 API Key
/v1/embeddings 推理服务 API Key
/v1/models Model Service API Key
/api/v1/auth/* User Service 无/JWT
/api/v1/keys/* User Service JWT
/api/v1/org/* User Service JWT
/api/v1/billing/* Billing Service JWT
/api/v1/usage/* Billing Service JWT/API Key
/api/v1/models/* Model Service JWT
/api/v1/fine-tuning/* Training Service JWT
/api/v1/datasets/* Data Service JWT
/admin/* 各管理服务 JWT (运维角色)
6.3 统一错误码
{
"error": {
"type": "error_type",
"code": "specific_code",
"message": "人类可读的错误描述",
"param": "出错的参数(如果有)"
}
}
错误码体系:
认证类 (401):
auth_key_invalid API Key 无效
auth_key_expired API Key 已过期
auth_key_revoked API Key 已吊销
auth_token_expired JWT 过期
auth_mfa_required 需要 MFA 验证
权限类 (403):
permission_denied 无此操作权限
model_not_allowed Key 不允许使用此模型
ip_not_whitelisted IP 不在白名单
计费类 (402/429):
billing_insufficient 余额不足
billing_quota_exceeded 套餐配额超限
rate_limit_exceeded 请求频率超限
资源类 (404/503):
model_not_found 模型不存在
model_unavailable 模型暂不可用
dataset_not_found 数据集不存在
training_gpu_unavail GPU 资源不足
请求类 (400):
invalid_request 请求格式错误
context_too_long 上下文超过模型最大长度
invalid_model 无效的模型名称
七、一张图总结
┌─────────────────────────────────────────────────────────────────┐
│ 客户端层 │
│ Web Console │ Python/Go SDK │ curl/HTTP │
└──────────┬──────────┴────────┬────────┴──────────┬──────────────┘
│ HTTPS │ HTTPS │ HTTPS
┌──────────▼──────────────────▼────────────────────▼──────────────┐
│ API Gateway (Go) │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │认证 │→│限流 │→│计量 │→│路由 │→│日志 │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │
└──┬───────┬───────┬───────┬───────┬───────┬──────────────────────┘
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐
│用户 ││计费 ││模型 ││训练 ││数据 ││推理 │
│服务 ││服务 ││服务 ││服务 ││服务 ││Operator│
│ ││ ││ ││ ││ ││ │
│注册 ││余额 ││注册 ││提交 ││上传 ││部署 │
│Key ││扣费 ││部署 ││监控 ││校验 ││伸缩 │
│权限 ││账单 ││路由 ││恢复 ││处理 ││灰度 │
└──┬───┘└──┬───┘└──┬───┘└──┬───┘└──┬───┘└──┬───┘
│ │ │ │ │ │
└───────┴───────┴───┬───┴───────┴───────┘
│
┌────────▼────────┐
│ 数据层 │
│ PostgreSQL Redis │
│ S3/NFS 向量DB │
└────────┬────────┘
│
┌────────▼────────┐
│ K8s 集群 │
│ GPU 推理 Pod │
│ GPU 训练 Job │
│ 平台服务 Pod │
└────────┬────────┘
│
┌────────▼────────┐
│ 运维观测 │
│ Prometheus │
│ Grafana + Loki │
│ Alertmanager │
└─────────────────┘