16 KiB
D601 k3s 开发环境建设计划
状态:本过程计划的环境分支方案已废弃。长期权威规则以
docs/reference/deploy.md和docs/reference/ci.md为准:dev/prod 期望状态统一写在master分支的根目录deploy.json,通过environments.dev和environments.prod区分,不再以deploy/dev或deploy/prod分支作为环境事实源。本文件保留为阶段性历史计划,不作为新实现依据。
目标
在现有 D601 原生 k3s 集群内建设一套与生产隔离的 UniDesk 开发环境,让以 LLM 为主力的开发流程可以部署、破坏、重建和验证 backend-core、frontend、Code Queue 及其数据库依赖,而不打断生产主 server。
第一版必须支持通过 GitHub commit id 部署。长期控制点是 GitHub 托管的 deploy.json:部署某个环境时,自动读取对应 GitHub 环境分支里的 deploy.json,并应用其中声明的 commit id。
初始环境分支:
deploy/dev:D601 k3s 开发环境的期望状态。deploy/prod:生产环境的期望状态。分支保护可以后续补上;第一版仍必须把 prod 部署命令和凭据与 dev 隔离。
非目标
- 第一版不创建第二套物理 k3s 控制平面。先复用现有 D601 原生 k3s 集群,通过 namespace 做隔离。
- 第一版不把生产主 server 的 backend-core/frontend 迁入 k3s。
- dev 环境不得共享生产 PostgreSQL 表、Provider 身份、Provider token、Code Queue 任务状态或部署 worktree 路径。
deploy/dev和deploy/prod不是普通源码开发分支的别名,只是环境期望状态分支。
目标开发拓扑
第一版 dev 环境运行在 D601 的 unidesk-dev namespace:
postgres-dev:dev 独立 PostgreSQL StatefulSet,或等价的持久化数据库。backend-core-dev:从deploy/dev:deploy.json声明的 commit id 构建。frontend-dev:从deploy/dev:deploy.json声明的 commit id 构建,并且只代理到backend-core-dev。code-queue-mgr-dev:轻量 Code Queue 控制面,使用 dev 数据库。code-queue-read-dev、code-queue-write-dev、code-queue-scheduler-dev:Code Queue k3s 执行组件,使用 dev 数据库、dev 日志、dev state 路径和 dev Code Queue 配置。- 第一阶段访问方式可选:SSH port-forward 或 D601 私有 ingress。阶段 1 不要求公网暴露。
所有 dev 服务的 /health 必须输出环境身份:
environment=dev- namespace 名称
- 数据库名称
- service id
- GitHub repo 和 commit id
- 部署 ref,预期为
origin/deploy/dev
核心隔离规则
- dev 服务只能使用
unidesk-devnamespace。 - dev 服务必须使用 dev PostgreSQL 实例或 dev 数据库,不能连接生产 PostgreSQL。
- dev Provider 身份必须独立,例如
D601-dev,不能复用生产D601的 provider id 或 provider token。 - dev Code Queue 的 task、queue、attempt、notification 和 trace state 不能写入生产表;除非表名已经显式 namespace 化并经过安全验证。第一版优先使用独立 dev 数据库。
- dev manifest 不得挂载生产部署根目录,例如主 server 的
/root/unidesk或 D601 生产部署路径;除非只读挂载且确实用于诊断。 - dev Code Queue 必须使用 dev workdir、dev log dir 和 dev state dir。
- 生产部署不能读取本地 dirty
deploy.json;必须从配置好的 GitHub 生产环境 ref 读取生产期望状态。 - LLM/Code Queue 开发任务默认只获得 dev 部署凭据。
部署清单模型
环境 manifest 使用同一套 schema:
{
"schemaVersion": 1,
"environment": "dev",
"services": [
{
"id": "backend-core",
"repo": "https://github.com/pikasTech/unidesk",
"commitId": "<commit>"
},
{
"id": "frontend",
"repo": "https://github.com/pikasTech/unidesk",
"commitId": "<commit>"
},
{
"id": "code-queue",
"repo": "https://github.com/pikasTech/unidesk",
"commitId": "<commit>"
},
{
"id": "code-queue-mgr",
"repo": "https://github.com/pikasTech/unidesk",
"commitId": "<commit>"
}
]
}
环境到 ref 的映射必须固定在代码或权威配置中:
dev映射到origin/deploy/dev。prod映射到origin/deploy/prod。
部署命令应接收环境名,而不是让生产部署任意指定分支。debug 或 admin-only 命令可以查看任意 ref,但普通 prod 部署必须走固定映射。
阶段 0:设计与护栏
目的:在加入第二套运行环境前,把目标行为说清楚。
实现项:
- 定义环境 manifest schema 和校验规则。
- 给 deploy manifest 增加
environment字段,并拒绝环境不匹配的 manifest。 - 定义固定环境映射:
dev -> deploy/dev,prod -> deploy/prod。 - 记录 dev 的目标 namespace、数据库、Provider 身份和 service id。
- 增加 CLI dry-run plan 输出:
- 选中的环境
- GitHub ref
- 解析到的 manifest commit
- services 和 commit id
- 目标 namespace
- 目标数据库指纹
- 目标 Provider 身份
验收标准:
deploy plan --env dev可以读取并校验 dev manifest,且不修改集群。deploy plan --env prod可以读取并校验 prod manifest,且不使用本地 worktree 的deploy.json。environment=prod的 manifest 必须被--env dev拒绝,反向也必须拒绝。
阶段 1:GitHub 环境分支作为部署源
目的:让 GitHub 里的环境期望状态 ref 成为部署真相源。
实现项:
- 创建或初始化
deploy/dev,包含有效的deploy.json。 - 创建或初始化
deploy/prod,包含有效的deploy.json。 - 增加 CLI 支持:fetch 环境 ref,并从该 ref 读取
deploy.json。 - 现有本地
deploy.json只保留为显式本地/管理员流程的兼容模式。 - 校验 manifest 中列出的 commit id 存在于声明的 repo。
- 确保 dev/prod 部署不依赖本地 dirty working tree。
验收标准:
deploy plan --env dev读取origin/deploy/dev:deploy.json。deploy plan --env prod读取origin/deploy/prod:deploy.json。- 修改本地
deploy.json不影响--env dev或--env prod。 - plan 输出包含实际使用的 Git ref 和 manifest blob/commit。
阶段 2:D601 开发 Namespace 与数据库
目的:创建 dev backend 和 Code Queue state 的最小隔离底座。
实现项:
- 增加
unidesk-devnamespace 的 k8s manifest。 - 增加 dev PostgreSQL StatefulSet/Service/PVC,或等价持久化 DB。
- 增加 dev DB init 和 migration 流程,用于 backend-core 和 Code Queue 表。
- 增加 dev secrets/config:
- 数据库凭据
- provider token
- auth/session secret
- 必要时的 Code Queue model secrets
- 增加资源 requests/limits,避免 dev DB 挤占 D601 生产 k3s workload。
技术决策:
- 优先使用独立 dev PostgreSQL 实例,而不是共享生产 PostgreSQL 的不同数据库名。独立实例的故障边界最清晰。
- 如果临时使用共享 PostgreSQL server,CLI 和服务启动时必须硬校验数据库名和连接目标。
验收标准:
kubectl -n unidesk-dev get pods,svc,pvc显示 dev DB ready。- dev DB 在 Pod 重启后数据仍存在。
- dev 服务误连生产数据库 URL 时,必须启动失败。
阶段 3:backend-core-dev 与 frontend-dev
目的:做出一套可用的 UniDesk dev 控制面,不依赖生产主 server Compose。
实现项:
- 增加
backend-core-dev和frontend-dev的 k8s manifest。 - 从
deploy/dev:deploy.json声明的 commit id 构建镜像。 - 向 backend-core 注入 dev-only config:
UNIDESK_ENV=dev- dev
MICROSERVICES_JSON - dev database URL
- dev provider token
- dev log paths
- 注入 frontend 配置,使其代理到
backend-core-dev,不能代理生产 backend-core。 - 增加 service health 和 readiness probe。
- 通过 port-forward 或私有 dev ingress 暴露 dev frontend。
技术决策:
- 第一版可以不做公网暴露。验证隔离时使用 port-forward 即可。
- dev frontend 必须有明显 DEV 环境标记,避免操作员混淆。
验收标准:
- dev backend-core
/health返回 ok,并包含environment=dev。 - dev frontend
/health返回 ok,并且只代理到 dev backend-core。 - dev backend/frontend 重部署期间,生产
bun scripts/cli.ts server status仍健康。 - 重建 dev backend/frontend 不触碰主 server Docker Compose 容器。
- 当前实施切片:
deploy apply --env dev --service backend-core|frontend先支持 dev core 两个服务;deploy/dev只保存deploy.json,不保存 k8s manifest 或源码。
阶段 4:code-queue-mgr-dev
目的:提供 dev 队列管理和提交路径,同时不写生产 Code Queue 表。
实现项:
- 增加
code-queue-mgr-devk8s manifest。 - 配置它只使用 dev 数据库。
- 配置 dev backend-core service catalog,使 dev 稳定
code-queue控制/读取路径路由到code-queue-mgr-dev。 - 确保
code-queue-mgr-dev可以提交、列出、汇总和更新 dev queue state。 - health 输出必须证明:
- role 是
master-control-plane或dev-control-plane - database 是 dev
- schema ready
- no runner dependencies
- role 是
验收标准:
- dev UI/CLI 可以向 dev DB 提交 dry-run 或 queued task。
- dev 提交不会改变生产 Code Queue task list。
code-queue-mgr-dev内存占用保持在轻量控制面预算内。
阶段 5:code-queue-dev 执行组件
目的:在 unidesk-dev 内运行 dev Code Queue 执行面,不干扰生产 Code Queue。
实现项:
- 增加 Code Queue manifest 的 dev 变体:
code-queue-read-devcode-queue-write-devcode-queue-scheduler-dev
- 所有 dev 组件使用 dev 数据库、dev 日志和 dev state 路径。
- 使用 dev service name 和 label,避免生产 k3s adapter 混淆 dev/prod 服务。
- 决定第一版支持真实 Codex 执行,还是只支持 smoke-only 执行。
- 如果启用真实执行:
- 隔离 workdir 路径
- 隔离 Codex/OpenCode XDG/state 路径
- 隔离通知
- 限制并发和内存
- 默认不写生产 OA Event Flow,除非显式配置为 dev
技术决策:
- 第一版采用真实 Code Queue 进程和 dev PostgreSQL,但部署验收先以执行面可部署、
/health通过和 dev DB 隔离为准。 - dev scheduler 使用
D601-dev作为本机 Provider 标识,默认工作目录为/workspace-dev,远程工作目录为/home/ubuntu/unidesk-dev-workspace。 - 默认禁用生产 ClaudeQQ 通知,不使用生产
d601-tcp-egress-gateway或生产 PostgreSQL 入口。 - dev frontend/backend-core 的稳定
code-queue业务路由需要等code-queue-mgr-dev和 dev service catalog 完成后再接入,本阶段不把 dev 执行面伪装成完整业务入口。
验收标准:
- dev Code Queue
/health返回 ok,并包含environment=dev。 deploy apply --env dev --service code-queue可以根据origin/deploy/dev:deploy.json构建unidesk-code-queue:dev,部署code-queue-scheduler-dev、code-queue-read-dev、code-queue-write-dev,并验证 health commit。- 后续接入
code-queue-mgr-dev后,dev scheduler 可以拾取 dev queued task,并推进到终态。 - 重启 dev scheduler 不影响生产 running task。
- dev Code Queue rollout 期间,生产
code-queuehealth 仍健康。
阶段 6:Dev 部署执行
目的:让 deploy/dev:deploy.json 端到端驱动 dev 环境。
实现项:
- 增加
deploy apply --env dev。 - 对 dev manifest 中的每个服务:
- fetch 声明的 repo 和 commit
- 在 D601 上构建镜像,或复用既有 target-side build 路径
- 用环境和 commit 给镜像打 tag
- apply dev k8s manifest
- 等待 rollout
- 从
/health或 Deployment annotation 验证 live commit
- 部署记录包含 environment、ref、service id、commit id、image tag、namespace 和 rollout 状态。
- 增加
deploy status --env dev或等价 drift check。
验收标准:
- 更新
deploy/dev:deploy.json到新 commit 后,运行deploy apply --env dev会更新 dev backend-core/frontend/code-queue 组件。 - live
/healthcommit 与 manifest commit 一致。 - dev 部署不会修改任何生产 Deployment、Service、Secret、PVC、DB table 或 Docker Compose 容器。
阶段 7:生产部署 Ref 兼容
目的:让生产部署从 deploy/prod 读取期望状态,同时保持生产运行方式不变。
实现项:
- 增加
deploy plan --env prod和deploy apply --env prod,读取origin/deploy/prod:deploy.json。 - 初期保持现有生产 executor:
- 生产 backend-core/frontend 和 direct sidecar 继续使用主 server Compose。
- 生产 Code Queue 执行面继续使用 D601 k3s。
- 强化生产命令护栏:
- 只能在权威根目录执行
- 生产凭据只存在主 server
- manifest 必须声明
environment=prod - 目标 namespace 和 Provider 身份必须匹配生产
- 建议后续给
deploy/prod增加 branch protection;第一版可暂缓。
验收标准:
- 生产部署不再依赖本地
deploy.json。 - 生产部署报告实际使用的 Git ref 和 manifest commit。
- 生产部署 rollout 后仍校验 live commit。
阶段 8:操作员与 LLM 安全
目的:降低 LLM agent 和人工操作员混淆环境的概率。
实现项:
- 每次 deploy 的 CLI 输出都清晰显示:
- environment
- ref
- namespace
- DB 指纹
- provider id
- services 和 commits
- dev frontend 增加明确 DEV 标记。
- 增加硬启动检查:
- dev service 拒绝生产 DB
- dev service 拒绝生产 provider id/token
- prod service 拒绝 dev namespace/DB
- 确保 LLM task container 默认只拿到 dev deploy 凭据,拿不到 prod 凭据。
- 增加 smoke check:故意尝试不安全组合,并验证它们失败。
验收标准:
- dev 服务使用生产 DB 配置启动时,在监听端口前失败。
- 从非权威上下文运行 prod deploy 时失败。
- LLM/Code Queue 默认环境可以部署 dev,但没有独立生产凭据路径时不能部署 prod。
风险与缓解
- 风险:namespace 不能隔离节点级 CPU、内存、Docker socket、hostPath 或 containerd 压力。
- 缓解:资源 requests/limits、独立 dev workdir、不挂载生产路径,并限制 Code Queue 并发。
- 风险:dev Code Queue 误写生产 task 表。
- 缓解:独立 dev DB、启动时 DB 指纹检查、health 输出 DB 身份。
- 风险:dev frontend 看起来像 prod,或代理到 prod backend-core。
- 缓解:可见 DEV 标记、
CORE_INTERNAL_URL固定到 dev service、proxy target health check。
- 缓解:可见 DEV 标记、
- 风险:deploy 命令误读本地 manifest,而不是 GitHub 环境 ref。
- 缓解:
--env模式必须只读取 remote ref,并报告实际使用的 ref/blob。
- 缓解:
- 风险:D601 k3s 控制面故障同时影响 dev 和生产 k3s workload。
- 缓解:Phase 1 接受该风险;只有 namespace 隔离被证明不足后,再考虑独立物理节点或节点级 dev 集群。
- 风险:
deploy/prod初期未开启 branch protection。- 缓解:即使没有 branch protection,生产部署仍必须要求权威主 server 凭据,并报告用于审计的 ref。
建议实现顺序
- Phase 0 和 Phase 1:建立 GitHub 环境分支期望状态和 dry-run planning。
- Phase 2 和 Phase 3:创建 dev namespace、dev DB、backend-core-dev 和 frontend-dev。
- Phase 4 和 Phase 5:增加 dev Code Queue 控制面和执行组件。
- Phase 6:让
deploy apply --env dev按 commit id 部署完整第一版 dev stack。 - Phase 7:把生产部署迁移到
deploy/prod。 - Phase 8:强化操作员和 LLM 安全检查。
第一个完整里程碑完成条件:deploy apply --env dev 可以根据 origin/deploy/dev:deploy.json 声明的 commit id,把 backend-core、frontend、code-queue-mgr 以及 Code Queue read/write/scheduler 部署进 unidesk-dev;反复 dev redeploy 不改变生产主 server status,也不改变生产 Code Queue state。阶段 3 的阶段性里程碑先以 --service backend-core 和 --service frontend 分别部署成功为准。