全部产品
Search
文档中心

容器服务 Kubernetes 版 ACK:Nginx Ingress FAQ

更新时间:Nov 14, 2024

本文主要为您介绍Nginx Ingress常见问题的处理方法。

Ingress支持哪些SSL/TLS版本?

Ingress-Nginx默认支持TLS V1.2及V1.3版本,对于部分旧版本的浏览器,或者移动客户端TLS版本低于1.2时,会导致客户端在与Ingress-Nginx服务SSL版本协商时报错。

修改kube-system/nginx-configuration configmap添加以下配置,以启用Ingress-Nginx对更多TLS版本的支持。具体操作,请参见TLS/HTTPS

说明

Nginx Ingress Controller 1.7.0及以后版本,如要启用TLS v1.0与TLS v1.1,需要将@SECLEVEL=0添加到ssl-ciphers中。

image.png

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:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
ssl-protocols: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"

Ingress L7请求头默认是透传的吗?

Ingress-Nginx默认透传客户端的请求头,有些不符合HTTP规则的请求头(例如Mobile Version),在转发到后端服务前会被过滤掉。为了不过滤掉这类请求头,您可以执行kubectl edit cm -n kube-system nginx-configuration命令在ConfigMap中添加配置。更多信息,请参见ConfigMap

enable-underscores-in-headers: true

后端服务为HTTPS服务访问时是否可以通过Ingress-Nginx转发?

对于后端业务是HTTPS服务,但同样希望可以通过Ingress-Nginx转发时,执行以下命令,在Ingress资源配置中添加以下Annotation。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: xxxx
  annotations:
    # 注意这里:必须指定后端服务为HTTPS服务。
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

Ingress L7透传客户端IP吗?

Ingress-Nginx默认会通过X-Forwarded-For和X-Real-IP来透传客户端IP,但是当客户端主动在请求头里指定了X-Forwarded-For和X-Real-IP时,会导致服务端无法获取到真实的客户端IP。

您可以执行kubectl edit cm -n kube-system nginx-configuration命令在ConfigMap中添加配置,以实现Ingress,L7透传客户端IP。

compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-forwarded-headers: "true"

如果在Nginx ingress之前有多层代理,您需要根据proxy-real-ip-cidr参数对配置进行调整,将前置代理的IP地址以CIDR格式添加到proxy-real-ip-cidr中,多个CIDR之间用逗号分隔。详细信息请参见使用WAF或透明WAF

proxy-real-ip-cidr:  "0.0.0.0/0,::/0"  

在IPv6场景下,如果Nginx Ingress收到的X-Forwarded-For头为空,并且前置有CLB可以启用CLB 的Proxy Protocol来获取客户端IP。关于Proxy Protocol详细信息请参见通过CLB四层监听获取客户端真实IP

Nginx Ingress Controller组件支持HSTS吗?

nginx-ingress-controller组件默认是开启HSTS的,有些浏览器第一次基于PLAIN HTTP访问时,服务端(开启HSTS)会在返回给客户端的响应头里携带Non-Authoritative-Reason: HSTS字段,说明服务端支持HSTS,当客户端也支持的情况下下次会直接以HTTPS方式访问服务端。服务端返回的响应头消息体中包含有307 Internal Redirect状态码,具体如下图所示。1

当客户端不希望支持自动转到HTTPS访问服务端时,您可以关闭nginx-ingress-controller组件的HSTS。具体操作,请参见HSTS

说明

在浏览器端HSTS默认是有缓存的,当关闭nginx-ingress-controller组件的HSTS后,请您清理缓存。

Ingress-Nginx支持哪些Rewrite配置?

目前Ingress-Nginx支持一些简单的Rewrite配置,具体请参见Rewrite。但是,对于一些高级的特别的Rewrite需求,您可以通过下面方式来配置。

  • configuration-snippet:请参见Configuration snippet,扩展一些配置到Location章节中。

  • server-snippet:请参见Server snippet,扩展一些配置到Server章节中。

