OpenKruise v0.5.0 版本发布,支持无损的流式分批发布策略
作者 | 酒祝? 阿里云技術(shù)專家
導(dǎo)讀:OpenKruise 是阿里云開源的大規(guī)模應(yīng)用自動(dòng)化管理引擎,在功能上對(duì)標(biāo)了 Kubernetes 原生的 Deployment/StatefulSet 等控制器,但 OpenKruise 提供了更多的增強(qiáng)功能如 優(yōu)雅原地升級(jí)、發(fā)布優(yōu)先級(jí)/打散策略、多可用區(qū) workload 抽象管理、統(tǒng)一 sidecar 容器注入管理等,都是經(jīng)歷了阿里巴巴超大規(guī)模應(yīng)用場(chǎng)景打磨出的核心能力。這些 feature 幫助我們應(yīng)對(duì)更加多樣化的部署環(huán)境和需求、為集群維護(hù)者和應(yīng)用開發(fā)者帶來(lái)更加靈活的部署發(fā)布組合策略。
目前在阿里巴巴內(nèi)部云原生環(huán)境中,絕大部分應(yīng)用都統(tǒng)一使用 OpenKruise 的能力做 Pod 部署、發(fā)布管理,而不少業(yè)界公司和阿里云上客戶由于 K8s 原生 Deployment 等負(fù)載不能完全滿足需求,也轉(zhuǎn)而采用 OpenKruise 作為應(yīng)用部署載體。
背景問(wèn)題
在介紹 OpenKruise 新增能力之前,我們先來(lái)看一下原生 K8s workload 所提供的發(fā)布能力:
- Deployment 目前支持 maxUnavailable 和 maxSurge:
- StatefulSet 目前支持 partition:
- 其余 workload 如 DaemonSet,也只支持了 maxUnavailable。
以上這些策略在測(cè)試環(huán)境或是小場(chǎng)景下尚且可行,但其實(shí)無(wú)法完全滿足大規(guī)模的應(yīng)用場(chǎng)景。比方說(shuō):
- 首先,Deployment 不支持灰度分批發(fā)布,你想只灰度升級(jí)其中 20% 的 Pod 做驗(yàn)證?抱歉做不到啊,用戶只能設(shè)置小一些的 maxUnavailable 等著它全部發(fā)完,或者發(fā)布出現(xiàn)問(wèn)題緊急 pause 暫停;
- StatefulSet 確實(shí)支持灰度分批(partition),但目前是只能一個(gè)一個(gè) Pod 來(lái)升級(jí)。如果 replicas 總數(shù)有個(gè)幾百上千的量,那么一次發(fā)布可能要等到天黑。
v0.5.0 新增功能
這里我們只針對(duì) v0.5.0 版本 CloneSet 和 SidecarSet 的兩個(gè)主要功能改動(dòng)來(lái)介紹,有興趣的同學(xué)可以在 Github changelog 上看到版本改動(dòng)明細(xì):https://github.com/openkruise/kruise/blob/master/CHANGELOG.md 。
CloneSet 支持 maxSurge 策略
在阿里巴巴內(nèi)部的云原生環(huán)境下,絕大部分無(wú)狀態(tài)應(yīng)用都使用 CloneSet 管理。為了應(yīng)對(duì)超大規(guī)模應(yīng)用的極致部署需求,我們?cè)谄渲兄С?#xff1a;
- 原地升級(jí)(發(fā)布前后 Pod 對(duì)象不變、IP 不變、volume 不變,只升級(jí)容器的鏡像)
- 縮小 replicas 指定 Pod 刪除
- 豐富的發(fā)布策略(流式、灰度分批、優(yōu)先級(jí)、打散等)
而在今年 2 月份的 Kruise v0.4.0 版本中,我們將 CloneSet 推出到開源。CloneSet 一經(jīng)發(fā)布就廣受關(guān)注,目前已經(jīng)有多家知名互聯(lián)網(wǎng)公司在調(diào)研使用。
最初版本的 CloneSet 并未支持 maxSurge(先擴(kuò)后縮發(fā)布),只支持了 maxUnavailable、partition 等策略。這對(duì)阿里巴巴內(nèi)部的大體量應(yīng)用來(lái)說(shuō)不是問(wèn)題,但是很多社區(qū)用戶的平臺(tái)上都有小規(guī)模的應(yīng)用,如果不能配置先擴(kuò)后縮,那么在發(fā)布階段可能會(huì)影響到應(yīng)用的可用性。
在收到社區(qū)的 issue #250 #260 反饋后,我們?cè)?CloneSet 中新增了 maxSurge 策略的支持并于 v0.5.0 版本中提供,在此也感謝社區(qū) fatedier shiyan2016 等成員的參與貢獻(xiàn)和寶貴建議。至此,CloneSet 已經(jīng)覆蓋了 K8s 原生 workload 的所有發(fā)布策略,下圖構(gòu)建了 CloneSet 目前提供的發(fā)布功能:
這里暫時(shí)不對(duì) CloneSet 的發(fā)布策略做詳細(xì)說(shuō)明,我們后續(xù)會(huì)有專項(xiàng)文章來(lái)介紹。我們只看一下新增的 maxSurge 是如何配合流式、分批發(fā)布來(lái)實(shí)現(xiàn)的呢?接下來(lái)我們用幾個(gè)簡(jiǎn)單的例子來(lái)看一下:
當(dāng)開始發(fā)布時(shí),CloneSet 會(huì)先根據(jù) maxSurge 多擴(kuò)出來(lái)一個(gè) Pod,此時(shí) Pod 總數(shù)為 6(5 個(gè)舊版,1 個(gè)新版):
$ kubectl get clone demo NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE demo 5 1 0 5 6 17m隨后,CloneSet 會(huì)在保證 maxUnavailable 的前提下逐漸把 Pod 刪除、新建的方式更新,直到滿足 partition=3 即剩余 3 個(gè)舊版本 Pod。此時(shí),因?yàn)橐呀?jīng)達(dá)到了期望的終態(tài),CloneSet 會(huì)把新版本 Pod 刪除一個(gè),此時(shí) Pod 總數(shù)為 5(3 個(gè)舊版,2 個(gè)新版):
$ kubectl get clone demo NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE demo 5 2 2 5 5 17m這里可以觀察一段時(shí)間,當(dāng)需要繼續(xù)往下發(fā)布時(shí),再次修改 partition 為 0。然后,CloneSet 會(huì)再次根據(jù) maxSurge 多擴(kuò)出來(lái)一個(gè) Pod,此時(shí) Pod 總數(shù)為 6(3 個(gè)舊版,3 個(gè)新版):
$ kubectl get clone demo NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE demo 5 3 2 5 6 17m隨后,CloneSet 會(huì)在保證 maxUnavailable 的前提下逐漸把 Pod 刪除、新建的方式更新,直到滿足 partition=0 即所有 Pod 都升級(jí)到新版本。最后,CloneSet 會(huì)把新版本 Pod 刪除一個(gè),此時(shí) Pod 總數(shù)為 5(5 個(gè)新版):
$ kubectl get clone demo NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE demo 5 5 5 5 5 17mCloneSet 提供了 Pod 原地升級(jí)和重建升級(jí)兩種升級(jí)方式,都可以配合 maxSurge / maxUnavailable / partition 等策略來(lái)發(fā)布。
apiVersion: apps.kruise.io/v1alpha1 kind: CloneSet # ... spec:updateStrategy:type: InPlaceIfPossiblemaxSurge: 20%如果在原地升級(jí)方式下配置了 maxSurge,CloneSet 會(huì)先擴(kuò)出來(lái) maxSurge 數(shù)量的 Pod,然后對(duì)舊版本 Pod 采用 in-place 的方式來(lái)升級(jí)(更新 Pod spec 中的 image 鏡像),最后在滿足 partition 終態(tài)之后再清理刪掉 maxSurge 數(shù)量的 Pod。
通過(guò)這種方式,既保證了發(fā)布過(guò)程的業(yè)務(wù)可用性,也盡量使 Pod 發(fā)布過(guò)程中 IP、volume 等信息不變。
SidecarSet 支持 volume 注入合并
SidecarSet 是 Kruise 提供的另一個(gè)重磅功能,不同于 CloneSet/StatefulSet 這些管理業(yè)務(wù) Pod 的 workload,SidecarSet 是負(fù)責(zé)統(tǒng)一管理集群中的 sidecar 容器版本和注入。
而 v0.5.0 版本中新增的功能,就是在 sidecar 容器注入的時(shí)候,解決了 SidecarSet 和 Pod 中 volume 重復(fù)定義的沖突問(wèn)題。這也是來(lái)自于一個(gè)社區(qū) issue #254 反饋,他們使用 SidecarSet 做日志采集 sidecar 的管理,并期望以旁路的方式注入到所有 Pod 中。
舉個(gè)例子,我們需要往集群中每個(gè) Pod 都注入一個(gè)日志采集 sidecar 容器。但是一來(lái)我們無(wú)法讓每個(gè)應(yīng)用開發(fā)者都在自己的 CloneSet/Deployment 中增加這個(gè)容器的定義,二來(lái)即使在所有應(yīng)用的 workload 中都加了,如果我們想要升級(jí)這個(gè)日志采集容器的鏡像版本,還得更新所有應(yīng)用的 workload,這樣做的成本實(shí)在太高了!
而 OpenKruise 提供的 SidcarSet 正是為了解決上述這個(gè)問(wèn)題。我們只需要將 sidecar 定義寫到一個(gè)全局的 SidcarSet 中,不管用戶用 CloneSet、Deployment、StatefulSet 等任何方式部署,擴(kuò)出來(lái)的 Pod 中都會(huì)注入我們定義好的 sidecar 容器。
以日志采集為例,我們可以先定義一個(gè) SidecarSet:
apiVersion: apps.kruise.io/v1alpha1 kind: SidecarSet metadata:name: log-sidecar spec:selector:matchLabels:app-type: long-term # 往所有帶 long-term 標(biāo)簽的 Pod 中注入containers:- name: log-collectorimage: xxx:latestvolumeMounts:- name: log-volumemountPath: /var/log # 將 log-volume 的卷掛到 /var/log 目錄,采集這個(gè)目錄下的日志volumes:- name: log-volume # 定義一個(gè)名為 log-volume 的卷emptyDir: {}這里大家可能會(huì)問(wèn),如果每個(gè)應(yīng)用打出日志的目錄路徑不同,怎么辦?不要急,這就是本次 volume merge 的功能所在。
這個(gè)時(shí)候,比如有一個(gè)應(yīng)用 A 擴(kuò)容的原始 Pod 如下:
apiVersion: v1 kind: Pod metadata:labels:app-type: long-term spec:containers:- name: appimage: xxx:latestvolumeMounts:- name: log-volumemountPath: /app/logs # 應(yīng)用自己的日志目錄volumes:- name: log-volume # 定義一個(gè)名為 log-volume 的卷persistentVolumeClaim:claimName: pvc-xxx那么 kruise webhook 就會(huì)將 SidecarSet 中定義的 log sidecar 容器注入到 Pod 中:
apiVersion: v1 kind: Pod metadata:labels:app-type: long-term spec:containers:- name: appimage: xxx:latestvolumeMounts:- name: log-volumemountPath: /app/logs # 應(yīng)用自己的日志目錄- name: log-collectorimage: xxx:latestvolumeMounts:- name: log-volumemountPath: /var/logvolumes:- name: log-volume # 定義一個(gè)名為 log-volume 的卷persistentVolumeClaim:claimName: pvc-xxx可以看到,因?yàn)?SidecarSet 和 Pod 中定義的日志 volume 名字都叫 log-volume,那么在注入的時(shí)候就會(huì)以 Pod 中定義的 volume 為準(zhǔn)。比如這里 Pod 中的 volume 采用了 pvc 的方式來(lái)掛載 pv,那么注入 sidecar 后,同樣會(huì)把這個(gè)卷掛到 sidecar 容器中的 /var/log 目錄下,然后執(zhí)行日志采集即可。
這樣以 SidecarSet 的方式管理 sidecar 容器,既和應(yīng)用部署發(fā)布做了解耦,也同樣可以和應(yīng)用容器共享 volume 卷,來(lái)實(shí)現(xiàn)日志采集、監(jiān)控等相關(guān) sidecar 功能。
總結(jié)
本次 v0.5.0 版本的升級(jí),主要帶來(lái)了應(yīng)用無(wú)損發(fā)布和 sidecar 容器管理上更加便捷的能力。
后續(xù) OpenKruise 還會(huì)持續(xù)在應(yīng)用部署/發(fā)布能力上做出更深的優(yōu)化,我們也歡迎更多的同學(xué)參與到 OpenKruise 社區(qū)來(lái),共同建設(shè)一個(gè)場(chǎng)景更加豐富、完善的 K8s 應(yīng)用管理、交付擴(kuò)展能力,能夠面向更加規(guī)模化、復(fù)雜化、極致性能的場(chǎng)景。
課程推薦
為了更多開發(fā)者能夠享受到 Serverless 帶來(lái)的紅利,這一次,我們集結(jié)了 10+ 位阿里巴巴 Serverless 領(lǐng)域技術(shù)專家,打造出最適合開發(fā)者入門的 Serverless 公開課,讓你即學(xué)即用,輕松擁抱云計(jì)算的新范式——Serverless。
點(diǎn)擊即可免費(fèi)觀看課程:https://developer.aliyun.com/learning/roadmap/serverless
“阿里巴巴云原生關(guān)注微服務(wù)、Serverless、容器、Service Mesh 等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢(shì)、云原生大規(guī)模的落地實(shí)踐,做最懂云原生開發(fā)者的公眾號(hào)?!?/p> 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的OpenKruise v0.5.0 版本发布,支持无损的流式分批发布策略的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CNCF 官方大使张磊:Kubernet
- 下一篇: 从零入门 Serverless | 架构