天天看點

OpenKruise v0.5.0 版本釋出,支援無損的流式分批釋出政策背景問題v0.5.0 新增功能......總結

OpenKruise v0.5.0 版本釋出,支援無損的流式分批釋出政策背景問題v0.5.0 新增功能......總結

目前在阿裡巴巴内部雲原生環境中,絕大部分應用都統一使用 OpenKruise 的能力做 Pod 部署、釋出管理,而不少業界公司和阿裡雲上客戶由于 K8s 原生 Deployment 等負載不能完全滿足需求,也轉而采用 OpenKruise 作為應用部署載體。

背景問題

在介紹 OpenKruise 新增能力之前,我們先來看一下原生 K8s workload 所提供的釋出能力:

  • Deployment 目前支援 maxUnavailable 和 maxSurge:
OpenKruise v0.5.0 版本釋出,支援無損的流式分批釋出政策背景問題v0.5.0 新增功能......總結
  • StatefulSet 目前支援 partition:
OpenKruise v0.5.0 版本釋出,支援無損的流式分批釋出政策背景問題v0.5.0 新增功能......總結
  • 其餘 workload 如 DaemonSet,也隻支援了 maxUnavailable。

以上這些政策在測試環境或是小場景下尚且可行,但其實無法完全滿足大規模的應用場景。比方說:

  • 首先,Deployment 不支援灰階分批釋出,你想隻灰階更新其中 20% 的 Pod 做驗證?抱歉做不到啊,使用者隻能設定小一些的 maxUnavailable 等着它全部發完,或者釋出出現問題緊急 pause 暫停;
  • StatefulSet 确實支援灰階分批(partition),但目前是隻能一個一個 Pod 來更新。如果 replicas 總數有個幾百上千的量,那麼一次釋出可能要等到天黑。

v0.5.0 新增功能

這裡我們隻針對 v0.5.0 版本 CloneSet 和 SidecarSet 的兩個主要功能改動來介紹,有興趣的同學可以在 Github changelog 上看到版本改動明細:

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

CloneSet 支援 maxSurge 政策

在阿裡巴巴内部的雲原生環境下,絕大部分無狀态應用都使用 CloneSet 管理。為了應對超大規模應用的極緻部署需求,我們在其中支援:

  • 原地更新(釋出前後 Pod 對象不變、IP 不變、volume 不變,隻更新容器的鏡像)
  • 縮小 replicas 指定 Pod 删除
  • 豐富的釋出政策(流式、灰階分批、優先級、打散等)

而在今年 2 月份的 Kruise v0.4.0 版本中,我們将 CloneSet 推出到開源。CloneSet 一經釋出就廣受關注,目前已經有多家知名網際網路公司在調研使用。

最初版本的 CloneSet 并未支援 maxSurge(先擴後縮釋出),隻支援了 maxUnavailable、partition 等政策。這對阿裡巴巴内部的大體量應用來說不是問題,但是很多社群使用者的平台上都有小規模的應用,如果不能配置先擴後縮,那麼在釋出階段可能會影響到應用的可用性。

在收到社群的 issue #250 #260 回報後,我們在 CloneSet 中新增了 maxSurge 政策的支援并于 v0.5.0 版本中提供,在此也感謝社群 fatedier shiyan2016 等成員的參與貢獻和寶貴建議。至此,CloneSet 已經覆寫了 K8s 原生 workload 的所有釋出政策,下圖建構了 CloneSet 目前提供的釋出功能:

OpenKruise v0.5.0 版本釋出,支援無損的流式分批釋出政策背景問題v0.5.0 新增功能......總結

這裡暫時不對 CloneSet 的釋出政策做詳細說明,我們後續會有專項文章來介紹。我們隻看一下新增的 maxSurge 是如何配合流式、分批釋出來實作的呢?接下來我們用幾個簡單的例子來看一下:

  1. 設定 maxSurge + maxUnavailable + partition 釋出:

apiVersion: apps.kruise.io/v1alpha1

kind: CloneSet

...

spec:

replicas: 5          # Pod 總數為 5           

updateStrategy:

maxSurge: 20%      # 多擴出來 5 * 20% = 1 個 Pod (rounding up)
maxUnavailable: 0  # 保證釋出過程 5 - 0 = 5 個 Pod 可用
partition: 3       # 保留 3 個舊版本 Pod (隻釋出 5 - 3 = 2 個 Pod)           

當開始釋出時,CloneSet 會先根據 maxSurge 多擴出來一個 Pod,此時 Pod 總數為 6(5 個舊版,1 個新版):

$ kubectl get clone demo

NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE

demo 5 1 0 5 6 17m

随後,CloneSet 會在保證 maxUnavailable 的前提下逐漸把 Pod 删除、建立的方式更新,直到滿足 partition=3 即剩餘 3 個舊版本 Pod。此時,因為已經達到了期望的終态,CloneSet 會把新版本 Pod 删除一個,此時 Pod 總數為 5(3 個舊版,2 個新版):

demo 5 2 2 5 5 17m