同时,snippet也支持一些全局配置,具体如下图所示。更多相关信息,请参见main-snippet2

在ACK组件管理中升级Nginx Ingress Controller组件时,系统会有哪些更新?

Nginx Ingress Controller组件在0.44之前的版本,包含以下资源:

  • serviceaccount/ingress-nginx

  • configmap/nginx-configuration

  • configmap/tcp-services

  • configmap/udp-services

  • clusterrole.rbac.authorization.k8s.io/ingress-nginx

  • clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx

  • role.rbac.authorization.k8s.io/ingress-nginx

  • rolebinding.rbac.authorization.k8s.io/ingress-nginx

  • service/nginx-ingress-lb

  • deployment.apps/nginx-ingress-controller

Nginx Ingress Controller组件在0.44版本及其之后的版本,额外包含以下资源:

  • validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission

  • service/ingress-nginx-controller-admission

  • serviceaccount/ingress-nginx-admission

  • clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission

  • clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission

  • role.rbac.authorization.k8s.io/ingress-nginx-admission

  • rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission

  • job.batch/ingress-nginx-admission-create

  • job.batch/ingress-nginx-admission-patch

在ACK的组件管理页面对Nginx Ingress Controller组件进行升级时,系统保留以下资源配置不变更:

  • configmap/nginx-configuration

  • configmap/tcp-services

  • configmap/udp-services

  • service/nginx-ingress-lb

所有其他资源的配置都会被覆盖成默认配置。以deployment.apps/nginx-ingress-controller资源配置为例,其默认的replicas参数为2。如果您升级Nginx Ingress Controller组件之前的replicas为5,但是通过组件管理升级Ingress后,其replicas将会变为2,和默认配置一致。

如何将Ingress-nginx的监听由四层改为七层(HTTPS/HTTP)?

Ingress Pod的负载均衡默认是TCP 443 和TCP 80,您可以创建一个HTTPS/HTTP类型的负载均衡,将Ingress-nginx的监听由四层改为七层。

说明

修改监听时服务会有短暂中断,建议在业务低谷期进行修改监听操作。

  1. 创建证书,并记录cert-id。具体操作,请参见选择阿里云签发证书

  2. 通过Annotation将Ingress所用负载均衡的监听由四层改为七层。

    1. 登录容器服务管理控制台,在左侧导航栏选择集群

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择网络 > 服务

    3. 服务页面顶部设置命名空间为kube-system,单击ingress-nginx-lb右侧操作列下的YAML 编辑

    4. 查看YAML对话框中,将ports中443端口的targetPort改为80。

        - name: https
          port: 443
          protocol: TCP
          targetPort: 80 # 将443端口的targetPort改为80

      annotations参数下添加以下内容,然后单击更新

      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "http:80,https:443"
      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-cert-id: "${YOUR_CERT_ID}"
  3. 结果验证。

    1. 服务页面,单击ingress-nginx-lb服务类型列的image

    2. 单击监听页签,可以看到监听的前端协议/端口显示HTTP:80和HTTPS:443,说明通过Annotation将负载均衡的监听由四层改为七层成功。

应用市场部署的ack-ingress-nginx如何使用已有SLB?

  1. 登录容器服务管理控制台,在左侧导航栏选择市场 > 应用市场

  2. 应用目录页面搜索ack-ingress-nginxack-ingress-nginx-v1

    • 1.20以下集群选中ack-ingress-nginx

    • 1.20以上集群选中ack-ingress-nginx-v1

  3. 部署Ingress Controller。详细信息,请参见部署多个Ingress Controller

    在部署过程中的参数页面,删除旧注解,添加新注解。

    1. 删除controller.service.annotations下的所有注解。

      image..png

    2. 添加新的注解。

      # 指定SLB
      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: "${YOUR_LOADBALANCER_ID}"
      # 强制覆盖监听
      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: "true"

      image..png

  4. 单击确定,继续部署。

  5. 部署成功后,配置对应的IngressClass,使用Ingress Controller。详细信息,请参见部署多个Ingress Controller

