為什麼公有雲的彈性能力很難被發揮出來?

雲端運算透過資源池化實現單位資源成本更優,使企業能夠將IDC 建置、基礎軟體研發和維運等工作外包給雲端廠商,從而更專注於業務創新。資源池不僅包括伺服器,還包括人才。雲端廠商集結了優秀工程師,透過雲端服務為許多企業提供專業服務,讓專業的事交給最專業的人。

雲端運算發展這麼多年,彈性是雲端運算從業人員最關注的技術能力之一,但是真正落實到具體的案例上,很少有客戶能把彈性用好,彈性反而成為了一種口號,一種理想的架構,本文嘗試討論為什麼現實和理想差距這麼大,以及有哪些低投入高回報的彈性方案。

雲廠商透過包年包月打折來留住客戶,與彈性場景相悖

下表是一份典型的包年包月EC2 價格與按量付費價格對比,總結出來的遊戲規則:

  • 包年包月相比按量付費大約有50% 的成本節省 這也是為什麼大多數企業選擇包年包月方式來使用EC2 資源。從雲端廠商的角度這麼設計非常合理,因為雲廠商是透過預測全網客戶的使用量來確定一個Region 要預留多少空閒水位,假設On Demand 和Reserved 實例價格一致,將導致雲廠商難以預測一個Region的水位,甚至會出現白天和晚上有巨大的差異,會直接影響供應鏈的採購決策。雲端廠商是典型的類零售商業模式,每個Region 的空閒機器數量類比為庫存,庫存比例越高,會導致利潤率越低。
  • Spot 實例恰好做到既便宜又是按小時付費 這也要求應用能處理好Spot 實例被強制回收帶來的影響,對於無狀態應用相對簡單,Spot 實例在回收之前會通知應用,大部分雲廠商會給到分鐘等級的回收窗口,應用程式只要做到優雅下線,就能做到對業務無影響。海外專業基於Spot 實例來管理運算資源的新創公司[1],有大量的產品化功能幫助使用者使用好Spot 實例。 AutoMQ 公司也累積了豐富的Spot 實例使用經驗[2]。但對於有狀態應用,Spot 實例使用起來的門檻變得非常高,實例被強制回收前,就需要做到將狀態轉移。例如Kafka,Redis,MySQL 這類應用。針對這類資料型的基礎軟體通常不建議使用者直接部署到Spot 實例。

這個遊戲規則既有合理的地方也有值得優化的地方,筆者認為至少還可以在以下方面做的更好:

  • Spot 回收機制提供SLA 要能鼓勵更多使用者使用Spot 實例,那麼Spot 的回收機制中的訊息通知要能提供確定的SLA,這樣一些關鍵業務就能敢於大規模使用Spot 實例。
  • 建立新實例API 提供SLA Spot 回收後,應用的兜底方案是繼續開通新的資源(如新的Spot 實例,或新的On-demand 實例),這時開通新實例的API 也要能有確定的SLA,這個SLA 會直接影響到應用程式的可用性。
  • 卸載雲端碟提供SLA Detach EBS 也要能有確定的SLA,因為一旦發生強制回收Spot 實例,要能允許使用者自動化處理好應用程式狀態卸載。

EC2 執行個體類型

價格/月

相對On Demand 價格比例

一經請求

56.210 美元

100%

$24.747

44%

預留1年

$35.259

63%

預約3年

$24.455

44%

AWS 美國東部 m6g.large

程式設計師很難做好資源回收這件事情

C/C++ 程式設計師大量的精力在和記憶體作鬥爭,但是仍然不能保證記憶體資源不會外洩。原因是資源準確回收是一件極具挑戰的事情,例如一個函數返回一個指針,那麼這個物件是誰負責回收,C/C++ 是沒有約定的,如果再涉及到多線程,則更加噩夢。為此C++ 發明了智慧指針,透過一個線程安全的引用計數來管理物件。 Java 透過內建的GC 機制,透過執行時期來偵測物件回收,徹底解決了物件回收問題,不過也帶來了一定的執行時間開銷。最近特別火的Rust 語言,本質上也是類C++ 的智慧指標回收方式,創新性的將記憶體回收檢查機製做到了編譯階段,從而大幅提升了記憶體回收的效率,避免了C/C++ 程式設計師常犯的記憶體問題,筆者認為Rust 將是C/C++ 的完美替代品。

回到雲端作業系統這個領域,程式設計師可以透過一個API 就能創建一台ECS,一個Kafka 實例,一個S3 Object,這個API 背後帶來的是帳單的變化。創建容易,回收則變得非常困難。創建時候通常會指定最大規格,例如建立Kafka 實例,先來20 台機器,因為未來擴容縮容都很困難,不如一次到位。

