作者 | 高朋(科賽網後端研發工程師)

編輯 | bot(才雲)

編者按:在這篇文章中,科賽網後端研發工程師高朋首先介紹了 Cluster Auto Scaler 的主要設計、功能和他們對 Cluster-Autoscaler 的一些改動,使得這個組件可以支持預測性伸縮。

Kubernetes 本身有很多方面的 scaling,包括 Pod 的垂直擴展和集群物理節點的擴展等。今天我想介紹的是 Cluster-Autoscaler 用於物理節點的擴展。如果大家經常關注 Kubernetes scaling 相關的一些 talk,應該會比較了解這一塊。我會先從子項開始,然後介紹我們怎麼做預測性擴展,談談在這個預測性擴展中我們嘗試過的一些演算法。

CA:一個按需伸縮物理資源的組件

Cluster-Autoscaler(CA)是一個在 Kubernetes 中做虛擬機節點擴展的組件,它可以幫你屏蔽掉資源的物理層需求。也就是說,當你申請的資源出現不足時,它會自動添加一個物理資源。

這樣的好處是不論你有多少台機器,你只需要關心自己用的 Pod,在容器層給用戶提供數據分析的工具和平台。當然,這也意味著我們面臨的用戶用量波動會很大,這就是為什麼我們需要這樣一個組件來做支撐,而不是一種靜態的技術。

Cluster-Autoscaler 主要由三個部分組成,第一個部分是 Predicate,主要負責確定一個 Pod 能否在某 Node 上調度,它的依據是 CPU、GPU 或者 memory。比如創建 Pod 時,它所需要的 GPU 和內存會被作為它能不能跑到 Node 上的判斷依據。

第二部分是 Priority。完成上一步後,如果我們發現有一些 Node 能滿足需求,那麼我們就要考慮一個新問題:該選用哪個 Node?這時的考慮情況也很多,比如 NodeSelector,或者更進一步的 NodeAffinity,或者在這個 Deployment 當中,它會盡量分散到不同的 Node 上。 這就是 Priority 替我們考慮一些事情。

最後一部分 Scheduler 處理的就是當我們把 Node 排序以後,我們從中找出一個最合適的,然後把 Pod 放進去。之前我們提到,在 CA 中,Predicate 的一個作用是驗證是否需要新增新的機器,Scheduler 也有相似的作用。即便我們沒找到合適的 Node,沒有 Priority,Scheduler 也可以發揮作用。

CA 基於 Group 的能力,它可以根據需求在雲廠商上自動擴展物理節點,通過 API 獲取 Node Group 原信息,並知道 Node Group 里機器的型號,以此構造一個虛擬的 Node,比如說一個 4G 或 8G 的機器。一旦有了這些 Node 模板,那麼當我們手頭有一些的 Pending Pod 時,我們就可以嘗試用這些假的 Node Template 去配合一下,看它能不能調動上去。

下面我介紹一下 CA 的主體邏輯,它的處理對象就是無法調度的 Pending Pod,整個調度默認每 10 秒執行如下邏輯:

  • 檢查集群中 Node Group 的健康狀態;
  • 嘗試解決集群現有的錯誤,如果有節點長期沒有加入到集群中,嘗試刪除並且重試;
  • 找到無法調度的 Pending Pod,如果 Pod 是剛創建的也會暫時過濾;
  • 找到一個 Node Group,通過擴展一定數量的機器可以讓 Pending Pod 運行,Node 的模板從公有雲的 API 中獲取,這也是為什麼需要使用 Scheduler 的邏輯;
  • 在模擬狀態下,確定選出的 Node Group 需要擴展的節點數量;
  • 決定最佳的擴展策略(expander option),最便宜/最小/最大,執行真正的擴展動作;
  • 查找低使用率(<50%,沒有無法遷移的 Pod,沒有無 RelipcaSet 的 Pod)的 Node;
  • 刪除長時間保持上述狀態的 Node,默認 10 分鐘。

如何實現預測性伸縮

如果大家經常關注 KubeCon,我記得負責人提過他們不會支持預測性。接下來我將介紹我們的修改邏輯,實現支持一個預測性的分組。

以我們公司為例,我們業務有幾個特點,一是你可以看到資源用量有明顯周期性,二是資源整體用量存在長期的增長趨勢,三是資源用量存在激增的突發情況。如下圖所示,我畫了一條合理的資源調動曲線。

理想情況下,如果我們調度的機器物理資源和實際用戶用量是完全一致,那麼我們就沒有浪費一分錢;如果機器的用量在這條曲線下面,說明物理資源滿足不了用戶需求,用戶在等或者用戶根本用不了;如果在上面,那我們就是在浪費錢。

我們的策略是盡量浪費少一點,確保能滿足用戶需求,也就是盡量不要讓機器用量在曲線下面。如果對這件事做抽象,計算資源無非就是 Pod 和 Node,如果我們是在公有雲上跑,它其實就又多了一層,就是雲廠商的物理節點。

我們希望用戶了解 Kubernetes,但他們有時候想知道更多東西,就像應用雖然跑在 Kubernetes Node 上,但他們並不知道下面的物理資源是怎麼分配的:應用跑在哪台機器上?用了多少資源?其他 CPU 還有多少內存?

我們需要把公有雲上物理節點加到 Kubernetes 集群當中,來滿足用戶的這些需求

