Nginx Ingress Controller使用建议

Nginx Ingress Controller是部署于集群内部的Ingress控制器,可以为您提供性能更好且定制性更高的使用方式。在社区版本的基础上,ACK集群提供的Nginx Ingress Controller整合了阿里云产品的一系列功能,提供更加便捷的使用体验。由于Nginx Ingress Controller部署在集群内部,因此它的稳定性与使用时的配置、当前集群状态密切相关。本文介绍Nginx Ingress Controller的使用建议,您可以参考以下使用建议,对集群内的Ingress Controller进行配置,获得最佳的使用效果。

索引

提升Nginx Ingress Controller的性能和稳定性

使用合适的副本数和资源限制

默认情况下,通过集群创建或从组件中心安装的Nginx Ingress Controller的副本数为2,您可以根据业务的实际需要进行调整。

在部署Nginx Ingress Controller时,请确保Nginx Ingress Controller分布在不同的节点上,避免不同Nginx Ingress Controller之间资源的抢占和单点故障。您也可以为其使用独占节点来保证性能与稳定性,具体操作,请参见使用独占节点保证Nginx Ingress性能与稳定性。同时建议您不要为Nginx Ingress Controller设定资源限制,避免OOM所带来的流量中断。如果确实有限制的需要,建议资源限制CPU不低于1000 Milicore(YAML配置里格式为1000m)和内存不低于2 GiB。

使用独占节点来提升Nginx Ingress性能与稳定性

优化Nginx Ingress性能

Nginx Ingress Controller性能调优主要分为系统参数调优和Nginx参数调优:

  • 系统参数调优:阿里云上的操作系统已经默认优化了一些常见参数,其他还需要调优的系统参数主要包括系统最大Backlog数和可用端口的最大范围。系统参数调优后可以保证Nginx处理高并发请求的能力,以及在连接后端时不会因为端口耗尽而失败。

  • Nginx参数调优:

    • 调整单个Worker的最大连接数:Nginx参数主要可以调整单个Worker的最大连接数来保证Nginx Ingress Controller处理高并发请求的能力。

    • 增加连接超时时间:Nginx Ingress Controller与Nginx默认表现不同,会使用长连接对后端业务Pod发起请求,因此Nginx参数还需要增加连接超时时间来让单条连接能够处理更多的请求,减少连接创建时的开销。

    • 设置长连接超时时间:请您确保后端的业务长连接的超时时间不低于Nginx Ingress Controller的连接超时时间( ACK集群中默认为900s)。

Nginx Ingress组件默认已经置入了相关的调优项,在一般场景中能够达到较优的表现。如果您有特殊需要,可以通过ConfigMap中的相关字段进一步优化系统参数和Nginx参数。关于ConfigMap的更多信息,请参见ConfigMaps

对Nginx Ingress Controller配置HPA进行自动扩容

一般情况下,Nginx Ingress Controller已经有足够的能力应对业务的突发流量。如果在高负载情况下仍不满足您的要求,也可以配置HPA对Nginx Ingress Controller进行扩容。具体操作,请参见容器水平伸缩(HPA)

重要

在Pod扩缩容时可能会导致部分业务连接的中断情况,请谨慎配置。

配置的YAML示例如下所示:

apiVersion: autoscaling/v2beta1
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
        targetAverageUtilization: 50

为后端服务配置合理的preStop Hook

在后端服务滚动更新时,Nginx ingress Controller会将正在终止的Pod的端点摘除,同时保持还在处理的请求的连接。如果后端服务Pod在收到结束信号后立即退出,就可能会导致正在处理的请求失败,或者由于时序问题,部分流量仍被转发到已经退出的Pod中,导致部分流量产生损失。

为了解决滚动更新时流量产生损失的情况,推荐在后端服务的Pod中配置preStop Hook,在端点被摘除后仍继续工作一段时间,解决流量中断的情况。

在Pod模板的容器配置中加入:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: app
        lifecycle:
          # 配置preStop Hook,等待30秒后退出。
          # 需要容器中存在sleep命令。
          preStop:
            exec:
              command:
              - sleep
              - 30

提升Nginx Ingress Controller的可观测性

使用SLS和阿里云Prometheus服务提升可观测性

