# 产品架构与部署白皮书

> 初稿（2026-11-05）。描述当前版本实际具备的架构与部署方式。安全控制见同一资料包中的[《安全白皮书》](/trust/security)；备份与恢复见[《备份与灾备说明》](/trust/backup-dr)。

## 1. 平台是什么

Raise（下称“平台”；可白标，你的用户看到的可能是你自己的品牌名）是面向企业与开发者的 Agent-SaaS 平台。用户在工作台里使用业务应用和 AI 助理；助理只能读取数据和起草方案，写入要由用户在拥有数据的应用里确认后才执行。租户拥有自己的应用与数据。同一套镜像通过“环境包”（Pack）适配本地机房和不同云厂商，不维护多个分支。

平台核心是一个模块化单体服务 kwork（管理、运营、审计、对象引擎、草稿、合规等 API 与后台任务），加上同一镜像以不同模块运行的 Agent 运行时。身份、数据库、密钥、对象存储、工作流、模型网关、观测都是独立的开源组件。

## 2. 服务清单

“圈”是组件的分层：圈 0 始终运行；圈 1 是生产用后端，每个都有圈 0 的替代（例如本地卷代替对象存储，主密钥代替 OpenBao）；圈 2 是可选功能。“Profile”是单机 Docker Compose 部署时打开该组件的开关。

### 2.1 始终运行（圈 0）

| 服务 | 做什么 | 许可证 |
|---|---|---|
| 网关（Caddy） | 唯一的入口：TLS、证书签发与续期、按域名路由、托管门户静态页、运营入口 | Apache-2.0 |
| kwork | 平台核心：管理 / 运营 / 审计 / 对象引擎 / 草稿 / 合规 / 归档 API；后台任务（Webhook、保留期、归档） | 厂商专有 |
| Zitadel | 身份：登录、组织（= 租户）、角色、服务账号、OIDC | AGPL-3.0（未修改） |
| PostgreSQL 17 | 业务库（行级安全）、审计库（只追加），以及 Zitadel、Temporal 等组件的库 | PostgreSQL |
| oauth2-proxy | 运营工具入口的单点登录代理 | MIT |

### 2.2 按需打开

| 服务 | 做什么 | 必需 / 可选 | 圈 | Compose profile | 许可证 |
|---|---|---|---|---|---|
| OpenBao | 敏感字段的信封加密、租户凭据（自带存储、自带模型的密钥） | `onprem` 与云 Pack 必需；`single` 不用 | 1 | `infra` / `core-infra` | MPL-2.0 |
| SeaweedFS | S3 兼容对象存储：平台文件、审计归档 | `onprem` 必需；云 Pack 改用云厂商的桶 | 1 | `infra` | Apache-2.0 |
| Gotenberg | PDF 渲染；目前没有功能调用它 | 可选 | 1 | `infra` | MIT |
| Agent 运行时（kwork-agent） | 助理对话、定时任务、MCP；与 kwork 同一镜像 | 使用助理时必需 | 1 | `shell` | 厂商专有 |
| Temporal（+ Temporal UI） | 助理与定时任务的工作流；UI 只给运营人员 | 使用助理时必需 | 1 | `shell` | MIT |
| Bifrost | 模型网关：所有模型调用都经过它，包括租户自带的模型；租户虚拟密钥、预算 | 使用助理或模型功能时必需 | 1 | `shell` / `llm` | Apache-2.0 |
| pg-backup（WAL-G） | 整个 Postgres 集群的持续备份 | 可选，生产建议打开 | 1 | `backup` | 脚本厂商专有，WAL-G Apache-2.0 |
| 容器引擎代理 | 托管 ISV 应用时，kwork 经它启动应用容器 | 托管应用时必需 | 1 | `apps` | Apache-2.0 |
| OTel Collector、Prometheus、Alertmanager、Tempo、Loki、Grafana | 链路、指标、告警、日志、看板；只给运营人员 | 可选 | 2 | `obs` | Collector / Prometheus / Alertmanager Apache-2.0；Tempo / Loki / Grafana AGPL-3.0（未修改） |
| Langfuse（+ ClickHouse、Redis） | 模型调用追踪；资源占用最大 | 可选 | 2 | `obs-llm` | Langfuse MIT（企业版功能关闭）；ClickHouse Apache-2.0；Valkey BSD-3 |
| Redis（Valkey） | 多个 kwork 副本共享限流计数 | 多副本时需要 | 2 | `coord` | BSD-3 |
| Cube、Superset | 外接 BI；目前没有接入租户数据 | 可选，镜像依赖尚未发布 | 2 | `analytics` | Apache-2.0 |

