簡述
為一個 pod 配置資源的預期使用量和最大使用量是 pod 定義中的重要組成部分。 通過設置這兩組參數, 可以確保 pod 公平地使用 Kubemetes集群資源, 同時也影響着整個集群pod的調度方式。
為Pod中的容器申請資源
我們創建 一 個pod 時,可以指定容器對CPU 和內存的資源請求量(即requests), 以及資源限制量(即Limt)。它們並不在 pod 里定義, 而是針對每個容器單獨指定。pod 對資源的請求量和限制量是它所包含的所有容器的請求量和限制量之和。
創建包含資源 requests 的 pod

apiVersion: vl kind: Pod metadata: name: requests-pod spec: containers: - image: busybox command: ["dd", "if=/dev/zero", "of=/dev/null"] name: main resources: #我們為主容器指定了資源請求 requests: cpu: 200m #容器申請200毫核(即一個CPU核心的1/5) memory: lOMi #容器申請了10M 內存
當我們不指定CPU requests時,表示我們並不關心系統為容器內的進程分配了多少CPU時間。在最壞情況下進程可能根本分不到CPU時間(當其他進程對CPU需求量很大時會發生)。這對一些時間不敏感、低優先級的batch jobs沒有問題,但對於處理用戶請求的容器這樣配置顯然不太合適。
資源 requests 影響調度
通過設置資源requests我們指定了pod對資源需求的最小值。調度器在將pod調度到節點的過程中會用到該信息。調度器在調度時只考慮那些未分配資源量滿足pod 需求量的節點。如果節點的未分配資源量小於pod 需求量,這時節點沒有能力提供pod對資源需求的最小量,因此Kubemetes不會將該pod調度到這個節點。
調度器在調度時並不關注各類資源在當前時刻的實際使用量,而只關心節點上部署的所有pod 的資源申請(request)量之和。盡管現有pods 的資源實際使用量 可能小於它 的 申請量,但如果使用基於 實際資源消耗量
的調度算法將打破系統為這些已部署成功的pods提供足夠資源的保證。
查看資源分配情況

