如何科學地估算 Kubernetes 所需的資源? App 角度篇
今年 2021 小弟上半年過度忙碌,加上換球隊打球,再加上有點遇到中年危機,導致發廢文量大幅下降,請大家多多擔待
地上爬的我:算 Kubernetes Sizing 好累,我都以為我改行成為 Excel 架構師了呢 天上飛的學長:雲原生服務到底是要 Sizing 什麼 =_= ? 不夠不就給他加下去就對了? 地上爬的我:我們是地端...Q_Q 天上飛的學長:恩...你保重
系列文前言
早在本篇開始,其實早在先前 Learnk8s Kubernetes Instance Calculator 已經有推出過一個蠻好看的網頁資源計算機供大家參考,但這個的問題是他沒有考量到多個 Kubernetes Namespace 部署的狀況,畢竟不可能每一個 Pod 的資源都長一樣。其次,地端跟雲端不一樣,前者採購硬體需要事先準備,後者則具備有限的無限資源可供使用,所以只要前者一個估不準就會出事。但身為一名 Ops 人員,我又應該要如何請 App 人員提供數字給你作為參考?
所以為了廣大的鄉民,我提供預估資源資源作法,大概可以解決八成左右的狀況 (其他兩成狀況,請洽業務找我去幫忙算 XD)。故以為了要管理好多個 Kubernetes 叢集需求之下,需要在每一個 Kubernetes 所部署的程式資源 Tanzu Mission Control Extension Manager 的這支程式作為估算範例
主要分為兩個方向夾擊抓資源
- Top-Down:以 App 角度出發的 Kubernetes Application 資源估算
- Bottom-Up:以 Ops 角度出發的 Hardware (or Cloud Provider) 資源估算
以 App 角度出發的 Kubernetes Application 資源估算
想問問大家一個 Kubernetes 要部署一個 Application 會需要什麼東西? 是的,你需要去描述你的應用程式資源和相關資訊,並且部署在特定的 Kubernetes Namespace,如 vmware-system-tmc,所以身為一個 App 人員的目標就是把 基於 namespace 為主的內部所需資源條列出來,擷取 Tanzu Mission Control Extension Manager L880-L957 內容,如下
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
tmc.cloud.vmware.com/orphan-resource: "true"
labels:
app: extension-manager
control-plane: extension-manager
controller-tools.k8s.io: "1.0"
tmc-extension: "true"
tmc-extension-name: extension-manager
tmc.cloud.vmware.com/managed: "true"
name: extension-manager
namespace: 'vmware-system-tmc'
spec:
minReadySeconds: 30
progressDeadlineSeconds: 600
replicas: 1
selector:
matchLabels:
control-plane: extension-manager
controller-tools.k8s.io: "1.0"
tmc-extension: "true"
strategy:
rollingUpdate:
maxSurge: 100%
template:
metadata:
labels:
control-plane: extension-manager
controller-tools.k8s.io: "1.0"
tmc-extension: "true"
tmc-extension-name: extension-manager
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
- matchExpressions:
- key: beta.kubernetes.io/os
operator: In
values:
- linux
containers:
- command:
- /usr/local/bin/manager
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: 'extensions.vmware-cloud.tmc.cloud.vmware.com/extensions/extension-manager/extension-manager@sha256:'
imagePullPolicy: Always
name: extension-manager
ports:
- containerPort: 9876
name: webhook-server
protocol: TCP
resources:
limits:
cpu: 100m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
securityContext:
runAsGroup: 1000
runAsUser: 10000
serviceAccountName: extension-manager
tolerations:
- operator: Exists
對於 Kubernetes Application 資源估算你應該要關心以下幾個點
- kind 的類型:主要先以可涵蓋大部分部署場景為主,常見有 3 大 Kind,Deployment、StatefulSet、DaemonSet,如本範例為例
kind: Deployment - spec.replicas 的數字:主要是要確認待會下面的 CPU / Memory 是要乘上多少,常見應該都是以
1為主,至於為什麼可參閱我於 之前在 Microsoft DevDays 2021 演講的內容,如果微服務能夠 Scale-Out 的話,就是2或以上的數字 - 每一個 Pod 所需要的 CPU 和 Memory 資源:主要是確定一個 Container 所需要的 CPU 及 Memory 的上下限,要留意
1 個 Pod 裡面會有 1 個或多個 Containers,可詳閱之前在 HKOSCon 2020 演講內容 - Storage 的選型:主要是要確定是要透過 hostPath 肚子的硬碟還是使用 PV/PVC 採用基於 CSI 介面的外掛儲存服務,常用協定如 NFS、iSCSI 及 FC 等,這個主要都是以服務對於 IOPS 或其特性的考量為採用標的,但本文不深入探究
所以把上面的資訊收集起來,會得到下面這張表

