Kubernetes實戰指南(三十一):零宕機無縫遷移Spring Cloud至k8s

1. 項目遷移背景

1.1 爲何要在「太歲」上動土?

目前公司的測試環境、UAT環境、生產環境均已經使用k8s進行維護管理,大部分項目均已完成容器化,而且已經在線上平穩運行許久。在咱們將大大小小的項目完成容器化之後,測試、UAT、生產環境的發版工具以及CICD流程慢慢的實現統一化管理,而且基於k8s開發了內部的發版審覈平臺,同時接入了Jira等項目管理工具。 前端

在自研平臺進行發版時,可以自動關聯項目的開發進度以及Release版本,最重要的是其能夠控制發版權限、統一發版工具及發版模式,而且支持一鍵式發版多個項目的多個模塊,同時也包括了發版失敗應用的統一回滾及單個應用的回滾。 安全

由於該項目從始至今一直在使用GitRunner進行發版,而且基於虛機部署,因此一直沒有集成到發版審覈平臺,可是因爲項目比較重要,而且涉及的服務和機器較多,因此必需要把這個項目進行容器化而且統一發版工具才能更好的適應公司的環境,以及更好的應對下一代雲計算的發展。服務器

1.2 爲何要棄用Git Runner?

首先咱們看一下Git Runner發版的頁面,雖然看起來很簡潔清爽,可是也不免不了會遇到一些問題。
在這裏插入圖片描述網絡

1.2.1 多分支並行開發問題

當多分支並行開發或者可以發版到生產環境的分支較多時,很容易在手動部署的階段點錯,或者看串行,固然這種機率很小。並且在一個項目的微服務拆分紅多個Git的Project時,發版時須要先找到對應的Project,而後在找到對應的發版分支,而後再點擊發版,若是有二十個微服務須要發版,那麼你須要重複二十次這個流程。 架構

咱們還能夠看到另一個問題,每次提交或者合併,都會觸發構建,當咱們使用Git Flow分支流時,可能同時有不少分支都在並行開發、並行測試、並行構建,若是Git Runner是基於虛機建立的,頗有可能會出現構建排隊的狀況,固然這個排隊的問題,也是能解決的。less

1.2.2 多微服務配置維護問題

其次,若是一個項目稍微大一些,維護起來也不是很方便。好比這個準備要遷移的項目,一個前端和二十多個業務應用,在加上Zuul、ConfigServer、Eureka將近三十個服務,每一個服務對應一個Git倉庫,而後每一個服務同時在開發的分支又有不少,若是想要升級GitLab CI腳本或者微服務的機器想要添加節點,這將是一個枯燥乏味的工做。運維

1.2.3 安全問題

最後,還有一個安全的問題,GitLab的CI腳本通常都是內置在代碼倉庫裏面的,這就意味着任何有Push或者Merge權限的人均可以隨意的修改CI腳本,這會致使意想不到的結果,同時也會威脅到服務器和業務安全,
針對發版而言,可能任何的開發者均可以點擊發版按鈕,這些可能一直都是一個安全隱患。 tcp

可是這些並不意味着Git Runner是一個不被推薦的工具,新版的GitLab內置的Auto DevOps和集成Kubernetes依舊很香。可是可能對於咱們而言,使用Git Runner進行發版的項目並很少,因此咱們想要統一發版工具、統一管理CI腳本,因此可能其它的CI工具更爲合適。ide

1.3 爲何要容器化?

1.3.1 端口衝突問題

容器化以前這個項目採用虛機部署的,每一個虛擬機交叉的啓動了兩個或者三個微服務,這會遇到一個問題,就是端口衝突的問題,在項目加入新應用時,須要考慮服務器之間端口衝突問題的,還要考慮每一個微服務的端口不能同樣,由於使用虛擬機部署應用時,可能會有機器節點故障須要手動遷移應用的狀況,若是部分微服務端口同樣,遷移的過程可能會受阻。 微服務

另外,當一個項目只有幾個應用時,端口維護起來可能沒有什麼問題,像本項目,涉及三十多個微服務,這就會成爲一件很痛苦的事情。而使用容器部署時,每一個容器相互隔離,全部應用能夠採用一樣的端口,就無需再去關心端口的問題。

1.3.2 程序健康問題

