DevOps 視角的前後端分離與實戰
本文作者:CODING – 廖紅坤
前言
隨着微前端、微服務等技術理念和架構的蓬勃發展,我們已經沒必要去討論為什麼要前後端分離這種話題,前後端分離已成為互聯網項目開發的標準模式。前後端在各自的領域發展越來越縱深。
DevOps 視角的前後端分離
今天我們換個視角,從 DevOps 的角度來聊聊前後端分離。
項目協同
DevOps 體系中包含了敏捷開發方法論,而前後端分離前的開發模式無法做到敏捷。開發過程中前後端強依賴,需多次反覆集成才能發佈可用版本,違背了敏捷開發「適應性」的特點(適應性即歡迎變化)。此外,前後端串行工作的方式拉長了版本發佈周期,違背了敏捷開發「快速發佈小版本」的理念。
- 前後端分離前的協作模式:
-
產品經理根據需求出原型
-
UI 出設計圖
-
前端做 html 頁面
-
後端將 html 頁面套成 jsp 頁面(前後端強依賴,後端必須要等前端的 html 做好才能套 jsp。如果過程中 html 發生變更,後端也要被迫調整,開發效率低)
-
集成出現問題
-
前端返工
-
後端返工
-
二次集成
-
集成成功
-
交付
- 分離後的協作模式:
-
產品經理根據需求出原型
-
UI 出設計圖
-
前後端約定接口、數據和參數
-
前後端並行開發(無強依賴,可前後端並行開發,如果需求變更,只要接口和參數不變,就不用兩邊都修改代碼,開發效率高)
-
後端 API 自動化測試
-
前後端集成
-
前端頁面調整
-
集成成功
-
交付
代碼管理
前後端分離後,前後端代碼分開管理,後端不需要合併前端代碼,減少代碼合併衝突問題。此外,前後端分離後,後端可以根據業務類型自由選用編程語言開發不同的組件,實現松耦合,與微服務架構不謀而合。
測試管理
前後端分離後,對應的測試也分離了。由於後端只輸出 api 接口,於是可以很方便的進行自動化測試,提早暴露問題,並且測試成本很低。而前端可以不依賴後端,自己本地 mock 數據,待前後端接口對接後,測試可以開始功能測試。
交付部署
1913 年,福特汽車開發了世界上第一條流水線,大幅提高了汽車的生產效率,每 24 秒流水線就能製造一輛汽車,實現了汽車的規模化生產,福特也因此成了美國最大的汽車製造商。
交付部署包含持續集成和持續部署,其核心就是流水線。從代碼分離開始,前後端就形成了兩條並行的流水線,各自獨立編譯,構建,打包,發佈。發佈過程中不需要對方在場,出現了問題各自回退。
從項目協同、代碼管理、測試到交付部署,需要一套完整的 DevOps 工具鏈支撐,比較典型的如 Jira + GitLab + Jenkins + Nexus + Kubernetes,但這些工具之間賬戶體系、操作習慣互不相通,試想團隊每加入一個新成員管理者都要在每個工具平台為其添加賬戶,新成員也要花時間去逐一熟悉。這對管理者和新人都是不必要的負擔。這樣的背景下,我們可以採用 CODING 提供的一站式 DevOps SaaS 服務,快速實現前後端分離的 DevOps 最佳實踐。
快速實踐 DevOps
本文以信奉敏捷開發理念的互聯網團隊 突突突小分隊
為例,基於 CODING DevOps,以項目管理為起點,持續部署為終點演示快速實現前後端分離項目的 DevOps 最佳實踐。相關人員:
- 團隊 Leader: 老李
- 運維:小胖
- 測試:小莉
- 後端:大熊
- 前端:阿強
技術棧:
- 後端(Python + Flask)://linrp.coding.net/p/front-back-cd/d/flask-backend/git
- 前端(React)://linrp.coding.net/p/front-back-cd/d/react-frontend/git
- 運維(Docker + Kubernetes)://linrp.coding.net/p/k8s-yaml/d/k8s-yaml/git
前提準備
- 使用騰訊雲 TKE 創建一個 Kubernetes 集群: //cloud.tencent.com/document/product/457/11741
創建項目和代碼倉庫
2020 年 10 月 26 日早上 11:00 整,突突突小分隊
Leader 老李在周會上召開了新項目啟動大會,由於是新項目,老李引進了 CODING DevOps 產品,目的是將 DevOps 理念和工作流貫徹到團隊實際工作中,規範團隊的開發、測試和運維流程,並進一步提升產品發佈效率。散會前老李當場創建兩個項目分別為 front-backend-cd
和 k8s-yaml
,並表示給大家一天的時間了解 CODING DevOps 產品。
突突突小分隊
成員之間配合已經有相當的默契,在了解了 CODING DevOps 產品後,第二天(10 月 27 日)各自開始了有條不紊的工作:
-
後端大熊在項目
front-backend-cd
中創建後端代碼倉庫flask-backend
-
前端阿強在項目
front-backend-cd
中創建前端代碼倉庫react-frontend
-
運維小胖在項目
k8s-yaml
中創建代碼倉庫k8s-yaml
-
測試小莉整理測試用例,根據 Leader 老李提供的接口文檔編寫後端 API 自動化測試代碼
將
k8s-yaml
作為獨立項目維護的原因是除了front-backend-cd
項目,k8s-yaml
也管理着其他項目的 Kubernetes yaml 文件,單獨建庫的目除了方便對 yaml 文件做版本控制,也便於開發和運維職責分明,開發不需要關注太多的運維基礎設施(Kubernetes),主要精力放在編碼、編譯和構建鏡像。
持續集成
代碼倉庫初始化後,後端大熊和前端阿強開始了愉快的編碼,同時在完成第一次代碼提交前,Leader 老李已經為團隊搭建好持續集成,並分別交由大熊和阿強維護。在下班前大熊和阿強完成了腳手架代碼,提交了代碼合併請求(MR,Merge Request)。
細心的前端阿強發現合併請求詳情頁正運行一個叫 合併狀態檢查
的任務,請教 Leader 老李後得知是合併請求觸發的自動構建計劃, 其作用是:自動構建源分支與目標分支合併後的結果,能夠儘可能早地發現集成中的錯誤。如果合併狀態檢查失敗,評審者不用過早介入代碼 review 流程,開發者可以自行檢查代碼
。
合併狀態檢查
處點擊 詳情
可查看構建計劃的執行詳情:
果然,第一次合併狀態檢查失敗,前端阿強根據構建日誌,發現了一個低級的字符拼寫錯誤,在內心深深的對自己鄙視一番後,立即修復,再次提交合併請求。
前後端代碼經 Leader 老李 review 合併到 release 後,會觸發相應的構建計劃,其起點都是代碼檢出,終點是將鏡像推送到製品庫。
持續部署
在後端大熊、前端阿強忙得熱火朝天的同時,運維小胖也沒有閑着,老李將小胖添加到團隊的【運維】用戶組,並授予【運維】用戶組部署設置權限,小胖跟着 CODING 持續部署的文檔開始一步步配置。
閱讀更多:CODING CD 幫助文檔
添加雲賬號
作為雲原生的先行團隊,突突突小分隊
很早就採用騰訊雲 TKE 作為生產環境,於是運維小胖添加了 TKE 類型的雲賬號。
配置應用和部署流程
添加完雲賬號後,運維小胖根據使用引導跳轉到 CODING 部署控制台,分別創建了應用 flaskBackend
和 reactFrontend
。
接着配置部署流程,運維小胖將 k8s-yaml
項目中的 manifest 文件以及製品庫中的 docker 鏡像配置為部署流程製品,並在 Kubernetes 資源部署階段(Deploy(Manifest)-Deployment)引用。
如圖只有以
release-
為前綴的 docker 鏡像才會成功匹配為發佈製品
在人工確認階段,運維小胖將自己設置為確認人,並將測試小莉加入通知人列表。
測試小莉也會接收到人工確認通知,雖然沒有權限進行確認操作,但可以對發佈過程 review,以降低發佈故障率。
將應用與項目關聯
配置部署流程的過程中,由於對 CODING 部署控制台不夠熟悉,一些小差錯讓運維小胖有點煩躁,但這些繁瑣的步驟不過是第一次麻煩點,接下來將應用與項目關聯後,發佈過程就可以交給開發同學提交了,想到這兒小胖露出邪魅的微笑。
版本發佈
新項目啟動的第三天(10 月 28 日),測試小莉上班第一件事是查看後端 API 自動化測試報告,中午飯點前前後端完成接口聯調,下午小莉在測試環境上完成了功能測試。是時候開始激動人心的 Staging(預發佈) 發佈了。
Staging 雖然不是最終的生產環境,但在 DevOps 實踐中其代碼、製品、應用配置等跟生產環境都是保持一致的,除了意外情況,Staging 發佈驗證無誤後,就可以隨時發佈到生產壞境。
老李新建了一個版本發佈,命名為 release-20200428.1
(相應地創建了同名的 tag),表示 2020 年 10 月 28 日的第一次發佈:
此 tag 會觸發 CI 構建,在 Jenkinsfile
中獲取此 tag 的名稱並應用到 docker 鏡像。
在項目內提交發佈
後端大熊和前端阿強在項目內提交發佈單,選擇部署流程執行必需的製品(docker 鏡像選擇最新的版本 release-20200428.1
)。
人工確認
部署流程執行到 人工確認
階段,Leader 老李和運維小胖收到了人工確認通知,小胖點擊部署詳情跳轉到發佈單詳情頁,確認製品信息無誤後點擊 繼續執行
。
2 分 43 秒後,發佈成功!
查看發佈信息
在【基礎設施】->【集群】中查看發佈成功的 Deployment 信息,可看到鏡像版本與代碼版本一致,如果生產環境出現故障,可快速追蹤到對應的代碼版本,進行修復工作。
測試小莉早已在運維小胖的提示下本地配置了 hosts,打開瀏覽器輸入 //react-frontend.com
即可查看發佈內容。這樣的版本肯定是不能發佈到線上的,不過作為前後端分離的 DevOps 最佳實踐 Demo,它成功的完成了使命。
結語
突突突小分隊
成功在五一勞動節前發佈了第一個小版本,這次發佈過程中,大家都感覺比以前舒心多了。
- 後端大熊和前端阿強不需要自己寫 k8s manifest,可以將時間和精力專註在業務代碼;
- 而運維小胖也不用像以前和女朋友約會時,還擔心開發請自己在測試環境拉取更新鏡像,現在他們可以實現自助發佈,小胖想如果以後 CODING 開發了 APP,打開手機即可一鍵完成人工確認操作,那小日子不要太爽;
- Leader 老李則表示對 CODING DevOps 是相見恨晚吶,早些年手工停服、ftp 上傳代碼、手工啟服的騷操作一去不復返了。
本文涉及的最佳實踐要點
- 前後端代碼倉庫分離:如本文中的
flask-backend
和react-frontend
- 開發和運維職責分離:運維配置雲賬號、應用和部署流程,開發提交發佈單
- 從代碼管理到製品發佈,保持一致的版本規則,生產環境發現故障時可及時追溯相應的代碼版本
- Docker 作為交付標準,保證開發、測試、生產環境依賴一致
- 運維人員使用獨立的 Git 倉庫管理 yaml 文件,方便對 yaml 文件做版本控制,開發不需要關心雲基礎設施
DevOps 泳道圖
參考資料
1、前端開發的歷史和趨勢://github.com/ruanyf/jstraining/blob/master/docs/history.md
2、DevOps 的分與合://cloud.tencent.com/developer/article/1610668
3、《鳳凰項目:一個 IT 運維的傳奇故事》://book.douban.com/subject/34820436
4、《DevOps 實踐指南》://book.douban.com/subject/30186150