全部產品
Search
文件中心

Container Service for Kubernetes:Nginx Ingress異常問題排查

更新時間:Sep 11, 2025

本文介紹關於Nginx Ingress異常問題的診斷流程、排查思路、常見檢查方法和解決方案。

本文目錄

類別

內容

診斷流程

診斷流程

排查思路

排查思路

常見排查方法

常見問題及解決方案

背景資訊

當前Kubernetes官方維護的是Nginx Ingress Controller,ACK基於社區版的Nginx Ingress Controller進行了最佳化。ACK的Nginx Ingress Controller與社區版完全相容,支援社區所有的Annotation。

為了使Nginx Ingress資源正常工作,叢集中必須要有一個Nginx Ingress Controller來解析Nginx Ingress的轉寄規則。Nginx Ingress Controller收到請求,匹配Nginx Ingress轉寄規則,將請求轉寄到後端Service所對應的Pod,由Pod處理請求。Kubernetes中的Service、Nginx Ingress與Nginx Ingress Controller有著以下關係:

  • Service是後端真實服務的抽象,一個Service可以代表多個相同的後端服務。

  • Nginx Ingress是反向 Proxy規則,用來規定HTTP/HTTPS請求應該被轉寄到哪個Service所對應的Pod上。例如根據請求中不同的Host和URL路徑,讓請求落到不同的Service所對應的Pod上。

  • Nginx Ingress Controller是Kubernetes叢集中的一個組件,負責解析Nginx Ingress的反向 Proxy規則。如果Nginx Ingress有增刪改的變動,Nginx Ingress Controller會及時更新自己相應的轉寄規則,當Nginx Ingress Controller收到請求後就會根據這些規則將請求轉寄到對應Service的Pod上。

Nginx Ingress Controller通過API Server擷取Ingress資源的變化,動態地產生負載平衡(例如Nginx)所需的設定檔(例如nginx.conf),然後重新載入負載平衡(例如執行nginx -s reload重新載入Nginx)來產生新的路由轉寄規則。S2

診斷流程

診斷流程Ingress.png

  1. 按照以下步驟,檢查是否是由於Ingress所導致的問題,確保Ingress Controller的配置正確。

    1. 在Controller Pod中確認訪問是否符合預期。具體操作,請參見在Controller Pod中手動訪問Ingress和後端Pod

    2. 確認Nginx Ingress Controller使用方法正確。具體操作,請參見Nginx Ingress社區使用文檔

  2. 使用Ingress診斷功能檢查Ingress和組件配置,並且根據相關提示進行修改。關於Ingress診斷功能具體操作,請參見使用Ingress診斷功能

  3. 按照排查思路,確認相關問題及解決方案。

  4. 如果以上排查無果,請按照以下步驟排查:

    • 針對HTTPS認證問題:

      1. 檢查網域名稱上是否啟用了WAF接入或WAF透明接入。

        • 如果啟用了,請確認WAF或透明WAF沒有設定TLS認證。

        • 如果沒啟用,請執行下一步。

      2. 檢查SLB是否為七層監聽。

        • 如果是,請確認SLB七層監聽上沒有設定TLS認證。

        • 如果不是,請執行下一步。

    • 非HTTPS認證問題,檢查Controller Pod中錯誤記錄檔。具體操作,請參見檢查Controller Pod中錯誤記錄檔

  5. 如果以上排查無果,請在Controller Pod和對應後端的業務Pod中進行抓包,確認問題。具體操作,請參見抓包

排查思路

排查思路

問題現象

解決方案

訪問不通

叢集內部Pod到Ingress訪問不通

叢集內訪問叢集LoadBalancer外部地址不通

Ingress訪問自己不通

無法訪問Ingress Controller自己

無法訪問TCP、UDP服務

添加TCP、UDP服務

HTTPS訪問出現問題

認證未更新或返回預設認證

叢集中添加或修改了TLS認證,但是訪問時還是預設認證或舊的認證

返回RX_RECORD_TOO_LONG/wrong version number

HTTPS訪問報SSL_ERROR_RX_RECORD_TOO_LONG錯誤

添加Ingress資源時出現問題

報錯failed calling webhook...

建立Ingress資源時報錯 "failed calling webhook"

添加了Ingress,但是沒有生效

Ingress規則沒有生效

訪問不符合預期

無法獲得用戶端源IP

Ingress Pod中無法保留源IP

IP白名單不生效或不按預期生效

無法串連到通過Ingress暴露的gRPC服務

無法串連到通過Ingress暴露的gRPC服務

灰階不生效

灰階規則不生效

灰階規則錯誤或影響到別的流量

流量分發與灰階規則不一致或其他流量進入灰階服務

出現The plain HTTP request was sent to HTTPS port

無法串連到後端HTTPS服務

出現502、503、413、499等錯誤

出現常見HTTP錯誤碼

載入頁面時部分資源載入不出來

配置了rewrite-target,資源訪問時出現404

重寫到根目錄後部分資源無法載入或白屏

資源訪問時出現net::ERR_FAILEDnet::ERR_HTTP2_SERVER_REFUSED_STREAM

出現net::ERR_HTTP2_SERVER_REFUSED_STREAM錯誤

常見檢查方法

使用Ingress診斷功能

  1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇巡檢和診斷 > 故障診斷

  3. 故障診斷頁面,單擊Ingress診斷

  4. Ingress診斷面板,輸入出現問題的URL,例如https://www.example.com。選中我已知曉並同意,然後單擊發起診斷

    診斷完成後,根據診斷結果解決問題。