使用過Java程序的人大部分都遇到過程序假死的狀況,好比端口明明是通的,可是請求就是不處理,這就是一種程序假死的現象。而咱們在使用虛機部署時,每每不能把健康檢查作的很好,或許在虛機上面並無作接口級的健康檢查,這就會形成程序假死沒法自動處理的問題,而且在虛機上面作一些接口級的健康檢查及處理操做並非一件簡單的事情,一樣也是一件枯燥乏味的事情,尤爲是當一個項目微服務過多,健康檢查接口不一致時更爲痛苦。

但在k8s上面,自帶的Read和Live探針用以處理上面的問題就極其簡單,如圖所示,咱們能夠看到目前支持三種方式的健康檢查:
healthCheck

  • tcpSocket: 端口健康檢查
  • exec: 根據指定命令的返回值
  • httpGet: 接口級健康檢查

同時這些健康檢查的靈活性也很高,能夠自定義檢查間隔、錯誤次數、成功次數、檢查Host等參數,並且上面提到的接口級健康檢查httpGet也支持自定義主機名、請求頭、檢查路徑以及HTTP或者HTTPS等配置,能夠看到用k8s自帶的健康檢查能夠省去咱們很大一部分工做,不用再去維護很是多使人討厭的腳本。

1.3.3 故障恢復問題

在使用虛機部署應用時,有時可能會碰到宿主機故障,單節點的應用沒法使用,或者多節點部署的應用因爲其餘副本不可用,致使自身壓力大出現服務延遲的狀況。而偏偏宿主機沒法很快恢復,這時可能就須要手動添加節點或者須要新加服務器才能解決這類問題,這個過程可能會很漫長,或許也很痛苦。由於須要去準備依賴環境,而後才能去部署本身的應用,而且有時候你可能還須要更改CI腳本。。。

而使用k8s編排時,咱們無需關心這類問題,一切的故障恢復、容災機制都由強大的k8s負責,你能夠去喝杯咖啡,或者你剛打開電腦去處理這個問題時,一切都已經恢復如初。

1.3.4 其餘小問題

固然k8s給咱們帶來的便利性和解決的問題遠不止上面所說的,容器鏡像幫咱們解決了依賴環境的問題,服務編排幫咱們解決了故障容災的問題,咱們可使用k8s的包管理工具一鍵建立一套新的環境,咱們可使用k8s的服務發現讓開發人員無需再關注網絡部分的開發,咱們可使用k8s的權限控制讓運維人員無需再去管理每臺服務器的權限,咱們可使用k8s強大的應用程序發佈策略讓咱們無需過多的考慮如何實現零宕機發布應用及應用回滾,等等,這一切的便利性正在悄悄的改變着咱們的行爲。

2. 遷移計劃

2.1 藍綠遷移

首先來看一下遷移以前的架構
vmStart
和大多數SpringCloud架構同樣,使用NodeJS做爲前端,Eureka用做服務發現,Zuul進行路由分發,ConfigServer做爲配置中心。這種架構也是SpringCloud在企業中最廣泛的架構,沒有使用更多額外的組件,因此咱們在第一次遷移時,也沒有考慮太多,仍是按照遷移其餘項目時用的方案,即在k8s上新建一套環境(本次遷移沒有涉及到中間件),也就是容器化環境,配置一個一樣的域名,而後添加hosts解析進行測試,沒有問題的話直接進行域名切換便可完成遷移。這種方式是最簡單也是最經常使用的方式,相似於程序發版的藍綠部署,此時在k8s新建一套環境對應的架構圖以下:
blueGreen
在進行測試時,此項目同時並行了兩套環境,一套虛機環境,一套容器環境,容器環境只接收測試人員的流量,兩套環境鏈接的是同一套中間件服務,由於其餘項目大部分也是按照這種方式遷移的,而且該項目在測試環境也進行過一樣的流程,沒有出現什麼問題,因此也一樣認爲這種方式在本項目也不會出現什麼問題。但每每現實總會與預期有所差別,在測試過程當中因爲兩套環境並存,致使了部分生產數據出現問題,因爲容器環境沒有通過完整性測試,也沒有強制切換域名,後來緊急關停了全部的容器問題才得以恢復。因爲時間比較緊迫,咱們並無仔細排查問題所在,只是修復了部分數據,後來咱們認爲多是遷移過程當中部分微服務master分支和生產代碼不一致形成的,固然也可能並非這麼簡單。爲了規避這類問題再次發生只能去修改遷移方案。

