配置高负载场景的Nginx Ingress Controller

更新时间:
复制为 MD 格式

在高负载场景下,默认配置的Nginx Ingress Controller可能会成为性能瓶颈,出现响应延迟增高、错误率上升,甚至在流量高峰期出现不可用的情况。通过规划独占基础设施、调整部署与调度策略、深度调优核心性能参数等一系列操作,确保 Nginx Ingress在高负载场景中保持高性能与高稳定性。

重要
  • 由于Ingress NGINX开源项目于20263月后停止维护更新,容器服务 Kubernetes 版将停止Nginx Ingress Controller组件维护,请充分了解使用风险。更多详细内容,请参见【产品公告】关于停止维护Nginx Ingress Controller组件的公告

  • 下列配置仅提供参考思路,是否使用某个配置和各项参数与规格的选择,请实际结合Nginx Ingress Controller负载进行选择。

保证组件资源充足

采用独占节点池部署

使用独占节点池部署,可使Nginx Ingress Controller的工作负载与集群中其他应用完全隔离,不受资源抢占影响。

重要

Nginx Ingress Controller Pod设置resources.limits可能因内存限制触发OOM,或因CPU限流导致流量中断或性能抖动,请勿配置资源限制。如业务场景必须配置,建议CPU不低于1核,内存不低于2 GiB。

创建专属节点池

Nginx Ingress Controller Pod创建专属节点池。请注意下列事项:

  • 节点规格选择:Pod的网络性能受所在节点实例规格限制。例如,节点PPS30万时,单PodPPS上限即为30万。建议选择网络增强型实例,并选择CPU32核或更多的规格。

  • 节点数量:Nginx Ingress Controller默认部署两个Pod,且采用了反亲和性配置,节点池中至少需要两个节点。

  • 污点与标签配置:节点池需要配置污点和标签,以避免其他Pod调度到该节点。例如,可在污点和标签中添加system-addon: nginx-ingress键值对,并将污点Effect设置为NoSchedule

  • Pod规格选择:由于Nginx的基础开销,在资源总量相同的情况下,单个高规格Pod(例如32核)的性能优于多个低规格Pod(例如两个16核)。在保证高可用的前提下,建议使用少量高规格Pod。

配置组件

登录容器服务管理控制台,在组件管理页面找到Nginx Ingress Controller卡片,单击配置

  1. NodeSelector中添加专属节点池标签。

    请勿删除已有的NodeSelector标签
  2. Tolerations中添加专属节点池标签,并将Effect设置为NoSchedule

  3. 单击确认,然后通过控制台确认Pod是否已调度到专属节点池。

调整负载均衡实例规格

负载均衡实例规格决定了Nginx Ingress的最大连接数和QPS上限,建议使用高规格实例。

执行以下命令编辑Service,通过service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec注解指定负载均衡实例规格:

kubectl edit service -n kube-system nginx-ingress-lb
apiVersion: v1
kind: Service
metadata:
  annotations:
    ...
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: "slb.s3.large" # 指定负载均衡实例规格
  name: nginx-ingress-lb
  namespace: kube-system
  ...
spec:
  ...
2026年前创建的按规格计费CLB实例支持此操作。CLB实例规格详情请参见实例性能

使用HPA进行自动扩容

采用独占节点池部署的Pod通常已具备应对业务突发流量的能力。如仍无法满足要求,可配置HPA(Horizontal Pod Autoscaler)对Nginx Ingress Controller进行自动扩容。

重要

Pod缩容可能导致部分业务连接中断,请谨慎配置缩容策略。

创建并保存以下内容为nginx-hpa.yaml,然后执行kubectl apply -f nginx-hpa.yaml创建HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-ingress-controller-hpa
  namespace: kube-system
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-ingress-controller
  minReplicas: 2
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

保证后端应用平滑下线

后端Pod进行滚动更新时,Nginx Ingress Controller停止将新的请求转发到正在终止的Pod,但仍保持还在处理请求的连接。如果Pod此时立即终止,可能会导致正在处理的请求发生错误。

通过配置preStop Hook,Pod会在收到SIGTERM信号后继续工作一段时间,保证现有的请求处理完成:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: app
        lifecycle:
          # 配置preStop Hook,等待30秒后退出。
          # 需要容器中存在sleep命令。
          preStop:
            exec:
              command:
              - sleep
              - 30
 ...
preStop的等待时间应根据业务最大请求处理时间确定,一般建议设置为最大响应时间的1.5~2倍。需要确认容器镜像中存在sleep命令。

通过监控与日志确认组件状态

SLS日志

  • 容器服务管理控制台网络 > 路由页面的Nginx Ingress 概览中,可以查看日志大盘,确认客户端访问数据;也可以在运维管理 > 日志中心 > 应用日志 > 日志库中选择nginx-ingress,查看具体日志条目。

  • 如果日志大盘中多项数据显示null,或日志库nginx-ingress的日志为空,说明在创建集群时未开启日志相关选项,请参见Nginx Ingress访问日志分析与监控手动配置。

Prometheus监控