通過Log ServiceSLS的Controller Pod查看訪問日誌

Ingress Controller訪問日誌格式可以在ConfigMap中看到(預設ConfigMap為kube-system命名空間下的nginx-configuration)。

ACK Ingress Controller預設的日誌格式為:

$remote_addr - [$remote_addr] - $remote_user [$time_local]
    "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length
    $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length
    $upstream_response_time $upstream_status $req_id $host [$proxy_alternative_upstream_name]
重要

改動日誌格式後,SLS的日誌收集規則也需要做相應改動,否則無法在SLS日誌控制台看到正確日誌資訊,請您謹慎修改日誌格式。

Log Service控制台的Ingress Controller日誌如下圖所示。具體操作,請參見採集ACK叢集容器日誌

SLS日誌.png

Log Service控制台的日誌和實際日誌欄位名稱會有部分不同,已在下表列出,欄位解釋如下表所示。

欄位

說明

remote_addr/client_ip

用戶端的真實IP。

request/(method+url+version)

請求的資訊。包括請求的方法、URL以及HTTP版本。

request_time

本次請求的時間。從接收用戶端請求起,到發送完響應資料的總時間。該值可能會受到用戶端網路條件等因素的影響,無法代表請求真實的處理速度。

upstream_addr

後端upstream的地址,如果該請求沒有到後端,則該值為空白。當後端因為失敗請求多個upstream時,該值為半形逗號(,)分隔列表。

upstream_status

後端upstream返回的 HTTP code。如果該值為正常 HTTP status code,代表該值由後端upstream返回。當沒有後端可以訪問時,該值為502。有多個值時由半形逗號(,)分開。

upstream_response_time

後端upstream的回應時間,單位為秒。

proxy_upstream_name

後端upstream的名稱。命名規則為<命名空間>-<服務名稱>-<連接埠號碼>

proxy_alternative_upstream_name

後端alternative upstream的名稱。當該請求轉寄到alternative upstream(例如使用Canary設定的灰階服務)時,該值不為空白。

預設情況下,執行以下命令,您也可以直接在容器中看到近期的訪問日誌。

kubectl logs <controller pod name> -n <namespace> | less

預期輸出:

42.11.**.** - [42.11.**.**]--[25/Nov/2021:11:40:30 +0800]"GET / HTTP/1.1" 200 615 "_" "curl/7.64.1" 76 0.001 [default-nginx-svc-80] 172.16.254.208:80 615 0.000 200 46b79dkahflhakjhdhfkah**** 47.11.**.**[]
42.11.**.** - [42.11.**.**]--[25/Nov/2021:11:40:31 +0800]"GET / HTTP/1.1" 200 615 "_" "curl/7.64.1" 76 0.001 [default-nginx-svc-80] 172.16.254.208:80 615 0.000 200 fadgrerthflhakjhdhfkah**** 47.11.**.**[]

檢查Controller Pod中錯誤記錄檔

您可以根據Ingress Controller Pod中的日誌,進一步縮小問題範圍。Controller Pod中錯誤記錄檔分為以下兩種:

  • Controller錯誤記錄檔:一般在Ingress配置錯誤時產生,可以執行以下命令過濾出Controller錯誤記錄檔。

    kubectl logs <controller pod name> -n <namespace> | grep -E ^[WE]
    說明

    Ingress Controller在啟動時會產生若干條W(Warning)等級錯誤,屬於正常現象。例如未指定kubeConfig或未指定Ingress Class等Warning資訊,這些Warning資訊不影響Ingress Controller的正常運行,因此可以忽略。

  • Nginx錯誤記錄檔:一般在處理請求出現錯誤時產生,可以執行以下命令過濾出Nginx錯誤記錄檔。

    kubectl logs <controller pod name> -n <namespace> | grep error

在Controller Pod中手動訪問Ingress和後端Pod

  1. 執行以下命令,進入Controller Pod。

    kubectl exec <controller pod name> -n <namespace> -it -- bash
  2. Pod中已預裝好了curl、OpenSSL等工具,您可以通過這些工具測試連通性、認證配置的正確性等。

    • 執行以下命令,測試能否通過Ingress訪問到後端。

      # 請將your.domain.com替換為實際要測試的網域名稱。
      curl -H "Host: your.domain.com" http://127.0.**.**/ # for http
      curl --resolve your.domain.com:443:127.0.0.1 https://127.0.0.1/ # for https
    • 執行以下命令,驗證認證資訊。

      openssl s_client -servername your.domain.com -connect 127.0.0.1:443
    • 訪問後端Pod測試的正確性。

      說明

      Ingress Controller不會通過Service Cluster IP的形式來訪問後端Pod,而是直接存取後端Pod IP。

      1. 執行以下命令,通過kubectl獲得後端Pod IP。

        kubectl get pod -n <namespace> <pod name> -o wide

        預期輸出:

        NAME                      READY    STATUS    RESTARTS   AGE    IP            NODE                        NOMINATED NODE    READINESS GATES
        nginx-dp-7f5fcc7f-****    1/1      Running   0          23h    10.71.0.146   cn-beijing.192.168.**.**    <none>            <none>

        由預期輸出獲得,後端Pod IP為10.71.0.146。

      2. 執行以下命令,在Controller Pod中訪問該Pod,確認Controller Pod到後端Pod能夠正常連通。

        curl http://<your pod ip>:<port>/path

