梁岸川 上汽通用五菱汽車股份有限公司 凌以靜 上汽通用五菱汽車股份有限公司
當前云計算在軟件公司中獲得了極大的普及。市場上已經有多個云服務巨頭:亞馬遜云服務(AWS),微軟azure,阿里云和谷歌云。與此同時,中型企業也開始進入這個市場。所有這些吸引力都源于云計算帶來的好處。例如,云中的后端服務允許公司不構建自己的基礎設施,而且安全性和備份也由云提供商負責。此外,kubernetes 可擴展的開源平臺在當今得到了廣泛的應用,它提供了創建自己的平臺解決方案的可能性,這些平臺解決方案可以執行容器化的應用程序。
應用程序的開發包括不同的階段:設計、編碼、測試、構建、發布等等。主要目標是滿足客戶的需求。為了實現這一目標,公司應該盡可能頻繁地迭代、發布產品。目的是為了更快地部署新功能和修復BUG。持續集成實踐有助于實現這些需求。
本文的目標是研究持續集成持續部署的最佳實踐,并構建一個自動化流水線。關鍵價值在于實現所有階段的流程自動化。
首先會回顧本課題項目研究的理論背景和技術背景,包括微服務、K8S,CICD 等。
最后將介紹具體持續集成的實現方法。要實現最終目標,需要通過多個實施步驟。
應用程序市場正在不斷增長。最終用戶希望獲得更優質的服務,包括具有豐富的功能,現代化、可感知的設計和全天候可用性。為了滿足這些需求,軟件公司需要盡可能頻繁地推出更新,更快速地迭代產品。
微服務架構包含多個松耦合的小組件。每個模塊都只執行自己的任務,并獨立于其他模塊。模塊之間通過 REST API 接口進行通信。微服務架構可以加快測試和部署速度。
1.1.1 微服務的特性
為了更好地理解微服務架構風格,需要回顧幾個特征。
代碼庫
特定微服務組件的代碼量相對較小,其功能應該僅限于完成特定的任務。在這種情況下,團隊中的新加入的開發人員更容易讀懂代碼邏輯以及貢獻新的代碼。此外,使用更小的模塊構建和運行應用程序的開發效率要快得多。
在傳統單體架構中,即使是很小的變化也需要構建整個項目。這可能會導致應用程序有很少的發行版本,卻有大量的更改。在微服務開發中,鼓勵更快更頻繁地發布。獨立部署服務時,更容易跟蹤故障,如果出現問題,則回滾到之前的穩定版本不會花費太多時間。
可擴展性
通常,為了擴展大型單體應用程序的高可用或負載均衡節點,則需要完整地部署整個系統。如果只是某些功能需要更多實例資源,同樣需要完整地部署多套系統,因此,擴展此類應用需要大量資源,很明顯,復制大型單體應用系統的效率并不高。相比之下,每個微服務可以具有不同數量的副本,這將提高應用程序的性能和資源的利用率。
1.1.2 微服務的挑戰
與單體應用相比,微服務架構具有許多優點,易于部署,擴展,修復等等。盡管如此,微服務架構還是存在一些挑戰。每個微服務組件都是一個獨立的模塊,它與其它獨立組件打包在一起工作,因此,處理服務之間的通信變得復雜。需要為微服務間的API 接口編寫良好的文檔,管理這些接口的工作成為重中之重。
測試
與單體架構相比,測試小型獨立組件更容易。然而,總體上測試系統變得更具挑戰性。需進行大量的集成測試,以驗證系統是否正常工作。此外,還需要更多資源來測試系統。在這種情況下,設計良好的pipline 是必須的。
代碼
微服務架構允許開發人員為他們需要實現的模塊選擇不同的技術,框架和庫。在特定模塊上工作的團隊的規模可能相對較小,因此如果一個成員離開公司,另一個團隊的開發人員必須學習新的工具才能接手這個模塊的工作。
安全
模塊可以被其它服務重用。模塊化使黑客有更多的入口點可以滲透到系統中。在處理用戶數據時,安全性是必須要考慮的,應該投入大量精力來處理微服務架構中的安全風險。
需要了解容器才能更好地掌握kubernetes。以前,應用程序部署在主機系統上,這會導致應用程序配置,生命周期和主機操作系統之間有較高的耦合度。
容器是打包應用程序和在不同環境中部署應用程序的方法。如何管理、擴展和恢復這些資源仍然是一個問題。Kubernetes 的出現是為了解決這些問題。
Kubernetes 源于谷歌內部的Borg 系統,提供了面向應用的容器集群部署和管理系統。Kubernetes 的目標旨在消除編排物理/虛擬計算,網絡和存儲基礎設施的負擔,并使應用程序運營商和開發人員完全將重點放在以容器為中心的原語上進行自助運營。
Kubernetes 用戶可以通過編寫yaml 或者json 格式的配置文件,通過直接請求Kubernetes API 創建應用,該配置文件中包含了用戶想要應用程序保持的狀態,就算整個Kubernetes 集群中的個別主機發生異常,都會保持用戶所期望的應用程序的狀態,這一切都由kubernetes 自動完成。
Kubernetes 集群是一組計算節點組成的一個資源集合。它由兩種類型的節點組成:主節點和從節點。Master 是管理節點,負責集群資源的調度、擴展、終止以及更新應用程序。從節點負責運行應用程序。圖1 展示了kubernetes 集群。