登录容器服务管理控制台,在运维管理 > Prometheus 监控中可以查看监控大盘。

  • 如果页面显示还未安装组件,请根据提示完成相关组件的安装和监控大盘的检查。

  • 选择集群Ingress流量监控页签,然后在Controller Class中选择k8s.io/ingress-nginx,即可查看Nginx Ingress监控。如果未显示k8s.io/ingress-nginx选项,表明还未安装Nginx Ingress Controller组件。

请为Ingress资源添加host字段。在默认配置下,没有host字段的Ingress资源不会被监控采集。如果无需区分Host进行监控,也可以在Nginx Ingress ControllerDeployment中修改controller启动参数,加入--metrics-per-host=false来解决该问题。

优化Nginx配置

配置日志自动轮转

Nginx Ingress Controller Pod将日志同时记录到/dev/stdout和容器内/var/log/nginx/目录。随着日志文件逐渐增大,记录新日志将耗费更多资源。通过日志轮转,定期将一个时间段中的日志保存到独立文件中,并清除原有日志记录,可降低记录日志的资源消耗。

  1. 登录部署Nginx Ingress Controller Pod的节点。

  2. /root目录下添加文件nginx-log-rotate.sh

    containerd节点

    #!/bin/bash
    # 最多保留日志文件个数,可根据需求进行调整。
    keep_log_num=5
    
    #获取所有运行中的ingress-nginx容器ID
    ingress_nginx_container_ids=$(crictl ps | grep nginx-ingress-controller | grep -v pause | awk '{print $1}')
    if [[ -z "$ingress_nginx_container_ids" ]]; then
     echo "error: failed to get ingress nginx container ids"
     exit 1
    fi
    
    # 随机睡眠5~10秒。
    sleep $(( RANDOM % (10 - 5 + 1 ) + 5 ))
    for id in $ingress_nginx_container_ids; do
     crictl exec $id bash -c "cd /var/log/nginx; if [[ \$(ls access.log-* | wc -l) -gt $keep_log_num ]]; then rm -f \$(ls -t access.log-* | tail -1); fi ; mv access.log access.log-\$(date +%F:%T) ; kill -USR1 \$(cat /tmp/nginx/nginx.pid)"
    done

    Docker节点

    #!/bin/bash
    # 最多保留日志文件个数,可根据需求进行调整。
    keep_log_num=5
    
    #获取所有运行中的ingress-nginx容器ID
    ingress_nginx_container_ids=$(docker ps | grep nginx-ingress-controller | grep -v pause | awk '{print $1}')
    if [[ -z "$ingress_nginx_container_ids" ]]; then
     echo "error: failed to get ingress nginx container ids"
     exit 1
    fi
    
    # 随机睡眠5~10秒。
    sleep $(( RANDOM % (10 - 5 + 1 ) + 5 ))
    for id in $ingress_nginx_container_ids; do
     docker exec $id bash -c "cd /var/log/nginx; if [[ \$(ls access.log-* | wc -l) -gt $keep_log_num ]]; then rm -f \$(ls -t access.log-* | tail -1); fi ; mv access.log access.log-\$(date +%F:%T) ; kill -USR1 \$(cat /tmp/nginx/nginx.pid)"
    done
  3. nginx-log-rotate.sh文件添加可执行权限。

    chmod 755 /root/nginx-log-rotate.sh
  4. /etc/crontab文件结尾添加以下内容:

    以下Cron表达式表明每15分钟对日志轮转一次,可根据实际需求进行调整。
    */15 * * * *  root /root/nginx-log-rotate.sh

关闭指标采集

Nginx Ingress Controller默认开启指标采集,会消耗一定的CPU资源。如无需获取指标,建议关闭采集。

执行kubectl edit deploy nginx-ingress-controller -n kube-system,编辑Controller所属的Deployment。在容器配置部分添加--enable-metrics=false配置,即可关闭所有指标采集。

v1.9.3或以下版本

spec:
  containers:
  - args:
    - ...
    - --enable-metrics=false

v1.9.3以上版本

v1.9.3以上版本的Nginx Ingress Controller支持单独关闭部分指标采集。例如添加--exclude-socket-metrics则可以停止Socket相关指标采集。更多信息,请参见cli-arguments

spec:
  containers:
  - args:
    - ...
    - --enable-metrics=true
    - --exclude-socket-metrics # 仅在--enable-metrics=true时有效

启用Brotli压缩

Brotli压缩算法相较于Nginx Ingress Controller默认的gzip压缩算法,在文本类数据(如网页资源)上的压缩率通常高约15%~30%。

具体提升取决于场景的详细情况。

执行kubectl edit cm -n kube-system nginx-configuration编辑Nginx Ingress ConfigMap,开启Brotli压缩。

data:
  enable-brotli: "true"
  brotli-level: "6"
  brotli-types: "text/xml image/svg+xml application/x-font-ttf image/vnd.microsoft.icon application/x-font-opentype application/json font/eot application/vnd.ms-fontobject application/javascript font/otf application/xml application/xhtml+xml text/javascript application/x-javascript text/plain application/x-font-truetype application/xml+rss image/x-icon font/opentype text/css image/x-win-bitmap"
  • enable-brotli:是否启用Brotli压缩算法,取值为 true 或 false

  • brotli-level:压缩级别,范围[1~11],默认为4。级别越高,CPU性能消耗越大。

  • brotli-types:指定使用Brotli即时压缩的MIME类型。

