conntrack 水位预警:阈值该用"使用率 80%"还是"当前翻台率下还剩多少秒余量"?请给一个能落地的推导
该问题的正文与回答。
背景
3 年网络工程,负责一批 K8s iptables 模式集群(12 个节点,内核 5.10,nf_conntrack_max 维持默认 262144,没改过)。业务以 HTTP/1.0 短连接 + 一个上游重试风暴入口为主,单节点稳态新建连接速率约 500 conn/s,峰值能冲到 1500 conn/s。
上周一个 P1:某业务到下游的 connect timeout 比例 20%,持续 3 分钟。事后在 3 个节点上抓到 nf_conntrack: table full, dropping packet 刷了约 4 万条,conntrack -C 显示那 3 台 count 顶到 262144。机制我懂了——新建 SYN 被内核直接丢,已建连的长连接还在跑,所以业务侧看到的就是"服务活着但连不上"。
现象
复盘里最难受的一点是:事发前 20 分钟,那 3 个节点的 nf_conntrack_count / nf_conntrack_max 已经爬到 0.86(约 225k),但没有告警——我们只挂了"count > 95% max 且持续 5 分钟"一条规则。等规则触发时,业务已经炸了 3 分钟,等于预警完全没起到提前量的作用。
已尝试的排查
- 对着社区里《conntrack 表打满后新连接全被丢》(id=445) 的排障路径走了一遍,确认机制定位没问题;
- 参考了《K8s 高峰期 Go 服务 p99 抖到 800ms:如何系统性排除 DNS / CNI / conntrack 嫌疑?》(id=995) 的排查清单,把 DNS 和 CNI 排除了,最终落在 conntrack;
- 看过《TCP 建连静默失败有没有可 7×24 落盘的内核级最小观测集》(id=1526),知道 eBPF 能采到 drop 事件,但那是事后观测,不是事前预警;
- 阈值方法论上看了《告警阈值:静态硬编码 vs 动态基线》(id=1551),知道"静态 80% 不靠谱",但没有一篇把 conntrack 的阈值和自身连接翻台率挂钩讲透——这是我要问的核心。
期望得到的答案形态
希望有人能给一个可推导、可复现的预警模型,具体到:
-
心智模型对不对:我现在的想法是
headroom_seconds = (max - current_count) / new_conn_rate。以 500 conn/s、count=225k、max=262144 算,余量只有约 74 秒;以 1500 conn/s 算,余量只有约 25 秒。这个"秒级余量"是不是 conntrack 预警的正确度量?还是应该用 d(count)/dt(斜率)? -
阈值到底挂哪个:是挂"使用率 ≥ 70%"(静态、简单、但稳态翻台率不同就误报/漏报),还是挂"当前翻台率下 headroom < 60s"(动态、贴业务、但需要实时采 new_conn_rate,怎么采最稳——
conntrack -C两次采样差 /nf_conntrack_count的 Prometheus 计数器差分 / eBPF 钩子)?你们线上实际跑的是哪种? -
到了 70% 水位该做什么:是加
nf_conntrack_max(治标,会不会把 OOM 风险往后推),还是先查上游是不是有重试放大 / 连接没复用(治本)?有没有一个判据能让我在告警触发的 60 秒内,判断"该扩表"还是"该掐上游"? -
一个能直接抄的告警规则:Prometheus / VictoriaMetrics 的 PromQL 长什么样,能把"使用率"和"翻台率斜率"两个条件 AND 起来,既不漏报也不狼来了?
我偏好带具体数字、命令、PromQL 的回答,而不是"建议做好监控"这种。