JuiceFS CSI:Mount Pod 的平滑升級及其實現原理

JuiceFS發表於2024-11-01

當叢集中需要升級 Mount Pod 時,目前推薦的方式是更新配置後重新掛載應用 Pod 進行滾動升級,但這種升級方式的問題在於需要業務重啟。

如果對業務的使用模式很清楚時,比如沒有資料寫入等,也可以選擇手動重建 Mount Pod 的方式。在更新配置後,手動刪除已有的 Mount Pod,並等待其重建,同時依賴 CSI 對掛載點的自動恢復功能,等待應用 Pod 中掛載點的恢復。這種升級的過程有幾個問題:

  1. 操作繁瑣:需要使用者自己使用 kubectl 命令,透過應用 Pod 找到對應的 Mount Pod;
  2. 升級時業務中斷:CSI 需要先等待舊的 Mount Pod 完全被刪除,才會去建立新的 Mount Pod。這就導致了在舊的 Mount Pod 刪除後、新的 Mount Pod 起來前,業務處於不可用狀態;
  3. 掛載點自動恢復對原 I/O 操作的影響:由於 CSI 使用了重新 bind 應用掛載點的方式實現了自動恢復,所以即使在恢復後,原先的 I/O 操作都會報錯。

為了解決現有的升級過程遇到的問題,JuiceFS CSI Driver 在 v0.25.0 版本中,實現了 Mount Pod 的平滑升級,即在應用不停服的情況下升級 Mount Pod。

相比有損升級的方式,使用平滑升級的好處在於:

  1. 操作簡單:在 CSI Dashboard 中,可以輕易的在應用 Pod 的頁面找到 Mount Pod,且點選按鈕即可觸發平滑升級;
  2. 業務不中斷:升級過程中,業務不會受到影響,使用者也可以使用平滑升級功能來進行 Mount Pod 的引數和配置修改。

01 CSI 如何實現 Mount Pod 的平滑升級

目前 JuiceFS CSI 支援兩種平滑升級方式,即二進位制升級和 Pod 重建升級。

二進位制升級

二進位制升級不會重建 Mount Pod,而是升級 Mount Pod 中的客戶端二進位制。其依賴 JuiceFS 客戶端自身的守護程序,即社群版版本在 v1.2.0 以上,商業版版本在 v5.0.0 以上。

整個二進位制升級的過程如下:

  1. 在觸發平滑升級後,CSI Node 啟動一個使用新映象的 Job,在 Job 中將 JuiceFS 客戶端二進位制 copy 到 Mount Pod 中;
  2. 等 Job 完成後,CSI Node 向 Mount Pod 傳送 SIGHUP 訊號;
  3. Mount Pod 接收到 SIGHUP 訊號後,將目前的 I/O 請求狀態資訊儲存到臨時檔案中,此時服務程序退出;
  4. Mount Pod 的服務程序退出後,守護程序會用新的二進位制再次啟動新的服務程序;
  5. 新的服務程序啟動後讀取中間狀態檔案,並繼續處理之前的請求;
  6. 新的服務程序向守護程序拿當前的 FUSE fd。

二進位制升級使用於僅需要升級客戶端的情況。但升級後檢視 Pod 的 yaml,其映象依然是舊的。由於沒有重建 Pod,這種升級的好處在於速度快且風險小,缺點在於不能更新 Mount Pod 的其他配置。

Pod 重建升級

Pod 重建升級指的是重建 Mount Pod 進行平滑升級。這種升級方式依賴 JuiceFS 本身的平滑升級功能,即社群版版本在 v1.2.1 以上,商業版版本在 v5.1.0 以上。

整個 Pod 重建升級的過程如下:

  1. 每個 Mount Pod 在啟動後,都會將自身使用的 FUSE fd 傳給 CSI Node,CSI Node 維護了每個 Mount Pod 使用的 FUSE fd 的關係表;
  2. 在觸發了平滑升級後,CSI Node 會先起一個與新 Mount Pod 相同配置的空 Job,這一步的作用是提前將新映象 pull 在節點上,從而節省升級時間;
  3. 等 Job 完成後,CSI Node 向舊的 Mount Pod 傳送 SIGHUP 訊號;
  4. 舊的 Mount Pod 接收到 SIGHUP 訊號後,將目前的 I/O 狀態資訊儲存到臨時檔案中,並退出。此時 Mount Pod 變為 Complete 狀態;
  5. CSI Node 根據 ConfigMap 中的配置,建立新的 Mount Pod;
  6. 新的 Mount Pod 起來後,讀取臨時檔案中的中間狀態資訊,從而繼續處理之前的請求;
  7. 新的 Mount Pod 向 CSI Node 拿當前的 FUSE fd。

