微服務架構下 CI/CD 如何落地

本文系雲原生應用最佳實踐杭州站活動演講稿整理。杭州站活動邀請了 Apache APISIX 項目 VP 溫銘、又拍雲平臺開發部高級工程師莫紅波、螞蟻金服技術專家王發康、有贊中間件開發工程師張超,分享雲原生落地應用的經驗心得,如下是莫紅波《微服務架構下 CI/CD 如何落地》分享內容。html

莫紅波,又拍雲平臺開發部高級工程師,目前專一於容器及虛擬化技術在又拍雲的私有云實踐,主要負責又拍雲容器雲的設計和開發工做。web

你們好,今天分享的主題是《微服務架構下 CI/CD 如何落地》,圍繞如下兩部分展開:數據庫

  • 理論篇,討論從單體到微服務的過程當中會面臨怎樣的挑戰,以及微服務的測試模型
  • 實踐篇,圍繞集成測試環境的服務發現須要怎麼作,如何落地持續交付和持續部署

背景

或許你們對於互聯網公司的共同印象是 996,對於我我的而言,互聯網公司還有另外一個特色,那就是常常須要擁抱變化。在互聯網公司,新產品上線、下線、調整,這都是很屢見不鮮的事情。在這種狀況下,一個好的鬆耦合的架構就顯得尤其重要。安全

恰好我最近就有遇到這個問題,我在作的項目,帳號這塊是對標 GitHub 的註冊制帳號機制的。本來的需求是用戶註冊咱們的平臺,註冊完成後能夠建立一個屬於本身的團隊,並將其餘人拉入本身的團隊。可是當咱們作完這部份內容後發現,客戶仍是更偏好「帳號+子帳號」的模式,公司一個總的帳號,全部員工單獨開子帳號進行關聯。這讓咱們已經作好的項目變得很是尷尬,須要當即擁抱變化,須要根據最新的需求進行調整。這時,我就發現擁有一套鬆耦合的架構的重要性,好比帳號這一部分,若是把它單獨拎出來,作好足夠的抽象,提供必要的對外接口,可能會更加靈活,擴展性更加好。服務器

那怎樣擁有一套鬆耦合的架構?有什麼好的方案呢?在我看來有兩個,一個是幾年前出現的 SOA,即將服務進行單獨化,將每一塊都進行拆分;另外一個就是最近幾年火熱的微服務了。我認爲,微服務跟 SOA 實際上是一回事,只不過微服務比 SOA 拆分粒度更細,功能也更小。網絡

在調研微服務過程當中,不少人會有疑問:「咱們是一個很小的團隊,小團隊適不適合上微服務呢?」。由於上微服務就意味着一個服務可能就會被拆分紅 10 個、20 個甚至更多個的服務,這就讓小團隊不得不去考慮本身的測試、部署、更新成本是否是會翻不少倍。架構

那麼我對於「小團隊適不適合上微服務」這個問題的答案是什麼呢?我認爲是徹底能夠上的,不過你須要注意一點:作好自動化,能交給自動化來實現的,就不要人工介入了。app

在聊如何作自動化集成測試(CI)以前,我先和你們談一談從單體如何到微服務,服務是如何拆分的,以及微服務的測試通常是怎麼作的。微服務

從單體到微服務

如上圖所示,咱們能夠看到圖左邊是一個單體服務,右邊則是通過微服務拆解後的。咱們能夠看到它有 4 個特色:單元測試

  • 根據不一樣領域拆分
  • 服務之間經過網絡協議通訊
  • 擁有獨立的數據庫
  • 擁有特定對外開放的接口

微服務測試模型

咱們都知道,若是須要一個服務可以穩定運行,那測試確定是少不了的。而就像咱們微服務化有一套理論同樣,微服務測試也擁有屬於本身的金字塔理論:最底層是單元測試,成本相對較低,像咱們在 API 認證部分作的簽名校驗模塊,它通常不須要依賴其餘東西,所以測試效率也比較高;第二層是集成測試,這一層你就必需要依賴一些第三方的服務模塊或者組件,好比咱們通常會用到數據庫的測試,就屬於集成測試的範疇;第三層是 e2e 測試,它會模擬客戶端的行爲來進行測試,你們也許都接觸過這類測試,像K8S 就有一個 e2e 測試,當你去申請 CNCF 的一致性認證時,就須要經過官方提供的 e2e 測試;最上層是 UI 測試,好比對於頁面的點擊調整是否符合預期,這部分咱們如今作的比較弱,還處在人工模式下,但咱們也在努力將它更新成自動化。

