雲端開發是個坑!4年後,我們又回到了本地環境

編譯 | 明知山、Tina

雲端開發環境是軟體工程的未來嗎?

一些執行在 Kubernetes 中的複雜微服務架構是 CPU 和記憶體密集型的,在某些情況下編譯或測試可能非常耗時且佔用大量資源。然而大多數工程師的標準裝置是膝上型電腦,有 CPU 和記憶體的限制,編譯一次的時間估計夠喝好幾杯咖啡。

建立在雲端的遠端例項通常可以根據需要進行擴充套件,以適應對容量的額外需求,因此在容器化變革的基礎上,一些企業開始不再那麼依賴於本地開發環境。雖然近一兩年有一些令人興奮的遠端方案,比如 GitHub Codespaces、AWS Workspaces 或其它使用雲的標準解決方案,但在它們足夠成熟和安全之前,很多企業早已選擇了自建雲端開發環境,Lyft 就是其中之一。

雲端開發逐漸成為了坑

早在 2018 年,Lyft 的工程師就將一個大單體拆分成了一系列微服務。基於 Docker 容器的模組化開發環境最終轉移到了雲端。然而隨著時間的推移,工程師、微服務和測試的數量的激增,他們的開發工具跟不上了。

實際上,Lyft 對綜合開發環境的第一次重大投資始於 2015 年,當時的工程師人數為 100 名,大部分開發還是在一個單體架構上,只有少數用例是微服務,但預計到工程師和服務的數量會增長,所以他們認為遷移到容器是很有意義的。最初的計劃是構建一個基於 Docker 的容器編配環境,工程師可以用它們做測試。它將在生產環境中使用多租戶環境,相比以前的解決方案,可以更便宜、更快地進行伸縮。

2016 年初,Lyft 釋出了一個本地開發環境,叫作 Devbox,是“盒子裡的開發環境”的縮寫,由一些管理本地虛擬機器及其配置的工具組成,包括資料生成、包和映象的下載和安裝。開發人員只需要發出一個命令就可以構建一個可以處理請求的環境。

這些體驗很棒,讓工程師們第一次擁有了一種一致的、可重複的、簡單跨多個服務開發方法,於是很快出現了共享這些環境的需求。Devbox 轉向了雲端,變成了 Onebox。Onebox 本質上是一個執行在 EC2 例項上的 Devbox 環境。由於它的容量更大,下載映象的速度更快,工程師們自然更喜歡它而不是 Devbox。

雲端開發是個坑!4年後,我們又回到了本地環境

兩種不同風格的開發環境

在將 Devbox 和 Onebox 作為容器化開發環境引入四年後,使用這些環境的工程師增加了十倍,微服務數量也一直在激增,配置和啟動 Onebox 例項變得越來越困難和耗時。

由於每個服務都有很深的互動樹結構,例項可能需要很多的資源。可觀察性工具不能跟上所有正在執行的環境,導致除錯工作變得很困難。打比方說,不可能在數百個環境中執行相同的可觀察性工具,當出現問題時,就很難查明確切原因。此外,工程師的認知負擔顯著增加,因為他們需要牢記整個系統,而不是專注於特定的元件。

根據 Lyft 的工程設計,工程師的程式碼變更過程可以分為“內部開發迴圈”和“外部開發迴圈”。前者應該只需要幾秒鐘就能給出反饋,因為它只涉及修改程式碼和執行一些測試。後者可能需要更長的時間(至少 10 分鐘),因為它涉及持續整合和程式碼評審。整合測試臃腫笨拙,花費一個小時是司空見慣的事情。並且 80% 以上的測試要麼是不必要的,要麼可以在短時間內重寫並在沒有外部依賴的情況下執行。測試失敗還要花費數小時的除錯時間,大多數還都是誤報。

雲端開發是個坑!4年後,我們又回到了本地環境

另一方面,執行內部開發迴圈通常需要將程式碼更改同步到開發人員自己在 Onebox 的遠端 VM 環境。考慮到 Onebox 環境的設定和啟動速度很慢,再加上明顯的不穩定性,工程師通常會依賴外部開發迴圈的 CI 測試來驗證每個程式碼變更迭代。

一年前,將開發環境遷移到 Kubernetes 之後,工程資源的變化讓大家不得不重新審視開發環境:維護基礎設施以支援這些按需環境變得過於昂貴,而且只會隨著時間的推移而惡化,所以需要對開發和測試微服務的方式進行更根本性的改變。

