1. 程式人生 > 其它 >Kubernetes叢集滾動更新導致Pod應用程式流量丟失的原因

Kubernetes叢集滾動更新導致Pod應用程式流量丟失的原因

Kubernetes叢集滾動更新導致Pod應用程式流量丟失的原因

原創  釋出於 2021-12-15  |  後端技術  |  瀏覽(35)  |  評論(0)

開場語(重新整理後不一樣):人生為棋,我願為卒,行動雖慢,可誰曾見我後退一步。

作為一名IT人,您可以買一個雲伺服器,除學習新技術外,也可以做網站、小程式、手機APP後端,也許您就是下個馬雲,馬化騰!!!雲優惠活動如下:
阿里雲新年活動   華為新年活動   騰訊雲新年活動  
 
轉載來自CSDN:https://blog.csdn.net/weixin_44953658/article/details/121901265

Kubernetes滾動更新導致Pod流量丟失的原因

文章目錄

1.Pod流量丟失的原因

我們在K8S叢集中的Pod應用程式需要經常性的進行滾動更新,每次滾動更新都會導致Pod流量的丟失,每次滾動更新之後,新的Pod雖然被創建出來了,但是隻要新的建立並且啟動成功後,就會將舊的Pod資源立刻刪除,舊的Pod應用程式很有可能此時正在提供服務,直接將舊的Pod資源刪除,如果沒有做任何處理的話,是會對應用程式的流量造成一定的影響,正在訪問被刪除的舊Pod資源的使用者就可能會出現介面異常的報錯資訊。

如果我們的Pod資源沒有設定健康檢查探針(readlinessprobe/livenessprobe)的話,Pod的應用狀態一直會被認為是就緒狀態的,即使Pod出現了故障,也會將使用者的請求轉發到該Pod上,並且在滾動更新過程中,新的Pod資源只要一處於Running狀態,Kube-Proxy更新第一個iptables轉發規則後,K8S就會將流量轉發到應用程式Server資源下管理的Pod資源,Pod資源這時也會告訴K8S叢集已經就緒了,其實這時候Pod資源只是啟動了,裡面的應用程式換沒有真正的啟動完畢,還不能正常處理流量的轉發,那麼使用者的請求落在這個Pod應用程式後,就會收到節點異常連線失敗的報錯資訊。

2.如何優雅的處理Pod流量丟失的問題

2.1.理解Pod刪除過程

Kubernetes的各個元件之間都是獨立執行的,是一個巨大的整體,這些元件在同步資料過程中會花費一定的時間,並不是實時性的同步。

當APIserver收到一個Pod資源刪除的請求後,首先去修改Etcd資料庫中的Pod資源狀態,也就是修改成Terminating狀態。然後通知Kubelet元件刪除具體的Pod資源,刪除掉Pod資源後,會呼叫Kube-Proxy將該Pod資源的轉發規則在iptables中刪除,此時就會迅速在Endpoints控制器中將刪除的Pod資源剔除,由於APIserver呼叫Kube-Proxy刪除iptables轉發規則並不是實時性的,會有一定的延遲,也就是說在iptables規則還沒有得到刪除時,使用者的流量還是會被分配到被刪除的Pod資源上,但是實際上提供服務的Pod資源已經被刪除了,就會造成流量的丟失。

Pod的刪除過程一共分為兩個事件

  • 事件A:APIserver收到Pod的刪除請求後,會盡快通知各個元件停止Pod一系列操作,此時就會呼叫Kubelet刪除Pod資源,並且會呼叫Kube-proxy將該Pod資源的iptables轉發規則刪除,如果Pod資源沒有響應,就會將Pod資源強制刪除。如果Pod在這些操作過程中相應了Kubelet的刪除請求,就會迅速進行刪除,此時使用者在該Pod上的流量就會丟失。
  • 事件B:收到Pod的刪除請求後,APIserver會向Endpoints資源傳送一個RESET請求,然後將Service管理的Pod副本中將這個被刪除的Pod資源剔除。

事件A與事件B都是同一時刻去處理的,但是從Endpoints中剔除應用程式的時間要比清除iptables轉發規則時間要短一些,APIServer需要向每一個節點的Kube-Proxy傳送刪除Pod的iptables的轉發規則的請求,所以用時會稍微長一些,但是刪除資源的資訊先被Endpoints控制器處理完了,轉發請求還沒有清理,使用者的請求就會被轉發到一個被刪除的Pod資源上,此時就產生了使用者訪問應用程式的流量丟失。

2.2.如何優雅的避免Pod流量丟失

我們已經明確了Endpoints會在轉發請求刪除之前就會將Pod資源刪除,如果我們可以讓Endpoints處理刪除Pod資源的請求時,讓Pod資源不要立刻刪除,稍微等待幾十秒,再讓Endpoints刪除該Pod,就可以避免由於iptables規則沒有清除導致Pod流量丟失的問題,因為刪除Pod資源和清除iptables規則是同時去做的,只是iptables的清除時間稍微長一些而已。

官方之前也提到過採用健康檢查探針的方式去解決這個問題,但是健康檢查探針是在容器啟動之前去處理的,並不能在容器退出時去完成這些操作。

針對如果讓Pod資源等待一段時間再去刪除的情況,我們可以通過Pod的鉤子函式來實現。

Pod的鉤子函式提供了容器在執行前和退出後執行一些操作的功能,我們可以配置一個容器退出後的鉤子函式,讓容器接收到被刪除的指令,在準備退出時執行一條命令比如sleep 30,讓容器等待幾十秒之後再退出,再這個時間內足夠能讓iptables的轉發規則得到清除,避免使用者的流量造成丟失。

        lifecycle:        
          preStop:       
            exec:       
              command: ["sh","-c","sleep 5"]

關於Pod鉤子函式在這裡也有詳細講解到:Kubernetes叢集Pod資源鉤子函式詳解