本文介紹Service Mesh中常見的503報錯情境及解決方案。
偶發503
情境一:使用自訂監控指標功能進行個人化配置,每當配置變更時,日誌監控發現少量請求出現503
問題原因
自訂指標功能的邏輯是通過產生一個對應的EnvoyFiter來進行istio.stats的配置更新。該配置在Envoy Listener層級生效,即通過LDS同步生效。Envoy在應用Listener層級的配置時,需要斷開已有串連。對應的在途請求因為串連被Reset或Close導致出現503。
解決方案
上遊Server主動Close串連時,您看到的503並非上遊Server發送,而是用戶端Sidecar因為上遊串連主動斷開,由本地返回的響應。
Istio預設的重試配置中未包含“上遊Server主動Close串連”的情況。EnvoyProxy的重試條件中,Reset符合這種情況對應的觸發條件。因此,您需要為對應服務的路由配置retry Policy。在VirtualService下的retry Policy配置包含Reset的觸發條件。
配置樣本如下。該配置僅針對Ratings服務生效。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- route:
- destination:
host: ratings.prod.svc.cluster.local
subset: v1
retries:
attempts: 2
retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes,reset,503相關FAQ
為什麼Istio預設的重試機制未生效?
Istio預設重試發生的條件如下。預設會重試2次。該情境未在重試條件內,因此未生效。
"retry_policy": {
"retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
"num_retries": 2,
"retry_host_predicate": [
{
"name": "envoy.retry_host_predicates.previous_hosts"
}
],
"host_selection_retry_max_attempts": "5",
"retriable_status_codes": [
503
]
}connect-failure:串連失敗。
refused-stream:當HTTP2 Stream流返回
REFUSED_STREAM錯誤碼。unavailable:當gRPC請求返回
unavailable錯誤碼。cancelled:當gRPC請求返回
cancelled錯誤碼。retriable-status-codes:當請求返回的
status_code和retriable_status_codes配置下定義的錯誤碼匹配。
關於最新版本的EnvoyProxy完整的重試條件,請參見以下文檔。
HTTP已有的重試條件配置(包含HTTP2和HTTP3):Router
gRPC專屬的重試條件配置:x-envoy-retry-grpc-on
情境二:偶發503,沒有規律,在此過程中並未發生配置變更
503偶爾出現,但是在流量密集時,會持續出現。通常出現在Sidecar的Inbound側。
問題原因
Envoy的空閑串連保持時間和應用不匹配。Envoy空閑連線時間預設為1小時。
Envoy空閑連線時間過長,應用相對較短:
應用已經結束空閑串連,但是Envoy認為沒有結束。此時如果有新的串連,就會報503UC。

Envoy空閑連線時間過短,應用相對較長:
這種情況不會導致503。Envoy認為之前的串連已經被關閉,因此會直接建立一個串連。

解決方案
方案一:在DestinationRule中配置idleTimeout
造成該問題的原因就是idleTimeout不匹配,因此在DestinationRule中配置idleTimeout屬於比較根本的解決辦法。
如果配置了idelTimeout,在Outbound和Inbound兩側都會生效,即Outbound和Inbound的Sidecar都會存在idleTimeout的配置。如果用戶端沒有Sidecar,idleTimeout也會生效,並能夠有效減少503。
配置建議:此配置與業務相關,太短會導致串連數過高。建議您配置為略短於業務應用真正的idleTimeout時間。
方案二:在VirtualService中配置重試
重試會重建串連,可以解決此問題。具體操作,請參見情境一的解決方案。
該操作為非等冪的請求,重試存在較大的風險,請謹慎操作。
情境三:Sidecar生命週期相關
問題原因
Sidecar和業務容器生命週期導致,常發生於Pod重啟。
解決方案
具體操作,請參見Sidecar生命週期。
必定503
情境一:應用監聽localhost
問題原因
當叢集中的應用監聽localhost網路地址時,如果localhost是本地地址,會導致叢集中的其他Pod無法對其進行正常訪問。
解決方案
您可以通過對外暴露應用服務解決此問題。具體操作,請參見如何使叢集中監聽localhost的應用被其他Pod訪問。
情境二:啟用Sidecar後,健全狀態檢查總是失敗,報錯503
問題原因
在Service Mesh開啟mTLS後,kubelet向Pod發送的健全狀態檢查請求被Sidecar攔截,而kubelet沒有對應的TLS認證,導致健全狀態檢查失敗。
解決方案
您可以通過配置連接埠健全狀態檢查流量免於經過Sidecar代理解決此問題。具體操作,請參見為什麼注入Sidecar後,健全狀態檢查總失敗或者無效。