從這個微服務測試金字塔咱們能夠看到,越靠近底層成本越低,你只須要幾行代碼就能完成,效率也很是高。同時越底層它對於三方或組件的依賴也越低,自動化也就越簡單。到這裏可能就有人想問:「既然越底層的成本越低,那咱們能不能只跑單元測試?」在解答這個問題前,你們先看下面這張圖。

這兩扇窗戶,每一扇單獨存在的時候都是無缺的窗戶,能夠正常開合。可是兩個都安裝到牆上後就沒有辦法正常開合。這就是咱們不能只跑單元測試的緣由了,不跑集成測試就沒法發現一些問題。同理不跑單元測試也會有一些沒法發現的問題,因此咱們在跑測試的時候,集成測試和單元測試,一項都不能少。

那具體實踐的時候要如何作呢,我推薦你們分紅兩步來進行:

  • 第一步是將底子打好:你須要對你的的微服務進行單元化測試,編寫單元化的測試用例,而後再強化集成測試。沒有好底子的微服務是不可靠的,任什麼時候候均可能會出問題,並且出問題後的排查會很是費時。
  • 第二步是自動化的持續集成環境:將可以自動化的部分所有進行自動化,減小人工的介入。

GitLab/CI

自動化集成環境這塊目前已經有不少的開源方案了,好比常見的 Jenkins,還有 GitLab。咱們選擇的是 GitLab,或者說是選擇了 GitLab/CI,選擇它的緣由有如下幾點:

  • 統一的 web 頁面
  • 能夠再 MR 中跳轉查看
  • Pipeline 編排直觀展現
  • 全部操做都在項目中搞定
  • GitLab 官方支持

GitLab WorkFlow

既然咱們選擇使用了 GitLab,那咱們內部就會嚴格遵照 GitLab 的 WorkFlow。WorkFlow 主要分爲兩個部分。

第一部分是面向代碼倉庫。代碼倉庫中,咱們通常會有三類分支,第一類分支是 master 分支,通常只會有一個,咱們會定義 master 分支,並基於這個分支進行線上版本的發佈。第二類分支是 develop 分支,通常也只會有一個,develop 分支是從 master 分支中 checkout 出來的,功能比 master 領先,包含一些已經完成功能開發,可是尚未發佈的功能。第三類分支是 feature 分支,特性分支,通常會有不少個,新功能都會在這個分支上進行開發,每每一個功能對應一個 feature 分支。最後一類是 hotfix 分支,這個就比較常見了,線上發佈後,若是發現了一個須要緊急修復的bug,這時你就能夠在 master 分支上 checkout 出來一個 hotfix 分支,把代碼改掉。不過進行這個操做時你須要注意,master 分支和 develop 分支都須要進行該 commit 合併,不然就不能算完成了 bug 修復。

第二部分與 CI/CD 有關。以咱們的流程舉例,研發的同窗提交代碼到 GitLab 倉庫,以後 GitLab 會觸發事先約定好的 CI 的 pipeline 進行測試和構建。等待測試和構建成功後再進行 code review 的確認,確認無誤後會合併到 develop 分支並最終合併到 master 分支進行發佈。這就是 GitLabCI 的一個配置,總結來看能夠劃分爲下圖的四個階段。

下圖是配置文件對應的 pipeline 的展現,你們能夠看一下。

微服務下的場景變形

其實到目前爲止的方案,已是微服務沒有大熱前的完備方案了。若是你想要將方案運用到微服務的集成測試裏,你還須要作一些變形,不妨參考下圖中所示的又拍雲如今使用的整套流程。

從圖中能夠看到,咱們目前使用的整套流程相比標準的其實有作一些小的變形,變形主要集中在中間的集成測試環境這一塊,咱們將每一個服務器都部署在了集成環境內,使集成環境變成一個準發佈環境。具體流程是,當咱們的建立 projectA 後,由它來 push 代碼,完成後觸發 CI,也就是在 GitLab runner 上進行測試。

