【Kubernete】CronJob 創建的Pod連接同集羣內其他Pod的服務返回404

晚上發現,使用Kubernetes CronJob創建定時任務時,CronJob創建的實例發送HTTP請求到同集羣內的其他服務,返回404。但第二天早上突然好了,非常神奇。

前提條件:
CronJob創建的Pod沒有Istio proxy組件,無法訪問一個有Istio Proxy的Pod
一個有Istio Proxy的Pod可以訪問另一個有一個有Istio Proxy的Pod
偶發性,有時CronJob創建的Pod可以訪問一個有Istio Proxy的Pod

以下是記錄排查過程

在這裏插入圖片描述
發現CronJob 無法訪問其他服務實例,先試試是不是連不上網,這樣可以去找運維處理。

能ping通,那就是Kubernetes集羣內部的問題。再試試,能不能ping通其他的node ip,… …嗯,也能ping 通。

或許是代碼寫的有問題?畢竟是日日夜夜寫Bug,寫些Bug也情有可原。

kubectl exec命令 登錄到這個pod上,用wget訪問出問題的那個接口

在這裏插入圖片描述
也是404,那還好代碼依然沒出Bug,好的代碼就是這麼自信。那就是天災,集羣網絡出了問題。

用計算機網絡的思路想想,Http Status Code 404,應用層報的錯。看看別的Pod能不能訪問這個接口。

於是從這個Pod部署的Node節點上,找了一個別的Pod,亦然用kubectl exec命令登陸進去,wget他。
在這裏插入圖片描述
嗯,沒問題。

看問題就集中在CronJob無法訪問其他Pod。

根據流量流轉模型
在這裏插入圖片描述

在這裏插入圖片描述

從 Kube-Proxy到pod 或者 從Istio Side-Car Proxy到Pod 都是沒有問題的,否則其他服務同樣無法訪問。

開始控制變量法思考,兩個實例之間有什麼區別。
兩個Pod之間應該只差了一個Istio Proxy,那麼先注入進去看看。
在這裏插入圖片描述
嗯 可以了。

但現在依然有兩個問題:

  1. 我並不知道爲什麼這個問題是偶發性的
  2. 注入Istio Proxy的Pod無法被CronJob控制,即Pod達到Completed狀態時,依然會以 1/2的形式存在,CronJob無法啓動新的Pod

問題1還要繼續分析下去
問題2解決方案至少有兩個,google上查Better support for sidecar containers in batch jobs就能查出來

看了一下我們的網絡架構,訪問的Service下有兩種實例,線上實例和灰髮實例。這兩種實例通過Deployment文件裏的Lable區分開。Service在做Pod之間負載均衡的時候,會有策略去訪問。我估計應該CronJob創建的實例在流量到Service時,不知道訪問那個Pod,所以報了404。

但我通過在CronJob中的JobTemplate中添加了相應的Label變量,亦然是404。
然後看了一下VirtualServiceDestinationRule,還是沒有什麼頭緒。決定先看看這個Istio Proxy加和不加有沒有什麼區別。

翻了一遍Istio 的 VirtualServiceDestinationRule的文檔,前者是流量對於Service的選擇,他可以選擇流量進入哪一個Service的哪一個Pod中, DestinationRule就是對那個Pod的定義。我發現在VirtualService中並沒有這樣的定義,導致從出問題的Pod出去的流量不知道應該選擇哪一個目標ServicePod最終導致404。非常符合我的猜想。

然後給VirtualService加了一個路由選擇的條件

spec:
  hosts:
  - "virtual-host"
  http:
  - match:
    - sourceLabels:
        type: normal
    route:
    - destination:
        host: virtual-host
        subset: normal

即請求中的hostvirtual-host且請求發送的Pod帶有normal標籤(Label)會被導入到 hostvirtual-hostServicenormal子集中。
同時,還應該在DestinationRule中對這個normal子集,進行定義。

這裏Debug的時候遇到了兩個坑。第一個是不允許出現多個VirtualService指向同一個host,否則Istio Proxy會報錯
在這裏插入圖片描述
第二個問題是,更新完VirtualService,記得要把CronJob刪除掉,重新建一個纔有用。

估計偶發性是因爲灰度發佈的時候,路由會根據Pod所帶的Label進行路由選擇,這個時候我的Pod由於沒有帶label所以不知道選擇正常的Pod還是灰度的Pod。一旦不在灰度發佈時段,由於只有一種Pod所以就默認選擇了正常的Pod

(完,掰掰, (:△」∠)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章