這裡可以觀察一段時間,當需要繼續往下釋出時,再次修改 partition 為 0。然後,CloneSet 會再次根據 maxSurge 多擴出來一個 Pod,此時 Pod 總數為 6(3 個舊版,3 個新版):

demo 5 3 2 5 6 17m

随後,CloneSet 會在保證 maxUnavailable 的前提下逐漸把 Pod 删除、建立的方式更新,直到滿足 partition=0 即所有 Pod 都更新到新版本。最後,CloneSet 會把新版本 Pod 删除一個,此時 Pod 總數為 5(5 個新版):

demo 5 5 5 5 5 17m

  1. maxSurge 配合原地更新:

CloneSet 提供了 Pod 原地更新和重建更新兩種更新方式,都可以配合 maxSurge / maxUnavailable / partition 等政策來釋出。

updateStrategy:

type: InPlaceIfPossible
maxSurge: 20%           

如果在原地更新方式下配置了 maxSurge,CloneSet 會先擴出來 maxSurge 數量的 Pod,然後對舊版本 Pod 采用 in-place 的方式來更新(更新 Pod spec 中的 image 鏡像),最後在滿足 partition 終态之後再清理删掉 maxSurge 數量的 Pod。

通過這種方式,既保證了釋出過程的業務可用性,也盡量使 Pod 釋出過程中 IP、volume 等資訊不變。

SidecarSet 支援 volume 注入合并

SidecarSet 是 Kruise 提供的另一個重磅功能,不同于 CloneSet/StatefulSet 這些管理業務 Pod 的 workload,SidecarSet 是負責統一管理叢集中的 sidecar 容器版本和注入。

而 v0.5.0 版本中新增的功能,就是在 sidecar 容器注入的時候,解決了 SidecarSet 和 Pod 中 volume 重複定義的沖突問題。這也是來自于一個社群 issue #254 回報,他們使用 SidecarSet 做日志采集 sidecar 的管理,并期望以旁路的方式注入到所有 Pod 中。

舉個例子,我們需要往叢集中每個 Pod 都注入一個日志采集 sidecar 容器。但是一來我們無法讓每個應用開發者都在自己的 CloneSet/Deployment 中增加這個容器的定義,二來即使在所有應用的 workload 中都加了,如果我們想要更新這個日志采集容器的鏡像版本,還得更新所有應用的 workload,這樣做的成本實在太高了!

而 OpenKruise 提供的 SidcarSet 正是為了解決上述這個問題。我們隻需要将 sidecar 定義寫到一個全局的 SidcarSet 中,不管使用者用 CloneSet、Deployment、StatefulSet 等任何方式部署,擴出來的 Pod 中都會注入我們定義好的 sidecar 容器。

OpenKruise v0.5.0 版本釋出,支援無損的流式分批釋出政策背景問題v0.5.0 新增功能......總結

以日志采集為例,我們可以先定義一個 SidecarSet:

kind: SidecarSet

metadata:

name: log-sidecar

selector:

matchLabels:
  app-type: long-term  # 往所有帶 long-term 标簽的 Pod 中注入           

containers:

  • name: log-collector

    image: xxx:latest

    volumeMounts:

    • name: log-volume

      mountPath: /var/log # 将 log-volume 的卷挂到 /var/log 目錄,采集這個目錄下的日志

    volumes:
  • name: log-volume # 定義一個名為 log-volume 的卷

    emptyDir: {}

    這裡大家可能會問,如果每個應用打出日志的目錄路徑不同,怎麼辦?不要急,這就是本次 volume merge 的功能所在。

這個時候,比如有一個應用 A 擴容的原始 Pod 如下:

apiVersion: v1

kind: Pod

labels:

app-type: long-term           

containers:

  • name: app
    • mountPath: /app/logs # 應用自己的日志目錄
  • persistentVolumeClaim:
    claimName: pvc-xxx           
    那麼 kruise webhook 就會将 SidecarSet 中定義的 log sidecar 容器注入到 Pod 中:
app-type: long-term           
    • mountPath: /var/log
  • claimName: pvc-xxx           
    可以看到,因為 SidecarSet 和 Pod 中定義的日志 volume 名字都叫 log-volume,那麼在注入的時候就會以 Pod 中定義的 volume 為準。比如這裡 Pod 中的 volume 采用了 pvc 的方式來挂載 pv,那麼注入 sidecar 後,同樣會把這個卷挂到 sidecar 容器中的 /var/log 目錄下,然後執行日志采集即可。

這樣以 SidecarSet 的方式管理 sidecar 容器,既和應用部署釋出做了解耦,也同樣可以和應用容器共享 volume 卷,來實作日志采集、監控等相關 sidecar 功能。

總結

本次 v0.5.0 版本的更新,主要帶來了應用無損釋出和 sidecar 容器管理上更加便捷的能力。

後續 OpenKruise 還會持續在應用部署/釋出能力上做出更深的優化,我們也歡迎更多的同學參與到 OpenKruise 社群來,共同建設一個場景更加豐富、完善的 K8s 應用管理、傳遞擴充能力,能夠面向更加規模化、複雜化、極緻性能的場景。

本文轉自<阿裡巴巴雲原生技術圈>——阿裡巴巴雲原生小助手