网络内核参数调优
网络内核参数调优
概述
Kubernetes 节点的网络不仅是 Pod 间通信的通道,更是 Service 转发、Ingress 流量、监控采集的基础设施。高并发场景下(大量 Service、密集 Pod 通信、东西向流量),网络内核参数的不当配置会直接导致连接丢失、延迟飙升和 CPU 软中断风暴。
一句话:K8s 每条 Service 规则 → iptables/nftables/eBPF 规则,每条连接 → nf_conntrack 条目。表满了,连接就丢了。
nf_conntrack —— 连接跟踪的生死线
原理
netfilter 的连接跟踪(connection tracking)是 Linux 防火墙的基石。它记录每条连接的状态(NEW / ESTABLISHED / RELATED / INVALID),Service 的 DNAT 转换依赖它来回映射。
Pod-A → Service ClusterIP:80
→ iptables DNAT → Pod-B:8080
→ nf_conntrack 记录: (Pod-A:随机端口 → ClusterIP:80) ↔ (Pod-A:随机端口 → Pod-B:8080)
→ 回包时根据 conntrack 做反向 DNAT
表的内部结构
# conntrack 表是一张哈希表
# 默认 hashsize = nf_conntrack_max / 8 (每 bucket 8 条)
# 链长超过 8 开始降级为链表遍历,性能急剧下降
# 查看当前设置
sysctl net.netfilter.nf_conntrack_max # 总条目上限
sysctl net.netfilter.nf_conntrack_buckets # 哈希桶数(只读)
cat /proc/sys/net/netfilter/nf_conntrack_count # 当前使用量
调优参数
| 参数 | 默认 | 建议值 | 原理 |
|---|---|---|---|
nf_conntrack_max | 262144 | 1048576 ~ 2097152 | 大型 K8s 集群(100+ 节点)需要百万级 |
nf_conntrack_tcp_timeout_established | 432000(5天) | 86400(1天) | 空闲 TCP 连接不及时回收,浪费条目 |
nf_conntrack_tcp_timeout_time_wait | 120 | 30 | 减少 TIME_WAIT 占用 |
nf_conntrack_tcp_be_liberal | 0 | 1 | 容忍窗口外的包(避免 NAT 环境下的 RST) |
nf_conntrack_generic_timeout | 600 | 120 | UDP 等无连接协议的默认超时 |
nf_conntrack_udp_timeout | 30 | 30 | DNS 查询常用 UDP |
nf_conntrack_udp_timeout_stream | 120 | 60 | UDP 流 |
爆表症状与处理
# 爆表确认
dmesg | grep "nf_conntrack: table full"
# nf_conntrack: table full, dropping packet
# 检查使用率
echo "scale=2; $(cat /proc/sys/net/netfilter/nf_conntrack_count) / $(cat /proc/sys/net/netfilter/nf_conntrack_max) * 100" | bc
# 紧急处理(不重启)
echo 2097152 > /proc/sys/net/netfilter/nf_conntrack_max
# 查看 Top 连接来源(谁在用最多 conntrack)
conntrack -S 2>/dev/null | sort -t'=' -k2 -nr | head -20
# 或
cat /proc/net/nf_conntrack | awk '{print $6}' | sort | uniq -c | sort -nr | head -20
什么时候可以禁用 conntrack
如果使用 Calico eBPF 模式或 Cilium KPR(kube-proxy replacement),Service 转发不走 iptables/nf_conntrack,可以显著降低 conntrack 压力。但这不意味着可以设为 0——kubelet 和 CNI 插件仍需 conntrack 处理基本网络。
TCP 调优
连接管理
| 参数 | 默认 | 建议 | 原理 |
|---|---|---|---|
tcp_tw_reuse | 0 | 1(客户端)/ 0(NAT 网关) | 允许重用 TIME_WAIT 的 socket。NAT 网关慎用(可能连错 IP) |
tcp_tw_recycle | 0 | 0(已废弃,内核 4.12 移除) | 曾导致 NAT 下连接异常 |
tcp_fin_timeout | 60 | 30 | FIN_WAIT-2 状态超时 |
tcp_keepalive_time | 7200 | 600 | 空闲 10 分钟开始保活探测 |
tcp_keepalive_intvl | 75 | 30 | 保活探测间隔 |
tcp_keepalive_probes | 9 | 3 | 保活探测失败次数 |
tcp_max_syn_backlog | 512 | 8192 | SYN 队列大小(防 SYN flood) |
tcp_max_tw_buckets | 180000 | 360000 | TIME_WAIT socket 上限 |
tcp_retries2 | 15 | 8 | 丢包重试次数(减少僵尸连接) |
缓冲区
| 参数 | 默认 | 建议 |
|---|---|---|
core.rmem_max | 212992 | 16777216(16MB) |
core.wmem_max | 212992 | 16777216(16MB) |
tcp_rmem | 4096 131072 6291456 | 4096 87380 16777216 |
tcp_wmem | 4096 16384 4194304 | 4096 65536 16777216 |
core.netdev_max_backlog | 1000 | 5000 |
tcp_rmem/wmem 的格式:min default max。大缓冲区对跨可用区(高延迟)的 K8s Pod 通信和 GPU 集群的 RDMA 流量有显著帮助。
注意:缓冲区不是越大越好。16MB max 意味着每连接最多预留 16MB 内核内存,10000 连接就是 160GB。按需设。
拥塞控制
# 查看可用算法
sysctl net.ipv4.tcp_available_congestion_control
# 查看当前算法
sysctl net.ipv4.tcp_congestion_control
# 推荐
# - 通用 → cubic(默认,稳定)
# - 长肥网络(跨地域 K8s)→ BBR(高吞吐、低延迟)
echo bbr > /proc/sys/net/ipv4/tcp_congestion_control
# BBR 还需加载模块
modprobe tcp_bbr
Socket 与 backlog
监听队列
Client → SYN → [SYN Queue (tcp_max_syn_backlog)]
← SYN-ACK ←
Client → ACK → [Accept Queue (somaxconn)]
↓
accept()
| 参数 | 作用 | 建议 |
|---|---|---|
net.core.somaxconn | Accept 队列最大长度 | 32768 |
net.ipv4.tcp_max_syn_backlog | SYN 队列最大长度 | 8192 |
net.core.netdev_max_backlog | 网卡驱动 ring buffer 溢出后软件接收队列 | 5000 |
应用层(如 Nginx、Envoy)的 backlog 参数不能超过 somaxconn,否则被截断。
SYN cookie
防 SYN flood 攻击,但不影响正常连接:
sysctl net.ipv4.tcp_syncookies=1 # 始终启用
ARP / 邻居表
K8s 节点有大量 Pod IP,ARP 表(邻居表)容易溢出。
| 参数 | 默认 | 建议 |
|---|---|---|
gc_thresh1 | 128 | 2048 |
gc_thresh2 | 512 | 4096 |
gc_thresh3 | 1024 | 8192 |
- thresh1:低于此值不触发 GC
- thresh2:超过此值开始温和 GC
- thresh3:超过此值强制 GC
# 检查 ARP 表大小
arp -an | wc -l
# 或
ip neigh show | wc -l
生产 K8s 节点网络调优脚本
#!/bin/bash
# k8s-network-tuning.sh
cat << 'EOF' > /etc/sysctl.d/99-k8s-net.conf
# === conntrack ===
net.netfilter.nf_conntrack_max = 2097152
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_tcp_be_liberal = 1
net.netfilter.nf_conntrack_generic_timeout = 120
# === TCP ===
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 360000
net.ipv4.tcp_retries2 = 8
# === 缓冲区 ===
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.netdev_max_backlog = 5000
# === Socket ===
net.core.somaxconn = 32768
# === IP 转发 ===
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
# === ARP ===
net.ipv4.neigh.default.gc_thresh1 = 2048
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192
EOF
sysctl --system
echo "Network tuning applied."
排障工具速查
# 查看当前 conntrack 条目(top talkers)
conntrack -L -o extended 2>/dev/null | awk '{print $5, $6, $7, $8}' | sort | uniq -c | sort -nr | head
# 查看 socket 统计
ss -s # 汇总:TCP/UDP/RAW 各状态数量
ss -tan state time-wait | wc -l # TIME_WAIT 数量
ss -tan state established '( sport = :6443 )' | wc -l # to API Server
# 查看网络软中断分布(检查是否集中在单个 CPU)
cat /proc/net/softnet_stat
# 每列:processed, dropped, time_squeeze, ...
# 如果 dropped 持续增长 → CPU 不够
# 查看网卡中断分布
cat /proc/interrupts | grep eth0
关联知识
- CPU 隔离与中断亲和性 — 网卡中断应分散到多核
- ../k8s/特性详解/CNI 网络插件对比与排障 — CNI 底层依赖 nf_conntrack + iptables/nftables/eBPF
- cgroup v2 详解 — cgroup net_prio 可做 Pod 级网络 QoS
- ../k8s/特性详解/etcd 运维详解 — etcd 依赖高性能 TCP 连接
参考资源
- Linux 网络调优:https://www.kernel.org/doc/html/latest/networking/
- nf_conntrack 详解:https://arthurchiao.art/blog/conntrack-design-and-implementation/
- BBR 拥塞控制:https://github.com/google/bbr
学习时间
| 阶段 | 时间 | 备注 |
|---|---|---|
| 梳理完成 | 2026-06-30 | nf_conntrack 原理、TCP 连接管理、缓冲区、ARP 表、生产脚本 |
状态: 🌱 学习中 下次复习日期: 2026-07-07