但實際上你填完,會注意到一些事情
- 這樣總資源是對的嗎?
- 有些欄位沒填的怎麼辦?
回應第一題,一定不對,因為你看 Replicas 有些是 2,所以實際上你應該要把左邊的資源全部乘上 Replicas 數字,身為一個 App 團隊你應該會得到下面這張表

這時候你把全部的資訊撈出來,可以獲得到 大約這支整個程式再怎麼跑,頂多 vmware-system-tmc 這個 namesapce,就是吃掉 4700m CPU 跟 6382M Memory,至於對於 Kubernetes 計算單位不熟的可以參考 Kubernetes Managing Resources for Containers,另附上 Google Sheet 參考文件
回應第二題,呈上,如果你沒寫資源,這不是代表他運作不用資源,是代表這份 Yaml 沒有定義 limits / requests 兩個數字去限制他的資源使用,而是會用 BestEffort 的方式運行。在這個狀況下,如果真的寫不出來,真的是只能憑經驗先估一個數字給 requests 確保不會爆炸,再來用 Metrics 服務,如自建 Prometheus、或 SaaS 服務 Tanzu Observability 長期觀測調整數字為比較務實的作法。倘若你如果選用的程式是 Java JVM 或者是自帶程式語言虛擬機,會相當好估算,但本文不深入探究
那額外問題來了,如果我在資源裡面填 0 的話會怎樣?
關於 0 的那些事
先講結論,建議還是要設定 limits 跟 requests 的值上去,最少也要有 limits
當資源真心不足的時候,則 Kubernetes 則有內建支援 QoS 服務管理能力,且支援作業系統等級的 OOM 控制,最小計算單位為 Pod。一般來說,估算計算資源 limits 比較重要,實際上運行調度則是 requests 比較重要
Kubernetes 會開始依據 QoS 三種等級(由最高到最低優先權排序):Guranted > Bursatable > BestEffort 進行權重排序,通常會發生 OOM (Out-of-Memory) 也都是因為撞到資源不足,然後優先權重又低,就被幹掉了,常見如 AI/ML 容器等會吃資源的容器服務,確切的詳細內容請參閱 Kubernetes - 配置 Pod 的服务质量
| 優先權 | QoS 類型 | 描述 |
|---|---|---|
| 1 (highest) | Guaranted | Pod 裡面的每一個 Container 都要設定 requests 等於 limits (兩個值皆有設定,且不等於 0) |
| 2 | Burstable | Pod 裡面的任一個 Container 具有 requests 不等於 limits 數值,且不符合 Guaranted 條件 |
| 3 (lowest) | BestEffort | 沒有設定任何資源請求和限制 |
當然你看完上面應該會霧傻傻,所以身為 Excel 精算師的我幫大家整理了以下列舉了已知組合,供大家參考

你看完上面的圖應該會知道一個事實,0 在 Kubernetes 來說是有意義的,所以資源估算請不要亂寫,他不代表無限大資源的意思...如果真的不知道請留空,而不是寫 0
以 App 角度出發的常見資源錯估誤區
你是不是覺得到這邊就可以估算結束了?很抱歉沒有,你還少算運行 Kubernetes 所需要的服務,如 kubelet、CNI、kube-proxy、OS 本身服務等等這些不存在於 kubernetes 的資源清單上,但實際上是需要這些服務才能夠好好的運行 Kubernetes 服務,那這是什麼意思呢?
拿房子權狀比喻,以上所做的事情都是在算室內面積(客廳、浴室、陽台),實際上你還有公設(樓梯、電梯、健身房)要算啊!所以最終估算 1 個 Kubernetes 所需資源的結果,一定會比 App 所寫的還要來得大上一點
而各大廠商為了要降低公設比,紛紛都推出了 Container OS 進行資源和效能上的最佳化,畢竟誰希望拿到 1 個 4c/8g 的 worker 節點,把一堆跟 kubernetes 沒關係的服務開起來就剩不到一半資源可以用,但因為各家出 Container OS 系統都不盡相同,所以會很仰賴各自廠商工程師的精算
結語
看完以上的文章,相信大家一定會覺得為啥我要個 Kubernetes 為啥要搞得這麼複雜,所以下篇會講,以 Ops 角度出發的 Hardware (or Cloud Provider) 資源估算,就是寫不出來的狀況下身為 Ops 到底該怎麼辦?
希望今年能寫得出來...希望...
特別感謝 Gene Kuo 和 Hwchiu 幫忙校稿 XD