Nginx Ingress排查相關命令

  • kubectl-plugin

    Kubernetes官方Ingress控制器原先基於Nginx,但自0.25.0版本起改用OpenResty。控制器通過監聽API Server上Ingress資源的更改,自動產生相應的Nginx配置,然後Reload重新載入配置以使之生效。更多詳情,請參見官方文檔

    隨著Ingress數量增加,所有配置匯聚於單一的Nginx.conf檔案,造成設定檔過長且難以調試。尤其是從0.14.0版本開始,Upstream部分採用Lua-resty-balancer動態產生,增加了調試難度。因此,社區貢獻了一個Kubectl外掛程式Ingress-nginx,以簡化Ingress-nginx配置的調試過程。相關操作,請參見kubectl-plugin

    執行以下命令,擷取Ingress-nginx控制器當前已知後端的服務資訊。

    kubectl ingress-nginx backends -n ingress-nginx
  • dbg命令

    除了Kubectl-plugin外掛程式方式外,也可以使用dbg命令來進行相關資訊的查看和診斷。

    1. 執行以下命令,進入Nginx Ingress容器。

      kubectl exec -itn kube-system  <nginx-ingress-pod-name>  bash
    2. 執行/dbg命令可看到如下輸出。

      nginx-ingress-controller-69f46d8b7-qmt25:/$ /dbg
      
      dbg is a tool for quickly inspecting the state of the nginx instance
      Usage:
        dbg [command]
      Available Commands:
        backends    Inspect the dynamically-loaded backends information
        certs       Inspect dynamic SSL certificates
        completion  Generate the autocompletion script for the specified shell
        conf        Dump the contents of /etc/nginx/nginx.conf
        general     Output the general dynamic lua state
        help        Help about any command
      Flags:
        -h, --help              help for dbg
            --status-port int   Port to use for the lua HTTP endpoint configuration. (default 10246)
      Use "dbg [command] --help" for more information about a command.

    查看某個網域名稱對應的認證是否存在。

    /dbg certs get <hostname>

    查看當前所有後端服務資訊。

    /dbg backends all 

Nginx Ingress狀態

Nginx包含一個自檢模組,可輸出運行統計資訊;在Nginx Ingress容器中,通過Curl訪問10246連接埠的nginx_status,可以查看Nginx的請求和串連統計資料。

  1. 執行以下命令,進入Nginx Ingress容器。

    kubectl exec -itn kube-system  <nginx-ingress-pod-name>  bash
  2. 執行以下命令,查看當前Nginx的請求、串連相關統計狀態資訊。

    nginx-ingress-controller-79c5b4d87f-xxx:/etc/nginx$ curl localhost:10246/nginx_status
    Active connections: 12818 
    server accepts handled requests
     22717127 22717127 823821421 
    Reading: 0 Writing: 382 Waiting: 12483 

    自Nginx啟動以來,它接受並處理了22717127個串連,且每個串連都成功處理,未出現立即關閉的情況。這22717127個串連共處理了823821421個請求,意味著每個串連平均處理約36.2個請求。

    • Active connections:表示當前Nginx伺服器上的活躍串連總數為12818個。

    • Reading:表示Nginx當前正在讀取要求標頭的串連數是0。

    • Writing:表示Nginx當前正在發送響應的串連數是382。

    • Waiting:表示保持長串連(keep-alive)的串連數12483個。

抓包

當無法定位問題時,需要抓包進行輔助診斷。

  1. 根據初步問題定位結果,簡單判斷網路問題出現在Ingress Pod還是業務Pod。如果資訊不足,可以對兩方的包都進行抓取。

  2. 登入出現異常的業務Pod或Ingress Pod所在節點。

  3. 在ECS(非容器內)執行以下命令,可以將Ingress流量資訊抓取到檔案中。

    tcpdump -i any host <業務Pod IP或Ingress Pod IP> -C 20 -W 200 -w /tmp/ingress.pcap
  4. 觀察日誌,當出現預期錯誤時,結束抓包。

  5. 結合業務日誌的報錯,定位到精準的報錯時間的報文資訊。

    說明
    • 在正常情況下,抓包對業務無影響,僅會增加小部分的CPU負載和磁碟寫入。

    • 以上命令會對抓取到的包進行rotate,最多可以寫200個20 MB的.pcap檔案。

叢集內訪問叢集LoadBalancer外部地址不通

問題現象

叢集中有部分節點下的Pod通過Nginx Ingress Controller外部地址(Server Load Balancer執行個體IP地址)無法訪問後端Pod,有部分能夠訪問。

問題原因

該問題由而Controller所屬Service的externalTrafficPolicy配置導致,該配置決定了外部流量的處理規則:當設定為local時,僅有與Controller所屬Pod處於同一節點的後端Pod可以成功接收請求;當設定為cluster時,則可以正常訪問。而叢集中的資源使用LoadBalancer的外部地址訪問時,請求也會被作為外部流量處理。