调整超时策略

通过减少FIN_WAIT2TIME_WAIT状态的超时时间,Nginx Ingress Controller可更快地关闭已完成数据发送的连接,降低资源占用。

重要

FIN_WAIT2TIME_WAIT等 TCP 协议栈参数直接影响 Nginx Ingress Controller 的连接回收机制。不当的配置可能导致连接池耗尽、端口资源枯竭或瞬间的高并发拥塞。在执行调整前,请确保已经了解TCP连接相关原理,并在修改后持续观察连接状态和资源使用情况,确保调整的影响在可控范围内。

执行kubectl edit deploy nginx-ingress-controller -n kube-system,编辑 Nginx Ingress Controller所属的Deployment。

initContainers中新增以下配置项:

  • net.ipv4.tcp_fin_timeout:FIN_WAIT2状态的超时时间,默认为60秒。

  • net.netfilter.nf_conntrack_tcp_timeout_time_wait:TIME_WAIT状态下的连接保持时间,默认为60秒。

dnsPolicy: ...
initContainers:
- command:  
  - /bin/sh
  - -c
  - |
    if [ "$POD_IP" != "$HOST_IP" ]; then
    mount -o remount rw /proc/sys
    sysctl -w net.core.somaxconn=65535
    sysctl -w net.ipv4.ip_local_port_range="1024 65535"
    sysctl -w kernel.core_uses_pid=0
    sysctl -w net.ipv4.tcp_fin_timeout=15 # FIN_WAIT2状态上限设置为15秒
    sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30 # TIME_WAIT状态上限设置为30秒
    fi
  env:                                                           
    ...                                                     
  image: ...
  imagePullPolicy: IfNotPresent                           
  name: init-sysctl            

优化HTTPS性能

调整下列参数优化Nginx Ingress ControllerHTTPS性能。它们保存在ConfigMap nginx-configuration中。

kubectl edit cm -n kube-system nginx-configuration
  • SSL会话缓存与超时

    设置SSL 共享会话缓存的大小以及超时时间,可以减少SSL握手的开销。

    data:
      ssl-session-cache-size: "10m"
      ssl-session-timeout: "10m"

    对应的nginx.conf配置

    对应Nginx侧的nginx.conf配置,可以根据实际场景需求调整。

    ssl_session_cache shared:SSL:10m; # 1m储存约4000个会话
    ssl_session_timeout 10m;
  • 启用OCSP Stapling,减少客户端证书验证的时间。

    data:
      enable-ocsp: "true"
  • 启用TLS 1.30-RTT功能,允许客户端在握手完成之前就发送数据,从而减少连接建立的延迟。

    data:
      ssl-early-data: "true"
      ssl-protocols: "TLSv1.3"
  • 调整Cipher优先级(无需手动调优)

    通过调整加密套件的优先级,可以有效降低延迟。Nginx Ingress Controller的默认配置已进行了优化。

    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;    # 优先使用服务器端的Cipher配置。

配置其他性能相关选项

下列配置项也会影响Nginx Ingress Controller的性能,它们保存在ConfigMap nginx-configuration中。执行kubectl edit cm -n kube-system nginx-configuration编辑ConfigMap。

配置项

配置参数

描述

下游keepalive

keep-alive: "60s"

下游keepalive连接的最大保持时间。

keep-alive-requests: "10000"

下游keepalive请求的最大数量。

上游keepalive

upstream-keepalive-connections: "1000"

最大上游keepalive连接数。

upstream-keepalive-requests: "2147483647"

允许的最大上游keepalive请求数。

upstream-keepalive-time: "1h"

上游keepalive连接的最大保持时间。

upstream-keepalive-timeout: "150s"

上游keepalive连接的空闲超时时间。

单个Worker最大连接

max-worker-connections: "65536"

单个Worker支持的最大连接数。

超时配置

可根据实际业务场景调整,按需配置。

proxy-connect-timeout: "3s"

建立TCP连接的超时时间。

proxy-read-timeout: "5s"

读取数据的超时时间。

proxy-send-timeout: "5s"

发送数据的超时时间。

优化重试机制

当后端服务异常情况下,多级重试的过多请求可能加重后端服务的负载引发雪崩问题。更多详情请参见Ingress-nginx官方文档

proxy-next-upstream-tries: "3"

失败后的重试次数,默认为3次,包括1次初始请求和2次重试。

proxy-next-upstream: "off"

指定重试条件,设置为off则关闭重试功能。

proxy-next-upstream-timeout: "5s"

指定请求重试的超时时间,根据实际应用场景进行调整。

相关文档

集群的容器网络插件(CNI Plugin)选择会影响集群内网络通信性能,进而影响Nginx Ingress Controller的性能表现,推荐使用Terway网络插件