原文:How We Build Code at Netflix
作者:Ed Bukoski, Brian Moyles and Mike McGarr
譯者:杰微刊兼職翻譯劉曉鵬
Netflix在部署到云環(huán)境之前是如何構(gòu)建代碼的?過去我們已經(jīng)討論過這個問題的部分內(nèi)容诡宗,現(xiàn)在是到分享更多細節(jié)的時候了。在這篇文章中穆役,我們將描述這個為7500,0000 全球Netflix成員提供電影和TV播放的應(yīng)用是如何實現(xiàn)從源代碼到服務(wù)部署的胡桃。
上面的圖表是對Spinnaker(我們的全球持續(xù)交互平臺)之前發(fā)布博文的擴展。每一行代碼在進入Spinnaker之前侈咕,都需要經(jīng)過很多的步驟:
1公罕、代碼構(gòu)建并使用 Nebula進行本地測試。
2耀销、將修改的代碼提交到git中心倉庫楼眷。
3、 Jenkins任務(wù)執(zhí)行 Nebula熊尉,包括構(gòu)建罐柳,測試以及應(yīng)用程序的打包。
4狰住、將新的版本放到AMI(Amazon Machine Image张吉,亞馬遜虛擬機鏡像)上“烘烤”。
5转晰、 通過Spinnaker流水線部署和升級修改后的代碼芦拿。
本文剩余部分將演示每個階段所使用的工具和處理過程士飒,以及為什么我們要采用這樣的方式。通過分享一些我們現(xiàn)在正處理的挑戰(zhàn)蔗崎,我們將變得更加密切酵幕。在Netflix 構(gòu)建和部署代碼的過程中使用了很多工具,也遇到了很多挑戰(zhàn)缓苛。你們可以期待這是描述這些工具和挑戰(zhàn)細節(jié)的第一篇文章芳撒。
文化,云與微服務(wù)
在深入 Netflix如何構(gòu)建代碼之前未桥,有必要強調(diào)幾個驅(qū)動和塑造我們解決方案的關(guān)鍵要素:我們的文化笔刹,云及微服務(wù)。
Netflix的文化是自由與責(zé)任冬耿,這種文化使得工程師可以采用任何他們認為最適合任務(wù)的工具來創(chuàng)建解決方案舌菜。根據(jù)我們的經(jīng)驗,如果一個工具被廣泛使用亦镶,那它一定是令人信服的日月,具有巨大價值的,并能減少絕大部分 Netflix工程師認知負擔(dān)的缤骨。團隊可以自由的修改實現(xiàn)方案爱咬,但同時也有責(zé)任來維護這些方案。Netflix核心團隊提供的工具本被認為是這條“柏油路”的一部分绊起。我們今天所關(guān)注的僅僅是這條“柏油路”上支持的引擎工具(Engineering Tool)精拟。
此外,2008 年虱歪,Netflix開始將流服務(wù)移植到AWS上蜂绎,并將基于Java 應(yīng)用的龐大數(shù)據(jù)中心轉(zhuǎn)換為基于 Java微服務(wù)的云。我們微服務(wù)架構(gòu)允許 Netflix團隊以松耦合的方式存在实蔽,并以他們認為合適的速度來構(gòu)建和推進更新荡碾。
構(gòu)建
自然,部署一個應(yīng)用或一個服務(wù)的第一步就是構(gòu)建局装。我們創(chuàng)建了 Nebula(一個 Gradle構(gòu)建系統(tǒng)上的可選插件集)來輔助繁重的構(gòu)建任務(wù)坛吁。Gradle為構(gòu)建,測試及打包 Java應(yīng)用(這包含了我們大部分的代碼)提供一流的支持铐尚。之所以選擇 Gradle是因為它易于編寫可測試的插件拨脉,同時降低了項目構(gòu)建文件的大小。Nubula繼承了 Gradle 健壯的自動化構(gòu)建功能宣增,包括一系列開源的依賴管理插件玫膀,版本管理、打包等等爹脾。
上面的“build.gradle”文件展示了在Netflix中是如何定義構(gòu)建一個簡單Java應(yīng)用的帖旨。該項目的構(gòu)建文件聲明了幾個 Java依賴箕昭,同時使用了 4 個Gradle插件,其中3個要么是Nebula的一部分解阅,要么是應(yīng)用在Nebula上的內(nèi)部插件落竹。“nebula”插件是一個只在內(nèi)部使用的Gradle插件货抄,為整合我們的基礎(chǔ)架構(gòu)提供規(guī)則和必要的配置述召。“nebula.dependency-lock”插件可以使項目生成一個基于版本的.lock的文件蟹地,用于解決依賴和重復(fù)構(gòu)建問題积暖。“netflix.ospackage-tomcat”插件及ospackage塊將在下文中接觸到怪与。
通過Nebula夺刑,我們提供可重用和一致的構(gòu)建功能,其目標是減少每個應(yīng)用程序構(gòu)建文件中的樣板文件琼梆。在以后的技術(shù)博客中將更加深入的討論 Nebula及其特性(我們已經(jīng)將其開源)⌒杂現(xiàn)在窿吩,我們可以通過Nebula 網(wǎng)站來獲取源碼茎杂。
整合
當(dāng)一行代碼構(gòu)建完成并通過了本地 Nebula的測試,就準備對其進行持續(xù)集成和部署了纫雁。第一步是將更新過的源碼推送到git倉庫煌往。團隊可以自由尋找git工作流。一旦提交了更新轧邪,就會觸發(fā)一個Jenkins的任務(wù)刽脖。我們使用 Jenkins進行持續(xù)集成已經(jīng)有好幾年了。一開始忌愚,數(shù)據(jù)中心使用的是一個大的 Jenkins master 曲管,現(xiàn)在,在AWS上已經(jīng)發(fā)展成為 25 個Jenkinsmaster了硕糊。在整個 Netflix上院水,Jenkins主要用于各種自動化測試的任務(wù),以上提到的只是簡單的持續(xù)集成简十。
一個Jenkins任務(wù)是可配置的檬某,涉及構(gòu)建、測試和應(yīng)用程序代碼的打包螟蝙。如果被構(gòu)建的倉庫是一個庫文件恢恼,Nebula將發(fā)布.jar 到我們的歸檔倉庫。如果倉庫是一個應(yīng)用胰默,Nebulaospackage插件就會執(zhí)行场斑。使用 Nebula ospackage(操作系統(tǒng)包的簡稱)插件漓踢,一個應(yīng)用構(gòu)建出的歸檔文件就會綁定到 Debian或RPM包上,它們的內(nèi)容通過一個簡單的基于DSL的Gradle來定義漏隐。然后彭雾,Nebula將會發(fā)布 Debian 文件到一個包倉庫,這個倉庫對處理流程的下一個階段——烘烤是有用的锁保。
烘烤
我們的部署策略是以不可變服務(wù)器為中心的模式薯酝。為了減少配置漂移,確保源代碼可重復(fù)部署爽柒,強力反對在線修改實例吴菠。Netflix的每次部署首先都會創(chuàng)建一個新的AMI。為了從源頭生成 AMI浩村,我們創(chuàng)建了一個“Bakery”做葵。
當(dāng)一個Jenkins任務(wù)執(zhí)行成功后,通常會觸發(fā)一個 Spinnaker流水線心墅。Spinnaker流水線可被一個Jenkins 任務(wù)或一次 Git提交觸發(fā)酿矢。Spinnaker將讀取由Nebula生成的操作系統(tǒng)的包,然后調(diào)用Bakery API來進行烘烤怎燥。
部署
一旦烘烤完成瘫筐,Spinnaker使得最終的AMI可以部署數(shù)十、數(shù)百甚至數(shù)千個實例铐姚。由于 Spinnaker對實例暴露的運行時環(huán)境是允許應(yīng)用在運行時自由配置的策肝,這樣就使得的AMI可以跨多個環(huán)境。一次成功的烘烤將觸發(fā) Spinnaker流水線的下一個階段——部署到測試環(huán)境隐绵。從這起之众,團隊通常會使用一連串的自動化集成測試來執(zhí)行部署。從這一點開始依许,特定應(yīng)用程序的部署流水線將變得非常定制化棺禾。團隊將使用 Spinnaker來管理多區(qū)域部署,Canary 版本峭跳、紅/黑部署等等膘婶。可以這么說坦康,Spinnaker流水線為團隊如何控制部署代碼提供了極大的靈活性竣付。
未來之路
總之,這些工具使得諸多工作變得高效和自動化滞欠。例如古胆,我們只需要 16 分鐘,就可以完成對云彈性計算和維護服務(wù)(JanitorMonkey)從代碼檢出到多區(qū)域部署的過程。
也就是說逸绎,我們一直在努力提高開發(fā)者經(jīng)驗惹恃,不斷的挑戰(zhàn)我們自己,以便做到更好棺牧,更快巫糙,同時更簡單。
我們正積極應(yīng)對的一個挑戰(zhàn)是如何在Netflix中管理二進制依賴颊乘。Nebula 提供的工具側(cè)重于簡化 Java的依賴管理参淹。例如,Nebuladependency-lock插件可以生成一個基于版本的.lock文件乏悄,從而使得應(yīng)用程序解決它們完整的二進制依賴浙值。Nubularesolutionrules 插件允許我們發(fā)布整個組織的依賴規(guī)則,從而影響整個Nebula的構(gòu)建檩小。這些工具使得二進制依賴管理更加簡單开呐,但是還是沒有將“痛苦”減少到可以接受的范圍。
另一個挑戰(zhàn)我們正在處理的是烘烤時間规求。不久之前筐付,16 分鐘完成從代碼提交到部署只是一個夢想。但是現(xiàn)在阻肿,由于系統(tǒng)其它部分都變得更快了瓦戚,這反而成為快速創(chuàng)新的一個障礙。從上面部署SimianArmy的例子可以看出冕茅,烘烤的過程花了 7 分鐘伤极,烘烤占據(jù)了整個部署時間的 44%。我們發(fā)現(xiàn)烘烤時間中最耗時間的操作是安裝包(包括依賴解決)和 AWS快照自身的處理姨伤。
隨著Netflix的成長和發(fā)展,存在一個不斷增長的需求庸疾,就是我們的構(gòu)建和部署工具需要為非 JVM語言提供很好的支持乍楚,如JavaScript/Node.js, Python, Ruby和 Go。對非 JVM應(yīng)用届慈,我們當(dāng)前推薦的的方式是使用 Nebulaospackage插件來生成 Debian包徒溪,以便對其進行烘烤,對工程師來說金顿,如果跳過構(gòu)建和測試臊泌,平臺是其首選的工具。這雖然解決了團隊當(dāng)前的需求揍拆,但是還是需要擴展其成為語言無關(guān)的工具渠概。
容器為最后兩個挑戰(zhàn)提供了一個有趣的可能的解決方案,我們正在探索如何通過容器來幫助我們改善構(gòu)建、烘烤和部署的過程播揪。如果我們能夠提供一個基于容器的本地環(huán)境贮喧,就能更類似的模擬云環(huán)境,從而可能減少開發(fā)和測試過程中的所需的烘烤次數(shù)猪狈,提高開發(fā)者的生產(chǎn)力箱沦,加速整個開發(fā)過程。如果容器可以部署在本地雇庙,這樣在服務(wù)器上就不需要進行修改谓形,從而減少認知的負擔(dān),工程師就只需關(guān)注問題的解決和創(chuàng)新疆前,而不是糾結(jié)bug的產(chǎn)生是不是因為環(huán)境的差異套耕。
你可以期待在以后的文章中提供我們?nèi)绻鉀Q這些問題的更新。如果聽到這些挑戰(zhàn)讓你感到興奮峡继,請加入我們的工程工具團隊冯袍。你可以查看我們現(xiàn)在開放的職位,并馬上申請碾牌!