摘要: 前言隨著微服務架構與容器虛擬化技術的發展,持續整合與持續傳遞的概念又重新回到了大家的視野,越來越多的公司開始使用持續整合的系統來解決頻繁發佈帶來的品質問題;使用持續傳遞的工具來實現代碼在不同環境上的自動部署。
前言
隨著微服務架構與容器虛擬化技術的發展,持續整合與持續傳遞的概念又重新回到了大家的視野,越來越多的公司開始使用持續整合的系統來解決頻繁發佈帶來的品質問題;使用持續傳遞的工具來實現代碼在不同環境上的自動部署。原本有些學院派烏托邦式的思想正被千千萬萬次的整合與部署證明著它應有的價值。那麼究竟是因為什麼讓持續整合與持續傳遞這個已經不再年輕的軟體發展與交付的思想重新煥發綻放迷人的光彩呢?
傳統軟體交付之殤
傳統軟體的開發與交付的週期都很漫長,一款普通的企業軟體通常需要十幾個開發人員,幾個月的時間來完成,從需求的剖析、系統的設計、編寫測試案例、系統開發、單元測試、組裝測試到交付偵錯。有條不紊的流程與規格像一輛綠皮火車下的枕木,穩定而強固許諾整個系統緩慢的推進,每一次交付、升級,都需要提供基礎的硬體、軟體的環境、軟體的代碼、軟體的文件與手冊。還記得剛剛邁入軟體發展產業的時候,跟隨公司的服務團隊,駐場交付產品,每一個駐場工程師都按照之前預演過好多遍的流程,對照著系統的部署手冊,一步一步的組裝硬體,安裝軟體,稍有差池,就要按照對應的應急預案進行復原。開始的時候覺得交付像一個神聖的儀式,將用智慧和汗水構建成的軟體交付給客戶使用,是一種非常榮耀和值得驕傲的事情;後來越來越多次的產品交付讓我深深的感覺每一次交付都像分娩一樣痛苦,捫心自問是否有簡單更舒暢的流程可以將軟體交付給客戶呢?
傳統圖樣的反思與CI/CD概念的提出
通常來講,一個軟體的生命週期分為問題的定義、可行性的剖析、系統設計、系統編寫、系統測試與偵錯、系統部署與交付、維修與升級等步驟。在傳統軟體的生命週期中,更傾向於使用瀑布流的圖樣來去有條不紊的規格整個流程,每一個階段都期望遵循“活動-結果-稽核-再活動-直至正確”的流程來許諾系統穩定。整個軟體的生命週期就變成了一個很長的二維線性流程。這也制約了軟體的開發反覆運算與交付的速度,前輩們想了非常多的辦法來提高整體的開發速度,比如將一個單體的系統系統設計成為服務化的分散式的子系統,這樣可以讓一個大型的單體軟體的開發變成多個小的硬地系統的並行開發;使用元件化的方式組建系統,在不同的系統間複用模組加速開發;通過自動化工具或者腳本進行自動化部署與交付等等。
誠然,這些都解決了軟體交付程序中的一些問題與痛點,但是這些方式都像西醫一樣,治標不治本,因為要想快速的交付,首先要明白軟體交付程序中遇到的核心問題是什麼。總結成兩個詞“自動”與“可靠”。自動是一個很寬泛的詞彙,在軟體交付中代表著測試自動化、交付自動化、運維自動化等等,而可靠講的是每一次交付要許諾是本期的交付是穩定的或可復原到穩定組建的。
為了解決“自動”與“可靠”的問題,敏捷開發鼻祖MartinFowler提出了持續整合與持續傳遞的概念,它所標題的軟體發展,是從原始需求辨識到最終產品部署到生產環境這個程序中,需求以小批量形式在團隊的各個角色間順暢流動,能夠以較短地週期完成需求的小細微性頻繁交付。頻繁的交付週期帶來了更迅速的對軟體的回饋,並且在這個程序中,需求剖析、產品的使用者體驗和互動設計、開發、測試、運維等角色密切協作,相比于傳統的瀑布式軟體團隊,更少浪費。通過這種小步快跑的方式,將小功能快速反覆運算、驗證、交付,通過自動化的工具,將測試、部署、運維自動化,減少需求在軟體生命週期中流動的時間。但是為什麼看上去可以奉為圭臬的持續整合與持續傳遞的思想卻在相當長的時間被開發人員束之高閣呢?
實現持續整合持續傳遞的痛點
對持續整合持續傳遞有一些理解與體會的開發人員會經常看到類似下面這張圖的持續傳遞流程。
在這張圖中我們講述了一個持續整合與持續傳遞的流程,從代碼的提交、構建與編譯、單元測試到部署環境、整合測試與發佈。軟體交付本身就是一件複雜的事情,不同的產品、不同的架構、不同的商務形態會導致持續整合與持續傳遞的實現上有非常大的不同。還記得很久以前流行一個關於哲學的笑話,當你問十個哲學家什麼是哲學的時候,你會得到十一種答案,因為每個人都有對哲學不同的理解。對於持續傳遞也一樣,MartinFowler講述了一個烏托邦式的軟體發展與交付的圖樣-持續整合與持續傳遞,但是前輩只給了我們先進的思想,並沒有給出預設的實現。不同的公司、不同的產品、不同的技術棧、不同的開發與部署形態決定了持續整合與持續傳遞註定是因人而異的,在大家不斷摸索什麼樣的方式是持續整合與持續傳遞的最佳實踐的程序中。有的人做少了,只實踐了其中的一部分,導致基本的交付能力上有缺欠;有的人做多了,引入了其他複雜的流程,導致原本應該提速的交付流程,像穿著名牌高跟鞋參加跨欄一樣,怎麼也快不起來。
如果將上面的流程具象化一個LNMP(Linux、Nginx、MySQL、PHP)的例子,就變成了如下的程序。
我們會發現當整個持續傳遞的流程流轉到了持續傳遞系統的時候,流程開始和具體的環境與程式設計架構開始耦合,比如單元測試在這個例子中需要執行PHPUnit相關的指令去實現;準備環境需要根據具體的部署環境是KVM的虛擬機器還是物理機或者是雲端服務器區別實現;設定環境需要根據具體的程式設計型號來準備在本例中會通過自動化配管工具例如Ansible來驗證與準備不同環境中的代碼執行階段環境;分發代碼後的流程在本例中是通過重啟Nginx實現。其實這就是持續整合與持續傳遞真正難的部份,它並沒有特定的要求規定什麼流程該用什麼方式做什麼,就像大型軟體系統的架構設計,只有“法”沒有“型”,這也就是為什麼程式師有很多,但架構師少的可憐的道理。
歸根結底,持續整合與持續傳遞的痛點在於如何遮罩不同語言、不同架構、不同系統之間的持續整合與持續傳遞流程的差異性。曾經幻想過是否能有一種方式可以歸約軟體的交付,而這就是MartinFowler留給我們的課後思考題-論如何?持續整合與持續傳遞的流程標準化。
新的交付之道——容器標準化交付
容器虛擬化這幾年隨著Docker的推出,也逐漸進入到開發人員的視野中。剛剛接觸Docker的時候,按照學習新知識的習慣,我將Docker和虛擬機器或者虛擬化進行了等同,認為他們是一個領域的不同實現,通過類比的方式來學習Docker。但是後來我發現,Docker的意義不在於解決軟體底層的環境定義的問題,其他的是在解決交付的問題。
在上文中我們討論了為什麼持續整合與持續傳遞對於很多公司來講是有難度的。而解決這個問題的最理想的辦法就是是否有一種方式可以將交付的流程程式設計一個標準化,這樣進行持續整合與持續傳遞的開發人員可以很快的像讀說明書一樣,一步一步完成自己的持續整合與持續傳遞流程。
容器給交付帶來最大的變革就是標準化。
Dockerfile:將代碼和環境封裝成了鏡像,將原來系統中分發的最小單元由代碼變成了鏡像,不同的環境、不同的軟體、不同的設定都可以通過Dockerfile的設定來實現,標準化了交付的最小單元,讓交付的最小單元不再和環境、程式設計架構耦合。
Docker API:將軟體的生命週期管理從原來的不同架構不同實現變成了統一標準的指令。啟動軟體變成了dockerrun,停止軟體變成了dockerstop,重啟軟體變成了dockerrestart。
Docker Compose:將軟體交付的方式進行了標準化,大型的軟體是由很多不同的部份組成的,而DockerCompose就是將軟體之間的關聯關聯用標準話的方式進行了標題,並通過分發DockerComopse的設定檔即可將軟體進行交付。
如上圖,我們將剛才的例子用Docker的方式進行推演,發現原本和程式設計架構或者環境耦合的部份現在通過Docker進行了標準化,這樣不同語言不同架構不同商務場景的開發人員就可以快速的時間自己的持續整合與持續傳遞了。
軟體定義程式交付年齡已到來?
雲端運算的興起,讓越來越多的IT基礎設施變成虛擬、軟體定義程式的,比如軟體定義程式隱藏、軟體定義程式網路等等。通過程式設計的方式可以將原本的IT基礎設施進行建立、配置、管理,遮罩掉了底層的硬體的異構。反過來看雲端交付的場景,是否可以變成軟體定義程式的。我們可以通過資源編排(例如阿裡雲的Ros或者AWSCloudFormation)定義基礎的設施;可以通過Docker軟體定義程式部署;雲資源和容器化的套用都可以用API的方式來實現軟體定義程式運維。
軟體定義程式基礎設施+軟體定義程式部署+軟體定義程式運維=軟體定義程式交付?這個問題留給大家其他的思考。
阿裡雲容器服務是阿裡雲2015年12月推出的基於容器的CaaS產品,整合了阿裡雲OSS、ECS、SLB、SLS、VPC、RDS等多款IaaS雲產品的能力。容器的交付方式雖然給交付帶來了很多的便利,但是還遠遠不夠,阿裡雲容器服務為微服務、持續傳遞提供了大量雲交付的能力,可以讓Docker的交付程序更順暢。在下一篇本文中,我們將討論下阿裡雲容器服務提供了什麼樣的功能屬性滿足大家的雲端交付場景。
簡歷
莫源,阿裡雲進階研發工程師。在上線阿裡巴巴之前,先後在北京天方地圓科技有限公司、微軟亞洲研究院任職。現主要負責阿裡雲容器服務供應項目的底層服務發現系統、集群管理系統的研發,從事容器的持續傳遞、持續整合的方案的設計與實現。在雲端運算、分散式系統、影像辨識與虛擬實境方向有多年的開發經驗。
相關產品:
- 容器服務(Docker)
- 雲效
- 企業級分散式套用服務
- 雲端服務器ECS