kubernetes集群升級的正確姿勢


kubernetes社區非常活躍,每季度都會發布一個release。但是線上集群業務可用性要求較高,場景復雜,任何微小的變更都需要非常小心,此時跟隨社區版本進行升級略顯吃力。但是為了能夠使用到最新的一些feature我們必須不定期進行一些升級操作,在經歷了一次線上集群的升級操作,踩完一些坑之后,分享一些收獲與感悟。原來的集群版本是1.10,為了提高GPU集群的資源利用率,需要在調度器層面支持一些搶占調度等新特性,所以升級到1.14,此次升級的集群規模不是特別大,但是有一些在線任務,還是需要慎重操作。目前kubernetes社區中所有的工具(包括使用較多的kubeadm,kops等工具)對於生產環境高可用的集群升級都顯的比較乏力,所以還是建議手動升級,更加安全可控,出現問題便於定位修復。

升級策略

升級方式可以分為原地升級和異地升級:

  • 原地升級是指在原有集群直接替換二進制進行升級,此種方式升級方便,運維代價較小,理論上來說多副本的業務不會有downtime,在充分測試的情況下優先選擇原地升級.
  • 異地升級是指新搭建一個一模一樣的高版本集群,然后手動或自動遷移業務到新集群。此種方式需要上層提供滾動升級的能力,支持兩個backend,需要額外的開發工作。且默認double一份原集群pod到新集群不會對業務造成影響,對於使用ceph等持久化存儲的集群來說,可能會有問題。但此種方式升級更加安全可控,風險更低。

官方建議升級過程

  1. 首先閱讀相關release note,重點關注其中幾部分: Known Issues,Action Requireed,Deprecations and removals。社區會將一些變化highlight到這里,閱讀這些變化可以明確自己需要采取哪些行動。
  2. kubernetes 建議不斷地進行小版本升級,而不是一次進行大的版本跳躍。具體的兼容策略是: slave組件可以與master組件最多延遲兩個小版本(minor version),但是不能比master組件新。client不能與master組件落后一個小版本,但是可以高一個版本,也就是說: v1.3的master可以與v1.1,v1.2,v1.3的slave組件一起使用,與v1.2,v1.3,v1.4 client一起使用。官方建議每次升級不要跨越兩個版本,升級順序為: master,addons,salve。
  3. slave節點的升級是滾動升級,官方建議首先使用kubectl drain驅逐pod之后,然后升級kubelet,因為kubelet會有一些狀態信息文件存儲在node節點上,社區並不保證這些狀態文件在版本間的兼容性。
  4. apiserver升級之前需要確保resource version被正常支持,目前kubernetes會逐步廢棄掉,例如: DaemonSet,Deployment,ReplicaSet 所使用的 extensions/v1beta1,apps/v1beta1,apps/v1beta2 將會在v1.16中完全廢棄掉,屆時,如果你再去讀取這些版本的資源,apiserver將不會認識這些資源,任何的增刪改查都無法進行,只能通過etcdctl進行刪除。目前社區正在開發遷移工具,並且在支持該工具之前,所有的版本移除操作都會被凍結,所以目前(2019.5.20)來說是相對安全的。