文件分析（DuckDB worker）和实时协作（collab）两个组件尚未交付。

## 3. 拓扑

```mermaid
flowchart LR
  U[用户浏览器 / 集成 / 外部智能体] -->|443| GW[网关]
  OPS[运营人员<br/>运维网络或 SSH 隧道] -->|8443| GW

  subgraph core[平台核心]
    K[kwork<br/>管理 · 审计 · 对象引擎 · 草稿 · 合规]
    A[Agent 运行时]
  end

  GW --> K
  GW --> A
  GW -->|运营工具| SSO[运营单点登录] --> ID
  GW -->|文件直传直下| S3[(对象存储)]

  K --> ID[身份<br/>Zitadel]
  K --> PG[(PostgreSQL<br/>业务库 · 审计库)]
  K --> BAO[密钥<br/>OpenBao]
  K --> S3
  K --> LLM[模型网关<br/>Bifrost]
  A --> WF[工作流<br/>Temporal]
  A -->|读取 / 起草| K
  A --> LLM
  LLM --> MP[模型供应商<br/>或本地模型]

  K -.-> OBS[观测<br/>指标 · 链路 · 日志 · 告警]
  A -.-> OBS
```

- 只有网关在主机上开放端口，其余服务只在内部网络里互相可达。
- 用户只访问门户和 API，门户只调用 kwork，后台组件由 kwork 调用，不直接面向用户。
- 观测组件不可用时不阻塞业务请求：遥测按尽力而为发送，后端不可用时丢弃。

## 4. 部署形态

### 4.1 单机 Docker Compose

一台 Linux 主机，一条安装命令完成系统检查、Docker 安装、防火墙、配置与密钥生成、镜像、DNS 检查和启动。脚本可以重复执行，已完成的步骤会跳过，密钥只在第一次生成。

- 系统：Ubuntu 22.04 / 24.04、Debian 12、RHEL / Rocky / Alma / Oracle Linux 9、Anolis、OpenCloudOS 等，x86_64 或 aarch64。openEuler、麒麟要先由系统厂商装好 Docker Engine 与 Compose v2（≥ 2.24）。
- 许可证：开发包以外，kwork 只启动许可证授权的模块，并且只接受能用厂商公钥验证签名的许可证。安装在启动任何服务之前检查许可证。
- 主机重启后容器自动启动。
- 单机形态不是高可用部署。

### 4.2 Kubernetes（Helm）

Chart 部署平台自己的工作负载：kwork（默认 2 个副本，按节点打散，至少 1 个副本在线）、Agent 运行时（可选）、网关、运营单点登录。要求 Kubernetes ≥ 1.30。

以下依赖不在 chart 里，由你提供并在配置里指过去：

| 依赖 | 要求 |
|---|---|
| PostgreSQL | 托管主备或集群内的 Postgres Operator；kwork 连跟随主库的地址。经 PgBouncer 只能用 session 模式 |
| Zitadel | 官方 chart，或集群内可访问的实例 |
| 对象存储 | S3 兼容；多副本时必须用对象存储 |
| Redis / Valkey | 多副本时共享限流 |
| Temporal、模型网关 | 只有打开 Agent 运行时才需要 |
| OpenBao | 选择 OpenBao 作为密钥后端时；chart 不负责初始化 |

安装与升级时，chart 的 hook 依次执行数据库角色、迁移、身份与存储初始化；任何一个 hook 失败，整次发布失败，工作负载不换新镜像。

### 4.3 离线安装包

每个架构（amd64、arm64）一个安装包，包含 `infra`、`backup`、`shell`、`obs` 所需的全部镜像、部署文件、门户与用户手册，以及 Helm 额外需要的镜像。