在跑測試的過程當中,由於 A 服務須要調用 B 和 C 服務,因此經過 API 去請求集成環境中的對應服務。若是測試完成後沒有問題,則合併到主線。再經過在 master 分支打 tag 的方式來觸發容器構建並推送到 Harbor 鏡像倉庫。最後咱們會作一個線上 release。這個就是咱們的大體流程了。

那麼接下來咱們來具體看一下變形中會遇到的問題。

服務發現

在微服務場景下的變形中遇到了不少問題,我以爲其中值得注意的是「服務發現」。好比咱們如今有這樣一個場景,A 服務在跑測試時須要依賴 B 服務和 C 服務,面對這個需求,在沒有引入 Kubernetes 以前,咱們能夠經過使用一臺共用機器,將服務都佈置到這臺機器上,並在測試代碼裏寫死 IP 地址,讓每一次測試都在這個環境內跑。但這個方法會有下面四個沒法忽視的問題:

  • 服務更新延遲
  • 環境權限混亂
  • 人工操做容易出錯
  • 維護成本太高

所以咱們引用了 Kubernetes Service 的方案進行優化。

Kubernetes Service 的流程你們能夠大概看一下。咱們先定義一個 Service, 咱們這邊建立的 ClusterIP 類型的,定義了暴露端口 8000,目標端口 8000,協議是 TCP,標籤選擇器是 app=holdon。經過這種方式,咱們能夠把一組相同功能的服務,綁定在同一個 Service 下。在 Kubernetes 集羣內,定義好 Service 後,會提供內部的 DNS 解析,你能夠經過一個固定的域名訪問指定的 Service。這樣當在跑測試的時候就能夠經過這個域名加對應端口,調用到對應服務了。

持續交付

持續交付(英語:Continuous Delivery,縮寫爲 CD)。每一個項⽬都要有⼀個 Dockerfile,提供了服務運⾏所需的環境,以及服務對應的軟件包。當須要發版本的時候,咱們會在主線上打上⼀個 tag,觸發鏡像構建,而後推送到 Harbor 鏡像倉庫。其中,這個 tag 也會對應到鏡像的版本號。

上圖是咱們的 CD 流程你們能夠參考看一下。須要提一下的是,咱們引用 Harbor 的緣由是由於它相對官方的 Registry 更安全。你們應該都知道,官方的 Registry 自己不帶權限校驗,當你公司內部使用的時候,這個問題會致使你的鏡像有被其餘部門的人覆蓋掉的可能性,因此咱們引入了 Harbor。但這裏也有一個問題,使用同一個 tag 去推依然會被覆蓋的狀況。不過好歹作到了小組和小組之間、部門和部門之間的隔離。

持續部署

持續部署(英語:Continuous deployment,縮寫爲 CD),目前這塊,在實踐過程當中,咱們是隻針對集成測試環境,線上更新仍是走常規的流程。給項⽬增長⼀個 k8s-deploy.yaml 的⽂件,⾥⾯包含了服務相關的配置、部署⽅式、訪問⽅式等等,等待鏡像構建完成後,apply 該⽂件就能夠了 。

持續部署流程圖

回顧

如今咱們再回到服務變形的流程圖來看一下,當咱們有 A、B、C 三個服務,且 A 服務在測試時須要調用集成環境內的 B 服務與 C 服務時,能夠經過 K8S 提供的內部域名進行訪問。等待整塊測試跑完後,咱們在主線上打 tag,讓 CI 去幫執行 image build 構建鏡像並推送到 Harbor 倉庫。

其中涉及到的準發佈環境,能夠經過 kubectl apply 的方式進行部署。因爲線上環境更復雜,推薦你們經過自研的容器雲平臺來進行操做,咱們就是這麼處理的,經過雲平臺發佈,功能更加全面安全,更加符合線上部署的流程。

成果展現

最後,跟你們分享下最近正在作的項目的狀況。從 2019 年 12月 開始到如今,咱們天天基本保持在一個較高的 commit 數上,而這其中一共進行了大約 4500 次的測試。想象下,若是沒有這套自動化持續集成環境,測試須要怎麼來進行,須要投入人力資源。

點擊閱讀可直接跳轉,獲取現場分享視頻、下載 PPT。

推薦閱讀

【實戰分享】從選型到項目落地,漫談 gRPC

白話科普,10s 瞭解 API

相關文章
相關標籤/搜索