proxy-pool/docs/operations/runbook.md

250 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Proxy Pool 运维手册
## 1. 运行边界
- Gateway 是数据面,正常请求热路径不访问 PostgreSQL、Redis 或 Provider。
- Controller 是权威控制面,负责 Fetch、生命周期、所有权、Snapshot、Extract
和审计;多个副本只有一个 Provider 逻辑 Leader。
- Checker 执行有界健康探测,只上报 Observation最终状态由 Controller
reducer 决定。
- Extract 是一次性独占发放。提交后状态为 `EXTRACTED`,没有 Lease、续租或
Release 接口。
- `reserveForGateway` 是共享池硬约束Extract 不得把 Gateway 库存清空。
- 集群峰值 100,000 QPS 是设计目标,只有完成本文容量验收后才能作为已验证
能力对外承诺。
## 2. 本地拓扑模板
当前仓库交付设计、契约、部署拓扑和关键领域实现;`cmd/proxy-*` 的完整运行时
装配属于 `implementation-plan.md` 后续任务。此处 Compose/Kubernetes 资产用于
评审网络、资源、探针和依赖关系,当前只执行静态渲染,不把模板写成可运行服务。
### 2.1 前置条件
- Docker Engine 25+Compose v2.30+。
- 至少 8 CPU、16 GiB 内存和 20 GiB 可用磁盘。
- 本地端口 `3000`、`8080`、`8081`、`8082`、`8404`、`9091` 未占用。
### 2.2 配置凭据
`deploy/config/local.yaml` 只用于本机拓扑验证。进入运行时实施阶段后,再通过
密钥系统提供下列变量,并把 Provider 地址替换为测试 fixture
```powershell
$env:PROXY_POOL_GATEWAY_PASSWORD = "LOCAL_GATEWAY_PASSWORD"
$env:PROXY_POOL_EXTRACT_TOKEN = "LOCAL_EXTRACT_TOKEN"
$env:PROXY_POOL_ADMIN_TOKEN = "LOCAL_ADMIN_TOKEN"
$env:PROVIDER_A_TOKEN = "PROVIDER_A_TOKEN"
$env:PROVIDER_B_TOKEN = "PROVIDER_B_TOKEN"
```
### 2.3 静态检查
```powershell
docker compose -f deploy/docker-compose.yml config
kubectl kustomize deploy/kubernetes/base > rendered.yaml
```
目标拓扑入口:
- Gateway`127.0.0.1:8080`
- Distribution`http://127.0.0.1:8081`
- Admin`http://127.0.0.1:8082`
- HAProxy 状态:`http://127.0.0.1:8404/stats`
- Prometheus`http://127.0.0.1:9091`
- Grafana`http://127.0.0.1:3000`
`deploy/config/local.yaml` 中的 `.invalid` Provider 是故障演示占位。未替换时
Fetch 应表现为 Error 与退避,不应增加 Empty 计数,也不影响已有 Proxy。
## 3. Kubernetes 发布
本节是运行时实施完成后的发布规格,不代表当前代码已达到生产就绪。
### 3.1 准备
1. 使用托管 PostgreSQL 和 Redis分别配置 TLS、备份、监控和多可用区。
2. 复制 `secret.example.yaml` 到环境私密配置系统,由 External Secrets、SOPS
或密钥管理平台生成 `proxy-pool-secrets`,不要提交真实 Secret。
3. 在环境 Overlay 替换镜像、Provider 地址、允许网段、外部存储地址、资源量
和 LoadBalancer 注解。
4. 根据集群 CNI 能力收紧 NetworkPolicy 的外部网段。
5. 在预发布环境完成数据库向前兼容迁移,再发布 Controller。
### 3.2 服务端应用顺序
```bash
kubectl apply -f deploy/kubernetes/base/namespace.yaml
kubectl -n proxy-pool apply -f ENVIRONMENT_SECRET.yaml
kubectl apply -k deploy/kubernetes/base
kubectl -n proxy-pool rollout status deployment/proxy-controller --timeout=5m
kubectl -n proxy-pool rollout status deployment/proxy-checker --timeout=5m
kubectl -n proxy-pool rollout status deployment/proxy-gateway --timeout=10m
```
### 3.3 探针语义
- `/livez`:进程事件循环仍可运行。数据库或 Redis 短暂失败不得导致 Gateway
liveness 失败。
- `/readyz`进程可以接收新工作。Gateway 只有在持有未超过 `maxStaleAge`
的完整 Snapshot 且仍有准入能力时才 Ready。
- Controller 只有在配置有效、存储可用、迁移兼容且控制接口已监听时才 Ready。
- Checker 在任务消费与结果上报通道可用时 Ready。
- `/metrics`独立于业务入口NetworkPolicy 仅允许监控命名空间访问。
探针不得执行 Provider 请求或完整数据库扫描。
### 3.4 发布顺序与兼容性
1. 先做向前兼容数据库迁移。
2. 发布 Controller确认旧 Worker 仍能消费旧 Snapshot 协议版本。
3. 发布 Checker。
4. 逐批发布 Gateway每次至少保留 PDB 要求的健康副本。
5. 观察 30 分钟,再清理已经无人读取的旧字段或旧迁移。
回滚只能回到仍兼容当前 Schema 和 Snapshot 版本的镜像。涉及不可逆数据迁移时,
必须使用前向修复。
## 4. 容量规划
```text
worker_replicas =
ceil(peak_qps / (tested_worker_qps * target_utilization))
+ largest_failure_domain_replicas
```
- `peak_qps`:当前目标为 100,000。
- `tested_worker_qps`:在同 CPU、内存、网络、Go 版本、Snapshot 规模、TLS 与
上游响应模型下测出的单 Pod 持续能力。
- `target_utilization`:不高于 0.60给突发、GC 和故障转移留空间。
- `largest_failure_domain_replicas`:最大单可用区失效时丢失的副本数。
禁止用 CPU 核数直接推算 QPS也禁止把短时峰值当持续容量。Kubernetes 基线的
6 个 Gateway 副本只是初始值,必须由压测结果调整。
HPA 使用 CPU/内存作为保护性信号;生产环境建议通过 Prometheus Adapter 加入:
- 每 Pod Gateway QPS。
- 活跃连接数和建连速率。
- p99 Dispatch 延迟。
- 拒绝率和 Available Slots。
连接型工作负载缩容至少稳定 10 分钟,终止前先 NotReady再等待现有隧道排空。
## 5. 日常检查
每班次检查:
1. Gateway QPS、错误率、p95/p99 和活跃连接。
2. Snapshot age、epoch/version、重同步与 ACK 延迟。
3. Available Slots、Reserved、Active、各 Proxy 状态数量。
4. Provider Success、Empty、Duplicate-only、Error、429 与退避。
5. Checker 队列、SUSPECT 数、检查延迟和目标级失败。
6. Extract requested/returned、insufficient、冲突和审计写入。
7. PostgreSQL 连接、锁等待、事务失败、WAL 与备份。
8. Redis 延迟、内存、主从状态和 Leader 租约抖动。
Prometheus 标签禁止包含 Proxy IP、Client ID、Session、完整 URL、request ID。
需要逐请求调查时使用受控、脱敏且采样的结构化日志。
## 6. 优雅停机
### Gateway
1. readiness 立即失败,停止新连接。
2. 停止应用新 Snapshot但保留当前不可变版本。
3. 等待 HTTP 请求和 CONNECT 隧道排空。
4. 到达 60 秒上限后关闭残余连接,保证容量 reservation 被释放。
### Controller
1. 停止接收新的 Extract/Admin 写请求。
2. 停止发起 Fetch释放 Provider Leader 租约。
3. 完成已进入数据库事务的 Extract 或回滚。
4. 刷新 outbox、审计和 Worker ACK再关闭连接池。
### Checker
1. 停止领取新任务。
2. 在 45 秒内完成或取消现有探测。
3. 批量上报已完成 Observation未完成任务由队列重新投递。
## 7. 故障处置
### 7.1 Snapshot 陈旧
症状:`ProxyPoolGatewaySnapshotStale`、Worker 重同步增加、Gateway Ready 下降。
1. 检查 Controller、控制流和 outbox 延迟。
2. 确认 Worker epoch 与 Controller epoch禁止手工降低 epoch。
3. 缺版本时强制完整 Snapshot不要继续应用 Delta。
4. `maxStaleAge` 内允许旧 Snapshot 服务;超限自动拒绝新流量并排空。
5. 不得通过无限增大 `maxStaleAge` 隐藏控制面故障。
### 7.2 PostgreSQL 不可用
1. Gateway 继续使用最后有效 Snapshot。
2. Controller 将 Distribution 和权威写操作置为不可用,避免返回未提交代理。
3. Provider Fetch 停止写入;已有流量不受影响。
4. 恢复后核对迁移、事务回滚、outbox backlog 与 Extract 审计连续性。
### 7.3 Redis 不可用
1. Gateway 不受影响。
2. Controller 停止需要分布式互斥的高风险工作,防止多个 Fetch Leader。
3. 本地限流只作为临时降级,不能声称满足全局额度。
4. 恢复后确认 Leader 唯一、租约 epoch 单调和重复 Fetch 去重。
### 7.4 Provider 故障
1. 超时、DNS、认证、非预期 HTTP、响应超限与模板错误全部计 Error。
2. 429 尊重 `Retry-After`,其余 Error 使用指数退避和 jitter。
3. Error 不增加 Empty合法候选为零才增加 Empty。
4. Duplicate-only 重置 Empty 并记录独立指标。
5. 达到 Empty 阈值后每条受影响 Routing 只原子切换一次。
### 7.5 Gateway 容量耗尽
1. 检查 Available Slots而不是只看 Proxy 数量。
2. 确认是否大量容量停留在 Reserved排查 Commit/Cancel 泄漏。
3. 检查 TTL safety margin、健康状态和 Worker 所有权是否导致候选被过滤。
4. 快速拒绝新请求,禁止无界等待或把压力转移到 Controller。
5. 扩容 Gateway 前确认存在可分配 Proxy 所有权切片。
### 7.6 Extract 库存不足
1. `partial` 返回实际数量;`allOrNothing` 不足时整批回滚。
2. 检查 TTL、health age、filter、Worker ownership 和 `reserveForGateway`
3. 不得降低 `reserveForGateway` 到导致 Gateway 容量告警的水平。
4. 回收 Worker-owned Proxy 必须先 DRAINING、等待 active/reserved 为零、清除
ownership再执行 `AVAILABLE -> EXTRACTED` 事务。
5. 已提取代理没有 Release客户端归还请求只记录为无效调用不恢复库存。
### 7.7 Checker 积压
1. 优先新 Proxy 与 SUSPECT 复检。
2. 降低稳定 AVAILABLE 的普通复检频率。
3. 检查目标超时、DNS 与出口网络,再按任务延迟扩容 Checker。
4. 队列必须有上限;不得无限积压耗尽内存或 Redis。
## 8. 备份与恢复
- PostgreSQL每日全量、连续 WAL/PITR至少每季度做恢复演练。
- Redis仅保存可重建协调状态不得把 Redis 备份当权威业务备份。
- 配置:版本化保存校验通过的不可变 Revision 与校验和。
- Secret由密钥平台版本化日志和备份中不得出现明文。
恢复顺序PostgreSQL -> Redis -> Controller -> Checker -> Gateway。恢复后验证
Proxy 状态、Extraction Record、Worker ownership epoch、outbox 和配置 Revision
单调一致,再开放 Gateway 与 Distribution。
## 9. Secret 轮换
1. 创建新 Secret 版本,不覆盖旧值。
2. Provider/API 凭据支持双版本重叠时先发布新版本。
3. 更新配置 Revision确认 Controller 成功重建 Adapter。
4. 观察 Fetch Error、认证失败与 Snapshot ACK。
5. 所有副本应用后撤销旧 Secret。
Proxy 凭据轮换必须增加 `credentialVersion`,确保唯一键不会把新旧凭据错误合并。