链接复制成功!
高负载场景下NGINX Ingress控制器的性能调优
Ingress对象为集群提供HTTP/HTTPS等七层协议的负载均衡访问方式,NGINX Ingress是社区常见的一种实现,目前CCE服务提供了一款基于社区的NGINX Ingress Controller优化的精选开源插件,提供丰富的七层负载均衡能力。而在高并发场景下,插件的CPU内存等预分配资源和网络连接数的不足会影响应用的性能。本文介绍如何通过调优NGINX Ingress控制器来支撑高负载业务。

调优过程涉及NGINX Ingress容器滚动升级,建议在业务低峰期进行调优操作。
前提条件
CCE集群中已经部署NGINX Ingress控制器插件。
调优建议
优化高负载场景下的NGINX Ingress插件需要考虑以下几个方面。
使用高性能节点
在高并发场景下,Ingress对CPU资源和网络连接数占用都非常高,所以可选增强型ECS实例。
- 登录CCE控制台,单击集群名称进入集群。
- 在左侧选择“节点管理”,在右侧选择“节点池”页签。
- 单击右上角“创建节点池”,创建新的节点池并添加2台节点,该节点池可以为Nginx Ingress独占。具体操作请参见创建节点池。
在高并发场景下,可选性能较强的增强型实例,例如通用计算增强型实例:c7.8xlarge.2(32 Core 64 GiB,30Gbit/s最大带宽,550万PPS)。
- 在“高级配置”中为节点池配置节点标签和污点。
- 设置污点的键为nginx-ingress-pod-reserved,值为true,Effect为NoExecute。
- 设置标签的键为nginx-ingress-pod-reserved,值为true。
- 在左侧选择“插件管理”,编辑NGINX Ingress控制器插件配置,修改调度策略。
- 节点亲和:设置自定义亲和策略,亲和nginx-ingress-pod-reserved: true的标签。
- 容忍策略:添加容忍策略,容忍键值为nginx-ingress-pod-reserved: true、Effect为NoExecute的污点。
优化NGINX Ingress插件配置
- 调整nginx-ingress-controller容器的资源限制。如应用处理的HTTP请求的每秒请求数(RPS)为30万,可将CPU/内存的requests和limits均设置为16 Core/20 GiB。
- 设置实例数大于等于2。
- 关闭插件的指标采集。
- 通过以下方式对Nginx全局配置进行调优:
- 调高keepalive连接最大请求数
Nginx针对client和upstream的keepalive连接,具备keepalive_requests参数来控制单个keepalive连接的最大请求数,默认值均为100。
当一个keepalive连接中请求次数超过默认值时,将断开并重新建立连接。 如果是内网Ingress,单个client的QPS可能较大,例如达到10000QPS,Nginx将可能频繁断开跟client建立的keepalive连接,并产生大量TIME_WAIT状态连接。
为避免产生大量的TIME_WAIT连接,建议您在高并发环境中增大Nginx与client的keepalive连接的最大请求数量,在Nginx Ingress中配置对应keep-alive-requests,可以设置为10000,详情请参见keep-alive-requests。
同样,Nginx针对upstream的keepalive连接的请求数量的配置是upstream-keepalive-requests,详情请参见upstream-keepalive-requests。

在非高并发环境,不必配置upstream-keepalive-requests参数。如果将其调高,可能导致负载不均,因Nginx与upstream保持的keepalive连接过久,导致连接发生调度的次数减少,将使流量负载不均衡。
- 调高keepalive最大空闲连接数
Nginx针对upstream可配置参数keepalive。该参数为最大空闲连接数,默认值为320。
在高并发环境下将产生大量请求和连接,而实际生产环境中请求并不是完全均匀,有些建立的连接可能会短暂空闲,在空闲连接数多了之后关闭空闲连接,将可能导致Nginx与upstream频繁断连和建连,引发TIME_WAIT飙升。在高并发环境下,建议将 keepalive 值配置为1000,详情请参见 upstream-keepalive-connections。
- 调高单个worker最大连接数
max-worker-connections控制每个 worker 进程可以打开的最大连接数,在高并发环境下建议调高该参数值,例如配置为65536,调高该值可以让 Nginx 拥有处理更多连接的能力,详情请参见 max-worker-connections。
- 调优网关超时时间nginx与upstream pod建立TCP连接并进行通信,其中涉及3个超时配置。
- proxy-connect-timeout:设置 nginx 与 upstream pod 连接建立的超时时间,ingress nginx 默认设置为 5s,由于在nginx 和业务均在内网同机房通信,可将此超时时间缩短一些,比如3秒。详情请参见proxy-connect-timeout。
- proxy-read-timeout 、proxy-send-timeout:设置nginx与upstream pod之间读写操作的超时时间,ingress nginx 默认设置为 60s,当业务方服务异常导致响应耗时飙涨时,异常请求会长时间夯住 ingress 网关,在拉取所有服务正常请求的 P99.99 耗时之后,将网关与 upstream pod 之间读写超时均缩短到适当数值如30s,使得 nginx 可以及时掐断异常请求,避免长时间被夯住。详情请参见proxy-read-timeout及proxy-send-timeout。
- 调高keepalive连接最大请求数
Nginx内核参数调优

