Google Kubernetes Engine (GKE) 中的 Ingress 問題可能會導致外部或內部流量無法連上您的服務。
請參閱本文,瞭解如何解決與 Ingress 類別、靜態 IP 註解、憑證金鑰大小,以及與網路層級互動相關的錯誤。
平台管理員和營運人員,以及部署及管理應用程式的應用程式開發人員,請詳閱本文資訊。這些應用程式會透過 GKE 中的 Ingress 公開。如要進一步瞭解 Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見 GKE 使用者角色和工作」。
Ingress 類別的註解不正確
症狀
建立 Ingress 時,您可能會看到下列錯誤:
Missing one or more resources. If resource creation takes longer than expected, you might have an invalid configuration.
可能原因
建立 Ingress 時,您可能在資訊清單中錯誤設定 Ingress 類別。
解決方法
如要指定 Ingress 類別,必須使用 kubernetes.io/ingress.class 註解。您無法使用 spec.ingressClassName 指定 GKE Ingress。
- 如要部署內部應用程式負載平衡器,請使用
kubernetes.io/ingress.class: gce-internal註解。 - 如要部署外部應用程式負載平衡器,請使用
kubernetes.io/ingress.class: gce註解。
靜態 IP 位址的註解不正確
症狀
將外部 Ingress 設定為使用靜態 IP 位址時,可能會看到下列錯誤:
Error syncing to GCP: error running load balancer syncing routine: loadbalancer <Name of load balancer> does not exist: the given static IP name <Static IP> doesn't translate to an existing static IP.
可能原因
- 您在部署 Ingress 前,未建立靜態外部 IP 位址。
- 您使用的註解不適用於負載平衡器類型。
解決方法
如果您要設定外部 Ingress:
- 部署 Ingress 前,請預留靜態外部 IP 位址。
- 在 Ingress 資源上使用
kubernetes.io/ingress.global-static-ip-name註解。
如要設定內部 Ingress,請按照下列步驟操作:
- 部署 Ingress 前,請先保留區域靜態內部 IP 位址。
- 在 Ingress 資源上使用
kubernetes.io/ingress.regional-static-ip-name註解。
靜態 IP 位址已在使用中
症狀
如果您指定靜態 IP 位址來佈建內部或外部 Ingress 資源,可能會看到下列錯誤:
Error syncing to GCP: error running load balancer syncing
routine: loadbalancer <LB name> does not exist:
googleapi: Error 409: IP_IN_USE_BY_ANOTHER_RESOURCE - IP ''<IP address>'' is already being used by another resource.
可能原因
其他資源已使用這個靜態 IP 位址。
停用 HTTP 並使用 Google 代管的憑證時發生錯誤
症狀
如果您要設定 Google 管理的 SSL 憑證,並停用 Ingress 上的 HTTP 流量,系統會顯示下列錯誤訊息:
Error syncing to GCP: error running load balancer syncing
routine: loadbalancer <Load Balancer name> does not exist:
googleapi: Error 404: The resource ''projects/<Project>/global/sslPolicies/<Policy name>' was not found, notFound
可能原因
設定 Ingress 時,您無法同時使用下列註解:
networking.gke.io/managed-certificates(將 Google 代管憑證與 Ingress 建立關聯)kubernetes.io/ingress.allow-http: false(停用 HTTP 流量)
解決方法
外部應用程式負載平衡器完成程式設計後,才能停用 HTTP 流量。您可以更新 Ingress,並在資訊清單中新增註解 kubernetes.io/ingress.allow-http: false。
內部 Ingress 缺少 Proxy 專用子網路
症狀
為內部應用程式負載平衡器部署 Ingress 時,您可能會看到下列錯誤訊息:
Error syncing to GCP: error running load balancer syncing routine:
loadbalancer <LB name> does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/<Region>/targetHttpsProxies/<Target proxy>'.
An active proxy-only subnetwork is required in the same region and VPC as
the forwarding rule.
可能原因
您在建立 Ingress 資源之前,並未建立僅限 Proxy 的子網路。內部應用程式負載平衡器必須使用僅限 Proxy 的子網路。
解決方法
部署內部 Ingress 之前,請建立僅限 Proxy 的子網路。
SSL 憑證金鑰過大
症狀
如果負載平衡器的 SSL 憑證金鑰大小過大,您可能會看到下列錯誤訊息:
Error syncing to GCP: error running load balancer syncing routine: loadbalancer gky76k70-load-test-trillian-api-ingress-fliismmb does not exist: Cert creation failures - k8s2-cr-gky76k70-znz6o1pfu3tfrguy-f9be3a4abbe573f7 Error:googleapi: Error 400: The SSL key is too large., sslCertificateKeyTooLarge
可能原因
Google Cloud SSL 憑證金鑰的位元數上限為 2,048 位元。
解決方法
將 SSL 憑證金鑰大小縮減至 2,048 位元以下。
在標準層級中建立 Ingress 時發生錯誤
症狀
如果您在專案中部署 Ingress,且專案預設網路層級設為「標準」,系統會顯示下列錯誤訊息:
Error syncing to GCP: error running load balancer syncing routine: load balancer <LB Name> does not exist: googleapi: Error 400: STANDARD network tier (the project''s default network tier) is not supported: STANDARD network tier is not supported for global forwarding rule., badRequest
解決方法
將專案預設網路級別設為「進階」。
預期 k8s-ingress-svc-acct-permission-check-probe 會發生「找不到」錯誤
Ingress 控制器會從 Google Cloud 專案擷取測試資源,定期檢查服務帳戶權限。您會看到這個項目是名為「k8s-ingress-svc-acct-permission-check-probe」的 (不存在) 全域 BackendService 的 GET。由於這個資源通常不存在,GET 要求會傳回「找不到」。這是正常情況,因為控制器會檢查 API 呼叫是否因授權問題遭到拒絕。如果建立同名的 BackendService,GET 會成功,而不是傳回「找不到」。
使用容器原生負載平衡時發生錯誤
請使用以下技巧確認您的網路設定。下列各節說明如何解決關於容器原生負載平衡的特定問題。
如要進一步瞭解如何列出網路端點群組,請參閱負載平衡器說明文件。
您可以在服務的
neg-status註解中,找到與該服務相對應的 NEG 名稱和區域。取得 Service 規格:kubectl get svc SVC_NAME -o yamlmetadata:annotations:cloud.google.com/neg-status註解會列出服務對應的 NEG 名稱和 NEG 區域。您可以透過下列指令,檢查與 NEG 相對應的後端服務狀態:
gcloud compute backend-services --project PROJECT_NAME \ get-health BACKEND_SERVICE_NAME --global後端服務的名稱與其 NEG 相同。
如何列印服務事件記錄:
kubectl describe svc SERVICE_NAME服務的名稱字串包含對應 GKE 服務的名稱和命名空間。
無法使用別名 IP 建立叢集
- 問題
嘗試使用別名 IP 建立叢集時,可能會碰到下列錯誤:
ResponseError: code=400, message=IP aliases cannot be used with a legacy network.- 可能原因
嘗試透過使用舊版網路的別名 IP 來建立叢集時,可能會發生上列錯誤。
- 解析度
請勿在啟用舊版網路的情況下使用別名 IP 建立叢集。別名 IP 使用詳情請參閱建立虛擬私有雲原生叢集。
流量未達端點
- 問題
- 502/503 錯誤或連線遭拒。
- 可能原因
新端點只要會回應健康狀態檢查,則在附加到負載平衡器後通常就可存取。如果流量達不到端點,就可能會發生 502 錯誤或連線遭拒。
如果容器無法處理
SIGTERM,也可能會造成 502 錯誤和連線遭拒。如果容器未明確處理SIGTERM,則會立即終止並停止處理要求。負載平衡器會持續將傳入的流量傳送至已終止的容器,導致發生錯誤。容器原生負載平衡器只有一個後端端點。在滾動更新期間,舊端點會先取消程式設計,再進行新端點的程式設計。
佈建容器原生負載平衡器後,後端 Pod 會首次部署到新區域。當可用區中至少有一個端點時,系統就會在該可用區中設定負載平衡器基礎架構。在可用區中新增端點時,系統會對負載平衡器基礎架構進行程式設計,導致服務中斷。
- 解析度
將置容器設為處理
SIGTERM,並在整個終止寬限期內 (預設為 30 秒) 繼續回應要求。將 Pod 設為在收到SIGTERM時,開始讓健康狀態檢查失敗。如此會向負載平衡器發出信號,要求在端點正在取消程式設計時,停止向 Pod 傳送流量。如果應用程式未正常關閉,且在收到
SIGTERM時停止回應要求,則可使用 preStop hook 處理SIGTERM,並在端點取消程式設計期間持續提供流量。lifecycle: preStop: exec: # if SIGTERM triggers a quick exit; keep serving traffic instead command: ["sleep","60"]請參閱 Pod 終止說明文件。
如果負載平衡器後端只有一個執行個體,請設定推出策略,以免在新的執行個體完全完成程式設計前,就拆除唯一的執行個體。如要為
Deployment工作負載管理的應用程式 Pod 達成此目的,請將maxUnavailable參數設為0,藉此設定推出策略。strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0如要對流量未抵達端點的問題進行疑難排解,請確認防火牆規則允許傳入 TCP 流量到
130.211.0.0/22和35.191.0.0/16範圍內的端點。詳情請參閱 Cloud Load Balancing 說明文件中的新增健康狀態檢查。查看專案裡的後端服務。相關後端服務的名稱字串,包含了對應的 GKE Service 名稱:
gcloud compute backend-services list向後端服務擷取後端健康狀態:
gcloud compute backend-services get-health BACKEND_SERVICE_NAME如果所有後端健康狀態不良,就表示防火牆、Ingress 或 Service 可能設定有誤。
如果有些後端健康狀態短時間不良,就表示網路程式設計延遲時間可能是原因所在。
如果有些後端沒有出現在後端服務清單,就表示程式設計延遲時間可能是原因所在。要確認這點,請執行下列指令,當中的
NEG_NAME是後端服務名稱。 (NEG 和後端服務共用同一個名稱):gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME確認所有預期的端點是否都已在 NEG 中。
如果容器原生負載平衡器選取的後端數量較少 (例如 1 個 Pod),請考慮增加副本數量,並將後端 Pod 分散到 GKE 叢集涵蓋的所有區域。這可確保底層負載平衡器基礎架構已完成程式設計。否則,請考慮將後端 Pod 限制在單一區域。
如果您為端點設定網路政策,請務必允許來自僅限 Proxy 子網路的輸入流量。
停止發布
- 問題
- 更新的 Deployment 延遲推出,且最新備用資源的數量與所選備用資源的數量不符。
- 可能原因
Deployment 的健康狀態檢查失敗。容器映像檔可能不正確,或是健康狀態檢查可能設定錯誤。Pod 的滾動式替換作業會等候新啟動的 Pod 傳送其 Pod 完備性門檻。只有當 Pod 在回應負載平衡器健康狀態檢查時,才會發生這種情況。如果 Pod 沒有回應,或是健康狀態檢查設定有誤,就無法達到完備性門檻,導致無法繼續發布。
如果您使用的是
kubectl1.13 或以上版本,則可以使用以下指令檢查 Pod 完備性門檻的狀態:kubectl get pod POD_NAME -o wide請勾選
READINESS GATES欄位。kubectl1.12 以下版本沒有這個資料欄。標記為處於READY狀態的 Pod,可能會有完備性門檻失敗的問題。如要驗證這一點,請使用以下指令:kubectl get pod POD_NAME -o yaml系統會在輸出結果中列出完備性門檻和其狀態。
- 解決方法
確認 Deployment 的 Pod 規格中的容器映像檔運作正常,且能回應健康狀態檢查。請確認健康狀態檢查設定正確無誤。
模式降級錯誤
- 問題
從 GKE 1.29.2-gke.1643000 版開始,更新 NEG 時,您可能會在記錄檢視器中看到服務的下列警告:
Entering degraded mode for NEG <service-namespace>/<service-name>-<neg-name>... due to sync err: endpoint has missing nodeName field- 可能原因
這些警告表示 GKE 在根據
EndpointSlice物件更新 NEG 時,偵測到端點設定錯誤,因此觸發更深入的計算程序,稱為降級模式。GKE 會盡力更新 NEG,方法是修正設定錯誤,或從 NEG 更新中排除無效端點。常見錯誤如下:
endpoint has missing pod/nodeName fieldendpoint corresponds to an non-existing pod/nodeendpoint information for attach/detach operation is incorrect
- 解析度
通常,這些事件是由暫時性狀態所導致,且會自行修正。不過,自訂
EndpointSlice物件設定錯誤導致的事件仍未解決。如要瞭解設定錯誤,請檢查與服務對應的EndpointSlice物件:kubectl get endpointslice -l kubernetes.io/service-name=<service-name>根據事件中的錯誤驗證每個端點。
如要解決這個問題,請手動修改
EndpointSlice物件。 更新會觸發 NEG 再次更新。如果不再有設定錯誤,輸出內容會類似如下:NEG <service-namespace>/<service-name>-<neg-name>... is no longer in degraded mode
使用 Google 代管 SSL 憑證時發生錯誤
本節說明如何解決 Google 管理的憑證問題。
檢查 ManagedCertificate 和 Ingress 資源的事件
如果憑證數量超出上限,系統會在 ManagedCertificate 中新增事件,並提供 TooManyCertificates 原因。您可以使用下列指令檢查 ManagedCertificate 物件的事件:
kubectl describe managedcertificate CERTIFICATE_NAME
將 CERTIFICATE_NAME 替換為您的 ManagedCertificate 名稱。
如果將不存在的 ManagedCertificate 附加至 Ingress,系統會在 Ingress 中新增 MissingCertificate 原因的事件。您可以使用下列指令,檢查 Ingress 上的事件:
kubectl describe ingress INGRESS_NAME
將 INGRESS_NAME 換成 Ingress 的名稱。
網域解析為多個負載平衡器的 IP 位址時,系統不會佈建代管憑證
如果網域會解析為多個負載平衡器的 IP 位址 (多個 Ingress 物件),您應建立單一 ManagedCertificate 物件,並將其附加至所有 Ingress 物件。如果改為建立許多 ManagedCertificate 物件,並將每個物件附加至個別的 Ingress,憑證授權單位可能無法驗證網域擁有權,部分憑證也可能無法佈建。如要順利完成驗證,憑證必須在網域解析的所有 IP 位址下都可見。
具體來說,當網域解析為 IPv4 和 IPv6 位址,且這些位址是透過不同的 Ingress 物件設定時,您應建立單一 ManagedCertificate 物件,並將其附加至兩個 Ingress。
Google 管理的憑證與 Ingress 之間的通訊中斷
受管理憑證會使用 ingress.gcp.kubernetes.io/pre-shared-cert 註解與 Ingress 通訊。舉例來說,如果發生下列情況,您可能會中斷這類通訊:
- 執行自動化程序,清除註解。
ingress.gcp.kubernetes.io/pre-shared-cert - 儲存 Ingress 快照,然後從快照刪除及還原 Ingress。在此期間,
SslCertificate註解中列出的ingress.gcp.kubernetes.io/pre-shared-cert資源可能已遭刪除。如果缺少任何附加的憑證,Ingress 就無法運作。
如果 Google 管理的憑證與 Ingress 之間的通訊中斷,請刪除 ingress.gcp.kubernetes.io/pre-shared-cert 註解的內容,然後等待系統完成協調。為避免再次發生,請確保註解不會遭到誤改或刪除。
建立 Google 管理的憑證時發生驗證錯誤
ManagedCertificate定義會在建立 ManagedCertificate 物件之前經過驗證。如果驗證失敗,系統就不會建立 ManagedCertificate 物件,並顯示錯誤訊息。以下說明各種錯誤訊息和原因:
spec.domains in body should have at most 100 items
您的 ManagedCertificate 資訊清單在 spec.domains 欄位列出超過 100 個網域。Google 代管憑證最多僅支援 100 個網域。
spec.domains in body should match '^(([a-zA-Z0-9]+|[a-zA-Z0-9][-a-zA-Z0-9]*[a-zA-Z0-9])\.)+[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]\.?$'
您在 spec.domains 欄位中指定了無效或含有萬用字元的網域名稱。ManagedCertificate 物件不支援萬用字元網域 (例如 *.example.com)。
spec.domains in body should be at most 63 chars long
您指定的網域名稱長度太長。Google 管理的憑證支援的網域名稱,長度上限為 63 個字元。
手動更新 Google 代管的憑證
如要手動更新憑證,讓舊網域的憑證在系統佈建新網域的憑證前繼續運作,請按照下列步驟操作:
- 為新網域建立
ManagedCertificate。 - 使用以半形逗號分隔的清單,在 Ingress 的
networking.gke.io/managed-certificates註解中新增ManagedCertificate的名稱。請勿移除舊憑證名稱。 - 等待
ManagedCertificate變成「Active」。 - 從 Ingress 中卸除舊憑證,然後刪除。
建立 ManagedCertificate 時, Google Cloud 會建立 Google 代管的 SSL 憑證。你無法更新這項憑證。如果您更新 ManagedCertificate, Google Cloud 會刪除並重新建立 Google 代管的 SSL 憑證。
如要為 GKE 叢集提供安全的 HTTPS 加密 Ingress,請參閱安全 Ingress 範例。
後續步驟
如果無法在說明文件中找到問題的解決方案,請參閱「取得支援」一文,瞭解如何取得進一步協助, 包括下列主題的建議:
- 與 Cloud 客戶服務聯絡,建立支援案件。
- 在 StackOverflow 上提問,並使用
google-kubernetes-engine標記搜尋類似問題,從社群取得支援。你也可以加入#kubernetes-engineSlack 頻道,取得更多社群支援。 - 使用公開 Issue Tracker 開啟問題或功能要求。