- 安装包的文件清单由厂商私钥签名。安装前先用厂商另行交给你的公钥校验签名，逐个文件核对校验和，并拒绝清单之外的文件；载入镜像后再核对镜像 ID。任何一步不符即停止并说明原因。
- 离线安装必须使用网关内置 CA 签发证书（没有外网就签不出公网证书）。
- Kubernetes：安装包可以把镜像推到你内网的镜像仓库，再用包里的 chart 安装。
- 托管 ISV 应用（`apps`）的镜像不在包里。

### 4.4 环境包（Pack）

| Pack | 平台文件存放 | 密钥后端 | 额外组件 |
|---|---|---|---|
| `single` | 本机数据卷 | 主密钥包裹（在 Postgres 中） | 无 |
| `onprem` | 自带 SeaweedFS | OpenBao | OpenBao、SeaweedFS、Gotenberg |
| `tencent` | 腾讯云 COS | OpenBao | OpenBao |
| `aliyun` | 阿里云 OSS | OpenBao | OpenBao |
| `aws` | AWS S3 | OpenBao | OpenBao |

另有 `dev` 包，只用于开发，不检查许可证。云 Pack 要填桶所在地域、桶名和只授权该桶的访问密钥；浏览器直接向桶上传下载，桶的 CORS 要放行工作台和应用的域名。

**安装后不能更换 Pack**（`single` 换 `onprem` 也不行）：文件存放与密钥后端随 Pack 变化，目前没有迁移工具，已有文件会找不到，加密数据会读不出来。

### 4.5 可替换为云托管服务的组件

| 组件 | 可替换为 | 现状 |
|---|---|---|
| 对象存储（SeaweedFS） | AWS S3、阿里云 OSS、腾讯云 COS 或其他 S3 兼容存储 | 单机形态用云 Pack；Helm 形态由你提供 |
| PostgreSQL | 托管 Postgres（RDS、PolarDB 等） | Helm 形态由你提供；单机 Compose 形态固定使用自带的 Postgres |
| Postgres 备份（WAL-G） | 托管 Postgres 自带的时间点恢复 | 使用托管 Postgres 时由其负责 |
| Temporal | 外部 Temporal 实例 | Helm 形态可配置地址；单机 Compose 形态固定使用自带实例 |
| 观测（OTel Collector） | 你自己的 OTLP 端点 | 可配置 |
| 告警投递 | Alertmanager 支持的任一接收方（企业微信、邮件、Webhook 等） | 出厂不发给任何人，装好后配置 |

密钥后端目前只有两种：主密钥（`single`）和 OpenBao；云厂商 KMS 不能代替 OpenBao。身份组件 Zitadel 不能替换：平台通过它的管理接口开通租户。

## 5. 网络暴露

| 端口 | 绑定 | 用途 |
|---|---|---|
| 80 / 443（含 443/udp） | 公网或用户网络 | 工作台、身份中心、API、开发者门户、用户手册、文件、托管应用、租户自定义域名 |
| 8443 | 默认只绑定 `127.0.0.1`，可改为运维网卡地址 | 运营台与运营工具（Grafana、Temporal UI、模型网关后台、OpenBao 等） |

- 其余所有服务都不在主机上开放端口。
- 运营入口与用户入口分开：8443 上的每个入口先经运营单点登录，登录时校验运营角色；运营 API 只在 kwork 的独立监听上，用户站点不转发它；内部接口在公网站点返回 404。
- 运营入口默认使用网关内置 CA 的证书，运维人员的电脑要导入这份根证书。
- Docker 开放的端口不受主机防火墙（ufw / firewalld）约束：8443 的暴露范围由绑定地址决定，云安全组也不要放行 8443。安装脚本在防火墙启用时放行 22、80、443。
- Kubernetes：网关的 80 / 443 默认是 LoadBalancer；8443 是集群内地址，只应经内网负载均衡或 VPN 暴露。
- 托管 ISV 应用运行在没有外网路由的内部网络里，唯一的出口是平台的出网代理。
- 对外出口：模型供应商、短信 / 邮件、云对象存储、证书签发（ACME）。离线部署没有出口，模型走本地 OpenAI 兼容端点。

## 6. 硬件规格

