1、前言
在當下微服務架構盛行的時代,用戶希望應用程序時時刻刻都是可用,為了滿足不斷變化的新業務,需要不斷升級更新應用程序,有時可能需要頻繁的發布版本。實現"零停機"、“零感知”的持續集成(Continuous Integration)和持續交付/部署(Continuous Delivery)應用程序,一直都是軟件升級換代不得不面對的一個難題和痛點,也是一種追求的理想方式,也是DevOps誕生的目的。
2、滾動發布
把一次完整的發布過程,合理地分成多個批次,每次發布一個批次,成功后,再發布下一個批次,最終完成所有批次的發布。在整個滾動過程期間,保證始終有可用的副本在運行,從而平滑的發布新版本,實現零停機(without an outage)、用戶零感知,是一種非常主流的發布方式。由於其自動化程度比較高,通常需要復雜的發布工具支撐,而k8s可以完美的勝任這個任務。
3、k8s滾動更新機制
k8s創建副本應用程序的最佳方法就是部署(Deployment),部署自動創建副本集(ReplicaSet),副本集可以精確地控制每次替換的Pod數量,從而可以很好的實現滾動更新。具體來說,k8s每次使用一個新的副本控制器(replication controller)來替換已存在的副本控制器,從而始終使用一個新的Pod模板來替換舊的pod模板。
大致步驟如下:
- 創建一個新的replication controller。
- 增加或減少pod副本數量,直到滿足當前批次期望的數量。
- 刪除舊的replication controller。
4、演示
使用kubectl更新一個已部署的應用程序,並模擬回滾。為了方便分析,將應用程序的pod副本數量設置為10。
kubectl -n k8s-ecoysystem-apps scale deployment helloworldapi --replicas=10
4.1. 發布微服務
查看部署列表
$ kubectl get deployments -n k8s-ecoysystem-apps
查看正在運行的pod
$ kubectl get pods -n k8s-ecoysystem-apps
通過pod描述,查看應用程序的當前映像版本
$ kubectl describe pods -n k8s-ecoysystem-apps
升級鏡像版本到v2.3
$ kubectl -n k8s-ecoysystem-apps set image deployments/helloworldapi helloworldapi=registry.wuling.com/justmine/helloworldapi:v2.3
4.2. 驗證發布
檢查rollout狀態
kubectl -n k8s-ecoysystem-apps rollout status deployments/helloworldapi
檢查pod詳情
kubectl describe pods -n k8s-ecoysystem-apps
從上圖可以看到,鏡像已經升級到v2.3版本
4.3. 回滾發布
kubectl -n k8s-ecoysystem-apps rollout undo deployments/helloworldapi
到目前為止,整個滾動發布工作就圓滿完成了!!!
那么如果我們想回滾到指定版本呢?答案是k8s完美支持,並且還可以通過資源文件進行配置保留的歷史版次量。由於篇幅有限,感興趣的朋友,可以自己下去實戰,回滾命令如下:
# 1. 查看版次
kubectl -n k8s-ecoysystem-apps rollout history deployment/helloworldapi
# 2. 回滾到指定版次
kubectl -n k8s-ecoysystem-apps rollout undo deployment/helloworldapi --to-revision=<版次>
5、原理
k8s精確地控制着整個發布過程,分批次有序地進行着滾動更新,直到把所有舊的副本全部更新到新版本。實際上,k8s是通過兩個參數來精確地控制着每次滾動的pod數量:
maxSurge
滾動更新過程中運行操作期望副本數的最大pod數,可以為絕對數值(eg:5),但不能為0;也可以為百分數(eg:10%)。默認為25%。maxUnavailable
滾動更新過程中不可用的最大pod數,可以為絕對數值(eg:5),但不能為0;也可以為百分數(eg:10%)。默認為25%。
如果未指定這兩個可選參數,則k8s會使用默認配置:
kubectl -n k8s-ecoysystem-apps get deployment helloworldapi -o yaml
5.1. 剖析部署概況
DESIRED
最終期望處於READY狀態的副本數CURRENT
當前的副本總數UP-TO-DATE
當前完成更新的副本數AVAILABLE
當前可用的副本數
當前的副本總數 = 10 + 10 * 25% = 13,所以CURRENT為13。
當前可用的副本數 = 10 - 10 * 25% = 8,所以AVAILABLE為8。
5.2. 剖析部署詳情
kubectl -n k8s-ecoysystem-apps describe deployment helloworldapi
整個滾動過程是通過控制兩個副本集來完成的,新的副本集:helloworldapi-6564f59f66;舊的副本集:helloworldapi-6f4959c8c7 。
理想狀態下的滾動過程:
- 創建了一個新的副本集,並為其分配3個新版本的pod,使副本總數達到13,一切正常。
- 通知舊副本集,銷毀2個舊版本的pod,使可用副本總數保持到8,一起正常。
- 當兩個副本銷毀成功后,通知新副本集,再新增2個新版本的pod,使副本總數達到13,一切正常。
只要銷毀成功,新副本集就會創造新的pod,一直循環,直到舊的副本集pod數量為0。
滾動升級一個服務,實際就是創建一個新的RS,然后逐漸將新RS中副本數增加到理想狀態,將舊RS中的副本數減小到0的復合操作;
無論理想還是不理想,k8s最終都會使應用程序全部更新到期望狀態,都會始終保持最大的副本總數和可用副本總數的不變性!!!
6、總結
本篇詳解了k8s滾動更新機制,並通過實戰演示了微服務的滾動更新,當然還可以加入健康檢查和歷史版次回滾,大家可以下去自己實踐,在實戰中學習和進步,基礎打牢后,我們將結合實際情況,實戰更多的例子,下一篇將實戰金絲雀發布微服務,請繼續關注。
本篇已貢獻給kubeasz,使用指南,特性實驗,Rollingupdate
如果你覺得本篇文章對您有幫助的話,感謝您的【推薦】。
如果你對 kubernets 感興趣的話可以關注我,我會定期的在博客分享我的學習心得。
7、延伸閱讀
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#rolling-update
https://kubernetes.io/docs/tutorials/kubernetes-basics/update-intro/
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#rolling-update
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/cli/simple-rolling-update.md
https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller
https://kubernetes.io/docs/tutorials/kubernetes-basics/update-interactive
https://kubernetes.io/images/docs/kubectl_rollingupdate.svg