Pod 是在 Kubernetes 體系中,承載使用者業務負載的一種資源。Pod 們執行的好壞,是使用者們最為關心的事情。在業務流量高峰時,手動快速擴充套件 Pod 的例項數量,算是玩轉 Kubernetes 的基本操作。實際上這個操作還可以更加自動化,運維人員可以事先設定好規則,讓 Pod 例項的數量,在指定情況下自動的調整例項的數量,這一操作依靠 Horizontal Pod Autoscaler 來實現。
場景描述
如果企業應用的終端使用者是人,那麼它的訪問壓力情況,都會有潮汐特徵。好比一款供企業內部人員使用的OA系統,工作日的流量遠比休息日高,工作時間的流量遠比下班時間高。那麼可否讓這款 OA 系統根據流量的大小,自動調整例項的數量。令其忙時啟動足夠數量的例項抵禦訪問壓力,閒時自動降低例項數量,將資源留給其他企業應用。
下圖是某個業務系統,在 24 小時內的效能監控曲線。其吞吐率和線上人數曲線都可以反映出一定的潮汐特性:
- 午夜 0 點直到次日早上8 點,這個系統都處於無人使用的狀態。在這一段時間裡,可以自動將業務系統的例項數量降下來,釋放一些計算資源。
- 上午 9 點直到晚間 21 點為系統使用高峰期,最高線上人數達到 1600 人。在這一段時間裡,業務系統的例項數量可以自動提升起來,滿足業務的需要。
關於 hpa
Kubernetes 在 1.2 版本開始支援了 Horizontal Pod Autoscaler(hpa) ,來應對 Pod 例項的自動伸縮場景。它可以基於例項的 CPU 使用率來決定是否為 Pod 進行例項數量的擴容。我們知道 Pod 的副本數量是被其控制器的配置所決定的,比如 Deployment、StatefulSet、ReplicaSet 。所以,hpa 是在獲取了 Pod 實際 CPU 使用率這一指標,和擴充套件例項的目標指標對比後,操作了其控制器來實現副本數量的擴縮的。
瞭解了以上內容後,我們起碼可以知道,在使用 hpa 進行自動伸縮的設定之前,Kubernetes 叢集和 Pod 的控制器都應該符合一定的先決條件。
- 存在 Metrics-server。Metrics-server 是 Kubernetes 叢集範圍資源用量資料的聚合器。Pod 的 CPU 使用率這一指標,是從 Metrics-server 中獲取 CPU 實際用量之後,與控制器中指定的 Pod 資源做比後所得。大多數 Kubernetes 發行版中都已經預設安裝了 Metrics-server ,它一般部署在 kube-system 名稱空間中。
- Pod 資源限額。既然使用的指標是 CPU 使用率,那麼就必須存在一個 CPU 可用的上限作為分母。這個上限,實際上就是在控制器中規定的 Pod 資源限額
spec.resources.limits.cpu
。
建立 hpa
建立 hpa 之前, 我們需要確保 Pod 控制器中規定了CPU資源限額。我當前使用的案例,使用了 Deployment 控制器。其 Pod 的 CPU 資源限額給到 500m。
Kubernetes 體系中,CPU 是一種可以再分的資源,1000m = 1 Core
kubectl get deployment demo-java -n my-namespace -o yaml
返回的結果中,包含了事先設定的資源限額資訊:
spec:
resources:
limits:
cpu: 200m
memory: 1Gi
requests:
cpu: 200m
最簡單的建立 hpa 的方式,是使用 kubectl autoscale
命令進行操作。下面的示例,意味著在 Pod 的 CPU 使用率超過 50% 之後,將會觸發自動伸縮,最多伸縮到 3 個例項。
kubectl autoscale deployment demo-java -n my-namespace --cpu-percent=50 --min=1 --max=3
返回結果:
horizontalpodautoscaler.autoscaling/demo-java autoscaled
建立完成後,我們可以檢視 hpa 資源的狀態:
kubectl get hpa -n my-namespace
返回結果中,自動伸縮已經被觸發,所有例項的綜合 CPU 使用率,已經低於設定的值:
hpa 資源只需要被設定一次,就會始終監控 Pod 指標,並根據設定進行自動伸縮
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
demo-java Deployment/demo-java 49%/50% 1 3 2 3m34s
檢視 Pod 實際 CPU 使用量,可以得出相應的使用率計算值,和 hpa 中的顯示是相符的。
kubectl top pod -n my-namespace
NAME CPU(cores) MEMORY(bytes)
demo-java-7d6d7d4c9c-lz8sw 197m 87Mi
demo-java-7d6d7d4c9c-52sdl 1m 90Mi
另一種建立 hpa 的方式,是通過 yaml 檔案進行定義。我們可以將已存在的 hpa 資源匯出,便可以瞭解這一資源的定義方式。
kubectl get hpa demo-java -n my-namespace -o yaml > hpa.yaml
其定義方式可以歸結如下:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: demo-java
namespace: my-namespace
spec:
maxReplicas: 3
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: demo-java
targetCPUUtilizationPercentage: 50
通過命令,可以將這一yaml檔案載入進 Kubernetes 叢集:
kubectl apply -f hpa.yaml
更多的伸縮指標
在上一個章節,已經實現基於 Pod 的 CPU 使用率來進行自動伸縮。利用 CPU 使用率作為伸縮判定指標,是官方預設提供的方式。那麼是否還有其他型別的指標可以作為伸縮判定指標呢?這需要 Kubernetes 使用者自行擴充套件。
我建議從兩個方向挑選更多的伸縮判定指標。第一個方向是資源的選擇,相較於 CPU 而言,記憶體也可以作為判定指標;第二個方向是維度,相較於使用率而言,使用量也可以作為判定指標。兩個方向彼此組合之後,除了 CPU 使用率,我們還得到了另外 3 種伸縮判定指標:
- CPU 使用量,單位 m
- 記憶體使用率,單位 %
- 記憶體使用量,單位 MB
在 CPU 與記憶體之間,個人更建議使用記憶體作為伸縮指標,原因是資源的不可壓縮性。CPU 是一種可以壓縮的資源,而記憶體不是,資源可壓縮意味著當 Pod 的 CPU 用量無限接近於資源限額時,對 Pod 例項的影響很小,只是效能表現不佳而已。但是當 Pod 的記憶體用量無限接近於資源限額時, Kubernetes 會對 Pod 執行 OOM kill 操作,這對業務的影響很大。如果當記憶體用量/率達到一定程度,Pod 的例項數量得到了擴充套件,就有可能避免 Pod 被系統殺死重啟。
Kubernetes 官方提供瞭如何擴充套件指標的方案,但這對於一般的使用者而言並不好掌握。我的建議是選用市面上可見的基於 Kubernetes 實現的應用管理平臺。它們往往已經將自動伸縮功能封裝成為簡單易用的功能,並且提供了上述幾種伸縮判斷指標。推薦使用北京好雨科技開源的 Rainbond 雲原生管理平臺。
Rainbond 目前已經整合了開箱可用的自動伸縮功能,下面是功能截圖。
功能介面已經將易用性做到了極致,即使不去關注之前章節所寫的純技術內容,也可以掌握相關的設定。
在這個功能介面的示例中,將 CPU 使用率和記憶體使用率同時設定了。在 Kubernetes 中,一旦出現同個 hpa 設定中,包含了多個判定條件時,會分別計算在每一種條件下,滿足條件的 Pod 例項數量,並在所有結果之中選擇最大值作為最終的例項數量。
更多需要了解的內容,可以參考 Kubernetes 官方手冊