解決方案

  • (推薦)在Kubernetes叢集內通過ClusterIP或者Ingress的服務名訪問。其中Ingress的服務名為nginx-ingress-lb.kube-system

  • 執行kubectl edit svc nginx-ingress-lb -n kube-system命令,修改Ingress的服務。將LoadBalancer的Service中externalTrafficPolicy修改為Cluster。如果叢集容器網路外掛程式為Flannel,請求會丟失用戶端源IP,如果使用Terway則可保留源IP。

  • 樣本如下:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        service.beta.kubernetes.io/backend-type: eni   # 直通ENI。
      labels:
        app: nginx-ingress-lb
      name: nginx-ingress-lb
      namespace: kube-system
    spec:
      externalTrafficPolicy: Cluster

    關於Service的Annotation的更多資訊,請參見通過Annotation配置傳統型負載平衡CLB

無法訪問Ingress Controller自己

問題現象

對於Flannel叢集,在Ingress Pod中通過網域名稱、SLB IP、Cluster IP訪問Ingress自身時,出現部分請求或全部請求不成功的情況。

問題原因

Flannel目前的預設配置不允許迴環訪問。

解決方案

  • (推薦)如果條件允許,建議您重建叢集,並使用Terway的網路外掛程式,將現有叢集業務遷移至Terway模式叢集中。

  • 如果沒有重建叢集的條件,可以通過修改Flannel配置,開啟hairpinMode解決。配置修改完成後,重建Flannel Pod使修改生效。

    1. 執行以下命令,編輯Flannel。

      kubectl edit cm kube-flannel-cfg -n kube-system
    2. 在返回結果cni-conf.json中的delegate增加 "hairpinMode": true

      樣本如下:

      cni-conf.json: |
          {
            "name": "cb0",
            "cniVersion":"0.3.1",
            "type": "flannel",
            "delegate": {
              "isDefaultGateway": true,
              "hairpinMode": true
            }
          }
    3. 執行以下命令,刪除重建Flannel。

      kubectl delete pod -n kube-system -l app=flannel   

叢集中添加或修改了TLS認證,但是訪問時還是預設認證或舊的認證

問題現象

您已經在叢集中添加或修改Secret並在Ingress中指定secretName後,訪問叢集仍使用了預設的認證(Kubernetes Ingress Controller Fake Certificate)或舊的認證。

問題原因

  • 認證不是由叢集內Ingress Controller返回的。

  • 認證無效,未能被Controller正確載入。

  • Ingress Controller根據SNI來返回對應認證,但TLS握手時可能未攜帶SNI。

解決方案

  • 通過以下任一方式,確認建立TLS串連時是否攜帶了SNI欄位:

    • 使用支援SNI的較新版本瀏覽器。

    • 使用openssl s_client命令測試認證時,攜帶-servername參數。

    • 使用curl命令時,添加hosts或使用--resolve參數映射網域名稱,而不是使用IP+Host要求標頭的方式。

  • 確認WAF、WAF透明接入或SLB七層監聽上沒有設定TLS認證,TLS認證應該由叢集內Ingress Controller返回的。

  • 在智能營運控制台進行Ingress診斷,觀察是否存在配置錯誤和錯誤記錄檔。具體操作,請參見使用Ingress診斷功能

  • 執行以下命令,手動查看Ingress Pod錯誤記錄檔,根據錯誤記錄檔中相關提示進行修改。

    kubectl logs <ingress pod name> -n <pod namespace> | grep -E ^[EW]

無法串連到通過Ingress暴露的gRPC服務

問題現象

通過Ingress無法訪問到其後的gRPC服務。

問題原因

  • 未在Ingress資源中設定Annotation,指定後端協議類型。

  • gRPC服務只能通過TLS連接埠進行訪問。

解決方案

  • 在對應Ingress資源中設定Annotation:nginx.ingress.kubernetes.io/backend-protocol:"GRPC"

  • 確認用戶端發送請求時使用的是TLS連接埠,並且將流量加密。

無法串連到後端HTTPS服務

問題現象

  • 通過Ingress無法訪問到其後的HTTPS服務。

  • 訪問時回複可能為400,並提示The plain HTTP request was sent to HTTPS port

問題原因

Ingress Controller到後端Pod請求使用了預設的HTTP請求。

解決方案

在Ingress資源中設定Annotation:nginx.ingress.kubernetes.io/backend-protocol:"HTTPS"

Ingress Pod中無法保留源IP

問題現象

Ingress Pod中無法保留真實用戶端IP,顯示為節點IP或100.XX.XX.XX網段或其他地址。

問題原因

  • Ingress所使用的Service中externalTrafficPolicy設為了Cluster

  • SLB上使用了七層代理。

  • 使用了WAF接入或WAF透明接入服務。

解決方案

  • 對於設定externalTrafficPolicyCluster,且前端使用了四層SLB的情況。

    可以將externalTrafficPolicy改為Local。但這可能會導致叢集內部使用SLB IP訪問Ingress不通,具體解決方案,請參見叢集內訪問叢集LoadBalancer外部地址不通

  • 對於使用了七層代理(七層SLB、WAF、透明WAF)的情況,可以按以下步驟解決:

    1. 確保使用的七層代理且開啟了X-Forwarded-For要求標頭。

    2. 在Ingress Controller的ConfigMap中(預設為kube-system命名空間下的nginx-configuration)添加enable-real-ip: "true"

    3. 觀察日誌,驗證是否可以擷取到源IP。

  • 對於鏈路較長,存在多次轉寄的情況(例如在Ingress Controller前額外配置了反向 Proxy服務),可以在開啟enable-real-ip時通過觀察日誌中remote_addr的值,來確定真實IP是否是以X-Forwarded-For要求標頭傳遞到Ingress容器中。若不是,請在請求到達Ingress Controller之前利用X-Forwarded-For等方式攜帶用戶端真實IP。

灰階規則不生效

問題現象

在叢集內設定了灰階,但是灰階規則不生效。

問題原因

可能原因有兩種:

  • 在使用canary-*相關Annotation時,未設定nginx.ingress.kubernetes.io/canary: "true"

  • 在使用canary-*相關Annotation時,0.47.0版本前的Nginx Ingress Controller,需要在Ingress規則裡的Host欄位中填寫您的業務網域名稱,不可為空。

解決方案

流量分發與灰階規則不一致或其他流量進入灰階服務

問題現象

設定了灰階規則,但是流量沒有按照灰階規則進行分發,或者有其他正常Ingress的流量進入灰階服務。

問題原因

Nginx Ingress Controller中,灰階規則不是應用在單個Ingress上,而是會應用在所有使用同一個Service的Ingress上。

關於產生該問題的詳情,請參見帶有灰階規則的Ingress將影響所有具有相同Service的Ingress

解決方案

針對需要開啟灰階的Ingress(包括使用service-match和canary-*相關Annotation),建立獨立的Service(包括正式和灰階兩個Service)指向原有的Pod,然後再針對該Ingress啟用灰階。更多詳情,請參見通過Nginx Ingress實現灰階發布和藍綠髮布

建立Ingress資源時報錯 "failed calling webhook"

問題現象

添加Ingress資源時顯示"Internal error occurred: failed calling webhook...",如下圖所示。

Ingress FAQ.png

問題原因

在添加Ingress資源時,需要通過服務(預設為ingress-nginx-controller-admission)驗證Ingress資源的合法性。如果鏈路出現問題,(例如服務被刪除,Ingress controller被刪除),會導致驗證失敗,拒絕添加Ingress資源。

解決方案

  • 按照Webhook鏈路檢查資源是否均存在且正常工作,鏈路為ValidatingWebhookConfiguration->Service->Pod。

  • 確認Ingress Controller Pod的admission功能已開啟,且能夠正常從外部存取到該Pod。

  • 如果Ingress Controller已被刪除或不需要Webhook功能,可以直接將ValidatingWebhookConfiguration資源刪除。

HTTPS訪問報SSL_ERROR_RX_RECORD_TOO_LONG錯誤

問題現象

訪問HTTPS時報錯SSL_ERROR_RX_RECORD_TOO_LONGroutines:CONNECT_CR_SRVR_HELLO:wrong version number

問題原因

HTTPS請求訪問到了非HTTPS連接埠,例如HTTP連接埠。

常見的原因如下:

  • SLB的443連接埠綁定了Ingress Pod的80連接埠。

  • Ingress Controller所對應服務的Service 443連接埠映射到了Ingress Pod的80連接埠。

解決方案

根據實際情況修改SLB設定或Service設定,使得HTTPS能夠訪問到正確的連接埠。

出現常見HTTP錯誤碼

問題現象

請求出現非2xx、非3xx錯誤,例如502、503、413、499等錯誤。

問題原因及解決方案

查看日誌,判斷是否為Ingress Controller返回的錯誤。具體方法,請參見通過Log ServiceSLS的Controller Pod查看訪問日誌。若是,請參考以下解決方案:

  • 413錯誤

    • 問題原因:Nginx Ingress Controller正常工作,但該請求的資料大小超過了最大限制

    • 解決方案:通過kubectl edit cm -n kube-system nginx-configuration修改Controller配置,按需求調整nginx.ingress.kubernetes.io/client-max-body-size nginx.ingress.kubernetes.io/proxy-body-size 值(預設值20m

  • 499錯誤

    • 問題原因:用戶端由於某些原因提前斷開了串連,不一定是組件或者後端業務問題。

    • 解決方案:

      • 有少量499錯誤時,取決於業務,可能為正常現象,可以忽略。

      • 有大量499錯誤時,請檢查後端業務處理時間和前端請求逾時時間是否符合預期。

  • 502錯誤

    • 問題原因:Nginx Ingress正常工作,但其所屬的Pod無法串連到目標後端Pod。

    • 解決方案:

      • 必現情況:

        • 可能由於後端Service及Pod內配置錯誤導致。請檢查後端Service的連接埠配置以及容器內業務代碼。

      • 偶發情況

        • 可能由於Nginx Ingress Controller所屬Pod負載過高導致。您可通過Controller所屬Server Load Balancer執行個體的請求數與串連數評估負載,並參見【部署高負載情境的Nginx Ingress Controller】為Controller提供更多資源。

        • 可能由於後端Pod主動關閉會話導致。Nginx Ingress Controller預設開啟長串連,請確認後端長串連的串連空閑逾時時間大於Controller的串連空閑逾時時間(預設900秒)。

      • 以上方法都無法確定問題的情況下,請進行抓包分析。

  • 503錯誤

    • 問題原因:Ingress Controller沒有找到後端Pod,或所有Pod均無法訪問。

    • 解決方案:

      • 偶發情況

        • 查看502錯誤解決方案。

        • 檢查後端業務就緒狀態,配置合理健全狀態檢查。

      • 必現情況

        檢查後端Service配置是否正確,是否存在Endpoint。

出現net::ERR_HTTP2_SERVER_REFUSED_STREAM錯誤

問題現象

訪問網頁時,部分資源無法正確載入,控制台中有net::ERR_HTTP2_SERVER_REFUSED_STREAMnet::ERR_FAILED報錯。

問題原因

資源並行請求數較多,達到HTTP/2最大流數限制。

解決方案

  • (推薦)在ConfigMap中根據實際需要,調整http2-max-concurrent-streams至更大值(預設128)。具體操作,請參見http2-max-concurrent-streams

  • 在ConfigMap中直接關閉HTTP2支援,設定use-http2false。具體操作,請參見use-http2

出現報錯“The param of ServerGroupName is illegal”

問題原因

ServerGroupName的產生格式是namespace+svcName+port。伺服器組名稱的長度為2~128個字元,必須以大小寫字母或中文開頭,可包含數字、半形句號(.)、底線(_)和短劃線(-)。

解決方案

按照伺服器組名稱的格式要求修改。

建立Ingress時報錯“certificate signed by unknown authority”

Ingress

問題原因

建立Ingress時,出現上圖報錯,原因是部署了多套Ingress,而各Ingress之間使用了相同的資源 (可能包括Secret、服務、Webhook配置等),導致Webhook執行時與後端服務通訊時使用的SSL認證不一致,從而出現錯誤。

解決方案

重新部署兩套Ingress,兩套Ingress包含的資源不能重複。關於Ingress中包含的資源資訊,請參見在ACK組件管理中升級Nginx Ingress Controller組件時,系統會有哪些更新?

Ingress Pod健全狀態檢查失敗導致重啟

問題現象

Controller Pod出現健全狀態檢查失敗導致Pod重啟。

問題原因

  • Ingress Pod或所在節點負載較高,導致健全狀態檢查失敗。

  • 叢集節點上設定了tcp_tw_reusetcp_tw_timestamps核心參數,可能會導致健全狀態檢查失敗。

解決方案

添加TCP、UDP服務

  1. 在對應ConfigMap中(預設為kube-system命名空間下的tcp-services和udp-services)添加對應條目。

    例如default空間下example-go的8080連接埠映射到9000連接埠,樣本如下。

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: tcp-services
      namespace: ingress-nginx
    data:
      9000: "default/example-go:8080"  # 8080連接埠映射到9000連接埠。
  2. 在Ingress Deployment中(預設為kube-system命名空間下的nginx-ingress-controller)添加所映射的連接埠。

  3. 在Ingress對應的Service中添加所映射的連接埠

    展開查看範例程式碼

    apiVersion: v1
    kind: Service
    metadata:
      name: ingress-nginx
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      type: LoadBalancer
      ports:
        - name: http
          port: 80
          targetPort: 80
          protocol: TCP
        - name: https
          port: 443
          targetPort: 443
          protocol: TCP
        - name: proxied-tcp-9000
          port: 9000
          targetPort: 9000
          protocol: TCP
      selector:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx

    關於添加TCP和UDP服務的更多資訊,請參見暴露TCP和UDP服務

Ingress規則沒有生效

問題現象

添加或修改了Ingress規則,但是沒有生效。

問題原因

  • Ingress配置出現錯誤,導致新的Ingress規則無法被正確載入。

  • Ingress資源配置錯誤,與預期配置不相符。

  • Ingress Controller的許可權出現問題,導致無法正常監視Ingress資源變動。

  • 舊的Ingress使用了server-alias配置了網域名稱,與新的Ingress衝突,導致規則被忽略。

解決方案

  • 使用智能營運控制台的Ingress診斷工具進行診斷,並按照提示進行操作。具體操作,請參見使用Ingress診斷功能

  • 檢查舊的Ingress是否有配置錯誤或配置衝突問題:

    • 針對非rewrite-target,且路徑中使用了Regex的情況,確認Annotation中配置了nginx.ingress.kubernetes.io/use-regex: "true"

    • 檢查PathType是否與預期相符(ImplementationSpecific預設與Prefix作用相同)。

  • 確認與Ingress Controller相關聯的ClusterRole、ClusterRoleBinding、Role、RoleBinding、ServiceAccount都存在。預設名稱均為ingress-nginx。

  • 進入Controller Pod容器,查看nginx.conf檔案中已添加的規則。

  • 執行以下命令,手動查看容器日誌,確定問題。

    kubectl logs <ingress pod name> -n <pod namespace> | grep -E ^[EW]

重寫到根目錄後部分資源無法載入或白屏

問題現象

通過Ingress rewrite-target annotation重寫訪問後,頁面部分資源無法載入,或出現白屏。

問題原因

  • rewrite-target可能沒有使用Regex進行配置。

  • 業務中請求資源路徑寫死在根目錄。

解決方案

  • 檢查rewrite-target是否與Regex以及擷取的群組一起使用。具體操作,請參見Rewrite

  • 檢查前端請求是否訪問到了正確的路徑。

當版本升級後SLS解析日誌不正常怎樣修複

問題現象

ingress-nginx-controller組件當前主要有0.20和0.30兩個版本,當通過控制台的組件管理從0.20升級到0.30版本後 ,在使用Ingress的灰階或藍綠髮布功能時,Ingress Dashboard會出現無法正確展示實際後端服務訪問情況。

問題原因

由於0.20和0.30預設輸出格式不同,在使用Ingress的灰階或藍綠髮布功能時,Ingress Dashboard會出現無法正確展示實際後端服務訪問情況。

解決方案

執行以下操作步驟進行修複,更新nginx-configuration configmapk8s-nginx-ingress配置。

  1. 更新nginx-configuration configmap

    • 如果您沒有修改過nginx-configuration configmap,儲存以下內容為nginx-configuration.yaml,然後執行kubectl apply -f nginx-configuration.yaml命令進行部署。

      apiVersion: v1
      kind: ConfigMap
      data:
        allow-backend-server-header: "true"
        enable-underscores-in-headers: "true"
        generate-request-id: "true"
        ignore-invalid-headers: "true"
        log-format-upstream: $remote_addr - [$remote_addr] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id $host [$proxy_alternative_upstream_name]
        max-worker-connections: "65536"
        proxy-body-size: 20m
        proxy-connect-timeout: "10"
        reuse-port: "true"
        server-tokens: "false"
        ssl-redirect: "false"
        upstream-keepalive-timeout: "900"
        worker-cpu-affinity: auto
      metadata:
        labels:
          app: ingress-nginx
        name: nginx-configuration
        namespace: kube-system
    • 如果您修改過nginx-configuration configmap,為了避免覆蓋您的配置,執行以下命令進行修複:

      kubectl edit configmap nginx-configuration -n kube-system

    log-format-upstream欄位末尾,添加 [$proxy_alternative_upstream_name], 然後儲存退出。

  2. 更新k8s-nginx-ingress配置。

    將以下內容儲存為k8s-nginx-ingress.yaml檔案,然後執行kubectl apply -f k8s-nginx-ingress.yaml命令進行部署。

    展開查看YAML內容

    apiVersion: log.alibabacloud.com/v1alpha1
    kind: AliyunLogConfig
    metadata:
      namespace: kube-system
      # your config name, must be unique in you k8s cluster
      name: k8s-nginx-ingress
    spec:
      # logstore name to upload log
      logstore: nginx-ingress
      # product code, only for k8s nginx ingress
      productCode: k8s-nginx-ingress
      # logtail config detail
      logtailConfig:
        inputType: plugin
        # logtail config name, should be same with [metadata.name]
        configName: k8s-nginx-ingress
        inputDetail:
          plugin:
            inputs:
            - type: service_docker_stdout
              detail:
                IncludeLabel:
                  io.kubernetes.container.name: nginx-ingress-controller
                Stderr: false
                Stdout: true
            processors:
            - type: processor_regex
              detail:
                KeepSource: false
                Keys:
                - client_ip
                - x_forward_for
                - remote_user
                - time
                - method
                - url
                - version
                - status
                - body_bytes_sent
                - http_referer
                - http_user_agent
                - request_length
                - request_time
                - proxy_upstream_name
                - upstream_addr
                - upstream_response_length
                - upstream_response_time
                - upstream_status
                - req_id
                - host
                - proxy_alternative_upstream_name
                NoKeyError: true
                NoMatchError: true
                Regex: ^(\S+)\s-\s\[([^]]+)]\s-\s(\S+)\s\[(\S+)\s\S+\s"(\w+)\s(\S+)\s([^"]+)"\s(\d+)\s(\d+)\s"([^"]*)"\s"([^"]*)"\s(\S+)\s(\S+)+\s\[([^]]*)]\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s*(\S*)\s*\[*([^]]*)\]*.*
                SourceKey: content

