6.6 KiB
6.6 KiB
Real Host Acceptance Runbook
日期:2026-05-16
目标
把当前 CONDITIONAL_APPROVED 的剩余外部门禁收敛为一套可直接执行的真实宿主验收流程,覆盖:
- 真实 sub2api 宿主接入探测
- pack 安装
- preview/import 验证
- access preview / access status 验证
- reconcile 验证
- rollback smoke
前置条件
控制面
sub2api-cn-relay-manager已启动CRM_BASE_URL可访问,例如http://127.0.0.1:8080- 已设置
CRM_ADMIN_TOKEN
真实宿主
- 已知真实宿主
HOST_BASE_URL - 已知宿主管理认证:
HOST_API_KEY或HOST_BEARER_TOKEN
- 至少一个真实 provider key
- 已知 pack 路径,例如
/app/packs/openai-cn-pack
推荐执行方式
1. 构建本地容器镜像(适用于代理/离线开发机)
cd /path/to/sub2api-cn-relay-manager
scripts/build_local_image.sh
默认输出:
- 二进制:
bin/sub2api-cn-relay-manager - 镜像:
sub2api-cn-relay-manager:local
2. 先 dry-run 检查真实验收参数
CRM_BASE_URL=http://127.0.0.1:8080 \
CRM_ADMIN_TOKEN=replace-me \
HOST_NAME=prod-sub2api \
HOST_BASE_URL=https://sub2api.example.com \
HOST_API_KEY=host-admin-key \
PACK_PATH=/app/packs/openai-cn-pack \
PROVIDER_ID=deepseek \
KEYS=sk-live-1,sk-live-2 \
ACCESS_MODE=self_service \
ACCESS_API_KEY=user-gateway-key \
DRY_RUN=1 \
scripts/real_host_acceptance.sh
3. 执行真实验收
CRM_BASE_URL=http://127.0.0.1:8080 \
CRM_ADMIN_TOKEN=replace-me \
HOST_NAME=prod-sub2api \
HOST_BASE_URL=https://sub2api.example.com \
HOST_API_KEY=host-admin-key \
PACK_PATH=/app/packs/openai-cn-pack \
PROVIDER_ID=deepseek \
KEYS=sk-live-1,sk-live-2 \
ACCESS_MODE=self_service \
ACCESS_API_KEY=user-gateway-key \
scripts/real_host_acceptance.sh
4. 订阅模式示例
CRM_BASE_URL=http://127.0.0.1:8080 \
CRM_ADMIN_TOKEN=replace-me \
HOST_NAME=prod-sub2api \
HOST_BASE_URL=https://sub2api.example.com \
HOST_BEARER_TOKEN=host-bearer-token \
PACK_PATH=/app/packs/openai-cn-pack \
PROVIDER_ID=deepseek \
KEYS=sk-live-1 \
ACCESS_MODE=subscription \
SUBSCRIPTION_USERS=user-a,user-b \
SUBSCRIPTION_DAYS=30 \
scripts/real_host_acceptance.sh
5. 导入后自动补 access 前置(可选)
当真实宿主需要额外完成“普通用户余额 / key-group 绑定 / 订阅写入 / 缓存失效”等宿主侧动作时,可在 import 完成后插入自定义 hook:
AFTER_IMPORT_HOOK_COMMAND='bash /path/to/host-access-hook.sh' \
... \
scripts/real_host_acceptance.sh
hook 执行时会额外导出:
BATCH_IDBATCH_DETAIL_FILE(若非 dry-run,会指向05a-batch-detail-pre-access.json)PROVIDER_IDHOST_BASE_URLCRM_BASE_URLACCESS_MODEMODEARTIFACT_DIR
标准产物会新增:
05a-batch-detail-pre-access.json05b-after-import-hook.stdout.txt05b-after-import-hook.stderr.txt
产物
脚本会把每一步 JSON 响应落到:
artifacts/real-host-acceptance/<timestamp>/
默认文件顺序:
01-create-host.json02-probe-host.json03-install-pack.json04-preview-import.json05-import.json05a-batch-detail-pre-access.json(若拿到了batch_id且非 dry-run)05b-after-import-hook.stdout.txt/05b-after-import-hook.stderr.txt(若配置了 hook)06-access-preview.json07-access-status.json08-provider-status.json09-reconcile.json10-batch-detail.json11-rollback.json(若未跳过)
通过标准
至少同时满足:
probe-host返回宿主版本与 capability 快照install-pack成功import返回batch_id,且 batch/provider 状态不为failedaccess-preview返回available=true或 access status 进入:subscription_readyself_service_readyfully_ready
reconcile不返回关键失败rollback smoke成功(若本次需要验证回滚链路)
当前门禁解释
- 若以上脚本在真实宿主环境全部通过:
- 可以把当前项目从 代码层
CONDITIONAL_APPROVED推进到 真实环境放行
- 可以把当前项目从 代码层
- 若脚本未执行:
- 仍然只能维持
CONDITIONAL_APPROVED
- 仍然只能维持
- 若脚本执行但失败:
- 失败应被归类为真实宿主兼容性 / 凭据 / 网络 / pack 内容问题,而不是再泛化成“代码是否已完成”
注意事项
- 默认会执行 rollback smoke;若当前环境不允许回滚,设置:
SKIP_ROLLBACK=1 scripts/real_host_acceptance.sh
PACK_PATH必须是控制面进程可读路径,不是用户本地概念路径。- 如果控制面部署在容器中,确保 pack 目录已经挂载进去。
HOST_API_KEY与HOST_BEARER_TOKEN二选一即可;脚本会自动推导auth.type=apikey|bearer。ACCESS_API_KEY必须使用真实未脱敏的普通用户 gateway key;不能直接复用数据库/列表接口中的展示值。- 真实宿主初始化只会准备管理员账号;普通用户账号/密码不会自动生成,验收前必须显式创建并留存可复用凭据。
self_service验证除普通用户 key 外,还需要该 key 绑定目标 group;若目标 group 是标准计费组,还需要用户侧具备可用余额,否则/v1/models可能从“未授权”转为INSUFFICIENT_BALANCE。subscription验证需要目标 group 本身是subscription类型,并且完成“普通用户订阅分配 + 普通用户 key 绑定该 group”;仅有管理员主体或未绑定 key 不足以通过/v1/models。- 若需要验证
reconcile收敛,优先在干净宿主场景或隔离 group 下执行,避免历史残留资源把结果污染成status=drifted/extra_count>0。 scripts/import_remote43_provider.sh现已内置 remote43 的 subscription 验收补全动作:会根据 import batch 自动解析目标 group,执行“普通用户最低余额补齐 + key/group 绑定 + user_subscriptions upsert + 定向 Redis 缓存失效(auth / balance / subscription)”,并把 SQL / host state 证据写入 artifact 目录。- 当 CRM 进程与 operator 到 host 的访问地址不一致时,优先显式设置
CRM_HOST_BASE,避免把 CRM 侧探测地址和本地运维隧道地址混用。 - 对
Upstream service temporarily unavailable一类 502,不要先认定是上游聊天链路故障;先看脚本落盘的09-models.headers.txt/10-models.body.json。若/v1/models已返回了别的 provider 模型集(例如 GPT 系列而不是预期的 DeepSeek/Minimax 模型),先检查普通用户 key/group 绑定,也要检查 CRM 导入时是否把 provider 的channel_template.model_mapping、restrict_models、billing_model_source一并下发到宿主 channel。