2.2 灰度遷移

因爲上面的遷移方案出了點問題,就從新定了一個方案,較上次略微麻煩,採用逐個微服務遷移至k8s,相似於應用程序發版的灰度發佈。

單個應用遷移時,須要確保容器環境和虛機環境的代碼一致,在遷移時微服務採用域名註冊的方式。也就是每一個微服務都配置一個內部域名,經過域名去註冊到Eureka,而不是採用容器的IP和端口去註冊(由於k8s內部的IP和虛擬機未打通),此時的環境以下圖所示:
canary
此時有一個域名service-c.interservice.k8s指向ServiceC,而後ServiceC註冊到Eureka時修改本身的地址爲該域名(默認是宿主機IP+端口),以後別的應用經過該地址調用ServiceC,當ServiceC測試無問題後,下線虛擬機裏面的ServiceC,最後的架構如圖所示:
canaryAll
除了Zuul、前端UI和Eureka,其餘服務都使用灰度的方式遷移到k8s,比藍綠的形式更爲複雜,須要爲每一個微服務單首創建Service、域名,在遷移完成以後還須要刪除。到這一步後,除了Eureka其餘服務都已經部署在k8s上,而對於Eureka的遷移,涉及的細節更多。

2.3 Eureka遷移

到這一步後,服務訪問沒有出現其餘問題,除了Eureka以外的服務,都已經部署在k8s,而Eureka的過分型遷移設計的問題可能會更多。由於咱們不能直接在k8s上部署一套高可用的Eureka集羣,而後直接把ConfigServer裏面的微服務註冊地址改爲k8s中的Eureka地址,由於此時兩個Eureka集羣都是獨立的Zone,註冊信息並不會共享,這種會在更改配置的過程當中丟失註冊信息,此時架構圖可能會出現以下狀況:
eureka
也就是在替換配置的過程當中,可能會有ServiceA註冊到了以前的Eureka上,ServiceB註冊到了k8s中的Eureka,就會致使ServiceA找不到ServiceB,反過來也是一樣的問題。

因此在k8s搭建Eureka的集羣后,須要給每一個Eureka實例配置一個臨時域名,而後更改以前的Eureka集羣和k8s裏面的Eureka集羣的zone配置,讓k8s裏面的Eureka和虛機裏面的Eureka組成一個新的集羣,這樣註冊信息就會被同步,不管註冊到Eureka都不會形成服務找不到,此時的架構圖以下(此時全部的服務仍是註冊到原來的Eureka集羣中):
eurekaVMK8s
接下來須要作的事情,就是更改微服務的配置,此時須要更改地方有三處:

  1. 微服務註冊到Eureka的地址更爲容器IP和端口,再也不使用域名註冊,由於此時微服務都已經在k8s中,直接經過內部Pod IP便可鏈接;
  2. 更改服務註冊的Eureka地址爲k8s Eureka的service地址,Eureka使用StatefulSet部署,直接經過eureka-0/1/2.eureka-headless-svc就能夠鏈接;
  3. 待全部的微服務都已經遷移完畢後,更改k8s的Eureka集羣的zone爲:eureka-0/1/2.eureka-headless-svc,並刪除其餘微服務的Service和域名。

最終的架構圖如圖:
end

3. 總結

爲了保證服務的可用性,咱們無奈的採用灰度的方式進行遷移,比藍綠的方式麻煩了不少,並且須要考慮的問題也有不少。在程序沒有任何問題的前提下,仍是建議採用藍綠的方式進行遷移,不只遇到的問題少,遷移也比較方便快捷。固然採用灰度的方式對於大型的項目或者不能中斷服務的項目可能更爲穩妥,由於一次性所有切換可能會有遺漏的須要測試的地方。固然不管哪一種方式,對應用的容器化、遷移至Kubernetes纔是比較重要的事情,畢竟雲計算纔是將來,而Kubernetes是雲計算的將來。

廣告時間
有須要學習k8s的能夠關注下這個視頻教程:https://edu.51cto.com/sd/518e5

相關文章
相關標籤/搜索