出現報錯“cannot list/get/update resource”

問題現象

通過檢查Controller Pod中錯誤記錄檔中所述方法發現Pod記憶體在Controller錯誤記錄檔。類似如下:

User "system:serviceaccount:kube-system:ingress-nginx" cannot list/get/update resource "xxx" in API group "xxx" at the cluster scope/ in the namespace "kube-system"

問題原因

Nginx Ingress Controller缺少對應許可權,無法更新相關資源。

解決方案

  • 根據日誌確認問題是由於ClusterRole還是Role產生的。

    • 日誌中包含at the cluster scope,問題則產生自ClusterRole(ingress-nginx)。

    • 日誌中包含in the namespace "kube-system",問題則產生自Role(kube-system/ingress-nginx)。

  • 確認對應許可權以及許可權綁定是否完整。

    • 對於ClusterRole:

      • 確保ClusterRole ingress-nginx以及ClusterRoleBinding ingress-nginx存在。若不存在,可以考慮自行建立、恢複、卸載組件重裝。

      • 確保ClusterRoleingress-nginx中包含日誌中所對應的許可權(圖例中為networking.k8s.io/ingresses的List許可權)。若許可權不存在,可以手動添加至ClusterRole中。77

    • 對於Role:

      • 確認Role kube-system/ingress-nginx以及RoleBinding kube-system/ingress-nginx存在。若不存在,可以考慮自行建立、恢複、卸載組件重裝。

      • 確認Role ingress-nginx中包含日誌中所對應許可權(圖例中為ConfigMap ingress-controller-leader-nginx的Update許可權)。若許可權不存在,可以手動添加至Role中。78

出現報錯“configuration file failed”

問題現象

通過檢查Controller Pod中錯誤記錄檔中所述方法發現Pod記憶體在Controller錯誤記錄檔。類似如下:

requeuing……nginx: configuration file xxx test failed(多行內容)

問題原因

配置錯誤,導致Nginx配置reload失敗,一般為Ingress規則或ConfigMap中插入的Snippet語法錯誤導致的。