開發環境必須回到工程師的機器上

為了擺脫不斷增長的煩惱和挫折,Lyft 將開發環境帶回到工程師的膝上型電腦上,同時重新構建內部開發迴圈。

在容器中執行程式碼並不是一種免費的抽象,因此他們決定在 MacOS 的隔離環境中執行服務程式碼,不使用容器或虛擬機器。

在 Lyft,大多數後端服務是用 Python 或 Go 語言開發的,而前端服務是用 Node 開發的:

對於 Python 服務,透過使用不可變的虛擬環境進行隔離。每次 requirements。txt 檔案發生變化,都會構建一個新的虛擬環境。

Go 服務利用 Go 模組工具鏈在 go run 或 go test 命令執行時自動下載和連結所有依賴項。

他們基於 nodeenv 構建了一個包裝器,用於根據每個 Node 服務的元資料為其建立合適的環境。

一些專門的服務,如資料儲存,也在本地執行,通常會使用容器。資料儲存在啟動時使用由服務所屬團隊維護的指令碼來載入新資料。

因此,在本地啟動服務需要多個步驟。透過手動來執行它們既乏味又容易出錯。Lyft 使用 Tilt 來協調服務的生命週期及其環境,避免透過手動執行所有的步驟。每個服務都有一個 Tiltfile,用於描述在本地執行服務所需的步驟。當工程師在 IDE 中修改了程式碼時,執行中的服務也會重新載入自己,從而進一步縮短內部開發迴圈。

除了執行服務之外,還需要與服務發生互動。由於 Lyft 使用了不同的傳輸格式,比如 gRPC、JSON/HTTP 和 protobuf/HTTP,因此向服務發出請求並不是那麼簡單。工程師們使用 Lyft 開發的一個工具向本地服務傳送請求。這個工具可以與服務的 IDL 整合,因此可以利用工具的自動補全功能。

最終結果

自從將這個工具推廣到整個公司以來,Lyft 工程師反饋非常積極。

開發人員喜歡無需任何遠端環境即可在膝上型電腦和 IDE 中執行測試的能力。建立一個新的 Onebox 環境通常需要大約一個小時,但現在膝上型電腦環境始終可以執行測試,使用 Tilt 在本地啟動服務只需幾分鐘。

負責基礎架構的高階軟體工程師 Scott Wilson 說:“我們還觀察到開發人員的行為轉變,因為他們花費更多時間專注於測試他們的服務。在測試本地服務時,使用者可以直接向服務 API 傳送請求,而不是透過移動應用程式與公共 API 對話。這增加了開發人員對服務 API 的熟悉程度,並縮小了在出現錯誤時的除錯範圍。”

而且讓使用者在他們的膝上型電腦上單獨執行服務意味著真正減少所需的總計算資源。“雖然成本不是這個專案的主要驅動因素,但不再為每個開發人員支付 Onebox 的 AWS 例項,我們最終節省了大量資金。”

總的來說,對於開發者來說,因開發環境而導致正常工作停滯不前是特別讓人不可忍受的。不好的開發環境會嚴重影響大家的生產力,而一個好的本地開發環境,允許開發人員在沒有破壞共享環境或干擾面向客戶的環境的風險的情況下執行和測試程式碼。而且,它通常是低成本的,依賴於已經支付的資產,比基於雲的環境更高效、更便宜。

另外,Scott Wilson 表示他們也正在密切觀望完全遠端的開發環境,例如 Github Codespaces,以瞭解它們成熟後是否適合自己。

參考連結:

https://eng。lyft。com/scaling-productivity-on-microservices-at-lyft-part-1-a2f5d9a77813

https://eng。lyft。com/scaling-productivity-on-microservices-at-lyft-part-2-optimizing-for-fast-local-development-9f27a98b47ee

https://eng。lyft。com/scaling-productivity-on-microservices-at-lyft-part-3-extending-our-envoy-mesh-with-staging-fdaafafca82f

https://eng。lyft。com/scaling-productivity-on-microservices-at-lyft-part-4-gating-deploys-with-automated-acceptance-4417e0ebc274

https://github。com/readme/guides/developer-onboarding

TAG: 環境服務開發工程師Lyft