雖然雲端運算提供了彈性,但程式設計師難以有效地按需管理資源,導致資源回收困難。這促使企業在雲端資源創建時設立繁瑣的審批流程,類似傳統IDC 的資源管理方式。最終導致的結果即程式設計師在雲端上使用資源的方式與IDC 趨同,即需要透過CMDB 進行資源管理,並依賴人工審批流程來避免資源浪費。

我們也看到了一些優秀的彈性實踐案例。例如某大型企業在使用EC2 時,每個EC2 的Instance ID 存活週期不超過1 個月,一旦超過, 就會被列為“爺爺輩的EC2”,要上團隊的黑榜單。這是一個非常棒的不可變基礎架構實踐方法,能有效避免工程師在伺服器上保留狀態,如配置,資料等,從而讓應用程式走向彈性架構變得可行。

目前雲端運算的階段還處在C/C++ 階段,還沒有出現優秀的資源回收解決方案,所以企業還在大量使用流程審批機制,實質上導致了企業無法發揮雲端的最大優勢:彈性。這也是導致企業雲端支出較高的主要原因之一。

相信只要有問題,一定會有更優秀的解法,解決雲端資源回收的類Java/Rust 方案一定會在不久的將來問世。

從基礎軟體到應用層,還沒有為彈性做好準備

筆者曾在2018 年開始為淘寶天貓的數千個應用設計彈性方案[3],當時淘寶天貓的應用已經做到了離線和在線混部來提升部署密度,但是在線應用仍然為預留模式,無法做到按需彈性。根本問題還是應用在擴縮時,可能會產生非預期的行為,即使運行在Kubernetes 之上,仍然不能徹底解決,如應用會調用各種中間件的SDK(資料庫、快取、MQ、業務快取等) ,應用本身啟動也消耗時間較長,看似無狀態的應用,實則也包含了各種狀態,如包括單元標籤,灰度標籤等,讓整個應用需要大量的人工操作,人工觀察才能有效擴縮容。

為了讓Java 應用從分鐘級的冷啟動提升到毫秒級,當時為Docker 開發了Snapshot 能力[3],這項能力的生產應用足足比AWS 領先了4 年(AWS 於2022 年Re:invent 會議上發布了Lambda SnapStart[4][5] 功能)。透過Snapshot 方式啟動應用程式可以數百毫秒就能增加一台可以立刻工作的運算節點,這項能力讓應用程式不需要改造成Lambda 函數方式就能做到像Lambda 一樣,根據流量來增減運算資源,也就是我們看到的Lambda 提供的Pay as you go 能力。

應用層做彈性已經如此複雜,到了基礎軟體做彈性挑戰更大,如資料庫、快取、MQ、大數據等產品。分散式高可用高可靠的要求決定了這些產品都需要將資料儲存多個副本。一旦資料量大,彈性將變得非常困難,遷移資料會影響業務的可用性。為此,要在雲端環境解決這個問題,就要用雲端原生的方式,我們在設計AutoMQ(賦能Kafka 的雲端原生方案)時,將彈性作為最高優先級,核心挑戰是要將儲存卸載到雲服務,例如按量付費的S3,而不是自建儲存系統。下圖是AutoMQ 線上的流量和節點變化圖,會看到AutoMQ 是根據流量全自動增減機器,如果這些機器採用Spot 實例,將為企業節省大量的成本,真正做到Pay as you go。

AutoMQ 根據流量自動增減節點

企業如何運用好彈性能力降本增效

Google 在2018 年推出了Cloud Run[6] 全託管式運算平台,基於HTTP 通訊的應用程式僅需提供監聽連接埠和容器映像檔給Cloud run,所有基礎架構的管理將全自動由Cloud run 執行。這種方式相比AWS Lambda 方式最大優勢是無需綁定到單一雲端廠商,未來可以更好的遷移到其他運算平台。很快地AWS 和Azure 跟進推出了類似的產品,Azure Container Apps[7] 和AWS App Runner[8]。

專業的事情交給專業的人做,彈性是一個非常有挑戰的工作,推薦雲端上的應用程式可以盡可能依賴這些無程式碼綁定託管框架,如Cloud run,做到應用程式消耗的運算資源可以按照請求來付費。

基礎軟體如資料庫、快取、大數據、MQ 等,很難用一個統一的託管框架來解決,這類應用的演進趨勢是每個品類都在向彈性架構演進,如Amazon Aurora Serverless,Mongodb Serverless[9 ],從雲端廠商到第三方開源軟體商都有共識要能走到徹底的彈性架構。

企業在選擇類似開源基礎軟體時,要盡量選擇具備彈性能力的產品,判斷的標準是是否能運行在Spot 實例上,是否能極具性價比。同時也要關注這類產品是否能更好的在多個雲端運行,這決定了企業在未來走向多雲架構,甚至混合雲架構時,是否具備移植性。