Nginx Ingress Controller提供了基于SLS日志以及Prometheus的监控大盘,帮助您更好地了解业务的流量情况。

  • SLS日志:

    • 创建集群时,如果您已经选中了启用日志组件及Ingress Dashboard,您就可以直接通过容器服务管理控制台网络 > 路由页面的Ingress概览中查看到基于SLS日志服务提供的大盘服务;您也可以直接在运维管理 > 日志中心查看到Nginx Ingress Controller产生的相关日志。具体操作,请参见Nginx Ingress访问日志分析与监控

    • 如果您在创建时没有选中日志以及Ingress的相关选项,也可以手动配置日志收集组件和规则。具体操作,请参见Nginx Ingress访问日志分析与监控。关于监控的更多信息,请参见Ingress Dashboard监控

  • 阿里云Prometheus监控:阿里云Prometheus监控可以在创建集群时选择安装,或者在创建集群后通过运维管理 > Prometheus监控安装或查看。具体操作,请参见阿里云Prometheus监控

    说明

    使用阿里云Prometheus监控时,请为集群中的Ingress资源添加host字段,否则在默认情况下,该Ingress的部分metrics将会缺失。您也可以通过在Nginx Ingress Controller的Deployment中修改controller启动参数,加入--metrics-per-host=false来解决该问题。

Nginx Ingress Controller进阶功能

使用多套Nginx Ingress Controller

在应用中,您可能会因为内外网隔离等需要,在集群中部署多套Nginx Ingress Controller。具体操作,请参见部署多个Ingress Controller

在集群内部访问Nginx Ingress Controller

在集群中,LoadBalancer Service的外部地址(Nginx Ingress Controller的公网 IP)通常会被Iptables或IPVS拦截并转发。当externalTrafficPolicyLocal,且节点上没有对应Nginx Ingress Pod时,会发生网络不通的问题。ACK集群中的Nginx Ingress Controller默认使用了Local模式的LoadBalancer Service,因此在集群内访问Nginx Ingress Controller绑定的CLB地址时,可能会出现网络不通的情况。

建议您在集群内部有访问Nginx Ingress Controller(通过公网IP或绑定公网IP的域名)的需要时,使用Service ClusterIP或内部域名(nginx-ingress-lb.kube-system)访问。同时请避免在Nginx Ingress Controller中对自身进行访问,也可能会因为Hairpin问题导致网络不通。关于该问题的解决方案,请参见Kubernetes集群中访问LoadBalancer暴露出去的SLB地址不通

使用WAF或透明WAF

为了阻挡恶意请求,您可以在Web应用防火墙控制台应用型负载均衡ALB控制台为集群Nginx Ingress Controller所使用的CLB开启WAF或透明WAF功能。在开启HTTPS端口上的WAF或透明WAF功能时,需要在控制台上配置所使用的证书。这种情况下,可能会出现以下问题:

  • TLS请求会在WAF或透明WAF上进行截断,因此集群内通过Secret配置的证书将不会被暴露在公网出口上。

  • 在集群内通过CLB IP或Service ClusterIP访问443端口可能不会经过WAF或透明WAF,导致证书返回错误。

  • 在开启WAF或透明WAF的情况下,Nginx Ingress Controller将默认无法获得真实的客户端IP。您可以通过在ConfigMap中 ( 通过组件管理安装的Nginx Ingress Controller默认为kube-system命名空间下的nginx-configuration)添加以下内容,配置启用Nginx的Realip模块,使用X-Forwarded-For头作为真实客户端地址。

    use-forwarded-headers: "true" # 0.30.0及更旧版本使用该选项。
    enable-real-ip: "true" # 0.44.0及更新版本使用该选项。
    proxy-real-ip-cidr: <您从WAF获取到的回源IP段>

通过Nginx Ingress Controller进行应用的蓝绿或灰度发布

您可以通过容器服务管理控制台的灰度发布或手动添加Annotation的方式来使用Nginx Ingress Controller提供的灰度功能,具体操作,请参见通过Nginx Ingress实现灰度发布和蓝绿发布

重要

请确保需要灰度所使用的服务(包括原服务和灰度服务)没有同时被灰度Ingress以外的Ingress资源引用。否则,可能会出现灰度规则的冲突,从而引发流量路由错误。

通过Nginx Ingress Controller代理非HTTP请求

Nginx Ingress Controller默认使用HTTP协议连接到后端服务,但同时提供了对多种后端协议的支持,其中比较常用的协议有WebSocket、HTTPS和gRPC。关于支持的后端协议具体类型,请参见Backend Protocol

  • WebSocket:Nginx Ingress Controller提供了对WebSocket的原生支持,您不需要进行任何配置即可转发WebSocket连接。如果您有持续较长的WebSocket连接,可以通过Annotation适当地调整后端连接的超时时间,防止业务因为超时而断连。关于调整的具体操作,请参见Custom timeouts

  • HTTPS:针对使用HTTPS的后端服务,您可以在Ingress中添加nginx.ingress.kubernetes.io/backend-protocol:"HTTPS"的Annotation切换为HTTPS连接。

  • gRPC:gRPC仅支持通过TLS端口访问。因此,请确保您的业务通过Nginx Ingress Controller访问gRPC服务时,使用的是加密的TLS端口。关于配置gRPC的具体操作,请参见通过Ingress Controller实现gRPC服务访问