生產實踐升級過程

  1. 如果采用官方建議的升級策略需要小版本不斷升級,但是線上運維壓力較大,業務場景復雜,大多數情況下不可能跟隨社區版本不斷升級,所以可以在充分測試的前提下進行大版本跳躍升級。
  2. 官方建議升級kubelet之前先將所有pod驅逐,但是此種方式可能會造成業務容器頻繁重啟。例如升級nodeA時pod漂移到未升級節點nodeB,后續升級nodeB可能需要繼續驅逐該pod。為避免頻繁重啟業務,在充分測試的情況下不用驅逐,直接原地升級即可。目前(2019.6.5)在master組件升級之后重啟或升級kubelet會導致大部分容器重啟,因為kubelet通過hash(container spec)來生成容器的唯一標識,不同版本間container spec會發生變化,引起hash值變化,進而導致容器重啟,參見kubernetes/kubernetes: Issue #63814。在不驅逐pod的情況下原地升級最壞情況下只有一次重啟,而且volume等信息不會發生變化,對於集群的擾動也較小。 有能力的同學可以研究下如何做到升級kubelet不重啟容器。
  3. 雖然kubernetes建議先升級master組件,然后再升級node組件,但是實際應用過程中建議先停掉controller-manager,然后升級master組件,node組件,最后再升級controller-manager,因為controller-manager中會進行一些狀態的調諧(reconcile),對於actual status不符合desire status的對象會觸發一些操作。升級過程中盡管我們會進行充分的測試,但是也難免出現一些非預期的情況下,例如apiserver中某些資源對象的兼容性不好,或者其中的某些字段進行調整,觸發controller-manager執行非預期操作,例如重建一個deployment下所有的pod,更糟糕的是,如果此時kubelet還未升級,就可能不認識新版本一些資源對象中的新增的某些字段,此時老的pod被刪掉了,但是新的pod沒有起來,就造成一定的服務中斷。(后面會有相關的案例)
  4. 升級過程中建議調高日志級別,方便定位問題,在升級完成之后在降低日志級別。
  5. 備份etcd數據,並進行故障恢復的演練,作為升級失敗的最后一道防線。
  6. 升級之前review集群狀態,確保所有組件正常工作,review重要業務的實例數,避免副本數為1,並且適當設置PDB; 需要檢查是否有單個node帶有特殊的label,可能有pod依賴於該label,如果該node異常導致pod也會發生故障(這個坑真的有人踩過:參見:ingress-cordoned)。

升級過程中發現的“坑” (已填)

  1. 上面的實踐3中就是筆者測試的時候發現的一個坑: 目前升級會導致部分controller(daemonset)重建容器,升級之后因為pod spec發生變化,部分controller會創建新的controllerrevision ,升級更新所有其控制的容器。如果先升級master/controller-manager,因為此時kubelet還未升級,版本較低,會出現不兼容的字段,嚴重情況下kubelet會reject掉該pod,導致最終該node上此daemonset container退出並無法重啟。如果daemonset 設置為滾動升級,並且maxUnavailable設置為1的話,可以避免一定損失,最多只允許同時掛掉一個daemonset container。參見kubernetes/kubernetes: Issue #78633。所以最佳實踐還是升級之前停掉Controller-manager,集群實際完畢之后最后升級controller-manager。設置所有controller的升級策略為滾動升級並設置最大不可用實例數。對於上述Issue官方在新版本中已經進行修復並backport到舊版本中。
  2. 對於一些剛從alpha轉到beta的特性,beta版本是默認開啟的版本,對於這些特性一定要非常小心,可能仍然會存在一些bug,建議還是手動關閉,對於一些可用性要求較高的集群建議只使用GA的feature。這次踩的一個坑就是node lease特性,該特性在1.14中剛好是Beta版本默認開啟,這是一個非常有用的feature,對於大規模集群可以有效降低apiserver,etcd的負載,但是kubelet中node lease的默認renew周期是hardcode的10s中且不可調整,也就是說此時node與master心跳的頻率只能是10s,此時指定--node-status-update-frequencyflag沒有任何作用,如果controller-manager中配置的--node-monitor-grace-period剛好是10s,這時候node會不斷地在ready和non-ready直接搖擺,參見kubernetes/kubernetes issue#80172,該issue已經被筆者給修復掉了 😃。

寫在后面

kubernetes還是在高速的迭代過程中,升級過程中出現不兼容是在所難免的, 唯有搞懂內部的實現機制才能保障集群的長治久安。發現問題也需要我們有能力去解決並且反饋到社區中,取之於社區,理應回報於社區。

reference

Kubernetes Release Versioning

2019.11.26 update: 對於先停掉controller-manager的這種做法其實也是有問題的,正常情況下,pod重啟endpoint controller會將該podIP從endpoint ip列表中移除出去,但是如果停掉controller-manager此時如果容器退出,可能會繼續將流量轉發到該podIP上,導致流量丟失,最好的方式是先停掉部分controller,例如deployment等,然后讓endpoint controller正常運行, 隨后再開啟deployment controller。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM