# UniDesk Sub2API ## 目录 - [先看报表](#先看报表) - [先读边界](#先读边界) - [部署与状态](#部署与状态) - [PK01 host-Docker target](#pk01-host-docker-target) - [D601 Egress Proxy](#d601-egress-proxy) - [镜像升级](#镜像升级) UniDesk 通过 `platform-infra sub2api` 运维 YAML 选中的 Sub2API target。当前 active target 以 `config/platform-infra/sub2api.yaml` 为准;PK01 可作为 host-Docker active target 并通过 PK01 Caddy 本地反代提供 `api.pikapython.com`,D518/D601 等 k3s target 仍可按 YAML 声明为 external-active 或 retired,G14 由同一 YAML/CLI 控制为 standby predeploy。日常操作统一使用 UniDesk CLI,不直接写 Kubernetes 资源或手工调用 Sub2API 管理 API。 **固定入口**: `cd /root/unidesk && bun scripts/cli.ts platform-infra sub2api ...` ## 先看报表 查 Codex pool 哨兵状态、账号冻结/恢复、marker 命中、下一次 probe、最近 CronJob run、token/cost 账本时,优先使用这个低噪声报表入口,不要先翻 ConfigMap、CronJob 日志或 Sub2API UI: ```bash bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-report ``` 需要机器处理或完整字段时再加 `--raw`;需要更多最近运行记录时加 `--events N`。 追溯某个 Codex/Sub2API request id 的中断、上游账号、切号、临时不可调度、账号选择失败和同窗口账号池信号时,优先使用低噪声 trace 报表,不要先手写 `kubectl logs | grep`: ```bash bun scripts/cli.ts platform-infra sub2api codex-pool trace --request-id ``` 默认输出类似 k8s/ps 的短表;机器处理用 `--raw` 读取 `.data.trace.*`;需要审计原始匹配日志时加 `--show-lines`;需要扩大搜索范围时使用 `--since 24h --tail 50000`。该命令只读:读取 Sub2API 日志、账号快照和 admin API 元数据,不改 `schedulable`、不清 runtime backoff、不中断请求。 ## 先读边界 - 仓库长期开发边界见 `docs/reference/platform-infra.md`,本 skill 承担日常操作手册。 - 配置真相是 YAML:`config/platform-infra/sub2api.yaml` 和 `config/platform-infra/sub2api-codex-pool.yaml`。 - 业务策略和具体数值只以 YAML 为准。已有字段的数值调整只改 YAML 并跑 `plan` / `sync --confirm` / `validate`;不要自动补代码硬编码、schema 硬范围、合同测试、单元测试或长期参考文档。配置校验只校验格式、类型、必填和可渲染性,不判断数值策略是否“合理”。 - 本 skill 目录下若存在 `agents/*.yaml`,只作为 skill/agent 展示与调用元数据,不是 Sub2API 或 Codex pool 运行配置;不要在 skill 目录维护第二份账号、capacity、priority、endpoint 或 Secret 配置。 - Runtime target 由 `config/platform-infra/sub2api.yaml` 声明;默认 target 来自 YAML `defaults.targetId`,当前 `api.pikapython.com` 使用 PK01 host-Docker target。`D518:k3s`、`D601:k3s` 这类 k3s target 必须通过显式 `--target` 选择并按 YAML role 判定 active/retired/standby,`G14:k3s` 是 standby target。master server 只是控制端和消费者,不部署 Sub2API/PostgreSQL/Redis。 - Standby target 不部署本地 PostgreSQL,不运行 sentinel、FRP 管理入口或 HTTPS egress proxy;只能预部署 namespace、NetworkPolicy、Service,以及 replicas=0 的 Sub2API/Redis Deployment。Redis 激活后也只允许 ephemeral cache。External-active target 仍不部署本地 PostgreSQL,必须直连 YAML 声明的外置 DB,使用本地 ephemeral Redis,并且只有在 YAML 启用时才运行 frpc、egress proxy 和目标级 sentinel;多个 external-active target 可以并存,不得把一个 target 的 public exposure 当作另一个 target 的替代或回退。 - Secret、`~/.codex/config.toml*`、`~/.codex/auth.json*` 是运行时输入或本地状态,不提交。 - 默认 `~/.codex/config.toml` 和 `~/.codex/auth.json` 只作为统一 Sub2API consumer 使用;`config.toml` 必须指向 YAML-selected active target 的 consumer URL,`auth.json` 必须使用统一 pool API key。新增上游账号不得覆盖这两个默认文件,只能新增 `config.toml.` / `auth.json.` 并在 YAML 里声明。 - 输出只能包含 Secret 路径、key 名、presence、fingerprint 和 `valuesPrinted=false`;禁止打印完整 API key、admin password、JWT secret、TOTP key、base64 payload 或可复制的 preview。 ## 部署与状态 ```bash bun scripts/cli.ts platform-infra sub2api plan bun scripts/cli.ts platform-infra sub2api plan --target G14 bun scripts/cli.ts platform-infra sub2api image-prepull --target PK01 bun scripts/cli.ts platform-infra sub2api image-prepull --target PK01 --confirm bun scripts/cli.ts platform-infra sub2api rollout --target PK01 --dry-run bun scripts/cli.ts platform-infra sub2api rollout --target PK01 --confirm bun scripts/cli.ts platform-infra sub2api smoke --target PK01 bun scripts/cli.ts platform-infra sub2api apply --dry-run bun scripts/cli.ts platform-infra sub2api apply --target G14 --dry-run bun scripts/cli.ts platform-infra sub2api apply --confirm bun scripts/cli.ts platform-infra sub2api apply --target G14 --confirm bun scripts/cli.ts platform-infra sub2api status bun scripts/cli.ts platform-infra sub2api status --target G14 bun scripts/cli.ts platform-infra sub2api validate bun scripts/cli.ts platform-infra sub2api validate --target G14 ``` - `plan` 读取 `config/platform-infra/sub2api.yaml`,渲染 `src/components/platform-infra/sub2api/sub2api.k8s.yaml`,检查 no Ingress/NodePort/LoadBalancer/hostPort/hostNetwork/resource limits,并要求 `NetworkPolicy/allow-all` 随 manifest 受控创建。 - `apply --confirm` 默认创建异步 job;按返回的 `job status` 命令轮询,再跑 `status` 和 `validate`。 - `status --full|--raw` 只在需要展开远端 stdout/stderr 或原始 JSON 时使用。 - `validate` 是按需验收,不是连续可用性探针。对 standby target,`validate --target ` 验证预部署形态,不要求外置 DB 当前可连接;对 external-active target,必须验证外置 DB、ephemeral Redis、Sub2API service、YAML egress proxy 和目标级 public exposure。 ## PK01 host-Docker target PK01 host-Docker target 由 `config/platform-infra/sub2api.yaml` 的 target `runtimeMode: host-docker` 控制。`api.pikapython.com` 的当前路径是 `client -> PK01 Caddy -> 127.0.0.1: -> PK01 host-Docker Sub2API`,不是 D601 FRP 路径。优先用以下受控入口分层判断: ```bash bun scripts/cli.ts platform-infra sub2api status --target PK01 bun scripts/cli.ts platform-infra sub2api validate --target PK01 ``` PK01 没有 k3s control plane。`codex-pool sync --target PK01 --confirm` 和 `codex-pool validate --target PK01` 走 host-Docker adapter:通过本机 Sub2API admin API 和 YAML `hostDocker.envPath` 对齐账号池,不使用 k8s Secret/CronJob,也不重启容器。`sentinel-report`、`sentinel-probe`、`sentinel-image` 和部分 `trace` 能力仍可能依赖 k8s/kubectl;在这些命令上看到 `kubectl` 缺失时,应归类为 CLI host-Docker adapter 缺口,不要误判为 Sub2API app、Caddy、上游或账号池故障。临时排障只能做只读 admin API、DB join 表和最小公网 `/v1/responses` smoke,并且不得打印 admin password、API key 或账号凭据。 PK01 host-Docker apply 仍必须由 `platform-infra sub2api apply --target PK01 --confirm` 受控执行。若 dry-run 或 apply 输出显示 `docker compose is absent; apply will use raw docker run fallback`,这表示 CLI 选择了 host-Docker fallback,不是裸手工 Docker 操作;只要 YAML image、env、ports、Caddy managed block 和 `status/validate` 最终对齐,可作为受控滚动升级证据。不要改用手工 `docker run`、手工 compose 文件或直接编辑 PK01 Caddyfile。 - 正式镜像升级优先使用 `platform-infra sub2api rollout`: - 同一入口组合镜像 presence、plan、apply dry-run、预拉、apply、status、validate 和既有消费配置 smoke; - `--confirm` 默认返回 async job,显式 `--wait` 只用于 job 内部或同步调试; - 镜像预拉长连接预算读取 `defaults.rollout.imagePrepullTimeoutSeconds`; - 禁止依赖默认 60 秒 SSH 上限反复续拉。 - `image-prepull` 只作为单阶段诊断入口,不作为标准升级主路径。 - 禁止用临时 `trans docker pull ...` 作为长期入口。 ## D601 Egress Proxy D601 的目标级 `egressProxy` 完全由 `config/platform-infra/sub2api.yaml` 控制。当前成熟形态是 master Docker `shadowsocks-rust` 作为加密出站源,D601 k3s 内 `sing-box` 暴露 HTTP/mixed ClusterIP proxy 给 Sub2API 和按 YAML 启用的 sentinel 使用。不要把 endpoint、端口、密码、健康探针或镜像 tag 写进 skill;只以 YAML 和 `config/platform-infra/sub2api-master-egress-proxy.compose.yaml` 为准。 master 侧 proxy 由 UniDesk checkout 内的 compose 文件管理: ```bash docker compose -f config/platform-infra/sub2api-master-egress-proxy.compose.yaml up -d --force-recreate bun scripts/cli.ts platform-infra sub2api apply --target D601 --confirm bun scripts/cli.ts platform-infra sub2api validate --target D601 bun scripts/cli.ts platform-infra sub2api codex-pool sync --target D601 --confirm bun scripts/cli.ts platform-infra sub2api codex-pool validate --target D601 ``` proxy secret/config 文件只允许放在受控 Secret/state 路径,输出只能披露路径、presence、fingerprint 或摘要,不能打印密码、完整订阅或生成配置。若 D601 到上游的 TLS/SNI 路径被 reset,不要用临时 JS 或简陋 HTTP CONNECT proxy 作为最终方案;通过 YAML/compose 更换或修复成熟加密 proxy source,再跑上面的 apply/validate/sync/validate 闭环。 ## 镜像升级 - 快速通道边界: - 只适用于单 target 的纯版本滚动; - 允许变更目标的 `image.repository`、`image.tag`、`pullPolicy` 和对应 TaskTree ExecutionReport; - 不允许夹带 Sub2API 源码、UniDesk CLI、账号池 runtime、代理、Secret、多 target 或其他配置变更; - 超出边界时使用独立分支和 PR,不得直接 push `master`。 - 开始前同步: - 固定主 worktree 保持在 `master`; - 落后 remote 且存在脏改时,按主 worktree 规范执行 `git stash push -u`、`git pull --ff-only` 和 `git stash apply`; - 精确保护和处理并行改动,禁止 reset、覆盖式 checkout 或把无关文件带入版本提交。 - 目标 patch: - 只修改目标 target 的 `image.repository`、`image.tag` 或 `pullPolicy`; - 使用 target 附近的上下文 patch; - 不按第一个 `tag:` 命中,不改全局默认或其他 target。 - 发布 dry-run: - 只调用一次 `sub2api rollout --target --dry-run`; - 默认摘要同时披露当前镜像、目标镜像、presence、plan 和 apply dry-run; - 摘要完整时不再分别调用 `status`、`plan`、`image-prepull` 和 `apply --dry-run`。 - 发布确认: - 只调用一次 `sub2api rollout --target --confirm`; - 按返回的唯一 `job status` 命令等待终态; - `job status` 默认投影 `prepull`、`apply`、`verify` 当前阶段、终态、验证子项和阶段耗时;只有原始 stderr/stdout 排障才使用 `--full`; - job 内顺序完成预拉和 apply,并行完成 status、validate 与既有消费配置 smoke; - 不在外部重复逐阶段轮询。 - 运行面验收: - 以 job 终态中的 status、validate 和既有消费配置 smoke 为标准证据; - 只有终态缺少 smoke 证据时,补一次 `sub2api smoke --target `; - rollout 或 smoke 未成功时不得提交和推送目标版本。 - 成功后收尾: - rollout 与 smoke 成功后再创建或补全 TaskTree Task 和 ExecutionReport; - 遗留 MDTODO 按 `$unidesk-tasktree` 迁移;目标镜像 YAML 仍单独精确提交; - 直接执行 `git push origin master`,不创建 draft PR、正式 PR 或 guarded merge; - 推送失败时先解决远端快进关系,不重复 rollout; - push 后核对远端 `master` 已包含该提交和目标镜像声明。 - 精确下钻: - 只有 rollout 终态缺少某项证据时,才使用输出给出的下钻命令; - 不固定重复执行 status、validate、public health 或 smoke。 - 镜像升级禁止配置对齐: - 不得执行 `codex-pool plan`、`codex-pool sync` 或 `codex-pool validate`; - 不得对齐账号、group、统一 key、capacity、load factor、WebSocket、临时不可调度规则、代理绑定或手工账号。 - 镜像升级的真实模型请求证据: - 只能复用升级前已经存在的消费配置执行无写入 smoke; - `rollout` 自动复用匹配目标 public URL 的 `~/.codex/config.toml` 和 `auth.json`; - 配置缺失或目标不匹配时只报告 skipped; - 不得为完成 smoke 创建、恢复、同步或覆盖任何配置。 - 正常热缓存升级的操作目标是 5 分钟内完成: - `rollout` 输出 `prepull`、`apply`、`verify` 和 `total` 分阶段耗时; - 超时先按失败 stage 下钻; - 不回退到旧的十余条手工串联流程。 不要把镜像版本写进脚本常量、JSON 或 manifest 模板。