圖1.Kubernetes 集群架構
每個工作節點都有kubelet 組件,它負責與管理節點進行通訊。此外,從節點需要這些組件來創建、運行和刪除容器應用程序。它可以是docker、rkt 或LXD。Master 節點的API 是集群的入口。可以使用Deployment 在kubernetes 集群中部署容器化應用程序。在kubernetes 中,Deployment 配置描述了如何更新和創建應用程序。當創建Deployment 時,kubernetes 會生成Pod,它是一種抽象概念,用于表示應用程序的一個實例以及與之相關的一組資源集合,通常包含一個或多個容器。當創建Pod時,它駐留在某個節點上,直到它被終止。如果Pod 所在的節點發生故障,則Kubernetes 集群會自動在另外一個健康節點生成同樣配置的Pod,這個新的Pod 對外提供與原Pod一模一樣的功能,對外部用戶來說,他們并不需要關心這些Pod 所支撐的服務運行在哪個節點之上。

圖2.kubernetes 集群中Pod 和Service 的關系示例[3]
kubernetes集群的主要優勢是可以輕松實現對Pod擴容和縮容。通過更改Pod 的副本數量可以輕松實現。當Master 節點擴展應用程序時,它會自動選擇在其中一個擁有足夠多資源的節點中創建Pod 副本。運行一個Pod 的多個副本需要相應的機制來分配流量。這由與該應用程序關聯的Service 負責,Servcie 內部實現了負載均衡[圖2]。
市場的高度競爭迫使企業分配大量的人力和計算資源來實現CI、CD。這些實踐為軟件開發帶來了很多好處。從頻繁的發布開始。這改善了用戶體驗,因為新功能交付得更快。
持續集成是一種軟件開發實踐,開發人員通常在日常工作中提交代碼。每次集成都由自動測試系統進行檢查,以便在早期階段捕獲問題。
持續交付是持續集成過程的延伸,它提供了一種可持續的產品發布方式。這意味著不僅測試過程、構建過程應該是自動化的,發布過程也應該是自動化的。為了開始開發這個過程,需要有穩定可靠的持續集成。這個過程有一個將產品部署到生產的手動步驟,但是部署應該是自動化的。持續交付的好處是你可以頻繁地進行小版本發布,在快速地交付小功能的同時也可以更快地修復bug。
常用的CI 工具有Jenkins、Travis 、Circle 等等,本文將介紹基于Jenkins 的CI 方法。Jenkins 是一個開源的、提供友好操作界面的持續集成(CI)工具,起源于Hudson(商業產品),主要用于持續、自動地構建、測試軟件項目,監控外部任務的運行。
在上一章中,我們回顧了微服務、k8s 等關鍵技術背景,微服務應用架構在當下非常流行,有著易于部署、擴展、修復等諸多優點,以docker 為代表的容器技術成為微服務架構應用的交付標準,而Kubernetes 又是當今容器編排技術的事實標準,將應用部署在云供應商提供的基礎設施所構建的Kubernetes 集群中,可同時獲得k8s以及云計算帶來的諸多好處,又可以避免被云供應商綁定。
Kubernetes 細化的應用程序的分解粒度,同時將服務發現、配置管理、負載均衡和健康檢查等作為基礎設施的功能,簡化了應用程序的開發。而且Kubernetes 這種聲明式配置尤其適合CI/CD 流程。圖1 展示了基于Kubernetes 和jenkins 的CI 過程。

圖3.基于 Kubernetes 和Jenkins 的CI 流程圖
應用構建和發布流程:
1.開發者向Gitlab 提交代碼,代碼中包含構建鏡像所需的Dockerfile,以及微服務應用所對應的服務類型、服務名稱、資源數量、實例個數。
2.代碼提交到遠程Git 倉庫之后,通過webhook 觸發Jenkins自動構建。
3.Jenkins 的CI 流水線自動編譯代碼并打包成docker 鏡像推送到Harbor 鏡像倉庫
4.Jenkins 的CI 流水線中包括了自定義腳本,根據我們已準備好的kubernetes 的YAML 模板,將其中的變量替換成用戶輸入的選項
5.生成微服務應用的kubernetes yaml 配置文件
6.更新Ingress 的配置,根據新部署的應用的名稱,在ingress的配置文件中增加一條路由信息
7.Jenkins 調用kubernetes 的API,部署應用。
以上的構建均在開發者提交Gitlab 之后全自動完成。
持續集成的目的,就是讓應用產品可以更快速地迭代,以適應不斷變化的業務需求。持續集成的關鍵不是集成,而是持續。所謂持續,就需要自動化。代碼的每次合并都會觸發持續集成服務器進行自動構建,這個過程包括了編譯、單元測試、集成、集成測試、質量分析、性能測試等步驟。在本文中,我們介紹了當今熱門的微服務架構以及容器編排工具Kubernetes,并且展示了基于Jenkins 和Kubernetes 的持續集成方案。