本文介紹關於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)來產生新的路由轉寄規則。
診斷流程

按照以下步驟,檢查是否是由於Ingress所導致的問題,確保Ingress Controller的配置正確。
在Controller Pod中確認訪問是否符合預期。具體操作,請參見在Controller Pod中手動訪問Ingress和後端Pod。
確認Nginx Ingress Controller使用方法正確。具體操作,請參見Nginx Ingress社區使用文檔。
使用Ingress診斷功能檢查Ingress和組件配置,並且根據相關提示進行修改。關於Ingress診斷功能具體操作,請參見使用Ingress診斷功能。
按照排查思路,確認相關問題及解決方案。
如果以上排查無果,請按照以下步驟排查:
針對HTTPS認證問題:
檢查網域名稱上是否啟用了WAF接入或WAF透明接入。
如果啟用了,請確認WAF或透明WAF沒有設定TLS認證。
如果沒啟用,請執行下一步。
檢查SLB是否為七層監聽。
如果是,請確認SLB七層監聽上沒有設定TLS認證。
如果不是,請執行下一步。
非HTTPS認證問題,檢查Controller Pod中錯誤記錄檔。具體操作,請參見檢查Controller Pod中錯誤記錄檔。
如果以上排查無果,請在Controller Pod和對應後端的業務Pod中進行抓包,確認問題。具體操作,請參見抓包。
排查思路
排查思路 | 問題現象 | 解決方案 |
訪問不通 | 叢集內部Pod到Ingress訪問不通 | |
Ingress訪問自己不通 | ||
無法訪問TCP、UDP服務 | ||
HTTPS訪問出現問題 | 認證未更新或返回預設認證 | |
返回 | ||
添加Ingress資源時出現問題 | 報錯failed calling webhook... | |
添加了Ingress,但是沒有生效 | ||
訪問不符合預期 | 無法獲得用戶端源IP | |
IP白名單不生效或不按預期生效 | ||
無法串連到通過Ingress暴露的gRPC服務 | ||
灰階不生效 | ||
灰階規則錯誤或影響到別的流量 | ||
出現 | ||
出現502、503、413、499等錯誤 | ||
載入頁面時部分資源載入不出來 | 配置了 | |
資源訪問時出現 |
常見檢查方法
使用Ingress診斷功能
登入Container Service管理主控台,在左側導覽列選擇叢集列表。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
在故障診斷頁面,單擊Ingress診斷。
在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叢集容器日誌。