如何获取多个Ingress Controller对应的访问日志?

前提条件

操作步骤:

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择集群信息

  3. 在集群信息页面,单击集群资源。然后在集群资源的列表中单击日志服务Project的右侧ID。

    image

  4. 跳转到目标集群的SLS日志服务,在日志库页面创建Logstore。具体操作,请参见管理Logstore。为确保日志不会重复采集,一个Logstore只采集一个Ingress Controller组件日志。

    • Logstore名称可以参考不同的Ingress Controller的组件名称。

    • 创建成功后,在弹出的数据接入向导框中,单击取消

  5. 日志库左侧列表栏,单击nginx-ingress > Logtail配置,然后在Logtail配置列表下,单击k8s-nginx-ingress进入配置页面。

  6. Logtail配置页面,单击复制。然后在Logtail复制页面,单击下拉框,选择新创建的Logstore名称,在容器过滤中,单击容器Label白名单列的添加,并以键值对的方式添加Ingress Controller组件容器Label。在Logtail复制页面,单击提交

    image

  7. 日志库左侧列表栏,单击新创建的Logstore名称。在右侧栏顶部,单击开启索引,然后在查询分析页面,单击确定。即可完成对Logstore的配置。

  8. 日志库左侧列表栏,选择新创建Logstore名称 > Logtail配置。在Logtail配置页面中,单击右侧操作列下的管理Logtail配置。在配置详情页面,单击处理插件名称列下的提前字段(正则模式),查看日志处理字段。

    8184e5bd055d3c2d8add99ce8a285eb0

  9. Logtail配置页面,单击切换为编辑器配置。在Logtail配置下,单击编辑。在插件配置中,配置对应日志字段Keys和Regex。配置完成,单击保存

    说明

    若不同的Nginx Ingress Controller日志格式定义有所区别,需要对应地修改Logtail配置下的processors部分。

如何开启nginx-ingress-controller的TCP协议?

ACK集群中的Ingress资源默认仅支持路由外部HTTP和HTTPS流量至服务内,通过修改ingress-nginx组件的配置,可以实现来自非HTTP协议的外部TCP流量通过在ConfigMap中定义的TCP端口映射,路由至集群内的服务。

操作步骤如下:

  1. tcp-echo服务模板部署Service、Deployment服务。

  2. 部署以下模板ConfigMap。

    1. 编辑tcp-services-cm.yaml,保存退出。

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: tcp-services
        namespace: kube-system 
      data:
        9000: "default/tcp-echo:9000" # 表示任何通过端口9000接收到的外部TCP流量都将被路由到default命名空间下名为tcp-echo的服务上,该服务监听的是内部端口9000。
        9001:"default/tcp-echo:9001" 
    2. 使用如下命令部署ConfigMap。

      kubectl apply -f tcp-services-cm.yaml
  3. 新增nginx-ingress-controller组件的Service TCP端口,保存退出。

    kubectl edit svc nginx-ingress-lb -n kube-system 
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: nginx-ingress-lb
      name: nginx-ingress-lb
      namespace: kube-system
    spec:
      allocateLoadBalancerNodePorts: true
      clusterIP: 192.168.xx.xx
      ipFamilies:
      - IPv4
      ports:
      - name: http
        nodePort: 30xxx
        port: 80
        protocol: TCP
        targetPort: 80
      - name: https
        nodePort: 30xxx
        port: 443
        protocol: TCP
        targetPort: 443
      - name: tcp-echo-9000       # 新增
        port: 9000                # 新增
        protocol: TCP             # 新增
        targetPort: 9000          # 新增
      - name: tcp-echo-9001       # 新增
        port: 9001                # 新增
        protocol: TCP             # 新增
        targetPort: 9001
    selector:
        app: ingress-nginx
      sessionAffinity: None
      type: LoadBalancer
  4. 测试配置生效。

    1. 执行以下命令,查看Ingress服务,获取Ingress SLB的地址。

       kubectl get svc -n kube-system| grep nginx-ingress-lb 

      预期输出。

      nginx-ingress-lb      LoadBalancer   192.168.xx.xx  172.16.xx.xx   80:31246/TCP,443:30298/TCP,9000:32545/TCP,9001:31069/TCP   
    2. 使用nc命令给Ingress IP的9000端口发送helloworld。无返回数据则表示测试正常。

      echo "helloworld" |  nc <172.16.xx.xx> 9000
      
      echo "helloworld" |  nc <172.16.xx.xx> 9001

