我們該怎麼給DevOps下個定義?
導讀ID:TOP100case
導語:越來越多的軟體企業開始通過實現持續部署來進入DevOps的世界。然而,企業所處階段、規模等等因素使得持續部署的實現並無唯一正確的方案,另一方面,目前很多企業以持續集成作為持續部署的基礎,甚至當做持續部署本身,此類部署並未做到一個高效部署系統所期望的可重複、可回滾、全自動的部署系統。
本案例將展示講師所在公司如何做到從半人肉的部署,到自動化運維,再到真正可重複、可回滾、全自動的部署系統,還將詳細分享這個過程遇到的問題,以及解決問題過程中關鍵系統的概念及設計。
(全文共4605字 預計閱讀時長:5分鐘)
DevOps受到廣泛關注,然而定義仍未定型
在2015年的Gartner應用開發成熟度曲線上(圖12-1),DevOps已由上升期進入頂峰。這意味著DevOps這一概念已獲得大量關注;相應的,業界此時對DevOps的認識也最為混亂。就如同許多新興概念,目前我們並不能給DevOps一個簡單的定義。
圖1 Gartner應用開發成熟度曲線
DevOps成為新軟體生命周期不可或缺的命題
如今的軟體開發已不僅僅局限於為客戶交付滿足其需求的可工作軟體。
一方面,來自敏捷的輕量級的軟體開發流程和實踐使軟體快速上線成為可能,這就意味著需要通過早期部署和運行儘早建立用戶反饋來降低軟體失敗的風險。
另一方面,多數的軟體企業是圍繞軟體的運營開展業務。
因此,軟體部署和運行成為新軟體研發生命周期的一部分。如圖2所示。
圖2 新軟體生命周期
如何讓圍繞著新軟體生命周期的各個團隊統一關注點、規範合作,從而使軟體相關工作流暢的開展。這正是DevOps在2009年經由敏捷會議提出時所面對的主要問題。如圖3所示。
圖3 DevOps提出時面對的主要問題
實施過程中,行業對DevOps的嘗試
從實施的角度看來,行業對DevOps的嘗試有以下兩種方式:
由開發入手,通過加速開發帶動交付或部署的效率。這正是DevOps起源的敏捷文化所擅長的,因此,它會更多地強調流程的梳理以及溝通的重要性,而之前的一些工程實踐,也在新的環境中被賦予新的角色加以推廣,不過這些新實踐的重點不僅僅關注在質量和效率方面,而是更多的關注部署。
例如,會以持續集成為集成來實現自動部署。這些改造讓流程更為輕量,團隊之間溝通合作,確實起到了良好的作用。但當缺乏有效工具支持時,卻很難做到期望的持續部署。因此,隨著越來越多的配置管理工具、部署工具的湧現,這部分工作被快速整合進DevOps的實施中,並發揮出一定的效果。
在一些大型的軟體公司中,傳統運維由於來自自身業務的壓力,也在積極尋求改變。如何讓運維自動化是其主要的探索方向。這其中一部分是圍繞傳統運維工作(資源管理)的升級——通過自動化工具提高單人可控資源的數量。而另一部分則將關注點放在部署本身。
一些公司在多年累計的系統及運維經驗的基礎上,開始構建軟體配置管理資料庫(CMDB),以便將系統信息集中管理,進而構架出適合自己的部署系統和工具。最終達到簡化部署工作,提高部署效率的目的。
綜合看來,這兩種途徑都有可取之處,在各自的場景下發揮著重要作用。但這兩者都沒有給出整體性的建議。那麼,究竟應該如何認識DevOps呢?或者拋開DevOps概念,看看今天軟體開發需要我們做出何種應對。
持續部署,讓開發運維成為一個統一的生態系統
在《DevOps:A Software Architect』s Perspective》一書中,作者給出了如下觀點:
DevOps is s set of practices intended to reduce the time between committing a change to a system and the change being placed into normal production, while ensuring high quality.
雖然這是一個非常寬泛的描述,但從其中不難看出兩個關鍵的階段:
軟體開發——由需求代碼提交系統,有可能涉及構建和中間製品的生成;
部署——將開發結果安裝到生產環境中。
就如何提高軟體開發效率而言,經過多年的摸索,這一領域已經有了一套行之有效的最佳實踐。因此,提高效率的難點就集中在部署環節上,沒有高質量的部署系統是無法保證最終系統的質量和效率。同時,為了配合部署,與軟體開發相關的配置管理工作也必須做出一定的調整,使開發和運維最終成為一個統一的生態系統。
持續部署是一個很好的切入點。但真正實現持續部署之前,首先必須能夠保證部署工作的自動化、部署的可重複性、可追蹤性,以及在整個組織內對部署的概念和行為進行統一。這些部署需求的實現要切合項目的實際情況,例如,為起步期的產品打造一個獨立的部署系統顯然是資源上的浪費,而對一個成熟的大企業來說,各個產品的部署還在依賴Jenkins之類的CI伺服器來進行也有問題。
讓我們通過一個實際的列子,看看在實現這些目標的過程中需要關注的問題,以及怎樣倒逼研發人員對相關的配置管理進行相應的調整。
首先,我們明確一下部署的含義。狹義的部署工作通常是在已經準備好的機器上安裝目標軟體;而廣義的部署包括了以下三部分工作:
準備運行環境。
安裝目標軟體以及依賴軟體。
啟動應用。
通常,對一個初創或小型項目。通過版本庫的同步機制可以很簡單的將最新的代碼整體部署到目標環境中。如果在Jenkins的基礎上,配合使用Puppe這樣的配置管理工具,以及RUNDECK這樣的命令批處理執行工具,就可以得到一個簡單的持續部署系統,如圖4所示。
圖4 簡單的持續部署系統
在這樣的部署系統中,目標機上的版本庫雖然方便代碼的部署工作,但它有污染代碼的風險,同時,它也無法直觀的告知用戶當前部署的版本,加之沒有對部署進行記錄,部署的追蹤和回滾就無從談起。另外,這樣的部署方式需要源代碼和目標代碼結構一致。最後,部署邏輯和啟動邏輯可能會被分散在Jenkins和RUNDECK這樣的工具中。
近年來,諸如Capistrano和Deployer這樣的部署工具給了我們很大的啟示。他們的思路非常簡單:
使用版本庫導出機制替換直接使用版本庫。
規範部署的目錄結構。
通過部署版本化來實現部署環節的可追溯性
具體而言,如圖5,我們依然使用代碼庫的同步機制來獲取代碼。獲取代碼後,我們將版本庫導出到產品庫部署文件夾下(_products),對新部署的文件夾給出:產品-分支-版本-部署編號這樣可以標識的名稱。建立從產品文件夾到對應部署文件夾的軟鏈接。而伺服器和其他的配置僅使用標準的路徑名稱,如/devops/products/tickets,如圖5所示。
圖5 標準的路徑名稱
為了實現更好的交互,可以在RUNDECK工具上收集需要部署的tag,並將一部分部署邏輯實現為腳本,通過RUNDECK調用,如圖6所示。
圖6 RUNDECK收集部署tag 調用腳本
對於Java這樣需要編譯發布的項目,必須把構建過程考慮在內。雖然將構建過程放在部署過程內在技術實現上沒有問題,但其缺點也很明顯。部署邏輯和構建邏輯交織在一起,部署的時間和失敗的風險都加大了,如圖7所示。
圖7 構建過程放在部署過程內
一個好的解決方法是引入成品庫,這樣不但能將構建邏輯獨立出去,還可以將目標機上的代碼庫一併去掉(如圖8),但代價是代碼的獲取機制必須要自己動手處理,例如通過部署腳本調用rsync從成品庫中獲取可部署版本。由於引入構建過程,使得從代碼變更到構建,由構建到部署的全程追蹤成為可能。
圖8 引入成品庫
對於大型系統,軟體的管理或許已經進行了拆分,不同部分之間的依賴需要在開發、構建和部署過程中得到妥善的處理。
軟體包讓配置管理和部署邏輯得到簡化
軟體包的概念並不新鮮。從早期的perl的軟體包庫CSPAN、Java的Maven到Linux不同發行版的包庫,以及現在的Gem、npm和Composer這樣的包庫。
軟體包為應用的依賴管理提供了便利。Puppet這樣的配置管理工具可以非常方便的管理標準的軟體包,並將其作為環境準備的一部分。但對於非標準包來說,其依賴的處理可能需要配置管理工具特殊處理。
Maven的軟體包在這方面做的很好。通過架設私服,可以將標準包和定製包統一起來,這樣配置管理部分或者部署部分的邏輯就會得到簡化。但對於非Java的應用,尤其是大型企業中多語言混合開發的情況,則有必要開發自己的一套包管理庫。
參考Maven和Gem類包庫,可以很容易地實現自己的包庫。我們所需要做的工作就是將項目(包)的元信息規範下來,並放入項目的源代碼中,如圖9、圖10所示。
這些信息包含:項目名稱、版本、編譯系統、部署設置、構建目標和各種依賴。如圖11所示。
圖9 代碼
圖10 包庫
圖11 包含信息
對於包管理系統而言,我們還需要一個中心庫存儲這些包的元信息以及依賴信息,如圖12所示。當這些信息就位時,我們可以看到一個項目對應版本的依賴集合,但這些信息最終可以幫助實現比軟體配置管理資料庫更細粒度的控制,並為部署系統的實現打下基礎。
圖12 中心庫存儲系統
系統安裝的包與開發中的包是一個概念的兩種視角。他們之間有聯繫,但在物理層面卻屬不同的東西,必須規範安裝包的格式。通常,遵照現有包庫的方式就可以,比如Ruby包,依然使用GEM進行安裝,不過需要將全局的作用範圍配置到項目(產品)一級,以避免一個目標機上部署多個應用時彼此影響。而這也正是當前公共包庫發展的趨勢。
源代碼上我們已經進行了規範,兩者建立聯繫和轉換的時機落在構建過程。而一個可能的構建系統的高層結構大致如圖13所示。
圖13 構建系統的高層結構
在依賴關係的上下游中,我們將其比喻為供應商-消費者的關係。被依賴的包提供了服務(供應商),其發布時負有不可推卸的責任,保證在兼容規則的約束下,不破壞所有依賴該版本的消費者。
PHP語言的PECL包庫定義了自己的兼容規則,我們可以參考。一般而言,y和z的兼容性要求完全不破壞消費者,而x則完全不考慮兼容性。在構建過程中,我們可以採取兼容性檢查來發現引入兼容問題的修改。當非主版本修改時,可以發起將所有直接依賴的消費者的構建,若其構建失敗,則該構建失敗。
部署系統實現後需要進一步抽象
系統發展至此,部署系統的實現基本完成。此時,尚需我們做一些抽象,其一是規範發布結構,保證異構的應用可以統一管理;另外則是對產品在概念級的抽象,或者說產品的運行環境,如圖14所示。我們已經有了統一的包,只要把所有工具包納入到包庫中,那麼一個軟體的環境就變成了包與配置的集合,如圖15所示。
圖14 產品的運行環境
圖15 包和配置的集合
對產品環境信息的記錄,也是CMDB的一項工作,只是我們所處的粒度更細而已。至此,源代碼包和可安裝包在整個軟體生命周期中被聯繫在一起,如圖16所示。
圖16 源代碼包和可安裝包聯繫在一起
在此基礎上,只需增加一個簡單的部署任務系統,那麼整個部署系統就基本上大功告成(如圖17)。當基於包和環境的部署系統就位時,我們可以不再使用Puppet和RUNDECK這樣的工具,當然,我們也可以將其作為基礎,在上面實現我們的部署系統。通過部署系統,我們可以在整個組織內對部署的概念和行為達成統一。而且部署的可追蹤性、可重複性也已經實現。
圖17 部署系統
面向業務,結合工具堅持DevOps
從簡單的部署到獨立的部署系統,整個過程中的每一步都可以說是DevOps,因為我們不能脫離了具體的業務場景和公司的現狀探討DevOps。另外,這其中任何一種解決方案的出發點是一致的,就是加快代碼從需求到生產的時間。出於此我們可以得出第一個啟示:
DevOps需要面向業務,適合而止。
另一個啟示是對工具的依賴和追求。脫離了自動化工具來探討DevOps是在浪費時間。但工具的追求往往會進入另一個極端,如同SOA這樣的概念被諸多大公司作為標籤來販售自己的軟體產品。
DevOps也面臨了同樣的問題:僅僅有工具也不完全,文化和流程上的支持是不可或缺的。那麼是使用開源的系統呢,還是開發自有系統呢?沒有標準答案。但對於起步階段的企業來說,拿來主義或許更加明智。無論獨立開發工具,還是使用現有工具,都要把持著如下四個標準:自動化、服務化、可視化和自服務。
如何驅動DevOps的實施,業界的已有兩個很好的標準:
You build it,You run it.
Eat your own dog food!
尤其是「誰構建,誰運維」。在這種理念下的組織,只需必要的運維支持人員和QA人員專註於本職工作,將軟體開發和運維的工作交給開發人員和自動化系統完成。如圖18所示。真正高效的溝通是不需要溝通,而真正高效的知識是可以執行的知識。
圖18 「誰構建,誰運維」
真正的DevOps是建立適合自己的研發生態系統
正如本文一開始所說,軟體的開發和運維是一個系統性的工程,不是單獨的一個系統的優化就可以達到快速部署的目的,這需要我們圍繞著開發和運維工作逐步建立適合自己的整個生態。
※千億成交額背後,京東技術團隊的敏捷轉型模式
※Thought Works的10個案例教你打造團隊文化
※用12年數據建模經驗告訴你如何3步走解決建模問題
※DFSS理論:新產品開發前,用「概念工程」驗證能否成為爆款!
※從架構細節到實施過程,如何基於Ceph做雲存儲設計
TAG:壹佰案例 |
※Hedi Slimane將會給我們帶來怎樣的Céline?
※Valentino不再浪漫?錯!這次她告訴我們什麼叫個性!
※我們不一樣,iPhoneX 定製版告訴你什麼才是個性
※Weiss Ratings:我們為什麼要給比特幣一個C+
※Crocodile 我們就是我們的大腦嗎?
※【Jaeger?LeCoultre】約定,讓我們從這一刻開始,成雙入對
※Weekly Newsletter:我們想和你分享這些
※Olivia Palermo向我們演繹了什麼叫做名媛式穿法
※Elopement Wedding,不如,我們私奔去結婚吧
※放下 iPhone,讓我們認真地拍張照吧
※沒搶到Golf le Fleur x Converse我們照樣有鞋穿
※甜美辣媽Angelababy,竟然這麼會穿,讓我們快來學一下
※我們看到了Versace之死
※沒有水,我們就失去了一切 《Ayo: A Rain Tale》向我們講述水的珍貴
※我們都愛inside-out,但現在要搞定它還不是太容易
※John Singer Sargent 他告訴我們什麼是現實主義
※果粉歡呼:這款iPhoneX,才是我們想要的
※沒有水,我們就失去了一切 《Ayo:A Rain Tale》向我們講述水的珍貴
※La paris之我們去哪裡呀
※Rise Again 我們必將再次被複興,你準備好了嗎