Log Service控制台的日誌和實際日誌欄位名稱會有部分不同,已在下表列出,欄位解釋如下表所示。
欄位 | 說明 |
| 用戶端的真實IP。 |
| 請求的資訊。包括請求的方法、URL以及HTTP版本。 |
| 本次請求的時間。從接收用戶端請求起,到發送完響應資料的總時間。該值可能會受到用戶端網路條件等因素的影響,無法代表請求真實的處理速度。 |
| 後端upstream的地址,如果該請求沒有到後端,則該值為空白。當後端因為失敗請求多個upstream時,該值為半形逗號(,)分隔列表。 |
| 後端upstream返回的 HTTP code。如果該值為正常 HTTP status code,代表該值由後端upstream返回。當沒有後端可以訪問時,該值為502。有多個值時由半形逗號(,)分開。 |
| 後端upstream的回應時間,單位為秒。 |
| 後端upstream的名稱。命名規則為 |
| 後端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
執行以下命令,進入Controller Pod。
kubectl exec <controller pod name> -n <namespace> -it -- bashPod中已預裝好了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。
執行以下命令,通過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。
執行以下命令,在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-nginxdbg命令
除了Kubectl-plugin外掛程式方式外,也可以使用
dbg命令來進行相關資訊的查看和診斷。執行以下命令,進入Nginx Ingress容器。
kubectl exec -itn kube-system <nginx-ingress-pod-name> bash執行
/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的請求和串連統計資料。
執行以下命令,進入Nginx Ingress容器。
kubectl exec -itn kube-system <nginx-ingress-pod-name> bash執行以下命令,查看當前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個。
抓包
當無法定位問題時,需要抓包進行輔助診斷。
根據初步問題定位結果,簡單判斷網路問題出現在Ingress Pod還是業務Pod。如果資訊不足,可以對兩方的包都進行抓取。
登入出現異常的業務Pod或Ingress Pod所在節點。
在ECS(非容器內)執行以下命令,可以將Ingress流量資訊抓取到檔案中。
tcpdump -i any host <業務Pod IP或Ingress Pod IP> -C 20 -W 200 -w /tmp/ingress.pcap觀察日誌,當出現預期錯誤時,結束抓包。
結合業務日誌的報錯,定位到精準的報錯時間的報文資訊。
說明在正常情況下,抓包對業務無影響,僅會增加小部分的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使修改生效。執行以下命令,編輯Flannel。
kubectl edit cm kube-flannel-cfg -n kube-system在返回結果cni-conf.json中的
delegate增加"hairpinMode": true。樣本如下:
cni-conf.json: | { "name": "cb0", "cniVersion":"0.3.1", "type": "flannel", "delegate": { "isDefaultGateway": true, "hairpinMode": true } }執行以下命令,刪除重建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透明接入服務。
解決方案
對於設定
externalTrafficPolicy為Cluster,且前端使用了四層SLB的情況。可以將
externalTrafficPolicy改為Local。但這可能會導致叢集內部使用SLB IP訪問Ingress不通,具體解決方案,請參見叢集內訪問叢集LoadBalancer外部地址不通。對於使用了七層代理(七層SLB、WAF、透明WAF)的情況,可以按以下步驟解決:
確保使用的七層代理且開啟了X-Forwarded-For要求標頭。
在Ingress Controller的ConfigMap中(預設為kube-system命名空間下的nginx-configuration)添加
enable-real-ip: "true"。觀察日誌,驗證是否可以擷取到源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欄位中填寫您的業務網域名稱,不可為空。
解決方案
根據上述原因,修改
nginx.ingress.kubernetes.io/canary: "true"或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資源時,需要通過服務(預設為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_LONG或routines: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_STREAM或net::ERR_FAILED報錯。
問題原因
資源並行請求數較多,達到HTTP/2最大流數限制。
解決方案
(推薦)在ConfigMap中根據實際需要,調整
http2-max-concurrent-streams至更大值(預設128)。具體操作,請參見http2-max-concurrent-streams。在ConfigMap中直接關閉HTTP2支援,設定
use-http2為false。具體操作,請參見use-http2。
出現報錯“The param of ServerGroupName is illegal”
問題原因
ServerGroupName的產生格式是namespace+svcName+port。伺服器組名稱的長度為2~128個字元,必須以大小寫字母或中文開頭,可包含數字、半形句號(.)、底線(_)和短劃線(-)。
解決方案
按照伺服器組名稱的格式要求修改。
建立Ingress時報錯“certificate signed by unknown authority”

問題原因
建立Ingress時,出現上圖報錯,原因是部署了多套Ingress,而各Ingress之間使用了相同的資源 (可能包括Secret、服務、Webhook配置等),導致Webhook執行時與後端服務通訊時使用的SSL認證不一致,從而出現錯誤。
解決方案
重新部署兩套Ingress,兩套Ingress包含的資源不能重複。關於Ingress中包含的資源資訊,請參見在ACK組件管理中升級Nginx Ingress Controller組件時,系統會有哪些更新?。
Ingress Pod健全狀態檢查失敗導致重啟
問題現象
Controller Pod出現健全狀態檢查失敗導致Pod重啟。
問題原因
Ingress Pod或所在節點負載較高,導致健全狀態檢查失敗。
叢集節點上設定了
tcp_tw_reuse或tcp_tw_timestamps核心參數,可能會導致健全狀態檢查失敗。
解決方案
對Ingress Pod進行擴容,觀察是否還有該現象。具體操作,請參見Nginx Ingress Controller的高可靠部署方式。
關閉
tcp_tw_reuse或設定為2,且同時關閉tcp_tw_timestamps,觀察是否還有該現象。
添加TCP、UDP服務
在對應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連接埠。在Ingress Deployment中(預設為kube-system命名空間下的nginx-ingress-controller)添加所映射的連接埠。
在Ingress對應的Service中添加所映射的連接埠。
關於添加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 configmap和k8s-nginx-ingress配置。
更新
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], 然後儲存退出。更新
k8s-nginx-ingress配置。將以下內容儲存為
k8s-nginx-ingress.yaml檔案,然後執行kubectl apply -f k8s-nginx-ingress.yaml命令進行部署。
出現報錯“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以及ClusterRoleBindingingress-nginx存在。若不存在,可以考慮自行建立、恢複、卸載組件重裝。確保ClusterRole
ingress-nginx中包含日誌中所對應的許可權(圖例中為networking.k8s.io/ingresses的List許可權)。若許可權不存在,可以手動添加至ClusterRole中。
對於Role:
確認Role
kube-system/ingress-nginx以及RoleBindingkube-system/ingress-nginx存在。若不存在,可以考慮自行建立、恢複、卸載組件重裝。確認Role
ingress-nginx中包含日誌中所對應許可權(圖例中為ConfigMapingress-controller-leader-nginx的Update許可權)。若許可權不存在,可以手動添加至Role中。
出現報錯“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行。

執行如下命令,查看對應行附近的配置是否有錯誤。
# 進入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"
問題原因
認證配置錯誤,常見的原因有認證所包含網域名稱與Ingress中佈建網域名不一致。部分Warning等級日誌不會影響到認證的正常使用(如認證中未攜帶SAN擴充等),請根據實際情況判斷是否出現問題。
解決方案
根據錯誤內容檢查叢集中認證問題。
認證的cert和key格式及內容是否正確。
認證所包含網域名稱與Ingress中所佈建網域名是否一致。
認證有無到期。
關於Controller存在大量未被清理的設定檔問題
問題現象
在舊版本(低於1.10)的Nginx Ingress Controller中,有一個已知的BUG。正常情況下,產生的nginx-cfg檔案應該被及時清理。然而,當Ingress配置存在錯誤並導致最終渲染的nginx.conf配置出錯時,這些錯誤設定檔未能如期清理,導致nginx-cfgxxx檔案逐漸累積,佔用大量磁碟空間。

問題原因
問題的原因是清理邏輯存在缺陷。雖然正確產生的設定檔會被正確清理,但對於產生無效設定檔的情況,清理機制無法正常工作,導致這些檔案始終保留在系統中。詳細資料請參見社區的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被調度到同一節點。這種方法可能會降低組件的高可用性。
Flannel CNI+IPVS叢集高並發下Nginx Ingress多CLB導致TCP串流問題
問題現象
在採用Flannel CNI和IPVS網路模式的ACK叢集中,如果Nginx Ingress Controller綁定了多個負載平衡(CLB),可能會在高並發情況下導致TCP串流問題。通過抓包可觀察到以下異常。
報文重傳
異常的TCP串連重設(reset)

問題原因
在使用Flannel網路外掛程式配置的ACK叢集中,CLB會將流量轉寄到Nginx Ingress Controller所在節點的NodePort連接埠。然而,當多個Service使用不同的NodePort時,高並發情況下可能會導致IPVS會話出現衝突問題。
解決方案
單一負載平衡器策略:僅建立一個Nginx Ingress Controller的LoadBalancer Service。其他CLB通過手動設定的方式綁定到節點的NodePort,以減少衝突的可能性。
避免多個NodePort同時生效:在同一節點上,盡量避免讓多個NodePort同時生效,以減少IPVS會話的衝突風險。