kubectl describe node node-name #整個節點總體資源 Capacity: cpu: 4 ephemeral-storage: 515922800Ki hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 15732704Ki pods: 23 #整個節點可以對外分配的資源 Allocatable: cpu: 4 ephemeral-storage: 475474451693 hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 14708704Ki pods: 23 ... #各個命名空間實際requests分配的情況,會有kube-system 下的系統級別的Pod申請了資源。 Non-terminated Pods: (15 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE --------- ---- ------------ ---------- --------------- ------------- --- default jianwei-k8s-3afe2134-3b6f-43a6-a473-ce4 0 (0%) 0 (0%) 1Gi (7%) 0 (0%) 58d filebeat filebeat-fdasd 250m (6%) 500m (12%) 500Mi (3%) 1Gi (7%) 21d kube-system flexvolume-dfhjj 100m (2%) 1 (25%) 100Mi (0%) 1000Mi (6%) 58d kube-system kube-proxy-worker-bqcmk 0 (0%) 0 (0%) 0 (0%) 0 (0%) 58d kube-system terway-eniip-fffvg 250m (6%) 0 (0%) 0 (0%) 0 (0%) 58d monitoring ack-prometheus-operator-adapter-7c 0 (0%) 0 (0%) 0 (0%) 0 (0%) 23d monitoring ack-prometheus-operator-grafana-5b 0 (0%) 0 (0%) 0 (0%) 0 (0%) 23d monitoring ack-prometheus-operator-kube-state 0 (0%) 0 (0%) 0 (0%) 0 (0%) 23d monitoring ack-prometheus-operator-operator-8 0 (0%) 0 (0%) 0 (0%) 0 (0%) 23d monitoring ack-prometheus-operator-prometheus-node 0 (0%) 0 (0%) 0 (0%) 0 (0%) 23d monitoring alertmanager-ack-prometheus-operator 100m (2%) 100m (2%) 225Mi (1%) 25Mi (0%) 23d monitoring prometheus-ack-prometheus-operator- 150m (3%) 150m (3%) 75Mi (0%) 75Mi (0%) 23d ad1 payshop-85dasdbcd4749-h625m 500m (12%) 2 (50%) 1Gi (7%) 4Gi (28%) 24d ad3 fdaf-supply-chain-go-64988c99d8-ppv2v 500m (12%) 1 (25%) 1Gi (7%) 2Gi (14%) 16d ad6 k8s-admin-soul-85d5945974-lxjh4 500m (12%) 2 (50%) 1Gi (7%) 4Gi (28%) 24d #整個節點匯總后實際requests分配的情況,k8s根據分配后的剩余量來調度pod Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 2350m (58%) 6750m (168%) memory 4996Mi (34%) 12364Mi (86%) ephemeral-storage 0 (0%) 0 (0%) ...
CPU requests影響CPU時間分配
現在有兩個pod運行在集群中(暫且不理會那些系統pod 因為它們大部分時間都是空閑的)。 一個請求了200毫核,另一個是前者的5倍。我們還沒有定義任何limts, 因此每個pod 分別可以消耗多少CPU並沒有做任何限制。那么假設每個pod內的進程都盡情消耗CPU時間,每個pod最終能分到多少CPU時間呢?CPU requests不僅僅在調度時起作用,它還決定着剩余(未使用) 的CPU時間如何在pod之間分配。第一個pod 請求了200毫核,另 一個請求了1000毫核,所以未使用的CPU將按照1:5的比例來划分給這兩個
pod。如果兩個pod 都全力使用CPU, 第一個pod 將獲得16.7%的CPU時間,另 一個將獲得83.3%的CPU時間。
另一方面,如果一個容器能夠跑滿CPU,而另 一個容器在該時段處於空閑狀態,那么前者將可以使用整個CPU時間(當然會減掉第二個容器消耗的少量時間)。畢竟當沒有其他人使用時提高整個CPU的利用率也是有意義的,對吧?當然 ,第二個容器需要CPU時間的時候就會獲取到,同時第一個容器會被限制回來。
定義和申請自定義資源
Kubemetes允許用戶為節點添加屬於自己的自定義資源,同時支持在pod資源 requests里申請這種資源。因為目前是一個alpha特性,所以不打算描述其細節,而
只會簡短地介紹一下。
首先, 需要通過將自定義資源加入節點API對象的capacity屬性讓
Kubemetes知道它的存在。這可以通過執行HTTP的PATCH請求來完成。資源名
稱可以是不以 kubernetes.io 域名開頭的任 意值,例如 example.org/my
resource ,數量必須是整數(例如不能設為 lOOm ,因為 0.1 不是整數;但是可以
設置為 l000m、 2000m ,或者簡單地設為1和2 。這個值將自動從 capacity
復制到 allocatable字段。
創建 pod 時只要簡單地在容器 spec resources requests 宇段下,或者像之前例子那樣使用帶 requests 參數的 kubectl run 命令來指定自定義資源名稱和申請 ,調度器就可以確保這個 pod 只能部署到滿足自定義資源申的節點,同時每個己部署的 pod 會減少節點的這類可分配資源數量。
一個自定義資源的例子就是節點上可用的 GPU 單元數量。如果pod 要使用GPU ,只 要簡單指定其 requests 調度器就會保證這個 pod 只能調度到至少擁有一
個未分配 GPU 單元的節點上。
限制容器的可用資源
設置 pod 的容器資源申請量保證了每個容器能夠獲得它所需要資源的最小量。現在我們再看看硬幣的另一面一一容器可以消耗資源的最大量。
CPU與內存的區別
CPU 是一種可壓縮資源,意味着我們可 在不對容器內運行的進程產生不利影響的同時,對其使用量進行限制而內存明顯不同一一是一種不可壓縮資源。一旦系統為進程分配了 塊內存,這塊內存在進程主動釋放之前將無法被回收。這就是為什么需要限制容器的最大內存分配的根本原因。
如果不對內存進行限制, 工作節點上的容器(或者 pod )可能會吃掉所有可用內存,會對該節點上所有其他 po 任何新調度上來的pod (記住新調度的 pod基於內存的申請量而不是實際使用量的)造成影響。單個故障 pod 或惡意 pod 幾乎可以導致整個節點不可用。
創建一個帶有資源 limits 的pod

apiVersion: vl kind: Pod metadata: name: limited-pod spec: containers: - image: busybox command: [ "dd”,”if=/dev/zero”,”of=/dev/null"] name: main resources: limits: cpu: 1 memory : 20Mi
可超賣的 limits
與資源 requests 不同的是,資源 limits 不受節點可分配資源量的約束所有limits 總和允許超過節點資源總量的 100%。
換句話說,資源 limits
以超賣。 如果節點資源使用超過 100% ,一些容器將被殺掉, 這是一個很重要的
結果 。
超過 limits
當容器內運行的進程嘗試使用比限額更多的資源時會發生什么呢?
我們己經了解了 CPU 是可壓縮資源,當進程不等待 IO 操作時消耗所有的 CPU 時間是非常常見的。 正如我們所知道的,對一個進程的 CPU 使用率可以進行限制,因此當為一個容器設置 CPU 限額時,該進程只會分不到比限額更多的 CPU 而己。
而內存卻有所不同 當進程嘗試申請分配比限額更多的內存時會被殺掉(我們會說這個容器被 OOMKilled 了, OMM是Out Of Memory 的縮寫〉 如果 pod 的重
啟策略為 Always 或 OnFailure ,進程將會立即重啟,因此用戶可能根本察覺不
到它被殺掉。但是如果它繼續超限並被殺死, kubernetes 會再次嘗試重啟,並開始
增加下次重啟的間隔時間。這種情況下用戶會看到 pod CrashLoopBackOff
狀態。
關於 CrashLoopBackOf

CrashLoopBackOf 狀態表示 Kubelet 還沒有放棄,它 味着在每次崩潰之后,Kubelet 會增加下次重啟之前的間隔時間 次崩漬之后, kubelet 立即重啟容器,如果容器再次崩潰, kubelet 會等待 10 秒鍾后再重啟,隨着不斷崩潰,延遲時間也會按照 20 40 80 160 秒以幾何倍數增長,最終收斂在 300s 。一旦間隔時間達300 秒, kubelet 將以5分鍾為間隔時間對容器進行無限重啟,直到容器正常運行或被刪除。 要定位容器 crash 原因,可以通過查看 pod 日志以及 kubectl describe pod 命令
在容器內看到的始終是節點的內存, 而不是容器本身的內存
kubectl exec -it limited-pod top #此命令查看到的是整個節點的資源
即使你為容器設置了最大可用內存的限額, top 命令顯示的是運行該容器的節點的內存數 ,而容器無法感知到此限制。
這對任何通過查看系統剩余可用內存數量,並用這些信息來決定自己該使用多
少內存的應用來說具有非常不利的影響。
對於 Java 程序來說這是個很大的問題,尤其是不使用一Xmx 選項指定虛擬機的最大堆大小時, JVM 會將其設置為主機總物理內存的百分值。在 kubemetes 開發集群運行 Java 容器化應用(比如在筆記本電腦上運行)時,因為內存 limit 和筆記本電腦總內存差距不是很大,這個問題還不太明顯但是如果 pod 部署在擁有更大物理內存的生產系統中, JVM 將迅速超過預先配置的內存限額,然后被 OOM 殺死也許你覺得可以簡單地設 Xmx 選項就可以解決這個問題,那么你就錯了,很遺憾。 Xmx 選項僅僅限制了堆大小,並不管其他 off heap 內存,好在新版本的Java 會考慮到容器 limits 緩解這個問題
容器內同樣可感知的是節點所有的 CPU
與內存完全一樣,無論有沒有配置 CPU limits 容器內也會看到節點所有的CPU 。將 CPU 限額配置為1 ,並不會神奇地只為容器暴露一個核。 CPU limit 做的只是限制容器使用的 CPU 時間。因此如果擁有1個 CPU 限額的容器運行在 64 CPU 上,只能獲得 1/64 的全部 CPU 時間 而且即使限額設置為1核, 容器進程也不會只運行在一個核上,不同時刻,代碼還是會在多個核上執行。
上面的描述沒什么問題,對吧?雖然一般情況下如此,但在一些情況下卻是災難。
一些程序通過查詢系統 CPU 核數來決定啟動 作線程的數量。 同樣在開發環境的筆記本電腦上運行良好,但是部署在擁有更多數量 CPU 的節點上,程序將快速啟動大量線程,所有線程都會爭奪(可能極其)有限的 CPU 時間。同時每個線程通常都需要額外的內存資源,導致應用的內存用量急劇增加。
不要依賴應用程序從系統獲取的 CPU 數量,你可能需要使用 Downward API將CPU 限額傳遞至容器並使用這個值。也可以通過 cgroup 系統直接獲取配置的 CPU限制,請查看下面的文件:
• /sys/fs/cgroup/cpu/cpu .cfs _quota_ us
• /sys/fs/cgroup/cpu/cpu.cfs _period_ us
pod QoS等級
前面己經提到資源 limits 可以超賣, 換句話說, 一個節點不一定能提供所有pod 所指定的資源 limits 之和那么多的資源量。如果兩個pod 爭搶內存資源,內存資源已經不足,那么哪個進程先被殺死?
Kubemetes 無法自己做出正確決策,因此就需要一種方式,我們通過這種方式可 以指定哪 pod 在該場景中優先級更高。 Kubernetes 將pod 划分為3種 QoS 等級

• BestEffort (優先級最低)
最低優先級的 QoS 等級是 BestEffort 會分配給那些沒有(為任何容器)設置任何 requests limits pod 。在這個等級運行的容器沒有任何資源保證。在最壞情況下,它們分不到任 何CPU 時間,同時在需要為其他 pod 釋放內存時這些容器會第一批被殺死。不過因為 BestEffort pod 沒有配置內存 limits 當有充足的可用內存時,這些容器可以使用任意多的內存
• Burstable
Burstable QoS 級介於 BestEffort Guaranteed 之間。其他所有 pod 屬於這個等級 包括容器的 requests limits 不相同的單容器 pod ,至少有一個容器只定義了 reques ts 但沒有定義 limits 的pod ,以及一個容器的 request limt 相等,但是另一個容器不指定 requests或limits 的pod。 Burstable pod 可以獲得它們所申請的等額資源, 並可以使用額外的資源(不超過 limits)。
• Guaranteed (優先級最高)
Guaranteed 等級會分配給那些所有資源 request limits 相等的 pod。 對於 Guaranteed 級別的 pod ,有以下幾個條件:
CPU 和內存都要設置 requests limits
每個容器都需要設置資源量
它們必須相等(每個容器的每種資源的 requests limits 必須相等)
了解多容器 pod 的 QoS 等級
對千多容器pod, 如果所有的容器的QoS等級相同, 那么這個等級就是pod的QoS等級。 如果至少有一個容器的QoS等級與其他不同,無論這個容器是什么等級,這個pod的QoS等級都是Burstable等級。
注意 運行kubectl describe pod以及通過pod的YAML/JSON描述的Status.qosClass字段都可以查看pod的QoS等級。
內存不足時哪個進程會被殺死
在一個超賣的系統,QoS等級決定着哪個容器第一個被殺掉, 這樣釋放出的資源可以提供給高優先級的pod使用。 BestEffort等級的pod首先被殺掉, 其次是 Burstable pod, 最后是Guaranteed pod。 Guaranteedpod只有在系統進程需要內存時才會被殺掉。
如何處理相同QoS等級的容器
每個運行中的進程都有一個稱為OutOfMemory (OOM)分數的值。系統通過比較所有運行進程的OOM分數來選擇要殺掉的進程。當需要釋放內存時分數最高的進程將被殺死。
OOM分數由兩個參數計算得出:進程已消耗內存占可用內存的百分比, 與 一個基於 pod QoS等級和容器內存申請量固定的OOM分數調節因子。 對於兩個屬於
Burstable等級的單容器的pod, 系統會殺掉 內存 實際使用量占內存申請量比例更高的pod。這說明我們不僅要注意requets和limits之間的關系,還要留心requests和預期實際消耗內存之間的關系
LimitRange 資源
用戶可以通過創建一個LimitRange資源來避免必須配置每個容器。 LimitRange資源不僅允許用戶 (為每個命名空間)指定能給容器配置的每種資源的最小和最大限額, 還支持在沒有顯式指定資源 request 時為容器設置默認值
LimitRange資源被LimitRanger准入控制插件。API服務器接收到帶有pod描述信息的POST請求時, LimitRanger插件對pod spec進行校驗。 如果校驗失敗, 將直接拒絕。 因此, LimitRange對象的一個廣泛應用場景就是阻止用戶創建大於單個節點資源量的pod。 如果沒有LimitRange, API服務器將欣然接收pod創建請求, 但永遠無法調度成功。Lmi itRange資源中的limit s應用千同一 個命名空間中每個獨立的pod、 容器,或者其他類型的對象。 它並不會限制這個命名空間中所有pod可用資源的總量, 總量是通過 Resource Quota對象指定的
LimitRange 對象的創建

apiVersion: v1 kind: LimitRange metadata: name: example sepc: limits: - type: pod min: cpu: 50m memory: 5Mi max: cpu: 1 memory: 1Gi - type: container defaultRequest: cpu: 100m memory: 10Mi default: cpu: 200m memory: 100Mi min: cpu: 50m memory: 50Mi max: cpu: 1 memory: 1Gi maxLimitRequestRatio: cpu: 4 memory: 10 - type: PersistentVolumeClaim min: storage: 1Gi max: storage: 1Gi 正如在上面例子中看到的,整個pod資源限制的最小值和最大值是可以配置的。它應用於pod內所有容器的requests和limits之和。 在更低一層的容器級別,用戶不僅可以設置最小值和最大值,還可以為沒有顯式指定的容器設置資源requests(defaultRequest)和limits(default)的默認值。 除了最小值、最大值和默認值,用戶甚至可以設置limits和requests的最大比例。上面示例中設置了maxLimitRequestRatio為4, 表示容器的CPU limits不能超過CPU requests的4倍。 因此,對於一個申請了200毫核的容器,如果它的CPU限額設置為801毫核或者更大就無法創建。而對於內存,這個比例設為了10。 這個例子只使用一個LimitRange對象, 其中包含了對所有資源的限制,而如果你希望按照類型進行組織,也可以將其分割為多個對象(例如一個用於pod限制, 一個用於容器限制, 一個用於PVC 限制)。多個LimitRange對象的限制會在校驗pod或PVC 合法性時進行合並。 由於L血itRange對象中配置的校驗(和默認值)信息在API服務器接收到新的pod或PVC創建請求時執行,如果之后 修改了限制,已經存在 的pod和PVC 將不會再次進行校驗, 新的限制只會應用於之后創建的pod和PVC 。
ResourceQuota 資源(限制命名空間中的可用資源總量 )
ResourceQuota的接納控制插件會檢查將要創建的pod是否會引起總資源量超出ResourceQuota。如果那樣,創建請求會被拒絕。因為資源配額在pod創建時進行檢查,所以ResourceQuota對象僅僅作用於在其后創建的pod ,並不會影響已經存在的pod。
資源 配額 限制了一個命名空間中pod和PVC存儲最多可以使用的資源總址。同時也可以限制用戶允許在該命名空間中創建pod、PVC,以及其他API對象的數量,因為到目前為止我們處理最多的資源是CPU和內存
限制可創建對象個數

對象個數配額目前可以為以下對象配置
• pod
• ReplicationController
• Secret
• ConfigMap
• Persistent Volume Claim
• Service (通用)及兩種特定類型的 Service ,比如 LoadBalancer Service (services.loadbalancers )和 Node Port Service (services.nodeports)
為特定的 pod 狀態或者 QoS 等級指定配額
目前為止我們創建的 Quota 應用於所有的 pod 不管 pod 的當前狀態和 QoS
級如何。但是 Quota 可以被 quota scopes 限制, 目前配額作用范圍共有4種:
BestEffort NotBestEffort Termination NotTerminating。
BestEffort和NotBestEffort 范圍決定配額是否應用於 BestEffort
QoS 級或者其他兩種等級(Burstable和Guaranteed)的pod
創建 ResourceQuota 時,可以為其指定作用范圍。目標 pod 必須與配額中配置的所有范圍相匹配 另外,配額的范圍也決定着配額可以限制的內容BestEffort 范圍只允許限制 pod 數,而其他3種范圍除了 pod 個數,還可以限 CPU 內存的 requests 和 limits
Terminating 和 NotTerminating
可以為每個 pod 指定被標記為 Failed ,然后真正停止之前還可以運行多長時間 這是通過在 pod pec 中配置 activeDeadlineSeconds 來實現的該屬性定義了一個 pod 從開始嘗試停止的時間到其被標記為 Failed 然后真正停止之前,允許其在節點上繼續運行的秒數 Terminating 配額作用范圍應用於這些配置了activeDeadlineSeconds 的pod 而 Not Terminating 應用於那些沒有指定該配置的 pod
創建的 ResourceQuota 對象

apiVersion: vl kind : ResourceQuota metadata: name: besteffort-notterminating-pods spec scopes - BestEffort - NotTerminating hard : pods: 4 這個配額允許最多4個屬於BestEffort QoS等級,並沒有設置activedeadline的pod。如果配額針對的是 NotBestEffort pod ,我們便可以指定requests.cpu,requests.memory,limit.cpu limits.memory
監控pod 的資源使用量
設置合適的 資源 request 和 limits 對充分利用 kubernetes十分重要,
如果 requests 設置得太高,集群節點利用率就會比較低,這樣就白白浪費了資源,
如果設置得太低,應用就會處於 CPU 飢餓狀態,甚至很容易被 OOM Killer 殺死
所以如何才能找到 requests limi ts 的最佳配置呢?
可以通過對容器在期望負載下的資源實際使用率進行監控來找到這個最佳配置。當然 旦應用暴露於公網,都應該保持監控並且在需要時對其資源的 request limits 進行調節
kubelet 自身就包含了一個名為 cAdvisor的agent ,它會收集整個節點和節點上運行的所有單獨容器的資源消耗情況。集中統計整個集群的監控信息需要運行一個叫作 Heapster 的附加組件。Heapste 以pod 的方式運行在某個節點上,它通過普通的 Kubernetes Service 暴露服務,使外部可以通過一個穩定的 IP 地址訪問 它從集群中所有的 cAdvisor收集數據,然后通過一個單獨的地址暴露。
顯示集群節點的CPU和內存使用量
在集群中運行Heapster可以通過kubectl top命令獲得節點和單個pod的資源用量。要看節點使用了多少CPU和內存,可以執行以下代碼清單所示的命令。

kubect1 top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% minikube 170m 8% 516Mi 21% 它顯示了節點上運行的所有pod當前的CPU和內存實際使用量,與kubectl describe node命令不同的是,后者僅僅顯示節點CPU和內存的requests和limits,而不是實際運行時的使用數據。
顯示單獨pod的CPU和內存使用量

$kubectl top pod --all-namespaces NAMESPACE NAME CPU(cores) MEMORY(bytes) kube-system influxdb-grafana-2r2w9 lm 32Mi kube-system heapster-40j6d 0m 18Mi default kubia-3773182134-63bmb 0m 9Mi kube-system kube-dns-v20-z0hq6 lm llMi kube-system kubernetes-dashboard-r53mc 0m 14Mi kube-system kube-addon-manager-minikube 7m 33Mi 提示要查看容器而不是 pod 的資源使用情況, 可以使用 --container 選項。 有一點需要提醒的是, 有時toppod命令會拒絕輸出任何指標而輸出以下錯誤: $ kubect1 top pod W0312 22:12:58.021885 15126 top_pod.go:186] Metrics not available for default/kubia-3773182134-63bmb, age: lh24ml9.021873823s error: Metrics not available for pod default/kubia-3773182134-63bmb, age 2h24ml9.D25674823s 如果看到這個錯誤, 先不要急於尋找出錯的原因,然后等待一會兒重新執行一可能需要好幾分鍾, 不過最終會看到指標的。 因為 kubectl top 命令從 Heapster 中獲取指標,它將幾分鍾的數據匯總起來,所以通常不會立即暴露。
保存並分析歷史資源的使用統計信息
top 命令僅僅展示了當前的資源使用量-它並不會顯示比如從一小時、一天或者一周前到現在 pod 的 CPU 和內存使用了多少。 事實上 cAdvisor 和 Heapster都只保存一個很短時間窗的資源使用量數據。如果需要分析一段時間的 pod 的資源使用情況, 必須使用額外的工具。如果使用 Google Container Engine, 可以通過Google Cloud Monitoring 來對集群進行監控,但是如果是本地Kubemetes 集群(通過 Minik:ube 或其他方式創建),人們往往使用 Influx.DB 來存儲統計數據,然后使用Grafana 對數據進行可視化和分析