全部產品
Search
文件中心

Container Service for Kubernetes:Nginx Ingress FAQ

更新時間:Jan 16, 2026

本文主要為您介紹Nginx Ingress常見問題的處理方法。

Nginx Ingress低版本已知缺陷

低版本Nginx Ingress有較多已知缺陷,您可參照下方的連結瞭解對應問題。推薦您將Nginx Ingress Controller升級到最新版本以規避潛在問題,具體操作,請參見升級Nginx Ingress Controller組件

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"

Nginx Ingress是否支援Lua指令碼?

ACK的Nginx Ingress與社區版本完全相容,配置方式和模組支援也保持了一致,支援通過ConfigMap  server-snippethttp-snippet或使用nginx.ingress.kubernetes.io/configuration-snippet、 nginx.ingress.kubernetes.io/server-snippet註解,注入自訂Lua指令碼或配置片段。

重要

Nginx Ingress Controller組件在1.9.3及以上版本預設禁用snippet能力,需在nginx-configuration ConfigMap中開啟allow-snippet-annotations: "true"才能使用。

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

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. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇網路 > 服務

    3. 服務頁面頂部設定命名空間為kube-system,單擊nginx-ingress-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. 登入Container Service管理主控台,在左側導覽列選擇市場 > 應用市場

  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. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇叢集資訊

  3. 叢集資訊頁面,單擊基本資料頁簽,定位至叢集資源地區,然後單擊Log Service Project右側的Project名稱。

  4. 在目的地組群SLSLog Service控制台的日誌庫頁面,建立Logstore。具體操作,請參見管理LogStore。為確保日誌不會混淆,請確保一個Logstore只採集一個Ingress Controller的組件日誌。

    • Logstore名稱可以參考不同的Ingress Controller的組件名稱。

    • 建立成功後,在彈出的資料接入嚮導框中,單擊資料接入嚮導

  5. 快速資料接入面板中,單擊K8S-標準輸-舊版 > 立即接入,然後在提示框中單擊繼續。在Kubernetes標準輸出頁面中完成以下操作。

    1. 建立機器組面板,單擊使用現有機器組

    2. 機器組配置面板,勾選k8s-group-<YOUR_CLUSTER_ID>,單擊>,將其移動到右側應用機器組地區。單擊下一步

    3. 在Logtail配置面板:

      1. 單擊匯入其他配置,選擇叢集的Project和k8s-nginx-ingress的配置,然後單擊確定

      2. 全域配置列,修改配置名稱,然後在容器過濾列,以索引值對的方式添加Ingress Controller組件容器Label。單擊下一步

      3. 處理配置列,單擊處理外掛程式名稱列下的提前欄位(正則模式)。查看Tlog欄位。

        說明

        若不同的Nginx Ingress Controller日誌格式定義有所區別,您可以配置對應日誌欄位Keys和Regex。

    4. 查詢分析配置面板,單擊下一步。然後在結束面板,單擊查詢日誌,可以查看上報的日誌內容。

如何開啟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中儲存的認證與私密金鑰是否匹配:

    kubectl get secret <YOUR-SECRET-NAME>  -n <SECRET-NAMESPACE> -o jsonpath='{.data.tls\.crt}' | base64 -d > /tmp/tls.crt && \ # <YOUR-SECRET-NAME>需要替換為您使用的Secret
    kubectl get secret <YOUR-SECRET-NAME>  -n <SECRET-NAMESPACE> -o jsonpath='{.data.tls\.key}' | base64 -d > /tmp/tls.key && \
    openssl x509 -noout -modulus -in /tmp/tls.crt | openssl md5 && \
    openssl rsa -noout -modulus -in /tmp/tls.key | openssl md5

    上方的命令使用kubectl從認證Secret中提取認證內容,經過base64解碼後,將認證儲存到/tmp/tls.crt,私密金鑰儲存到/tmp/tls.key。然後使用OpenSSL MD5對認證和私密金鑰進行雜湊計算。

    如果認證與私密金鑰的雜湊值不同,則說明認證與私密金鑰不匹配,建議您通過重新設定正確的認證和私密金鑰進行修複。

  • 檢查認證是否與網域名稱匹配:

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

    上方的命令會輸出認證的部分詳細資料。其中的CN(Common Name)欄位會包含認證的網域名稱資訊,形式類似於CN = example.com。如果CN中不包含使用者使用的網域名稱,說明認證的網域名稱與實際網域名稱不匹配,請進行修複。

流量高負載情況下健全狀態檢查失敗怎麼辦?

健全狀態檢查將通過訪問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升級至最新版本,配置高負載情境的Nginx Ingress Controller特別注意那些會顯著影響記憶體的指標,比如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認證,確保使用加密方式進行通訊。

路徑匹配優先順序的邏輯是什嗎?

在 NGINX 中,Regex遵循最初相符策略。為了實現更準確的路徑匹配,ingress-nginx 首先按長度降序排列路徑,然後將其作為位置塊寫入 NGINX conf 下,具體參考: https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/

為什麼不會重試非等冪請求?

自1.9.13起,NGINX 在發生錯誤時不會重試非等冪請求(POST、LOCK、PATCH)。您可以通過修改配置 ConfigMap nginx-configuration 中的retry-non-idempotent=true恢複以前的行為

如何支援用戶端Header或者Cookie過大的請求?