為了實現這點,首先我們會設計統一的 Interface,使得預測模型只需要預測接下來會需要多少 Pod。預測演算法需要統一介面,根據時間、當前 Pod 的資源用量,輸出需要進行擴展的 Pod。這個問題可以歸類到時序預測的範疇中,需要相關人員有相應的 Kubernetes 專業背景知識,同時也要有時序預測的統計學和機器學習相關的知識。

那麼具體該怎麼實現呢?我們需要構造 Pod 模板,對 Pod 進行粒度劃分,虛擬 Pending。因為真實用戶的 Pod 其實有很多種,它們可能是 0.5 和 1.5 的,也可能是 4.5 核的,它們的 GPU 資源也不統一,很難實現統一操控。如果我們對 Pod 做分級,按照 Node Group 這樣一個抽象的概念,有個 virtual Pod,這個 virtual Pod 其實就是 Pod 的模板。

同時,為了避免虛擬 Pod 構造太大造成浪費和虛擬 Pod 構造太小無法觸發擴展兩種情況,我們在完成預測性推斷之後,又在真實的 Pending Pod 之後追加 Predictive Pod。用戶走 CA 流程時只看到一批 Pending Pod,它們可能是真的也可能是假的,假的那部分是我們通過預測做出來的。

還有一個需要修改的地方就是社區的 CA,如果觸發 Scale Up,它是不會 Scale Down 的。這個也很好理解,如果我們要加機器,為什麼要減機器呢?但這很多時候不一定準確,你也不知道需不需要減機器。所以我們關閉了一些 CA 的優化邏輯,在有 Pending Pod 的情況下始終觸發 Scale Down 檢查,並且通過貪心和時間排序把虛擬 Pod 盡量佔領相對固定的 Node

預測演算法

我們先從一個簡單的線性模型看起。我們根據當前用戶資源的使用情況,乘上一定係數作為當前需要準備的資源用量。

比如說我希望我們的 Node,不管有沒有 Pod,我都有三台機器, 那 b 就是 3。我希望我的資源永遠比現在的用戶多一點,比如多 30%,那麼我就把 a 設成 1.3。

它的優點不用說,簡單,不需要藉助第三方的推斷服務,在代碼中實現靜態的 Interface,更新參數重啟即可。但它的缺點也很突出,就是不夠靈活,我之前那張資源調動曲線圖就是最好的證明。如果突發很多的話,假設這個值是 1 萬,那麼 1.3 就是就是 13000,相當於我為了開 1 萬台機器,需要多開 3000 台機器,這個成本可想而知。這種線性模型不符合我們的實際期望,所以雖然簡單但是不合理。

接下來,我們再試著用一些傳統統計學方法去做這種預測。Facebook 有 prophet 預言家工具庫,它很簡單,只有兩個維度:t 是時間,Y 是一個數值。

這是一種傳統的統計學方法,只要把數據傳進去,它就能自動做持續預測。它有三個值,其中 S 表示 season,也就是它的周期,周期模擬的方式等同於傅立葉級數,就是通過 N 個三角函數疊到一起,它就能模擬不同的周期函數。T 表示趨勢,它是一個 basis,你可以把 basis 理解為假期,比如說公司臨時放假一天,它在周末周期規劃之外,但一天時間並不夠你回老家,這時你可以把節假日都算進去,統一起來。最後的 R 表示剩餘項。

這種預測演算法的調用方式也很簡單,只需一行 Python 就可以做預測了。除此之外,對沒有相關背景的人非常友好也是它的優點,任何人都能通過它得到非常好的效果。

但它也有缺點,就是它是一個 Python 庫,只能以 Python Service 的方式部署。同時,由於只是一個基於時間的持續預測,它在面對突發情況時表現往往不是特別好,因為它沒有輸入 Pod,它只與時間相關,所以雖然大部分情況下它的效果都不錯,但在突發的那條高線上,它還是無法滿足我們的需求。

最後,我們再聊一聊 LSTM。LSTM 也叫長短期記憶網路,它是 RNN 的變種。RNN 把上一層的輸出作為下一層的輸入,從某種程度上說,它是一個無限長的多層感知機,而 LSTM 對 RNN 的優化在於它很「健忘」。

這個概念在文本任務中比較常見,比如說我們在做一個喜歡貓還是喜歡狗的預測,期間有條輸入是「我喜歡金魚」,它就可以被選擇性遺忘。儘管最常見於文本任務,LSTM 在時間序列預測上的表現也很好,在我們的場景下,它可以結合 Pod 的資源分配和時間進行動態預測,把突發情況也統一到模型當中,相對來說更靈活。演算法也可以交由數據部門優化,後端無感

它的缺點是如果要構成一個獨立的服務的話,可能是 PB 或者是 ONNX,因為它要用 tf 或 torch 去訓練。其實這應該不算缺點,這是標準的,它可以通過 tf-serving 部署。所以如果我們把介面統一成 PB 的話,那預測模型就不需要修改,我們只要統一 Model 介面。

總結

以上就是我們的整個設想,如何對預測區伸縮做改進。最後我再對本次演講做一下總結:

  • CA 是一個用於在公有雲上進行集群自動伸縮的組件;
  • 架構分層和專業分層要求介面的分層(後端工程師和演算法工程師);
  • CA 按照公有雲的虛擬機分級,構造虛擬 Pod;
  • 介紹時序預測的方法:線性模型、fbprophet、LSTM。

講師簡介:高朋,科賽網後端研發工程師,主要關注 Kubernetes 後端架構和數據分析工具的結合。


推薦閱讀:
相关文章