解決方案

  • 查看日誌中錯誤提示(warn等級的提示可忽略),大致定位問題位置。若錯誤提示不夠清晰,可以根據錯誤提示中的檔案行數,進入Pod中查看對應檔案。以下圖為例,檔案為/tmp/nginx/nginx-cfg2825306115的第449行。95

    執行如下命令,查看對應行附近的配置是否有錯誤。

    # 進入Pod執行命令。
    kubectl exec -n <namespace> <controller pod name> -it -- bash
    # 帶行數資訊查看出錯的檔案,在輸出中查看對應行附近的配置有無錯誤。
    cat -n /tmp/nginx/nginx-cfg2825306115
  • 根據錯誤提示和設定檔,根據自身實際配置,定位錯誤原因並修複。

出現報錯“Unexpected error validating SSL certificate”

問題現象

通過檢查Controller Pod中錯誤記錄檔中所述方法發現Pod記憶體在Controller錯誤記錄檔。類似如下:

Unexpected error validating SSL certificate "xxx" for server "xxx"

94

問題原因

認證配置錯誤,常見的原因有認證所包含網域名稱與Ingress中佈建網域名不一致。部分Warning等級日誌不會影響到認證的正常使用(如認證中未攜帶SAN擴充等),請根據實際情況判斷是否出現問題。

解決方案

根據錯誤內容檢查叢集中認證問題。

  • 認證的cert和key格式及內容是否正確。

  • 認證所包含網域名稱與Ingress中所佈建網域名是否一致。

  • 認證有無到期。

關於Controller存在大量未被清理的設定檔問題

問題現象

在舊版本(低於1.10)的Nginx Ingress Controller中,有一個已知的BUG。正常情況下,產生的nginx-cfg檔案應該被及時清理。然而,當Ingress配置存在錯誤並導致最終渲染的nginx.conf配置出錯時,這些錯誤設定檔未能如期清理,導致nginx-cfgxxx檔案逐漸累積,佔用大量磁碟空間。

image

問題原因

問題的原因是清理邏輯存在缺陷。雖然正確產生的設定檔會被正確清理,但對於產生無效設定檔的情況,清理機制無法正常工作,導致這些檔案始終保留在系統中。詳細資料請參見社區的GitHub Issue #11568

解決方案

為解決此問題,可以考慮以下方案。

  • 升級Nginx Ingress Controller:建議將Nginx Ingress Controller 升級到1.10或更高版本。詳情請參見升級Nginx Ingress Controller組件

  • 手動清理舊檔案:定期手動刪除未被清理的nginx-cfgxxx檔案。可以編寫指令碼來自動化此過程,以減少手動操作的負擔。

  • 檢查配置錯誤:在應用新的Ingress配置之前,務必仔細檢查其正確性,以避免產生無效的設定檔。

Controller升級後Pod持續Pending的問題排查

問題現象

在升級Nginx Ingress Controller 時,可能會出現Pod無法成功調度的情況,即Pod長時間處於Pending狀態。

問題原因

在升級Nginx Ingress Controller時,由於預設配置了節點親和性和Pod反親和性規則,可能會導致新版本的Pod無法調度。需要確保叢集中有足夠的可用資源。

您可以使用以下命令來查看具體的原因:

kubectl -n kube-system describe pod <pending-pod-name>
kubectl -n kube-system get events

解決方案

為解決此問題,可以考慮以下方案。

  • 擴容叢集資源:增加新的節點,以滿足親和性規則的要求。詳情請參見手動擴縮容節點池

  • 調整親和性:在資源緊張的情況下,可以通過執行 kubectl edit deploy nginx-ingress-controller -n kube-system命令來放寬反親和性要求,從而允許Pod被調度到同一節點。這種方法可能會降低組件的高可用性。

    展開查看配置樣本

          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:   ## 替換為preferredDuringSchedulingIgnoredDuringExecution。
                - labelSelector:
                    matchExpressions:
                    - key: app
                      operator: In
                      values:
                      - ingress-nginx
                  topologyKey: "kubernetes.io/hostname"
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  # virtual nodes have this label
                  - key: type
                    operator: NotIn
                    values:
                    - virtual-kubelet
              preferredDuringSchedulingIgnoredDuringExecution:
              - preference:
                  matchExpressions:
                  # autoscaled nodes have this label
                  - key: k8s.aliyun.com
                    operator: NotIn
                    values:
                    - "true"
                weight: 100

Flannel CNI+IPVS叢集高並發下Nginx Ingress多CLB導致TCP串流問題

問題現象

在採用Flannel CNI和IPVS網路模式的ACK叢集中,如果Nginx Ingress Controller綁定了多個負載平衡(CLB),可能會在高並發情況下導致TCP串流問題。通過抓包可觀察到以下異常。

  • 報文重傳

  • 異常的TCP串連重設(reset)

image

問題原因

在使用Flannel網路外掛程式配置的ACK叢集中,CLB會將流量轉寄到Nginx Ingress Controller所在節點的NodePort連接埠。然而,當多個Service使用不同的NodePort時,高並發情況下可能會導致IPVS會話出現衝突問題。

解決方案

  • 單一負載平衡器策略:僅建立一個Nginx Ingress Controller的LoadBalancer Service。其他CLB通過手動設定的方式綁定到節點的NodePort,以減少衝突的可能性。

  • 避免多個NodePort同時生效:在同一節點上,盡量避免讓多個NodePort同時生效,以減少IPVS會話的衝突風險。