7.0 KiB
Sentinel
sentinel.monitor.enabled: 账号级 marker 哨兵监控开关;开启后codex-pool sync --confirm会在platform-infra创建/更新 k8s CronJob、ConfigMap、Secret、ServiceAccount、Role 和 RoleBinding。CronJob 直打 YAML-managed 上游账号的 OpenAI Responsesgpt-5.5,用确定 marker 作为唯一健康标准,并在独立 state ConfigMap 中记录 token/cost 账本。sentinel.actions.enabled: 账号级哨兵冻结/恢复动作开关;当前 marker-only guard 要求开启。动作关闭时只记录would-freeze,不会调用 Sub2API admin API 改schedulable。动作开启后,只要不满足 marker match,不论是 HTTP 200 私货、4xx/5xx、非 JSON、连接错误还是空输出,都进入同一个冻结/恢复状态机。sentinel.sdk.openaiPythonVersion: 哨兵容器使用的 OpenAI Python SDK 固定版本;模型请求必须通过标准 SDKresponses.create,不要手工拼/v1/responses请求体或手写响应解析。后续升级 SDK 只改 YAML 并sync --confirm。sentinel.probe.maxOutputTokens: 哨兵本地流式 delta 收集上限,必须保持小值;它不作为上游max_output_tokens字段发送,以保持与 Sub2API WebUI 默认账号连接测试的 Responses SSE 请求形态一致。哨兵不限制并发和每轮账号数,所有到期账号会在同一轮并发探测。sentinel.probe.userAgent: 哨兵 direct upstream probe 的默认 User-Agent,通过 OpenAI SDKextra_headers传递;默认贴近 Sub2APInet/http账号连接测试形态,个别账号仍可用profiles.entries[].upstreamUserAgent覆盖。sentinel.cadence: 成功信任指数退避配置。当前口径是从 1 分钟开始,连续成功后按账号trustUpstream选择可信/不可信最大退避;任意非 marker match 清零成功信任并进入冻结退避。可信/不可信最大退避数值只写 YAML。sentinel.freeze: 失败冻结 TTL 指数退避配置。当前口径是初始 1 分钟,失败后1m -> 2m -> 4m -> 8m -> 10m,最大 10 分钟;失败 probe 基本不消耗有效输出 token,因此冻结窗口保持短周期。冻结到期后只做恢复 probe,通过才自动恢复,不能仅靠 TTL 到期解封。sentinel.pricing: 直打上游时哨兵自己的 token/cost 估算价格。因为 direct upstream probe 不经过 Sub2API 普通用量账本,哨兵必须自己记录全局与 per-account token/cost;这些账本只用于观察,不作为跳过探测的预算门禁。
对已支持的 k3s target,sync --confirm 会登录 Sub2API admin、创建/更新 group、创建/更新 YAML 中的 unidesk-codex-* accounts、创建/复用统一 API key Secret,并部署/更新哨兵资源;它不把既有 managed account 直接恢复为 schedulable=true。恢复只由哨兵在读取 Sub2API runtime schedulable=false 后触发 recovery probe,并在 marker 命中时执行。sync 默认不删除 YAML 中缺席的 managed account。只有明确退役上游时才使用 sync --confirm --prune-removed 删除缺席且 extra.unidesk_managed=true 的 unidesk-codex-* account。对 manualAccounts.protected,sync 只执行 YAML 显式允许的窄同步;当前允许项是从目标 egressProxy 创建/更新 Sub2API internal proxy 记录并绑定 proxy_id,以及把受保护手动账号加入当前 pool.groupName。它仍不接管该账号凭据、status、schedulable、priority/capacity/loadFactor 或哨兵状态。PK01 host-Docker target 在 codex-pool adapter 补齐前不具备这条完整 sync 路径。
sentinel-image status|build 管理哨兵 Python 运行环境镜像。镜像由 YAML 的 sentinel.image 基础镜像和 sentinel.sdk.openaiPythonVersion 派生,发布到目标 runtime 的本地 registry;build --confirm 会先检查 registry tag,存在则快速复用,不存在才在目标 host 构建并 push。CronJob 启动时只校验 SDK 版本,不在运行时 pip install。目标是否启用哨兵以 config/platform-infra/sub2api.yaml 的 sentinel.enabledOnTargets 为准;未启用的 target 在 sync/validate 中应显示 skipped-target-disabled,不得要求镜像构建、CronJob、Secret 或 state ConfigMap 存在。
sync --confirm 同时会按 YAML 渲染账号级哨兵资源,并在 monitor 开启时先确保可复用哨兵镜像存在。当前目标是 sentinel.monitor.enabled=true + sentinel.actions.enabled=true 的 marker-only 自动冻结/恢复;不要手工 patch CronJob、Secret 或 Sub2API account。若 YAML 新增账号或修改 profile/base URL/API key fingerprint/upstream User-Agent/Responses WebSocket mode,sync 会从变更前 runtime state 写入 pending probe 记录并立即安排 sentinel probe,但不会把既有账号直接恢复为可调度;只有 sentinel 读取到 Sub2API runtime schedulable=false 后执行 recovery probe,且 marker 命中,才恢复 schedulable=true。sentinel 冻结/恢复只改 schedulable=false|true,不得顺手调用 Sub2API recover-state 清除请求路径临时不可调度或其他 runtime backoff。无关账号的既有成功/失败退避不能被重置。若 YAML 下调失败冻结最大窗口,sync 会把仍 active 的旧冻结状态迁移到当前最大窗口内并立即安排 recovery probe,但不会直接解冻。若怀疑某个账号被误判,先用 codex-pool sentinel-probe --account <accountName> --confirm 立即触发该账号测量;该命令从现有 CronJob 模板派生一次性 Job,复用同一份 Secret、ConfigMap、OpenAI SDK probe、token/cost 账本和冻结/恢复状态机。
trace --request-id <requestId> 是只读 request 追溯报表,不触发 probe、不修改账号。默认输出请求开始/最终状态、failover、account_select_failed、窗口内 account_temp_unschedulable、admin schedulable 写入计数和当前账号快照;reason=failover-attempted-no-candidate 表示 Sub2API 已进入自动切号,但排除当前失败账号后没有可用候选。需要机器处理时使用 --raw,需要原始匹配行时加 --show-lines。
sentinel-report 是只读低噪声报表,不触发 probe、不修改账号。默认输出类似 ps 的文本表,展示每个账号的探测次数、Sub2API runtime schedulable、最近 marker/HTTP/动作、冻结 TTL、成功退避、下一次 probe 和最近 run 事件;SCH 展示 Sub2API runtime schedulable,PROT 展示账号级保护阈值,P_FAIL 展示最近一次保护确认中的失败次数/阈值;需要机器处理时使用 sentinel-report --raw。
对已支持的 k3s target,sync --confirm 和 validate 可能超过单次 SSH/runtime 短连接窗口。必须继续使用 bun scripts/cli.ts platform-infra sub2api codex-pool ... --target <k3s-target>,由 CLI 在目标远端提交作业并短轮询状态;不要改用裸 trans <target>:k3s sh 等一个长连接等待完整结果。若看到 UNIDESK_SSH_RUNTIME_TIMEOUT,先按 docs/reference/platform-infra.md 的规则处理为控制面可见性问题,修 CLI/job/poll 或重跑受控命令,不要手工 patch Sub2API credentials 或源码。