若用戶端請求Header或者Cookie過大,訪問Nginx Ingress時遇到報錯資訊類似"400 Request Header Or Cookie Too Large /Bad Request"時,您需要調整相關buffer size 配置。具體有如下兩個配置參數:

您可通過執行kubectl edit cm -n kube-system nginx-configuration編輯ConfigMap並修改這兩個配置參數。例如:

client-header-buffer-size: "16k"
large-client-header-buffers: "4 32k" 

配置完之後,請確認配置在Nginx資料面是否生效。您可通過執行kubectl exec <nginx-ingress-pod> -n kube-system -- cat /etc/nginx/nginx.conf | vim -查看nginx.conf配置,確認是否與ConfigMap中的修改同步。

為什麼我的Ingress下針對特定路徑設定pathTypeExactPrefix,最終生效的還是正則匹配呢?

如果在給定的host下其中任意一個Ingress規則下有配置use-regex或者rewrite-target註解,該host下的所有路徑將強制執行不區分大小寫正則匹配規則。這個是當前Nginx Ingress Controller的實現邏輯。更多資訊,請參見社區文檔

image.png

在具有很多Ingress規則的叢集下新增Ingress,為什麼validation webhook響應較慢?

這是當前Nginx Ingress Controller版本(v1.12及以下版本)社區實現的已知效能問題,請參見Issue: #11115

解決辦法

  1. 如果對回應時間可以容忍,並且不接受增量校正。若當前響應已遇到Webhook逾時問題,可以將Webhook配置validatingwebhookconfigurations ingress-nginx-admission的逾時時間調大,預設值為10s,最大不能超過30s。請注意,該參數取值會在組件升級流程中被覆蓋。

  2. 修改Nginx ingress controller的deployment啟動參數,增加--disable-full-test=true配置。該配置開啟後,對Ingress規則只做增量校正,可以提高校正速度,但無法校正出Ingress條目之間衝突的情況。

Snippet問題說明

若在多個Ingress下配置了針對同一個網域名稱的多個snippet,會出現類型報錯,會導致配置不符合預期。

W0619 14:58:49.323721       7 controller.go:1314] Server snippet already configured for server "test.example.com", skipping (Ingress "default/test.example.com")
W0619 14:58:49.323727       7 controller.go:1314] Server snippet already configured for server "test.example.com", skipping (Ingress "default/test.example.com")
W0619 14:58:49.323734       7 controller.go:1314] Server snippet already configured for server "test.example.com", skipping (Ingress "default/test.example.com")

通過Secret配置的認證為什麼沒生效?

您可執行kubectl -n kube-system logs <nginx-ingress-controller-pod-name> | grep "Error getting SSL certificate"確認Nginx Ingress Controller Pod日誌。若日誌出現下列內容,請根據下方的步驟排查問題,其中xxxx對應為您的Secret名稱。

Error getting SSL certificate "xxxx": local SSL certificate xxxx tls was not found. Using default certificate

這個日誌資訊出現有三種原因:

  1. 這個xxxx對應的Secret不存在。

  2. Secret配置的tls.crttls.key,即認證的公開金鑰和私密金鑰不匹配。當tls.crttls.key不匹配時,若通過命令kubectl create secret tls方式建立tls類型的Secret會提示錯誤資訊,例如:

    root@Aliyun ~/ssl # kubectl create secret tls tls-test-ingress --key example.com.key --cert httpbin.example.com.crt
    error: tls: private key does not match public key

    對於已經建立的Secret,您可通過執行下方命令確認Secret是否有此問題:

    export SECRET_NAME=<Your Secret Name>
    export NAME_SPACE=<Your Secret Namespace>
    diff <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.key}' | base64 -d | openssl rsa -noout -modulus | openssl md5) && echo "Certificate and Key match" || echo "Certificate and Key do not match"

    如果Secret有此不匹配問題,則會輸出類似於下方的內容:

    root@Aliyun ~/ssl # export SECRET_NAME=test
    root@Aliyun ~/ssl # export NAME_SPACE=default
    root@Aliyun ~/ssl # diff <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.key}' | base64 -d | openssl rsa -noout -modulus | openssl md5) && echo "Certificate and Key match" || echo "Certificate and Key do not match"
    1c1
    < (stdin)= 66a309089e87e32d1b6fe361ebf8cd88
    ---
    > (stdin)= 12e15c5fe35585b6fd9920abc8e8706d
    Certificate and Key do not match
  3. 對同一個網域名稱在多個Ingress下配置了多個TLS,但其中一個配置有誤。請您檢查TLS配置並修複。

認證到期,然後我更新了認證,為什麼還是收到認證到期的警示資訊?

低版本Nginx Ingress Controller存在相關bug,更新認證後,metrics nginx_ingress_controller_ssl_expire_time_seconds指標可能會存在殘留,需要變換Nginx Ingress Controller。建議更新群組件版本到v1.11.4+ 版本,高版本不存在此問題。關於升級組件的操作步驟,請參見升級Nginx Ingress Controller組件

如何查看Nginx Ingress Controller不同版本下的預設配置?

Nginx Ingress Controller已經迭代發布了多個版本,同一個參數在不同的版本可能有不同的預設配置,例如use-gzip在低版本v0.35.0及之前的版本中預設開啟,而在v1.11.4版本中預設不開啟。

您可通過查看對應版本分支下configmap.md文檔確認參數的在特定版本中的行為,例如controller-v1.8.0,您可在左側切換版本。

image.png