istio 503處理


istio上線一段時間后發現部分高並發的業務會頻繁告警503,於是開始排查:

業務架構:

 

 在我們的環境中istio只攔截inbound的流量,不攔截outbound的流量

 

 1.查看apisix 端的envoy日志發現日志中有大量response_code:503 ,response_flags: UC

 2.查看業務容器的envoy 日志並未發現503日志,由此猜測是apisix 到業務容器中間鏈路發生503,請求未到達業務容器

 3.在業務容器中tcpdump抓包,發現業務端口大量業務返回的 reset包,waht?業務主動斷開了連接?

 

 於是讓業務梳理了業務場景,檢查了相關代碼邏輯,確定是否有主動關閉tcp連接的操作,業務給出了否定答案,確定沒有相關邏輯,gogle了相關問題,發現有很多人遇到了類似的問題,按照網上的方法設置了一下參數:

1.istio 增加503 retry

2.禁用業務容器envoy的keepalive

3.設置envoy連接池空閑緩存時間(讓envoy主動斷開空閑連接,而不是讓業務容器斷開envoy的長鏈接)

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: xthk-live-api-pub-vs
  namespace: prod-main
spec:
  hosts:
    - xthk-live-api-pub
  http:
    - match:
        - port: 80
      retries:
        attempts: 3
        perTryTimeout: 2s
        retryOn: 'gateway-error,connect-failure,refused-stream,503'
      route:
        - destination:
            host: xthk-live-api-pub
            port:
              number: 80
            subset: v1
    - match:
        - port: 443
      route:
        - destination:
            host: xthk-live-api-pub
            port:
              number: 443
            subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: xthk-live-api-pub-dr
  namespace: prod-main
spec:
  host: xthk-live-api-pub
  subsets:
    - labels:
        version: v1
      name: v1
  trafficPolicy:
    connectionPool:
      http:
        idleTimeout: 1s
        maxRequestsPerConnection: 1
    tls:
      mode: ISTIO_MUTUAL

經過一段時間的操作,發現然並卵,錯誤依舊

再次仔細查看envoy日志,發現了異常

 

 upstream_cluster為PassthroughCluster,調用k8s集群內的服務,為什么upstream_cluster不是服務名稱的cluster呢?(當cluster為PassthroughCluster,證明istio沒有通過k8s發現該服務,這樣的話就不會走istio的路由,而是通過k8s的svc轉發,就會多走一層kube-proxy轉發)

為了排查 upstream_cluster為PassthroughCluster的問題,將apisix envoy的日志設置為debug,有兩種設置方式:

1.直接在進入envoy 調用envoy接口配置,這種方式實時生效,且不重啟envoy,envoy重啟后失效 curl -X POST localhost:15000/logging?level=debug

2.設置pod annoations: sidecar.istio.io/logLevel: debug,這種方式pod會重建,但是重啟后debug模式依舊生效

查看envoy 日志:

 

 通過日志我們發現authority 為一個外網域名,即istio向后轉發時使用的host 是一個外網域名而不是集群內的service name,而istio中的VirtualService以及DestinationRule都是靠其中的host字段來匹配的,所以導致istio向pod轉發流量時走的istio的passthroughCluster,而不是對應集群內服務(Outbound Cluster),所以沒有走istio的路由直接轉發給pod(istio的轉發是不經過kube-proxy),而是走了k8s 的service ip,通過kube-proxy轉發到pod,這中間相當於就多了一層轉發,那為什么會造成這個原因呢,看了apisix的配置,發現了問題

 

 apisix 向后轉發時可以配置轉發到后端時主機名的保持,有三種方式:

1.保持與客戶端請求一致的主機名:他的意思是客戶端請求的是什么域名,轉發到k8s pod時 host 就是客戶端請求的域名,如:客戶端請求的是 www.baidu.com,這時候轉發到集群時,hostName 就是 www.baidul.com,就會導致本次訪問的host 與istio vs以及dr規則匹配不到,就會當成不是集群內的服務,會走passthroughCluster,不會走istio的路由,而是通過k8s的kube-proxy最終轉發到pod

2.使用目標節點列表中的主機名或IP,這個選項的意思是無論客戶端通過什么域名來請求,apisix轉發到k8s集群時都是用我們自己配置的主機名,如上游主機我們配置的是k8s的svc name,這時轉發到后端時就會使用k8s的svc name而不是客戶端訪問的域名

3.自定義Host請求頭:這個的意思和第二個選項類似,只不過我們可以自定義向后攜帶的hostName

我把apisix修改成了上述第二個選項使用目標節點列表中的主機名或IP,再次查看apisix 的envoy日志:

 

 這時發現upstream_cluster變成了對一個k8s服務的outbond,說明istio已經識別了目標服務為k8s集群內的服務,這時候就會走istio自己的路由,不走kube-proxy.

一天后查看對應業務的訪問日志

 

 

查看了一天的日志,發現503消失

相關參考鏈接:

https://blog.csdn.net/luo15242208310/article/details/96480095

https://zhuanlan.zhihu.com/p/412262801

https://jishuin.proginn.com/p/763bfbd310c3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM