如何对NginxIngress进行内核参数调优,设置内核参数的方法可以用initContainers的方式,后面会有示例。
调大连接队列的大小
进程监视的套接字的连接队列的最大大小受内核参数net.core.somaxconn的限制。在高并发环境中,如果队列太小,队列可能会溢出,从而使连接的连接部分无法建立。要增加NginxIngress的连接队列,您只需要调整somaxconn内核参数的值,但是我想与您分享其背后的相关原理。
当该进程调用listen系统调用以监视端口时,它还会传入一个backlog参数,该参数确定套接字连接队列的大小,并且其值不得大于somaxconn的值。当Go程序标准库侦听时,默认情况下它将直接将somaxconn读取为队列大小,但是Nginx在侦听套接字时不会读取somaxconn,但具有自己的单独参数配置。在nginx.conf中侦听端口的位置,还可以设置一个名为backlog的参数,该参数确定nginx侦听端口的连接队列大小。
server{
listen80backlog=1024;
...
如果不设置,backlog在linux上默认为511:
backlog=number
setsthebacklogparameterinthelisten()callthatlimitsthemaximumlengthforthequeueofpendingconnections.Bydefault,backlogissetto-1onFreeBSD,DragonFlyBSD,andmacOS,andto511onotherplatforms.
也就是说,即便你的somaxconn配的很高,nginx所监听端口的连接队列最大却也只有511,高并发场景下可能导致连接队列溢出。
不过这个在NginxIngress这里情况又不太一样,因为NginxIngressController会自动读取somaxconn的值作为backlog参数写到生成的nginx.conf中:https://github.com/kubernetes/ingress-nginx/blob/controller-v0.34.1/internal/ingress/controller/nginx.go#L592
也就是说,NginxIngress的连接队列大小只取决于somaxconn的大小,这个值在TKE默认为4096,建议给NginxIngress设为65535:sysctl-wnet.core.somaxconn=65535。
扩大源端口范围
高并发场景会导致NginxIngress使用大量源端口与upstream建立连接,源端口范围从net.ipv4.ip_local_port_range这个内核参数中定义的区间随机选取,在高并发环境下,端口范围小容易导致源端口耗尽,使得部分连接异常。TKE环境创建的Pod源端口范围默认是32768-60999,建议将其扩大,调整为1024-65535:sysctl-wnet.ipv4.ip_local_port_range="102465535"。
TIME_WAIT复用
如果短连接并发量较高,它所在netns中TIME_WAIT状态的连接就比较多,而TIME_WAIT连接默认要等2MSL时长才释放,长时间占用源端口,当这种状态连接数量累积到超过一定量之后可能会导致无法新建连接。
所以建议给NginxIngress开启TIME_WAIT重用,即允许将TIME_WAIT连接重新用于新的TCP连接:sysctl-wnet.ipv4.tcp_tw_reuse=1
调大最大文件句柄数
Nginx作为反向代理,对于每个请求,它会与client和upstreamserver分别建立一个连接,即占据两个文件句柄,所以理论上来说Nginx能同时处理的连接数最多是系统最大文件句柄数限制的一半。
系统最大文件句柄数由fs.file-max这个内核参数来控制,TKE默认值为838860,建议调大:sysctl-wfs.file-max=1048576。
配置示例
给NginxIngressController的Pod添加initContainers来设置内核参数:
initContainers:
-name:setsysctl
image:busybox
securityContext:
privileged:true
command:
-sh
--c
-|
sysctl-wnet.core.somaxconn=65535
sysctl-wnet.ipv4.ip_local_port_range="102465535"
sysctl-wnet.ipv4.tcp_tw_reuse=1
sysctl-wfs.file-max=1048576
推荐阅读:架构师培训:Docker引擎核心组件