其中 Mount Pod 和 CSI Node 之間透過 Unix domain socket 來傳遞檔案控制代碼。當某個 FUSE 請求未能在升級期間完成,會被強制中斷,建議在負載比較低的時候進行升級操作。

可以看到整個平滑升級的過程,與宿主機上客戶端的平滑升級類似,唯一的區別在於由 CSI Node 向舊的服務程序傳送 SIGHUP 訊號以及新的服務程序啟動後向 CSI Node 拿 FUSE fd。這是因為 Mount Pod 在重建後,其中的守護程序無法向舊的守護程序傳送 SIGHUP 訊號以及無法透過 Unix domain socket 傳遞檔案控制代碼,所以在 K8s 環境中這些工作就交由 CSI Node 來完成。

這種升級方式由於重建了 Pod,缺點在於如果叢集環境比較複雜,重建 Pod 的過程中出錯的風險比較大;其優點在於可以更新 Mount Pod 的其他配置,且檢視 Pod 的 yaml,其映象是新的。

02 如何觸發平滑升級

目前平滑升級可以在 CSI Dashboard 或者 kubectl 外掛中觸發。

Dashboard 中觸發

首先在 CSI Dashboard 中,點選「配置」按鈕,更新 Mount Pod 需要升級的新映象版本。

其次,在 Mount Pod 的詳情頁,有兩個升級按鈕,分別是「Pod 重建升級」和「二進位制升級」。

  • Pod 重建升級:Mount Pod 會重建,可用於更新映象、調整掛載引數、調整 pod 資源等。Mount Pod 的最低版本要求為 1.2.1(社群版)或 5.1.0(企業版);
  • 二進位制升級:Mount Pod 不重建,只升級其中的二進位制,不可變更其他配置,且升級完成後 Pod yaml 中所看到的依然是原來的映象。Mount Pod 的最低版本要求為 1.2.0(社群版)或 5.0.0(企業版)。

點選升級按鈕,即可觸發 Mount Pod 的平滑升級。

觸發後可以看到整個過程,完成後頁面會自動跳轉到新的 Mount Pod 的詳情頁。

kubectl 外掛中觸發

使用 kubectl 在 CSI ConfigMap 配置中更新 Mount Pod 所需要升級的映象版本。

apiVersion: v1
data:
   config.yaml: |
      mountPodPatch:
         - ceMountImage: juicedata/mount:ce-v1.2.0
           eeMountImage: juicedata/mount:ee-5.1.1-ca439c2
kind: ConfigMap

使用 JuiceFS kubectl plugin 觸發 Mount Pod 的平滑升級。

# Pod 重建升級
kubectl jfs upgrade juicefs-kube-node-1-pvc-52382ebb-f22a-4b7d-a2c6-1aa5ac3b26af-ebngyg --recreate
# 二進位制升級
kubectl jfs upgrade juicefs-kube-node-1-pvc-52382ebb-f22a-4b7d-a2c6-1aa5ac3b26af-ebngyg

03 總結

鑑於目前的有損升級方案存在諸多缺陷,JuiceFS CSI Driver 在 v0.25.0 版本中,支援了 Mount Pod 的平滑升級。CSI 提供了兩種平滑升級方案,包括二進位制升級和 Pod 重建升級。二進位制升級風險小,但不支援更新 Mount Pod 的其他配置;Pod 重建升級在叢集環境較複雜的情況下有失敗的風險,但支援更新 Mount Pod 的其他配置,比如可以根據 Mount Pod 的實際資源使用情況,動態調整資源配比等。使用者可以根據需要,選擇更適合的升級方式,同時建議在負載比較低的時候進行升級操作。

相關文章