17 KiB
部署与运维模块
1. 定位
本模块规定 cpa-ext 如何构建、安装、启动、观察、备份、升级和恢复。它把 dev.md 的 native runtime 约束、security.md 的 fail-closed 前提和 persistence.md 的数据库规则转成可执行运维流程。
当前仓库仍是只声明 usage_plugin 的基础骨架,不具备本文所述完整生产能力。只有 test-plan.md 的相应发布门禁通过后,才能把某个版本标记为 production-ready。
2. 支持基线
设计验证基线:
| 项目 | 目标 |
|---|---|
| CLIProxyAPI | v7.2.130 / f43aad7637ad813745bf7d341acb5663617570c5 |
| Native ABI | 1 |
| RPC schema | 3 |
| cpa-ext plugin ID | cpa-ext |
| 当前 module Go | 1.24 |
| CPA module Go | 1.26.0 |
| Home mode | 不支持,必须关闭 |
| CPA build | 必须是 CGO/plugin-capable,不能使用 no-plugin 产物 |
生产兼容性按“精确 CPA tag + OS + arch + cpa-ext artifact”发布,不只写“ABI 1”。每次升级 CPA 都要重新跑 ABI、E2E、安全、性能和 soak 门禁。
目标发布矩阵:
- Linux amd64/arm64
.so; - Windows amd64
.dll; - macOS amd64/arm64
.dylib(若实际维护); - WSL 构建的
.so只供运行在 WSL/Linux 的 CPA,不能装入 Windows CPA。
Go c-shared 需要目标平台 C toolchain,不能只设置 GOOS/GOARCH 假装完成 CGO 交叉编译。
3. 运行拓扑
3.1 默认 MVP
reverse proxy / readiness gate
│
▼
CLIProxyAPI + cpa-ext.so
│
├─ synchronous short SQLite transactions
├─ callback-driven bounded maintenance
└─ no long-lived plugin worker
第一版默认 callback-driven:认证、准入、事实和账本在回调内完成必要短事务;聚合追赶、清理和 checkpoint 只在安全宿主调用中按时间/页数预算推进。
3.2 Sidecar 拓扑
P0 runtime/24h soak 失败,或需要长期 quota refresh、备份、归档、大导出时:
CLIProxyAPI + thin cpa-ext plugin ── SQLite/IPC ── cpa-ext sidecar
sidecar 只承担长期任务/公共 API,不得形成第二套余额或价格权威。SQLite 单 writer、IPC 认证、文件锁和 crash ownership 必须另行验证。
3.3 Worker 拓扑
只有目标 CPA/Go/toolchain/SQLite driver 的双 runtime 24h soak 通过,才允许动态库启用有界 worker。发布元数据必须标出 topology;不能在补丁版本中静默从 callback-driven 改为 worker。
4. 文件与权限布局
建议 Linux 布局:
<cpa-root>/
├─ cliproxy
├─ config.yaml
├─ plugins/
│ └─ linux/amd64/cpa-ext-v0.1.0.so
└─ data/cpa-ext/
├─ cpa-ext.db
├─ cpa-ext.db-wal
├─ cpa-ext.db-shm
├─ backups/
└─ diagnostics/
/etc/cpa-ext/
└─ hmac-keyring.json # 或 OS secret store,绝不放进 data/backups
要求:
- CPA 运行用户拥有 plugin/data,其他用户默认不可读;
- keyring
0600、目录0700; - DB/backup
0600、目录0700; - plugin binary 只由发布/运维用户写,运行用户只读;
- 数据目录不能位于临时目录、网络共享或会被自动清理的位置;
- 不把 SQLite、WAL、keyring、Auth、日志放进发布归档;
- Windows 使用等价 ACL,不能只依赖扩展名。
5. 目标配置
remote-management:
allow-remote: false
secret-key: "<strong-random-management-key>"
# 仅保留一个运维离线 sentinel;绝不分发给用户。
api-keys:
- "<strong-random-sentinel-key>"
plugins:
enabled: true
dir: plugins
configs:
cpa-ext:
enabled: true
priority: 100
store:
version: "0.1.0"
codex_only: true
data_dir: data/cpa-ext
database_file: cpa-ext.db
settlement_currency: USD
frontend_auth_exclusive: true
unbound_key_policy: deny
unpriced_usage_policy: deny_new_requests
maintenance_mode: callback
说明:
- 上述是完整目标配置,当前基础插件只解析
codex_only; - CPA
Home是由-home-jwt注入的 runtime-only 状态,YAML 中的home:会被当前 parser 忽略;生产启动命令不得使用-home-jwt,并由 readiness 检查实际 runtime 状态; enabled、priority是 CPA host-owned 字段,也会出现在config_yaml;store.version用于选择版本化动态库;database_file相对data_dir解析,不能允许..逃逸;settlement_currency第一版只能是 USD;- HMAC keyring 通过受限 secret-file/OS store locator 注入,不把 key 值放进 YAML;
- 生产不允许 observe-only、unbound allow 或 unknown price=0;
- 所有可互相绑定的 Codex Auth 应使用相同 CPA priority。
热配置:UI 展示、查询限制、非安全统计刷新参数、明确允许的业务阈值。冷配置:data/database path、keyring source、currency、plugin identity、runtime topology。冷配置变化由 LKG reconfigure 拒绝并提示排空重启。
6. 本地开发构建
6.1 WSL/Linux
cd /mnt/d/agent/cpa-plugin
./scripts/check-env.sh
go test ./...
go test -race ./...
./scripts/build.sh
file bin/cpa-ext.so
nm -D bin/cpa-ext.so | grep cliproxy_plugin_init
build.sh 会执行 gofmt、go mod tidy、单元测试和 c-shared 构建。正式 CI 应把“依赖文件是否被意外修改”作为检查,不能让 tidy 的变化无人审阅。
6.2 PowerShell 调用 WSL
./scripts/build.ps1
wsl file /mnt/d/agent/cpa-plugin/bin/cpa-ext.so
wsl nm -D /mnt/d/agent/cpa-plugin/bin/cpa-ext.so
当前产物是 Linux .so。Windows .dll 必须在 Windows CGO toolchain 下单独构建和验证 export。
6.3 当前测试宿主
仓库已有:
./scripts/run-test-host.sh
tail -f .runtime/cliproxy.log
./scripts/stop-test-host.sh
.runtime/ 只用于本地测试,不是生产目录。/healthz 只证明 CPA 进程存活,不证明 cpa-ext active、价格可用或不存在认证旁路。
7. 发布物
每个 artifact 必须包含/伴随:
cpa-ext动态库;- version、git commit、build timestamp;
- target OS/arch、Go version、C toolchain;
- minimum/exact tested CPA version;
- ABI=1、max RPC schema=3、capability 清单;
- runtime topology;
- LICENSE、NOTICE/THIRD_PARTY;
- SHA-256 checksum,推荐额外签名/provenance/SBOM。
CPA plugin store zip 根目录中的动态库文件名使用:
cpa-ext.so
# 或
cpa-ext-v0.1.0.so
安装目标可位于 plugins/<goos>/<goarch>/。发布包不能包含生成 .h,除非消费者明确需要。
8. 安装前检查
- 确认 CPA exact version、plugin-capable build 和平台架构;
- 确认 CPA 未使用
-home-jwt启动,实际 runtimeHome.Enabled=false; - 备份 CPA config、SQLite 和匹配 keyring;
- 校验 artifact checksum/signature;
- 校验动态库 export
cliproxy_plugin_init; - 检查 data/keyring 目录权限和磁盘余量;
- 检查只有 sentinel 留在 CPA native
api-keys,没有用户 Key; - 检查 management 仅 loopback/受信网关可达;
- 检查所有可绑定 Codex Auth priority;
- 准备 gateway drain 和 rollback artifact;
- 首次生产部署必须先有已审阅 published price version;
- 确认 P0 runtime/performance/soak gate 结论与所选 topology 一致。
9. 首次安装
- 在排空环境停止 CPA;
- 原子复制版本化 dynamic library 到目标目录;
- 创建 data/keyring 目录和权限;
- 写入/审阅配置,先不开放用户入口;
- 启动 CPA,观察 plugin load/register/schema/capabilities;
- 等待 migration、integrity 基础检查、keyring、price 和 recovery 完成;
- 用 Management
/plugins确认cpa-extactive 和版本; - 调用 cpa-ext
/readiness与最小/ready; - 执行无效用户 Key 负向探针,确认不能访问上游;
- 在隔离测试账户完成“签发 → 准入 → strict route → Usage → 金额账本”;
- 对比无插件 OAuth 基线的 TTFT/吞吐;
- gateway 才开始逐步放量。
任何一步失败都保持用户入口关闭。不能因为 CPA /healthz 为 200 就继续。
10. 启动顺序与 readiness
插件内部:
- 解析 lifecycle config/schema;
- 验证冷配置和路径;
- 打开 SQLite、migration、quick integrity;
- 加载 HMAC keyring;
- 加载 active PriceVersion;
- 恢复 pending/Usage/settlement/outbox;
- 加载账户、Credential、route 和统计 Snapshot;
- 装配 callback runner/sidecar;
- 原子发布 Runtime;
- 返回 registration。
Readiness component:
| Component | 失败影响 |
|---|---|
| runtime/schema/capabilities | 不注册/不开放流量 |
| SQLite/migration/ledger | fail closed |
| HMAC keyring | fail closed |
| active pricing | fail closed |
| Credential/account directory | fail closed |
| statistics projection | 可降级,显示 lag |
| quota refresh | 可降级,显示 stale |
| UI resources | 不影响计费,但管理页不可用 |
| backup/archive runner | 告警,不允许掩盖核心 readiness |
外部 gate 组合:
- CPA process health;
- Management plugin active/version/capabilities;
- cpa-ext self readiness;
- resource
/ready存在; - Home 关闭;
- 负向认证探针;
- gateway 自己确认 sentinel 未被分发。
11. 监控与告警
最低指标:
| 类别 | 指标 |
|---|---|
| Runtime | active/fused/reconfigure rejected/schema/topology |
| RPC | 每 method 调用数、错误、panic、耗时、payload bytes |
| Auth | success/reject/unknown/dependency failure、rate limit |
| Access | terminate code、strict mismatch、scheduler fallback |
| Billing | settlement、amount、late revision、unpriced、unmeasured、negative balance |
| Persistence | transaction latency/error/busy、WAL/DB size、integrity、backup age |
| Projection | event_seq、checkpoint、lag、rebuild status |
| Upstream | account active/missing/priority shadow、quota age/error |
| Performance | TTFT、total latency、chunk gap、alloc/GC、stream RPC bytes |
| Gateway | open/drained、last readiness/negative probe |
必须告警:
- plugin route/active 状态消失或 fuse;
- readiness 核心 component 失败;
- persistence gap、账本不一致;
- active price 缺失/未知 GPT-5.6;
- unpriced/unmeasured 超阈值;
- keyring mismatch;
- DB/WAL/磁盘逼近上限;
- backup 超过目标 RPO;
- projection lag;
- priority 变化导致 binding 不可用;
- stream 性能相对基线退化。
指标端点默认只在 Management/受信 sidecar 暴露,不把账户数、金额或错误详情放进公开 /ready。
12. 日常维护
12.1 每日
- 检查 readiness、gateway 和关键告警;
- 检查 unpriced/unmeasured/persistence gap;
- 检查 backup 成功和磁盘;
- 检查 quota stale、missing Auth 和 strict mismatch;
- 检查异常 Credential 消费和负余额。
12.2 每周
- 运行账本余额 reconciliation;
- 检查 projection checkpoint 与 archive eligibility;
- 审阅价格候选,但不自动发布;
- 审阅 audit、Key rotation/expiry 和管理员操作;
- 抽样恢复 backup 到隔离目录。
12.3 每月/发布前
- 完整离线 restore drill;
- 容量/查询计划检查;
- 依赖、CPA 和价格来源复审;
- sentinel/Management/HMAC/key rotation 演练;
- 安全故障注入和 24h soak(涉及 runtime/toolchain/SQLite 变化时)。
13. 备份与恢复
13.1 备份
- 使用 SQLite online backup API,不直接复制 WAL 模式
.db; - 备份包含 schema/version/content hash/created_at;
- keyring 单独加密备份,记录非秘密 fingerprint/key IDs;
- 保留 7~30 天并至少一份异地副本;
- 备份目录不由 public API 任意下载;
- 每次破坏性 migration 和版本升级前强制备份;
- backup 成功必须通过打开、integrity 和基本账本检查。
13.2 离线恢复
- gateway 排空并停止 CPA/sidecar;
- 保存损坏现场副本;
- 选择匹配时间点的 SQLite + keyring;
- 在隔离目录验证 checksum、schema、integrity、key fingerprint;
- 替换明确目标文件,不操作宽泛目录;
- 启动时运行 migration/recovery;
- 从权威事实重建 projection;
- 运行账本、Credential 和 PriceVersion reconciliation;
- 完成全套 readiness/负向/计费探针;
- 逐步恢复流量并记录事件审计。
缺失/不匹配 keyring 时不得自动生成新 key 后继续;保持 fail closed。
14. 升级与回滚
14.1 禁止热替换生产动态库
当前 CPA binary hot reload 会把旧 native 实例放入 retired 集合,直到宿主整体 shutdown 才真正 shutdown。旧 runtime/worker/SQLite handle 可能继续存在,因此生产升级固定为:排空 → 停 CPA → 替换/切换 version pin → 启动。
14.2 升级流程
- 阅读 release notes、CPA compatibility、migration 和 topology 变化;
- staging 完成 test-plan 全门禁;
- 备份 SQLite + keyring + config;
- gateway drain;
- 停止 CPA 并确认进程退出;
- 安装新版本化 artifact、更新 version pin;
- 启动、migration/recovery/readiness;
- 执行负向认证、金额 golden、route、cancel/stream 和性能 smoke;
- 小流量观察;
- 标记升级完成并保留旧 artifact/backup。
14.3 回滚
如果 migration 保持旧版兼容,可以停机切回旧 artifact。若 schema 已不兼容:
- 停机;
- 恢复升级前 SQLite + 对应 keyring;
- 恢复旧 config/artifact;
- 重新完成 readiness/探针;
- 对升级窗口产生的真实上游消费人工 reconciliation,不能静默丢账。
价格回滚不需要二进制回滚,走 pricing.md 的“创建新发布版本”。
15. 配置变更
- 使用 CPA Management API/YAML 变更前保存当前 revision;
- 安全敏感变更必须双人复核和 reason;
- 写入后检查 LKG/
reconfigure_rejected; - capability shape 不因热配置错误消失;
- 冷配置只在排空重启中修改;
- 不用手改 SQLite 代替管理 API;
- 不在 config 中放 Management/downstream/HMAC/OAuth secret 的副本;
- 变更 Codex Auth priority 前预览受影响 binding。
16. 常见故障 Runbook
16.1 CPA 正常但 /ready 404
立即撤流量 → 检查 Home、plugin global/instance enabled、文件名/版本 pin、架构、export、load/register 日志 → 不要临时删除 sentinel 或放开 native Key。
16.2 Readiness 显示 DB/keyring/price unhealthy
撤流量 → 保留现场 → 检查权限、磁盘、key ID、migration、active price → 修复后运行 integrity/reconciliation → 不切 observe-only。
16.3 用户请求突然变慢
先 A/B 比较同 CPA/OAuth/model/tier/transport:无插件、空 hook、collection-only、完整插件 → 检查 schema=3、每 chunk RPC 字节、HistoryChunks、response-before 重复 body、DB/锁和 GC → 超过 dev.md 阈值即回滚/撤下相关 hook。
16.4 strict binding 不可用
检查 CPA Auth active/disabled/unavailable、模型和 priority → 查看 scheduler candidates/bindable reason → priority_shadowed 时统一 priority 或调整产品绑定,不强行返回隐藏 Auth ID。
16.5 quota stale
不影响已由 CPA candidate 证明可用的基础 strict 请求,但 UI 标 stale → 手动小批 refresh → 检查 provider allowlist、Auth ref、限流和 sidecar → 不把 stale 写成 0/无限。
16.6 persistence gap/unmeasured 激增
撤流量或收紧并发 → 检查 callback、DB、response correlation 和 CPA 版本 → 保存上游证据 → 修复后追加 settlement/adjustment;禁止猜 Token 或覆盖旧账本。
17. 容量与保留
发布前用真实形状数据验证:
- 50/500/更多 Credential 与上游账户;
- 百万级 Request/Execution/Usage/Ledger;
- 30/90 天查询;
- streaming 长 Prompt/多 chunk;
- 并发 1/8/32 及计划上限;
- WAL、backup、rebuild 和 archive;
- 磁盘增长、峰值内存、CPU、p95/p99。
容量结论记录最后成功点和最小失败点,生产持续负载取安全折扣。可参考 usage-keeper internal/benchmark/capacity-v1 的 canonical dataset、clone、cgroup memory peak 和 p99 方法,但需要增加 native plugin/CPA/stream 维度。
18. 验收标准
- 文档明确当前骨架与 production-ready 版本的差别;
- artifact、CPA、ABI/schema、OS/arch/toolchain 可追溯;
- 安装前 checksum/export/权限/version pin 均验证;
- 生产 gateway、sentinel、exclusive 和负向探针缺一不可;
/healthz不被误用为插件 readiness;- SQLite/keyring 成对备份和隔离恢复演练通过;
- 升级一定排空并重启 CPA,不热替换;
- migration 失败、keyring mismatch、price 缺失时保持 fail closed;
- 关键指标/告警/日常检查和故障 runbook 可执行;
- WSL/Linux 与 Windows artifact 不混用;
- 生产配置不使用
000、observe-only、用户 native CPA Key 或未确认价格; - 发布流程引用并满足 test-plan.md 全部门禁。