Nginx Ingress证书匹配逻辑是什么?

当在Ingress资源配置中指定TLS证书时,证书的配置位于spec.tls字段下,但实际使用的域名则引用spec.rules.host字段。而在Nginx Ingress Controller中,Controller会以Lua Table的形式存储域名到证书的映射关系。

当客户端向Nginx发起HTTPS请求时,会通过SNI携带请求的域名host信息,Nginx ingress采用certificate.call()来查找对应的域名是否存在配置的证书,若不存在则返回fake证书。

相关的Nginx配置如下:


    ## start server _
    server {
        server_name _ ;
        listen 80 default_server reuseport backlog=65535 ;
        listen [::]:80 default_server reuseport backlog=65535 ;
        listen 443 default_server reuseport backlog=65535 ssl http2 ;
        listen [::]:443 default_server reuseport backlog=65535 ssl http2 ;
        set $proxy_upstream_name "-";
        ssl_reject_handshake off;
        ssl_certificate_by_lua_block {
            certificate.call()
        }
   ...
   }
    
    
    ## start server www.example.com
    server {
        server_name www.example.com ;
        listen 80  ;
        listen [::]:80  ;
        listen 443  ssl http2 ;
        listen [::]:443  ssl http2 ;
        set $proxy_upstream_name "-";
        ssl_certificate_by_lua_block {
            certificate.call()
        }
    ...
    }

Ingress Nginx支持OCSP Stapling技术功能,可以改进证书状态的验证过程。基于此功能,客户端无需直接向CA站点查询证书状态,从而减少证书验证时间,提升访问速度。更多信息,请参见配置OCSP Stapling

Nginx Ingress证书为什么不匹配?

找到您配置的证书Secret下对应的证书内容保存为文件(需要BASE64解码后的内容),然后使用openssl命令进行解码查看。

kubectl get secret  <YOUR-SECRET-NAME>  -n <SECRET-NAMESPACE>  -o jsonpath={.data."tls\.crt"} |base64 -d  | openssl x509  -text -noout

查看CN(Common Name)字段中是否包含您请求的域名,如果不符,您需要重新生成证书

流量高负载情况下健康检查失败怎么办?

健康检查将通过访问Nginx在10246端口上监听的/healthz路径,以验证Nginx的状态是否健康且服务正常运行。

健康检查失败时,预期如下:

I0412 11:01:52.581960       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:01:55 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:01:55.895683       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:02.582247       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:05 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:05.896126       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:12.582687       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:15 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:15.895719       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:22.582516       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:25 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:25.896955       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:28.983016       7 nginx.go:408] "NGINX process has stopped"
I0412 11:02:28.983033       7 sigterm.go:44] Handled quit, delaying controller exit for 10 seconds
I0412 11:02:32.582587       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:35 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:35.895853       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:38.986048       7 sigterm.go:47] "Exiting" code=0

当Nginx工作进程负载过高时,会消耗大量CPU资源,有时甚至导致CPU资源接近100%。这种情况可能引发健康检查失败。建议增加Pod副本数量,以便分散负载,确保健康检查能够成功执行。

cert-manager不符合预期,导致证书签发失败怎么办?

如果您使用的证书管理工具Cert-manager未能按预期工作,导致证书签发失败,原因可能是启动了Web应用程序防火墙(WAF)。WAF在开启状态下可能会干扰HTTP01请求,妨碍证书的签发流程。建议关闭WAF,从而消除对证书签发过程的影响。关闭WAF前,需充分评估其他因素,避免带来不必要的影响。

