OpenKruise V1.4 版本解讀:新增 Job Sidecar Terminator 能力

作者:立衡

前言

OpenKruise 是阿里雲開源的雲原生應用自動化管理套件,也是當前託管在 Cloud Native Computing Foundation (CNCF) 下的孵化項目。它來自阿里巴巴多年來容器化、雲原生的技術沉澱,是阿里內部生產環境大規模應用的基於 Kubernetes 之上的標準擴展組件,也是緊貼上游社區標準、適應互聯網規模化場景的技術理念與最佳實踐。

OpenKruise:

https://github.com/openkruise/kruise

OpenKruise 在 2023.3.31 發佈了最新的 v1.4 版本(ChangeLog [ 1] ),新增 Job Sidecar Terminator 重磅功能,本文將對新版本做整體的概覽介紹。

01 重要更新

  • 爲了方便大家使用 Kruise 增強能力,默認打開了一些穩定的能力,如下:ResourcesDeletionProtection,WorkloadSpread,PodUnavailableBudgetDeleteGate,InPlaceUpdateEnvFromMetadata, StatefulSetAutoDeletePVC,PodProbeMarkerGate。上述能力大部分是需要特別配置纔會生效的,所以默認打開一般不會對存量集羣造成影響,如果有一些特性不想使用,可以在升級時關閉。
  • Kruise-Manager leader 選舉方式從 configmaps 遷移爲 configmapsleases,爲後面遷移到 leases 方式做準備,另外,這是官方提供的平滑升級的方式,不會對存量的集羣造成影響。

02 Sidecar 容器管理能力:Job Sidecar Terminator

在 Kubernetes 中對於 Job 類型 Workload,人們通常希望當主容器完成任務並退出後,Pod 進入已完成狀態。然而,當這些 Pod 擁有 Long-Running Sidecar 容器時,由於 Sidecar 容器在主容器退出後無法自行退出,導致 Pod 一直無法進入已完成狀態。

面對這個問題,社區的常見解決方案一般都需要對 Main 和 Sidecar 進行改造,兩者通過 Volume 共享來實現 Main 容器退出之後,Sidecar 容器完成退出的效果。

社區的解決方案可以解決這個問題,但是需要對容器進行改造,尤其對於社區通用的 Sidecar 容器,改造和維護的成本太高了。

爲此,我們在 Kruise 中加入了一個名爲 SidecarTerminator 的控制器,專門用於在此類場景下,監聽主容器的完成狀態,並選擇合適的時機終止掉 Pod 中的 sidecar 容器,並且無需對 Main 和 Sidecar 容器進行侵入式改造。

運行在普通節點的 Pod

對於運行於普通節點的 Pod(常規 Kubelet),使用該特性非常簡單,用戶只需要在要在目標 sidecar 容器中添加一個特殊的 env 對其進行標識,控制器會在恰當的時機利用 Kruise Daemon 提供的 CRR 的能力,將這些 sidecar 容器終止:

kind: Job
spec:
  template:
    spec:
      containers:
        - name: sidecar
          env:
            - name: KRUISE_TERMINATE_SIDECAR_WHEN_JOB_EXIT
              value: "true"
        - name: main
... ...

運行在虛擬節點的 Pod

對於一些提供 Serverless 容器的平臺,例如 **ECI [ 2] ** 或者 **Fargate [ 3] **,其 Pods 只能運行於 **Virtual-Kubelet [ 4] ** 之類的虛擬節點。然而,Kruise Daemon 無法部署和工作在這些虛擬節點之上,導致無法使用 CRR 能力將容器終止。但幸運地是,我們可以藉助原生 Kubernetes 提供的 Pod 原地升級機制來達到同樣的目的:只需要構造一個特殊鏡像,這個鏡像的唯一作用就是當被拉起後,會快速地主動退出,這樣一來,只需要在退出 sidecar 時,將原本的 sidecar 鏡像替換爲快速退出鏡像,即可達到退出 sidecar 的目的。

步驟一:準備一個快速退出鏡像

  • 該鏡像只需要具備非常簡單的邏輯:當其被拉起後,直接退出,且退出碼爲 0。
  • 該鏡像需要兼容原 sidecar 鏡像的 commands 和 args,以防容器被拉起時報錯。

步驟二:配置你的 sidecar 容器

kind: Job
spec:
  template:
    spec:
      containers:
        - name: sidecar
          env:
            - name: KRUISE_TERMINATE_SIDECAR_WHEN_JOB_EXIT_WITH_IMAGE
              value: "example/quick-exit:v1.0.0"
        - name: main
... ...

使用你自己準備的快速退出鏡像來替換上述 "example/quick-exit:v1.0.0".

注意事項

  • sidecar 容器必須能夠響應 SIGTERM 信號,並且當收到此信號時,entrypoint 進程需要退出(即 sidecar 容器需要退出),並且退出碼應當爲 0。
  • 該特性適用於任意 Job 類型 Workload 所管理的 Pod,只要他們的 RestartPolicy 爲 Never/OnFailure 即可。
  • 具有環境變量 KRUISE_TERMINATE_SIDECAR_WHEN_JOB_EXIT 的容器將被視爲 sidecar 容器,其他容器將被視爲主容器,當所有主容器完成後,sidecar 容器纔會被終止:

<!---->

    • 在 Never 重啓策略下,主容器一旦退出,將被視爲"已完成"。
    • 在 OnFailure 重啓策略下,主容器退出代碼必須爲0,纔會被視爲"已完成"。

03 增強版本的工作負載

CloneSet 優化性能 :新增 FeatureGate CloneSetEventHandlerOptimization

當前,無論是 Pod 的狀態變化還是 Metadata 變化,Pod Update 事件都會觸發 CloneSet reconcile 邏輯。CloneSet Reconcile 默認配置了三個 worker,對於集羣規模較小的場景,這種情況並不會造成問題。

但對於集羣規模較大或 Pod Update 事件較多的情況,這些無效的 reconcile 將會阻塞真正的 CloneSet reconcile,進而導致 CloneSet 的滾動升級等變更延遲。爲了解決這個問題,可以打開 feature-gate CloneSetEventHandlerOptimization 來減少一些不必要的 reconcile 入隊。

CloneSet 新增 disablePVCReuse 字段

如果一個 Pod 被外部直接調用刪除或驅逐時,這個 Pod 關聯的 PVCs 還都存在;並且 CloneSet controller 發現數量不足重新擴容時,新擴出來的 Pod 會複用原 Pod 的 instance-id 並關聯原來的 PVCs。

然而,如果 Pod 所在的 Node 出現異常,複用可能會導致新 Pod 啓動失敗,詳情參考 **issue 1099 [ 5] **。爲了解決這個問題,您可以設置字段 disablePVCReuse=true,當 Pod 被驅逐或者刪除後,與 Pod 相關的 PVCs 將被自動刪除,不再被複用。

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
spec:
  ...
  replicas: 4
  scaleStrategy:
    disablePVCReuse: true

CloneSet 增加 PreNormal 生命週期鉤子

CloneSet 已經支持了 PreparingUpdate、PreparingDelete 兩種生命週期鉤子,用於應用的優雅下線,詳情參考**社區文檔 [ 6] **。爲了支持優雅上線的場景,本次新增加了 PreNormal 狀態,具體如下:

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
spec:
  # define with finalizer
  lifecycle:
    preNormal:
      finalizersHandler:
      - example.io/unready-blocker

  # or define with label
  lifecycle:
    preNormal:
      labelsHandler:
        example.io/block-unready: "true"

當 CloneSet 創建一個 Pod(包括正常擴容和重建升級)時:

  • 如果 Pod 滿足了 PreNormal hook 的定義,纔會被認爲是 Available,並且纔會進入 Normal 狀態

這對於一些 Pod 創建時的後置檢查很有用,比如你可以檢查 Pod 是否已經掛載到 SLB 後端,從而避免滾動升級時,舊實例銷燬後,新實例掛載失敗導致的流量損失。

04 高級的應用運維能力

容器重啓新增 forceRecreate 字段

當創建 CRR 資源時,如果容器正在啓動過程中,CRR 將不會再重啓容器。如果您想要強制重啓容器,可以使用以下字段開啓:

apiVersion: apps.kruise.io/v1alpha1
kind: ContainerRecreateRequest
spec:
  ...
  strategy:
    forceRecreate: true

鏡像預熱支持 Attach metadata into cri interface

當 Kubelet 創建 Pod 時,Kubelet 將會 attach metadata 到 container runtime cri 接口。鏡像倉庫可以根據這些 metadata 信息來確定拉鏡像的來源業務,如果發生了倉庫過載、壓力過大的情況,可以對具體的業務進行降級處理。OpenKruise 鏡像預熱同樣支持類似的能力,如下:

apiVersion: apps.kruise.io/v1alpha1
kind: ImagePullJob
spec:
  ...
  image: nginx:1.9.1
  sandboxConfig:
    annotations:
      io.kubernetes.image.metrics.tags: "cluster=cn-shanghai"
    labels:
      io.kubernetes.image.app: "foo"

社區參與

非常歡迎你通過 Github/Slack/釘釘/微信 等方式加入我們來參與 OpenKruise 開源社區。你是否已經有一些希望與我們社區交流的內容呢?可以在我們的**社區雙週會 [7 ] **上分享你的聲音,或通過以下渠道參與討論:

  • 加入社區 **Slack channel [ 8] **(English)
  • 加入社區釘釘羣:搜索羣號 23330762 (Chinese)
  • 加入社區微信羣(新):添加用戶 openkruise 並讓機器人拉你入羣 (Chinese)

相關鏈接:

[1] ChangeLog

https://github.com/openkruise/kruise/blob/master/CHANGELOG.md

[2] ECI

https://www.aliyun.com/product/eci

[3] Fargate

https://aws.amazon.com/cn/fargate/

[4] Virtual-Kubelet

https://virtual-kubelet.io/#:~:text=Virtual%20Kubelet%20is%20an%20open,as%20serverless%20cloud%20container%20platforms.

[5] issue 1099

https://github.com/openkruise/kruise/issues/1099

[6] 社區文檔

https://openkruise.io/docs/user-manuals/cloneset/#lifecycle-hook

[7] 社區雙週會

https://browser.alibaba-inc.com/?Url=https://shimo.im/docs/gXqmeQOYBehZ4vqo

[8] Slack channel

https://kubernetes.slack.com/?redir=%2Farchives%2Fopenkruise

點擊此處,查看 OpenKruise 項目官方主頁與文檔

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