在 Kubernetes 生产环境中,Ingress 作为南北向流量的统一入口,常常成为整个链路里最先遭遇连接数瓶颈的组件。无论是 Nginx Ingress Controller 还是其他基于 Envoy、HAProxy 的实现,当客户端并发连接数持续攀升,如果没有针对性的调优,就会出现连接等待、重置甚至大面积 502。理解连接数上限到底受哪些因素制约,是做有效调优的第一步。

一、Ingress 连接数上限的底层制约因素
很多人以为 Ingress 连接数不够只要增加 Ingress Controller 的 Pod 副本数就行,实际上单实例能承受的连接数由多层限制叠加而成。以最常见的 Nginx Ingress 为例,Nginx 自身有 worker_processes 和 worker_connections 的配置,前者一般设为 auto 即等于 CPU 核数,后者默认常常是 10240。理论上单 Worker 的连接数乘以后台 Worker 数就是 Nginx 能处理的最大并发连接,但这只是用户态的限制。
在 Linux 内核态,还有 net.core.somaxconn 控制全连接队列长度,net.ipv4.tcp_max_syn_backlog 控制半连接队列。如果 Nginx 配置的 listen backlog 大于内核 somaxconn,实际生效的仍是内核值。当瞬时新建连接超过队列长度,内核直接丢弃 SYN 包,客户端表现为连接超时。此外,fs.file-max 与每进程的文件描述符限制也决定了单 Pod 能打开的 socket 数量,连接本质上就是文件描述符,描述符耗尽连接必然失败。
另一个容易被忽视的是 Ingress 与后端 Service 之间的连接复用。如果 upstream 的 keepalive 没有开启或设置过短,每次请求都新建到后端的连接,不仅消耗 Ingress 自身连接数,也加重后端负担。因此调优不能只盯入口,还要看出口连接的复用效率。下面用一个典型的配置片段说明如何观察当前限制:
# 查看 Nginx Ingress Pod 内的连接相关内核参数 kubectl exec -it -n ingress-nginx deploy/ingress-nginx-controller -- sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog fs.file-max # 查看 Nginx 当前生效的 worker_connections kubectl exec -it -n ingress-nginx deploy/ingress-nginx-controller -- cat /etc/nginx/nginx.conf | grep worker_connections
二、通过注解与 ConfigMap 调整 Ingress 控制器参数
Nginx Ingress Controller 提供了丰富的注解(annotation)和 ConfigMap 来微调连接行为,不需要重新编译镜像就能生效。例如,可以通过 ConfigMap 设置 worker-connections 调高单 Worker 连接数,同时开启 keep-alive 让客户端复用 TCP 连接。对于入口监听的 backlog,可通过 listen-backlog 注解让生成的 listen 指令带上更大的队列值,从而匹配内核调高后的 somaxconn。
在具体 Ingress 资源上,也能用注解控制单个域名的行为。比如 nginx.ingress.kubernetes.io/proxy-read-timeout 和 nginx.ingress.kubernetes.io/proxy-send-timeout 如果设置过长,会导致大量空闲连接占用连接表;设置过短又可能误杀慢请求。经验值是读写超时都设在 30 到 60 秒,并配合 nginx.ingress.kubernetes.io/upstream-keepalive-connections 让后端连接池保持在合理规模,例如 32 到 64 之间,避免后端服务被连接数冲垮。
以下示例展示了一个经过调优的 ConfigMap 与 Ingress 注解组合,将单实例连接处理能力从默认一万出头提升到五万以上,并优化了队列与超时:
# ConfigMap 调整 Nginx 全局参数
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
worker-connections: "65535"
keep-alive: "60"
listen-backlog: "65535"
upstream-keepalive-connections: "64"
upstream-keepalive-timeout: "60"
---
# Ingress 资源注解细化
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/upstream-keepalive-connections: "64"
spec:
ingressClassName: nginx
rules:
- host: api.ipipp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-svc
port:
number: 80
需要注意的是,ConfigMap 修改后 Ingress Controller 会自动 reload Nginx,但 reload 本身有短暂中断,高频修改并不合适。对于连接数这类全局调优,建议在业务低峰一次性改好,并通过监控观察 reload 后的连接曲线是否平滑上升而非陡降。
三、内核参数与节点级资源限制的协同优化
只改 Ingress 配置而不动节点内核,调优效果会大打折扣。Kubernetes 节点通常运行在云厂商的标准镜像上,其 net.core.somaxconn 默认只有 128 或 4096,远低于我们上面设置的 listen backlog。必须通过 DaemonSet 或 kubelet 的 sysctl 配置将以下参数调高:net.core.somaxconn=65535、net.ipv4.tcp_max_syn_backlog=65535、net.core.netdev_max_backlog=65535,以及 fs.file-max=2097152。这些可以在节点启动脚本或特权 DaemonSet 里用 sysctl -w 写入。
同时,Ingress Controller 的 Pod 必须放开文件描述符限制。在 Deployment 的 securityContext 或 resources 中,要设置 limits 不约束 fd,并通过 ulimit -n 或容器运行时配置让进程能打开超过十万的文件符。如果使用了 PodSecurityPolicy 或 Kyverno 策略,需白名单放行 SYSCTL 能力。否则内核参数在节点改了,Pod 内看到的依旧是旧值。
下面给出一个用于初始化节点网络参数的 DaemonSet 示例,它确保每个 Ingress 所在节点都应用了高并发友好的内核设定:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: sysctl-tuner
namespace: kube-system
spec:
selector:
matchLabels:
app: sysctl-tuner
template:
metadata:
labels:
app: sysctl-tuner
spec:
hostPID: true
containers:
- name: tuner
image: alpine:3.18
command: ["sh", "-c"]
args:
- >
sysctl -w net.core.somaxconn=65535;
sysctl -w net.ipv4.tcp_max_syn_backlog=65535;
sysctl -w net.core.netdev_max_backlog=65535;
sysctl -w fs.file-max=2097152;
sleep infinity
securityContext:
privileged: true
完成内核与控制器双层调优后,还要用 Prometheus 抓取 Ingress Controller 的 nginx_ingress_controller_requests 和 nginx_ingress_controller_nginx_process_connections 指标,观察活跃连接数是否逼近上限。若活跃连接长期低于新上限且错误率下降,说明调优生效;若仍出现 502,则需继续排查后端 Service 的 Endpoint 就绪或负载均衡算法问题。
四、监控验证与常见误区分析
调优不是改完配置就结束,必须通过真实压测验证。常见误区之一是认为副本数越多越好,实际上在 NodePort 或 LB 模式下,如果负载均衡策略未开启一致性哈希,扩容会导致大量长连接被重新分发,引发后端冷启动抖动。正确做法是在调高单实例连接数后,用例如 wrk 或 k6 做阶梯加压,记录 P99 延迟与错误率拐点。
另一个误区是只调大连接数却不限制单客户端速率,容易被恶意爬虫打满入口。Ingress 可配合 nginx.ingress.kubernetes.io/limit-connections 与 limit-rps 注解做限流,在提升总上限的同时保护集群。如下片段限制单 IP 并发连接为 10,每秒请求为 20:
metadata:
annotations:
nginx.ingress.kubernetes.io/limit-connections: "10"
nginx.ingress.kubernetes.io/limit-rps: "20"
最后要强调的是,连接数调优是系统工程,从 DNS 解析、LB 会话保持、Ingress 内核参数到后端 keepalive 是一根链条。任何一环仍是默认窄口径,整体吞吐就上不去。建议每次只改一层并压测对照,才能定位真正的瓶颈点,而不是盲目堆配置。
Kubernetes_Ingress连接数调优性能瓶颈修改时间:2026-08-18 14:02:39