399 lines
21 KiB
Markdown
399 lines
21 KiB
Markdown
# Proxy Pool 运维手册
|
||
|
||
## 1. 运行边界
|
||
|
||
- Gateway 是数据面,正常请求热路径不访问 PostgreSQL、Redis 或 Provider。
|
||
- Gateway 的 Proxy Outcome 仅进入进程内有界队列;Controller 只维护当前 session
|
||
的最后确认序列和摘要,原始 Outcome 不写入 Redis 或 PostgreSQL。队列满时丢弃
|
||
观测样本,代理转发和 Redis session TTL 不受影响。
|
||
- Controller 编排 Fetch、生命周期、所有权、Snapshot 与 Extract;多个副本只有
|
||
一个 Provider 逻辑 Leader。短效 Proxy 明细只存在于 Redis TTL 活动池和节点
|
||
内存,可由 Provider 重建。
|
||
- PostgreSQL 只持久化配置版本、Upstream/Routing 管理状态、Admin 审计与
|
||
outbox,以及可选聚合指标;不保存 Proxy 明细或逐次提取记录。
|
||
- Checker 执行有界健康探测,只上报 Observation,最终状态由 Controller
|
||
reducer 决定。
|
||
- Extract 是一次性独占发放。Redis 在单次原子操作中校验并从可分配活动池移除
|
||
候选,同时写入带 TTL 的幂等结果;没有 Lease、续租或 Release 接口。
|
||
- `reserveForGateway` 是共享池硬约束,Extract 不得把 Gateway 库存清空。
|
||
- 集群峰值 100,000 QPS 是设计目标,只有完成本文容量验收后才能作为已验证
|
||
能力对外承诺。
|
||
|
||
## 2. 本地拓扑模板
|
||
|
||
`cmd/proxy-controller` 已完成配置单次加载、PostgreSQL 迁移、Redis 活动池、
|
||
Distribution/Admin/Metrics 独立监听和有界停机装配。Provider 自动补池、分布式
|
||
配额、动态重载和 Admin 低基数统计已装配;Controller 已装配 Redis BASIC/EGRESS/TARGET 任务 broker,
|
||
`proxy-checker` 可执行 HTTP/HTTPS/SOCKS5 BASIC/EGRESS/TARGET 探测。`proxy-loadgen` 已提供有界 HTTP、
|
||
CONNECT 长连接和 Extract 场景,并可按最大错误率和 p99 延迟输出机器可判定的验收结果;
|
||
它不替代代表性集群压测。Compose 已声明本地 Controller/Gateway/Checker mTLS 拓扑,
|
||
但本机尚未完成容器端到端启动;Kubernetes 仍需要环境专属的工作负载身份 Overlay。
|
||
|
||
### 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:PROXY_POOL_CONFIG_FINGERPRINT_KEY = "LOCAL_HIGH_ENTROPY_KEY_AT_LEAST_32_BYTES"
|
||
$env:PROVIDER_A_TOKEN = "PROVIDER_A_TOKEN"
|
||
$env:PROVIDER_B_TOKEN = "PROVIDER_B_TOKEN"
|
||
```
|
||
|
||
首次启动 Compose 前,生成不入库的本地控制面证书。生成器要求目标目录为空,避免覆写
|
||
已有密钥:
|
||
|
||
```powershell
|
||
.\scripts\generate-local-controlplane-certs.ps1
|
||
```
|
||
|
||
### 2.3 静态检查
|
||
|
||
```powershell
|
||
docker compose -f deploy/docker-compose.yml config
|
||
kubectl kustomize deploy/kubernetes/base > rendered.yaml
|
||
```
|
||
|
||
Compose 启动后,Gateway 的 `/readyz` 需要先接收有效 Snapshot;Checker 的 `/readyz`
|
||
需要成功建立一次任务领取流,并会在后续领取失败时回到未就绪。两者的 `/livez` 只表示
|
||
进程仍在运行。
|
||
|
||
本地 Compose 的 Redis 只作为可重建短效状态 fixture,固定使用
|
||
`--appendonly no --save ""`,且不挂载 `/data` 或命名卷。真实 Redis 8.2 契约可
|
||
通过 `.\scripts\test-redis.ps1` 执行;脚本使用唯一命名空间并在结束时定向清理,
|
||
不执行 `FLUSHDB`。生产环境的 Redis 高可用与持久化策略必须独立评审,不能照搬
|
||
本地 fixture。
|
||
|
||
PostgreSQL 管理面集成测试通过 `.\scripts\test-postgres.ps1` 启动
|
||
`postgres:18-alpine`,仅绑定 `127.0.0.1:15432`,并将 PG18 数据根目录挂载为
|
||
tmpfs。`ApplyMigrations` 在同一物理连接上执行仓库内嵌的幂等前向迁移;测试为
|
||
每个契约创建唯一 Schema,结束时只删除该 Schema 和临时 Compose 项目。该脚本
|
||
禁止指向开发或生产数据库。
|
||
|
||
`.\scripts\test-controller.ps1` 同时启动两个隔离 fixture,验证 Controller
|
||
bootstrap 的迁移、启动配置提交、Redis Readiness、Admin Status、`/readyz` 与
|
||
Prometheus 输出。脚本不启动
|
||
部署模板中的 Controller 容器,也不连接开发或生产存储。
|
||
|
||
目标拓扑入口:
|
||
|
||
- Gateway:`127.0.0.1:8080`
|
||
- Distribution:`http://127.0.0.1:8081`
|
||
- Admin:`http://127.0.0.1:8082`
|
||
- Controller Metrics:`http://127.0.0.1:9090`
|
||
- 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。
|
||
`PROXY_POOL_CONFIG_FINGERPRINT_KEY` 必须使用至少 32 字节的高熵随机值,所有
|
||
Controller 副本保持一致,且与配置中的业务 Secret 分离管理。
|
||
3. 在环境 Overlay 替换镜像、Provider 地址、允许网段、外部存储地址、资源量
|
||
和 LoadBalancer 注解。
|
||
4. 根据集群 CNI 能力收紧 NetworkPolicy 的外部网段。
|
||
5. 在预发布环境完成数据库向前兼容迁移,再发布 Controller。
|
||
|
||
环境 Overlay 应保持 ConfigMap 内容哈希,令配置变化进入 Deployment Pod 模板并触发滚动更新。
|
||
由外部系统以固定名称注入的 Secret 不会天然改变 Pod 模板;完成 Secret 轮换后,必须按受影响
|
||
工作负载执行受控滚动,并先验证新旧信任根的重叠窗口。
|
||
|
||
### 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-gateway --timeout=10m
|
||
```
|
||
|
||
### 3.3 探针语义
|
||
|
||
- `/livez`:进程事件循环仍可运行。数据库或 Redis 短暂失败不得导致 Gateway
|
||
liveness 失败。
|
||
- `/readyz`:进程可以接收新工作。Gateway 只有在持有未超过 `maxStaleAge`
|
||
的完整 Snapshot 且仍有准入能力时才 Ready。
|
||
- Controller 按能力判定就绪:Distribution/Fetch 依赖 Redis 活动池,Admin 持久化
|
||
写依赖 PostgreSQL 与兼容迁移。PostgreSQL 故障不得单独使 Extract 返回 503。
|
||
- 同一 Controller 同时启用 Distribution 与 Admin 时,Pod `/readyz` 以 Redis
|
||
活动池为服务流量门槛;PostgreSQL 故障由 Admin 接口独立返回不可用,不把仍可
|
||
完成的 Extract 从 Service 摘除。Admin-only 进程才同时检查 PostgreSQL 与 Redis。
|
||
- `/metrics`:独立于业务入口,NetworkPolicy 仅允许监控命名空间访问。
|
||
|
||
探针不得执行 Provider 请求或完整数据库扫描。
|
||
|
||
Checker 指标使用固定标签集:
|
||
|
||
- `proxy_pool_checker_tasks_dispatched_total{level}`:成功写入 Checker 任务流后的任务数。
|
||
- `proxy_pool_checker_observations_total{level,result}`:已解码的 Observation 被 Controller 接受或拒绝的数量。
|
||
|
||
`level` 仅为 BASIC、EGRESS、TARGET,`result` 仅为 accepted、rejected。不得将
|
||
Proxy ID、IP、Checker ID、目标 URL、Client ID 或凭据加入指标标签。
|
||
|
||
Gateway 指标同样使用固定标签集:
|
||
|
||
每个 Gateway Worker 还暴露 requests_total、requests_in_flight 与 active_tunnels
|
||
三类本地连接指标。protocol 标签只允许 HTTP、CONNECT;请求指标覆盖从 Handler
|
||
接受请求到全部转发、拒绝或隧道关闭的生命周期。活跃隧道只在成功写出 CONNECT 200
|
||
并开始 relay 后增加,关闭后立即减少。这些指标用于核对入口准入、连接池调优、
|
||
文件描述符预算和长连接排空,不得按 Proxy、路由、目标、Client 或凭据拆分。
|
||
|
||
- `proxy_pool_gateway_outcomes_total{stage,result}`:每次代理尝试在最远完成阶段的成功/失败数量。
|
||
- `proxy_pool_gateway_outcome_queue_dropped_total`:Outcome 本地有界队列已满后丢弃的观测数量。
|
||
|
||
`stage` 仅为 DIAL、PROXY_HANDSHAKE、RESPONSE_HEADERS、TUNNEL,`result` 仅为 success、failure。
|
||
前者在写入本地队列前计数,后者用于识别观测背压;二者均不包含 Proxy ID、路由、目标、客户端或凭据。
|
||
|
||
### 3.4 发布顺序与兼容性
|
||
|
||
1. 先做向前兼容数据库迁移。
|
||
2. 发布 Controller,确认旧 Worker 仍能消费旧 Snapshot 协议版本。
|
||
3. 发布 Checker。
|
||
4. 逐批发布 Gateway;每次至少保留 PDB 要求的健康副本。
|
||
5. 观察 30 分钟,再清理已经无人读取的旧字段或旧迁移。
|
||
|
||
迁移失败时停止 Controller 发布,不自动重试结果不确定的管理 mutation。恢复后
|
||
先确认 Schema 版本、最近 revision、审计和 outbox 一致,再开放 Admin 写入口。
|
||
|
||
回滚只能回到仍兼容当前 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 连接、管理事务失败、outbox backlog、WAL 与备份。
|
||
8. Redis 延迟、内存、TTL 淘汰、原子操作错误、主从状态和 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. 等待已提交 Redis 原子操作返回;未确认请求的客户端必须使用相同幂等键重试。
|
||
4. 刷新 Admin outbox、审计和 Worker ACK,再关闭 PostgreSQL/Redis 连接池。
|
||
|
||
Outbox 发布器必须以稳定 consumer ID 有界领取;发布成功后原子 ACK。进程在发布
|
||
成功但 ACK 结果不确定时,不得伪造确认;等待租约到期后重领,并由下游事件消费者
|
||
按事件 ID/revision 去重。持续积压时先暂停新的管理变更,检查发布目标、租约和
|
||
最老未发布事件,不删除未发布行。
|
||
|
||
### 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. Redis 健康且运行配置有效时,Distribution 继续执行原子 Extract,Provider
|
||
按 last-known 管理状态继续刷新 TTL 活动池;状态读取失败不得触发全进程退出。
|
||
3. 拒绝配置版本、Upstream/Routing 管理状态和其他需要 Admin 审计/outbox 的写入;
|
||
不得把 Proxy 明细临时落入 PostgreSQL。
|
||
4. 恢复后核对迁移、管理事务回滚、Admin 审计与 outbox backlog;不存在 Proxy
|
||
明细或逐次提取记录恢复步骤。
|
||
5. 若权威配置指纹已变化,确认每个 Controller 的共享配置源和 Secret 版本已同步;
|
||
同时确认 `PROXY_POOL_CONFIG_FINGERPRINT_KEY` 一致。指纹不匹配的副本会停止旧
|
||
Provider,匹配并预检成功后按 PostgreSQL revision 自动恢复;迟到旧 revision
|
||
不会覆盖较新本地配置。
|
||
|
||
### 7.3 Redis 不可用
|
||
|
||
1. Gateway 继续读取节点内最后有效 Snapshot,直到 `maxStaleAge`;请求热路径不
|
||
回查 PostgreSQL 或 Provider。
|
||
2. Distribution 立即失败关闭并返回 503,禁止本地内存提取或 PostgreSQL 兜底。
|
||
3. Controller 停止活动池写入和需要分布式互斥的工作,防止多个 Fetch Leader;
|
||
Distribution 的 Redis 权威限流同时失败关闭,本地早期限流不冒充跨副本额度。
|
||
4. 恢复后确认 Leader 唯一和租约 epoch 单调,由 Provider 重新 Fetch 并构建 TTL
|
||
活动池,再恢复 Distribution。Redis 整体丢失会终止原活动池代次的排他状态和
|
||
短期幂等窗口;高可用、持久化、监控和告警必须明确并降低该风险。
|
||
|
||
### 7.4 Provider 故障
|
||
|
||
1. 超时、DNS、认证、非预期 HTTP、响应超限与模板错误全部计 Error。
|
||
2. 429 尊重 `Retry-After`,其余 Error 使用指数退避和 jitter。
|
||
3. Error 不增加 Empty;合法候选为零才增加 Empty。
|
||
4. Duplicate-only 重置 Empty 并记录独立指标。
|
||
5. 达到 Empty 阈值后每条受影响 Routing 只原子切换一次;最后一个可用 Upstream
|
||
仍持续 Empty 且配置为 `stop` 时,确认审计中存在 `disable_routing` 和
|
||
`routing.disabled` Outbox 事件,并检查 Gateway 已收到关闭该 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` 不足时不改变 Redis 活动池。
|
||
2. 检查 TTL、health age、filter、Worker ownership 和 `reserveForGateway`。
|
||
3. 不得降低 `reserveForGateway` 到导致 Gateway 容量告警的水平。
|
||
4. 回收 Worker-owned Proxy 必须先 DRAINING、等待 active/reserved 为零、清除
|
||
ownership,再由 Redis 原子操作将其从可分配活动池移除并写入短期幂等结果。
|
||
5. 已提取代理没有 Release;客户端归还请求只记录为无效调用,不恢复库存。
|
||
|
||
### 7.7 Checker 积压
|
||
|
||
1. 优先新 Proxy 与 SUSPECT 复检。
|
||
2. 降低稳定 AVAILABLE 的普通复检频率。
|
||
3. 检查目标超时、DNS 与出口网络,再按任务延迟扩容 Checker。
|
||
4. 队列必须有上限;不得无限积压耗尽内存或 Redis。
|
||
|
||
### 7.8 持续 UNHEALTHY 回收
|
||
|
||
1. 先确认 `check.maxConsecutiveFailures`、检查目标和出口网络;首次失败进入
|
||
SUSPECT,阈值达到后才进入 UNHEALTHY。
|
||
2. `check.unhealthyRemoveAfter: 0s` 仅保留异常状态;设置正值后 Controller 才会在
|
||
持续异常超过该窗口时执行有界回收。
|
||
3. 回收器只删除没有 Worker ownership 的记录。发现所有权时会延后处理,不得手动
|
||
删除 Redis 记录或索引。
|
||
4. 对已分配代理,按既有流程执行 DRAINING,等待 Worker ACK 且 active/reserved
|
||
都归零;所有权清除后,下一轮回收才会删除该异常 Proxy。
|
||
|
||
## 8. 备份与恢复
|
||
|
||
- PostgreSQL:每日全量、连续 WAL/PITR,保护配置版本、Upstream/Routing 管理
|
||
状态、Admin 审计与 outbox;至少每季度做恢复演练。
|
||
- Redis:保存可由 Provider 重建的 TTL 活动池、所有权/Leader 协调和短期幂等
|
||
结果;生产环境可使用高可用与受控持久化降低窗口丢失风险,但不把它当长期
|
||
业务档案或备份源。本地 Compose 刻意关闭持久化并且不挂载数据卷。
|
||
- 配置:版本化保存校验通过的不可变 Revision 与校验和。
|
||
- Secret:由密钥平台版本化,日志和备份中不得出现明文。
|
||
|
||
管理面恢复顺序:PostgreSQL -> Controller/Admin;代理运行面恢复顺序:Redis ->
|
||
Provider 重建活动池 -> Controller/Checker -> 发布新 Snapshot。验证 Worker
|
||
ownership epoch、活动池 TTL、短期幂等窗口、outbox 和配置 Revision 一致后,再
|
||
开放相应能力;Gateway 在旧 Snapshot 未超过 `maxStaleAge` 时无需等待数据库恢复。
|
||
|
||
## 9. Secret 轮换
|
||
|
||
1. 创建新 Secret 版本,不覆盖旧值。
|
||
2. Provider/API 凭据支持双版本重叠时先发布新版本。
|
||
3. 更新配置 Revision,确认 Controller 成功重建 Adapter。
|
||
4. 观察 Fetch Error、认证失败与 Snapshot ACK。
|
||
5. 所有副本应用后撤销旧 Secret。
|
||
|
||
Proxy 凭据轮换必须增加 `credentialVersion`,确保唯一键不会把新旧凭据错误合并。
|
||
|
||
控制面 mTLS 的叶证书、私钥和信任根会在每次新的 TLS 握手时重新读取;Kubernetes 投影
|
||
Secret 或 CSI 写入短暂不完整时保留最后一次有效材料。既有 gRPC 长连接不会被强制替换,
|
||
因此根 CA 轮换必须先发布包含新旧根的重叠信任包、确认新连接成功,再按 PDB 约束滚动
|
||
重启或排空旧 Worker,最后才撤销旧根并使旧流重新认证。
|
||
|
||
## 10. 主机与网络容量基线
|
||
|
||
在预发布压测和每次生产扩容前,记录 Gateway 节点、容器运行时和 Pod 内的下列只读基线;
|
||
不要在故障处理中临时提高内核限制,任何变更都必须经过压测和变更评审。
|
||
|
||
```bash
|
||
ulimit -n
|
||
cat /proc/self/limits | grep 'open files'
|
||
sysctl fs.file-max net.core.somaxconn net.ipv4.ip_local_port_range
|
||
test -r /proc/sys/net/netfilter/nf_conntrack_max && cat /proc/sys/net/netfilter/nf_conntrack_max
|
||
ss -s
|
||
```
|
||
|
||
同时从节点或受监控的 NAT 网关采集 conntrack 使用率、丢包、重传、SYN backlog、TIME_WAIT、
|
||
端口分配失败与 SNAT 端口耗尽事件。`conntrack -L` 会遍历整个表,不得在高峰时将它作为
|
||
常规排障命令;优先使用节点监控或 `conntrack -S` 的聚合计数。
|
||
|
||
Gateway 的文件描述符预算必须按实际连接模型计算,而不是仅按 QPS:每条活跃 CONNECT
|
||
隧道通常占用客户端和上游两个 socket;HTTP 上游并发、idle 连接池、监听 socket、日志和
|
||
运行时也会占用描述符。部署前确认 Pod 内 `ulimit -n`、容器运行时 `LimitNOFILE` 与节点
|
||
`fs.file-max` 均高于下式结果并保留至少 20% 余量:
|
||
|
||
```text
|
||
fd_budget = 2 * max_active_connect_tunnels
|
||
+ max_concurrent_http_upstreams
|
||
+ max_idle_transport_connections
|
||
+ process_reserve
|
||
```
|
||
|
||
如果节点通过 NAT 访问上游,源端口和 conntrack 表同样构成硬上限。压测报告必须记录每个
|
||
节点的 egress IP 数、可用临时端口范围、NAT/SNAT 设备限制与单目标连接分布;单一 egress IP
|
||
不足时应在发布前增加 egress IP 或拆分节点池,不能依靠无限重试掩盖端口耗尽。
|
||
|
||
建议将 FD、conntrack、NAT 端口利用率、SYN overflow、TCP retransmit、TIME_WAIT、CPU、RSS
|
||
和 Gateway p99 作为同一份容量证据采集。任何一项超过预设预警线时停止扩容或发布,先降低
|
||
新连接速率并保留现有 CONNECT 隧道排空;回滚到兼容镜像或配置 revision 后,再根据原始
|
||
指标分析根因。
|