Nginx大压力流量下为什么占用大量内存?

如果发现Nginx在处理大流量时内存占用异常增高,导致OOM事件,可以进入Pod内部重点检查Controller进程的内存占用较多,应该是Metrics相关性能指标导致内存泄漏。这个问题为Nginx Ingress Controller v1.6.4的已知问题,推荐您将Nginx Ingress Controller升级至最新版本,关闭Metrics采集,修改启动参数,添加--enable-metrics=false。特别注意那些会显著影响内存的指标,比如nginx_ingress_controller_ingress_upstream_latency_seconds。更多详情,请参见Ingress Controller高压测试Prometheus Metric内存泄漏及相关的Metrics PR

修正Nginx Ingress Controller过期的升级状态

当Nginx Ingress Controller灰度升级过程中,如果遇到卡在验证阶段的情况,无法继续操作(出现提示“Operation is forbidden for task in failed state”),这通常是因为组件升级任务由于超出预定的4天有效期而被系统清除导致的。在这种情况下,您需要手动调整组件的灰度状态以纠正问题。

如果组件的升级进度已经达到发布阶段,那么无需执行升级操作。直到当前的任务因超过预设的过期时间(4天)而自动终止即可。

操作步骤

完成修改后,组件升级将自动继续,替换旧版本Pod以完成灰度升级。不过,在控制台的组件管理界面中将依然会显示升级中的状态,该状态将在大约两周后消失恢复正常。

  1. 执行以下命令,编辑nginx-ingress-controller的Deployment。

    kubectl edit deploy -n kube-system  nginx-ingress-controller
  2. 将以下参数修正回指定值。

    • spec.minReadySeconds: 0

    • spec.progressDeadlineSeconds: 600

    • spec.strategy.rollingUpdate.maxSurge: 25%

    • spec.strategy.rollingUpdate.maxUnavailable: 25%

    image

  3. 编辑完成后保存退出。

从控制器v1.10版本起,为什么分块传输(Transfer-Encoding: chunked)无法正常工作?

如果您的代码设置了HTTP头部Transfer-Encoding: chunked,并且控制器的日志中出现关于重复头部的错误信息,这可能与Nginx的更新有关,关于更新记录请参见Nginx的更新日志。v1.10起的Nginx版本强化了对HTTP响应的校验,导致后端返回多个Transfer-Encoding: chunked头部时被视为无效响应。因此,需要确保您的后端服务仅返回一个Transfer-Encoding: chunked头。更多详情,请参见GitHub Issue #11162

Nginx Ingress如何配置IP黑白名单访问控制

Nginx Ingress支持在ConfigMap中添加键值对或在Ingress路由中添加Annotation的方式配置IP黑白名单访问控制。ConfigMap为全局生效,Ingress在路由维度生效,Ingress路由维度优先级高于全局维度。如需在Ingress中添加Annotation,请参见下表。更多信息,请参见Denylist Source RangeWhitelist Source Range

Annotation

说明

nginx.ingress.kubernetes.io/denylist-source-range

IP黑名单,支持IP地址或CIDR地址块,以英文半角逗号(,)分隔。

nginx.ingress.kubernetes.io/whitelist-source-range

IP白名单,支持IP地址或CIDR地址块,以英文半角逗号(,)分隔。

Nginx Ingress v1.2.1已知问题

在Ingress资源中配置defaultBackend时,可能会覆盖默认server的defaultBackend设置。更多详情请参见GitHub Issue #8823。为了解决这个问题,建议将Nginx Ingress Controller组件升级至v1.3或更高版本。关于如何升级组件的操作步骤,请参见升级Nginx Ingress Controller组件

使用curl命令访问公网服务时出现连接重置

在使用curl命令通过HTTP协议访问境外公网服务时,可能会遇到错误提示:curl: (56) Recv failure: Connection reset by peer。通常是由于HTTP明文请求中可能包含敏感词,这些敏感词导致请求被阻断或响应被重置。您可以为路由规则配置HTTPS证书,确保使用加密方式进行通信。