| 规模 | 组成 | CPU / 内存 | 磁盘 |
|---|---|---|---|
| 最小部署 | `single`，只有圈 0（5 个容器） | 4 vCPU / 8 GB | 40 GB 可用，SSD |
| 私有化标准 | `onprem` + Agent（`shell`） | 8 vCPU / 16 GB 起，建议 32 GB | 100 GB 起，建议 500 GB |
| 私有化全量 | 再加分析与观测（不含 `obs-llm`） | 16 vCPU / 64 GB，或拆成 2–3 台 | — |

- 打开 `obs-llm`（Langfuse + ClickHouse）再加 8 GB 内存。
- 以上是初始估计。目标服务器上的容量压测尚未完成，容量数字（租户数、并发用户数）目前是目标，不是实测值。
- 已有一份开发机上的性能基线（2026-11-10）：单副本、限到 4 核 8 GB 时，典型读约 400 次/秒以内 P95 13 ms，草稿应用约 25 条/秒以内 P95 95 ms，登录约 2 次/秒以内 P95 1.9 s；200 个用户各约每秒读一次时 P95 13 ms。CPU 不是目标服务器的，只能说明形状，不是容量承诺。

## 7. 升级机制

- **发布物**：kwork、网关（含门户）等镜像，同时提供 amd64 与 arm64，附 SBOM 与构建来源证明，用 cosign 无密钥签名，你可以用 cosign 核对签名身份；Helm chart 以 OCI 形式发布，版本号与镜像相同；离线包按 §4.3 签名。
- **单机升级**：升级脚本分四步：
  1. 先检查、不改动主机：拉取新镜像，用新镜像检查许可证，从新网关镜像取出门户。许可证不认新版本或镜像拉不下来，就在这里停下；
  2. 打开了备份时，先做一次数据库全量备份和一次状态包备份；没打开时提示你自己先备份；
  3. 用新镜像重新执行安装：数据库角色、迁移、身份初始化，然后所有服务换到新镜像；
  4. 安装成功后才把配置指向新版本。安装失败时配置仍指向原来的版本。
- **Kubernetes 升级**：`helm upgrade`，迁移 hook 先执行，然后滚动更新，更新期间不减少可用副本。
- **回滚**：用上一版本的部署文件和镜像再执行一次升级。迁移不回滚，且不全是只加不减：越过删表或改表的版本回滚时，要把数据库恢复到升级前的那次全量备份，之后写入的数据会丢失。离线包只含本版本的镜像，要回滚请保留上一版的离线包。
- **使用 OpenBao 时**：新版本更换了 OpenBao 镜像或配置，OpenBao 会重建并处于封存状态，升级停下等解封，需要解封密钥的保管人在场。
- **现状**：截至本文日期，正式发布流水线尚未成功产出发布版本，cosign 签名验证尚未在发布版本上执行过。

## 8. 职责划分

以下是私有化部署的划分。

| 事项 | 你 | 厂商 |
|---|---|---|
| 主机、操作系统、Docker 或 Kubernetes 集群、网络与安全组 | 负责 | 提供要求与预检脚本 |
| 域名解析、证书信任（内置 CA 时分发根证书） | 负责 | 网关自动签发与续期 |
| 许可证 | 妥善保存原件 | 签发许可证与厂商公钥 |
| 镜像、chart、离线包、安装与升级脚本 | 执行安装与升级 | 构建、签名、发布；离线包公钥另行交付 |
| Helm 形态的 PostgreSQL、Zitadel、对象存储、Redis、Temporal、模型网关、OpenBao | 提供与运维 | 说明配置要求 |
| 打开备份、选择备份存储、保管备份加密密钥 | 负责 | 提供备份、恢复与演练工具 |
| OpenBao 解封密钥保管与每次重启后的解封 | 负责（指定保管人） | 安装时生成密钥份额 |
| 告警接收方、外部拨测 | 配置 | 提供告警规则 |
| 模型供应商的账号与密钥、短信 / 邮件通道 | 提供 | 平台内的配置入口 |
| 租户自带的存储桶（版本控制、跨区复制） | 由租户负责 | 不备份 |
| 厂商支持人员访问租户数据 | 由租户管理员批准，可随时撤销 | 只读、全程写入租户审计 |