如您需要自定义修改内核参数,请在修改之前,请务必确保您已完全理解该内核参数的具体含义和功能。请谨慎操作,错误的参数设置可能导致系统出现意外的错误,影响正常运行。
请特别注意以下两点:
- 确保了解内核参数的含义:需清楚内核参数的作用和影响,这将有助于您正确设置相应的值。
- 填写有效的内核参数值:内核参数值必须有效且符合预期要求,否则修改将不会生效。
您可通过以下方式对Nginx Ingress进行内核参数调优,并可使用initContainers方式设置内核参数。
CCE在2.2.75、2.6.26、3.0.1及以上版本的NGINX Ingress控制器插件中默认为您开启内核参数调优。
- 调高连接队列的大小
在高并发环境下,如果连接队列过小,则可能导致队列溢出,使部分连接无法建立。进程监听socket的连接队列大小受限于内核参数 net.core.somaxconn,调整somaxconn内核参数的值即可增加Nginx Ingress连接队列。
进程调用listen系统监听端口时会传入一个backlog参数,该参数决定socket连接队列大小,且其值不大于somaxconn取值。Go程序标准库在listen时,默认直接读取somaxconn作为队列大小,但Nginx监听socket时并不会读取somaxconn,而是读取nginx.conf。在nginx.conf中的listen端口配置项中,可以通过backlog参数配置连接队列大小,来决定Nginx listen端口的连接队列大小。配置示例如下:
server { listen 80 backlog=1024; ...如果未配置backlog值,则该值默认为511。在默认配置下,即便somaxconn的值配置超过511,但Nginx所监听端口的连接队列最大只有511,因此在高并发环境下可能导致连接队列溢出。
而Nginx Ingress Controller会自动读取somaxconn的值作为backlog参数,并写到生成的nginx.conf中,因此Nginx Ingress的连接队列大小只取决于somaxconn的大小,该取值在CCE中默认为4096。在高并发环境下,建议执行以下命令,将 somaxconn 设为65535:
sysctl -w net.core.somaxconn=65535
- 扩大源端口范围
高并发环境将导致 Nginx Ingress 使用大量源端口与 upstream 建立连接,源端口范围从 net.ipv4.ip_local_port_range 内核参数中定义的区间随机选取。在高并发环境下,端口范围小容易导致源端口耗尽,使得部分连接异常。CCE环境创建的 Pod 源端口范围默认为32768 - 60999,建议执行以下命令扩大源端口范围,调整为1024 - 65535:
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
- 调整TIME_WAIT
建议执行以下命令,为Nginx Ingress开启TIME_WAIT复用,即允许将TIME_WAIT连接重新用于新的TCP连接,并且减小FIN_WAIT2状态的参数net.ipv4.tcp_fin_timeout的时间,和减小TIME_WAIT状态的参数net.netfilter.nf_conntrack_tcp_timeout_time_wait的时间 ,让系统尽快释放它们所占用的资源。
sysctl -w net.ipv4.tcp_fin_timeout=15 sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
为Nginx Ingress Controller的Pod添加initContainers并设置上述内核参数。可参考以下代码示例:
...
initContainers:
- name: setsysctl
image: ***(cce默认使用社区的nginx-ingress镜像)
securityContext:
runAsUser: 0
runAsGroup: 0
capabilities:
add:
- SYS_ADMIN
drop:
- ALL
command:
- sh
- -c
- |
if [ "$POD_IP" != "$HOST_IP" ]; then
mount -o remount rw /proc/sys
if [ $? -eq 0 ]; then
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_fin_timeout=15
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
else
echo "Failed to remount /proc/sys as read-write. Skipping sysctl commands."
fi
fi
env:
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: HOST_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP 
