本文獨立博客閱讀地址:https://thiscute.world/posts/finops-for-kubernetes/
FinOps 是一種不斷髮展的雲財務管理學科和文化實踐,通過幫助工程、財務、技術和業務團隊在數據驅動的預算分配上進行協作,使成本預算能夠產生最大的業務價值。
雲計算成本管控
隨着越來越多的企業上雲,雲計算的成本管控也越來越受關注。在討論 Kubernetes 成本之前,先簡單聊下如何管控雲計算成本,有一個新名詞被用於形容這項工作——FinOps.
傳統的數據中心的成本是比較固定的,所有的成本變動通常都伴隨着硬件更替。
而在雲上環境就很不一樣了,由於雲服務的按量收費特性,以及五花八門的計費規則,開發人員稍有不慎,雲成本就可能會出現意料之外的變化。另一方面由於計費的複雜性,業務擴容對成本的影響也變得難以預測。
目前的主流雲服務商(AWS/GCP/Alicloud/...)基本都提供基於資源標籤的成本查詢方法,也支持將成本導出並使用 SQL 進行細緻分析。
因此其實要做到快速高效的雲成本分析與管控,主要就涉及到如下幾個點:
- 契合需求的標籤規範: 從公司業務側需求出發,制定出合理的、多維度的(Department/Team/Product/...)、有擴展空間的標籤規範,這樣才能按業務側需要進行成本分析。
- 資源標籤的準確率: 隨着公司業務的發展,標籤規範的迭代,標籤的準確率總是會上下波動。而標籤準確率越高,我們對雲計算成本的管控能力就越強。
但是也存在許多特殊的雲上資源,雲服務商目前並未提供良好的成本分析手段,Kubernetes 集羣成本就是其中之一。
Kubernetes 成本分析的難點
目前許多企業應該都面臨着這樣的場景:所有的服務都運行在一或多個 Kubernetes 集羣上,其中包含多條業務線、多個產品、多個業務團隊的服務,甚至除了業務服務,可能還包含 CICD、數據分析、機器學習等多種其他工作負載。而這些 Kubernetes 集羣通常都由一個獨立的 SRE 部門管理。
但是 Kubernetes 集羣本身並不提供成本拆分的能力,我們只能查到集羣的整體成本、每個節點組的成本等這樣粗粒度的成本信息,缺乏細粒度的成本分析能力。
此外,Kubernetes 集羣是一個非常動態的運行環境,其節點的數量、節點規格、Pod 所在的節點/Zone/Region,都可能會隨着時間動態變動,這爲成本分析帶來了更大的困難。
這就導致我們很難回答這些問題:每條業務線、每個產品、每個業務團隊、或者每個服務分別花了多少錢?是否存在資源浪費?有何優化手段?
而 FinOps for Kubernetes,就是通過工程化分析、可視化成本分析等手段,來回答這些成本問題,分析與管控 Kubernetes 的成本。
接下來我會先介紹下雲上 Kubernetes 成本分析的思路與手段,最後再介紹如何使用 Kubecost 分析 Kubernetes 集羣的成本。
要做好 Kubernetes 成本工作,有如下三個要點:
- 理解 Kubernetes 成本的構成,搞懂準確分析 Kubernetes 成本有哪些難點
- 尋找優化 Kubernetes 集羣、業務服務的手段
- 確定 Kubernetes 集羣的成本拆分手段,建立能快速高效地分析與管控集羣成本的流程
Kubernetes 成本的構成
以 AWS EKS 爲例,它的成本有這些組成部分:
- AWS EKS 本身有 $0.1 per hour 的固定費用,這個很低
- EKS 的所有節點會收對應的 EC2 實例運行費用、EBS 數據卷費用
- EKS 中使用的 PV 會帶來 EBS 數據卷的費用
- 跨區流量傳輸費用
- 所有節點之間的通訊(主要是服務之間的互相訪問),如果跨了可用區,會收跨區流量傳輸費用
- EKS 中的服務訪問其他 AWS 服務如 RDS/ElastiCache,如果是跨可用區,會收取跨區流量費用
- 如果使用了 Istio IngressGateway 或 traefik 等網關層代理 Pod,那這些 Pod 與服務實例之間,有可能會產生跨區流量
- NAT 網關費用
- EKS 中的容器如果要訪問因特網,就需要通過 NAT 網關,產生 NAT 費用
- 如果 VPC 未配置 endpoints 使訪問 AWS 服務(dynamodb/s3 等)時直接走 AWS 內部網絡,這些流量會經過 VPC 的 NAT 網關,從而產生 NAT 網關費用
- 服務如果要對外提供訪問,最佳實踐是通過 aws-load-balancer-controller 綁定 AWS ALB, 這裏會產生 ALB 費用
- 監控系統成本
- Kubernetes 的監控系統是不可或缺的
- 如果你使用的是 Datadog/NewRelic 等雲服務,會造成雲服務的成本;如果是自建 Prometheus,會造成 Prometheus 的運行成本,以及 Pull 指標造成的跨區流量成本
總結下,其實就是三部分成本:計算、存儲、網絡。其中計算與存儲成本是相對固定的,而網絡成本就比較動態,跟是否跨區、是否通過 NAT 等諸多因素有關。
Kubernetes 資源分配的方式
Kubernetes 提供了三種資源分配的方式,即服務質量 QoS,不同的分配方式,成本的計算難度也有區別:
- Guaranteed resource allocation(保證資源分配): 即將 requests 與 limits 設置爲相等,確保預留所有所需資源
- 最保守的策略,服務性能最可靠,但是成本也最高
- 這種方式分配的資源,拆分起來是最方便的,因爲它的計算成本是靜態的
- Burstable resource allocation(突發性能): 將 requests 設置得比 limits 低,這樣相差的這一部分就是服務的可 Burst 資源量。
- 最佳實踐,選擇合適的 requests 與 limits,可達成性能與可靠性之間的平衡
- 這種資源,它 requests 的計算成本是靜態的,Burstable 部分的計算成本是動態的
- Best effort resource allocation(盡力而爲): 只設置 limits,不設置 requests,讓 Pod 可以調度到任何可調度的節點上
- 下策,這個選項會導致服務的性能無法保證,通常只在開發測試等資源受限的環境使用
- 這種方式分配的資源,完全依賴監控指標進行成本拆分
最佳實踐
要做到統一分析、拆分 Kubernetes 與其他雲資源的成本,如下是一些最佳實踐:
- 按產品或者業務線來劃分名字空間,不允許跨名字空間互相訪問。
- 如果存在多個產品或業務線共用的服務,可以在每個產品的名字空間分別部署一個副本,並把它們當成不同的服務來處理。
- 這樣名字空間就是成本劃分的一個維度,我們還可以在名字空間上爲每個產品設置資源上限與預警。
- 按產品或業務線來劃分節點組,通過節點組的標籤來進行成本劃分
- 這是第二個維度,但是節點組劃分得太細,可能會導致資源利用不夠充分。
- 這個方案僅供參考,不一定好用
- 爲 Kubernetes 服務設計與其他雲資源一致的成本標籤,添加到 Pod 的 label 中,通過 kubecost 等手段,基於 label 進行更細緻的成本分析
- 標籤一致的好處是可以統一分析 Kubernetes 與其他雲資源的成本
- 定期(比如每週一) check 雲成本變化,定位並解決成本異常
- 建立自動化的成本異常檢測與告警機制(部分雲服務有提供類似的服務,也可自建),收到告警即觸發成本異常分析任務
- 始終將資源標籤準確率維持在較高數值,準確率低於一定數值即自動告警,觸發標籤修正任務
- 將成本上升的壓力與成本下降的效益覆蓋到開發人員,授權他們跟蹤服務的 Kubernetes 利用率與成本,以激勵開發人員與 SRE 合作管控服務成本。
成本優化實踐:
- 多種工作負載混合部署,提升資源利用率。但是需要合理規劃避免資源競爭
- 調節集羣伸縮組件,在保障 SLA 的前提下提升資源利用率
- 比如 aws 就可以考慮在一些場景下用 karpenter 來做擴縮容、引入 AWS Node Termination Handler 提升 Spot 實例的 SLA
多雲環境
上述討論的絕大部分策略,都適用於多雲環境。在這種涉及多個雲服務提供商的場景,最重要的一點是:搭建平臺無關的成本分析與管控平臺。而其核心仍然是文章最前面提到的兩點,只需要補充兩個字 一致:
- 一致的資源標籤規範: 從公司業務側需求出發,制定出跨平臺一致的標籤規範,這樣才能統一分析多雲成本。
- 資源標籤的準確率: 隨着公司業務的發展,標籤規範的迭代,標籤的準確率總是會上下波動。而標籤準確率越高,我們對雲計算成本的管控能力就越強。
這樣就可以把不同雲服務商的數據轉換成統一的格式,然後在自有的成本平臺上進行統一的分析了。
搭建一個這樣的成本分析平臺其實並不難,許多大公司都是這麼幹的,小公司也可以從一個最小的平臺開始做起,再慢慢完善功能。
以我現有的經驗看,其實主要就包含這麼幾個部分:
- 成本數據轉換模塊:將來自不同雲的成本數據,轉換成與雲服務無關的格式,方便統一處理
- 折扣模塊:處理不同資源的折扣
- 比如 CDN 在用量高的時候通常會有很高的折扣比例
- 還有 SavingPlans/CommitmentDiscounts 也需要特殊的處理
- 標籤修整模塊
- 隨着標籤體系的發展,總會有些標籤的變更,不方便直接在資源上執行,就需要在成本計算這裏進行修正、增補或者刪除
- 成本拆分模塊
- 有些資源的成本是共用的,就需要結合其他來源的數據進行成本拆分,比如 Kubernetes 集羣的成本
- 成本報表:將最終的數據製作成符合各類人員需求的可視化圖表,按需求還可以考慮添加交互式特徵
- 可使用 Grafana/Google DataStudio 等報表工具
Kubernetes 成本分析
前面討論的內容都很「虛」,下面來點更「務實」的:Kubernetes 成本分析實戰。
目前據我所知,主要有如下兩個相關的開源工具:
- Kubecost: kubecost 應該是目前最優秀的開源成本分析工具了,self-hosted 是免費的,支持按 deployment/service/label 等多個維度進行成本拆分,而且支持拆分網絡成本。收費版提供更豐富的功能以及更長的數據存儲時間。
- crane: 騰訊開源的一款 Kubernetes 成本優化工具,支持成本報表以及 EHPA 兩個功能,纔剛開源幾個月,目前還比較簡陋。
其中 kubecost 是最成熟的一個,我們接下來以 kubecost 爲例介紹下如何分析 Kubernetes 成本。
安裝 kubecost
kubecost 有兩種推薦的安裝方法:
- 使用 helm 安裝免費版
- 包含如下組件:
- frontend 前端 UI 面板
- cost-model 核心組件,提供基礎的成本拆分能力
- postgres 長期存儲,僅企業版支持
- kubecost-network-costs 一個 daemonset,提供網絡指標用於計算網絡成本(貌似未開源)
- cluster-controller 提供集羣「大小調整(RightSizing)」以及「定時關閉集羣」的能力
- 只保留 15 天的指標,無 SSO/SAML 登錄支持,無 alerts/notification, 不可保存 reportes 報表
- 每個 kubecost 只可管理一個集羣
- 包含如下組件:
- 只安裝 Apache License 開源的 cost-model,它僅提供基礎的成本拆分功能以及 API,無 UI 面板、長期存儲、網絡成本拆分、SAML 接入及其他商業功能。
開源的 cost-model 直接使用此配置文件即可部署:https://github.com/kubecost/cost-model/blob/master/kubernetes/exporter/exporter.yaml
而如果要部署帶 UI 的商業版,需要首先訪問 https://www.kubecost.com/install#show-instructions 獲取到 kubecostToken
,然後使用 helm 進行部署。
首先下載並編輯 values.yaml 配置文件:https://github.com/kubecost/cost-analyzer-helm-chart/blob/develop/cost-analyzer/values.yaml
然後部署:
kubectl create namespace kubecost
helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm install kubecost kubecost/cost-analyzer -n kubecost -f kubecost-values.yaml
通過 port-forward 訪問:
kubectl port-forward --namespace kubecost deployment/kubecost-cost-analyzer 9090
現在訪問 http://localhost:9090 就能進入 Kubecost 的 UI 面板,其中最主要的就是 Allocation 成本拆分功能。
kubecost 的成本統計原理
1. CPU/RAM/GPU/Storage 成本分析
Kubecost 通過 AWS/GCP 等雲服務商 API 動態獲取各 region/zone 的上述四項資源的每小時成本:CPU-hour, GPU-hour, Storage Gb-hour 與 RAM Gb-hour,或者通過 json 文件靜態配置這幾項資源的成本。
OD 按需實例的資源價格通常比較固定,而 AWS Spot 實例的成本波動會比較大,可以通過 SpotCPU/SpotRAM 這兩個參數來設置 spot 的默認價格,也可以爲 kubecost 提供權限使它動態獲取這兩項資源的價格。
kubecost 根據每個容器的資源請求 requests 以及資源用量監控進行成本分配,對於未配置 requests 的資源將僅按實際用量監控進行成本分配。
kubecost 的成本統計粒度爲 container,而 deployment/service/namespace/label 只是按不同的維度進行成本聚合而已。
2. 網絡成本的分析
https://github.com/kubecost/docs/blob/b7e9d25994ce3df6b3936a06023588f2249554e5/network-allocation.md
對提供線上服務的雲上 Kubernetes 集羣而言,網絡成本很可能等於甚至超過計算成本。這裏面最貴的,是跨區/跨域傳輸的流量成本,以及 NAT 網關成本。
使用單個可用區風險比較高,資源池也可能不夠用,因此我們通常會使用多個可用區,這就導致跨區流量成本激增。
kubecost 也支持使用 Pod network 監控指標對整個集羣的流量成本進行拆分,kubecost 會部署一個綁定 hostNetwork 的 daemonset 來採集需要的網絡指標,提供給 prometheus 拉取,再進行進一步的分析。
kubecost 將網絡流量分成如下幾類:
- in-zone: 免費流量
- in-region: 跨區流量,國外的雲服務商基本都會對跨區流量收費
- cross-region: 跨域流量
更多的待研究,看 kubecost 官方文檔吧。
另外還看到 kubecost 有忽略 s3 流量(因爲不收費)的 issue: https://github.com/kubecost/cost-model/issues/517
kubecost API
https://github.com/kubecost/docs/blob/b7e9d25994ce3df6b3936a06023588f2249554e5/apis.md
- 成本拆分文檔:https://github.com/kubecost/docs/blob/b7e9d25994ce3df6b3936a06023588f2249554e5/cost-allocation.md
- 成本拆分 API 文檔:https://github.com/kubecost/docs/blob/b7e9d25994ce3df6b3936a06023588f2249554e5/allocation.md
查詢成本拆分結果的 API 示例:
import requests
resp = requests.get("http://localhost:9090/model/allocation", params={
"window": "2022-05-05T00:00:00Z,2022-05-06T00:00:00Z",
"aggregate": "namespace,label:app", # 以這幾個緯度進行成本聚合
"external": True, # 拆分集羣外部的成本(比如 s3/rds/es 等),需要通過其他手段提供外部資源的成本
"accumulate": True, # 累加指定 window 的所有成本
"shareIdle": False, # 將空閒成本拆分到所有資源上
"idleByNode": False, # 基於節點進行空閒資源的統計
"shareTenancyCosts": True, # 在集羣的多個租戶之間共享集羣管理成本、節點數據捲成本。這部分成本將被添加到 `sharedCost` 字段中
"shareNamespaces": "kube-system,kubecost,istio-system,monitoring", # 將這些名字空間的成本設爲共享成本
"shareLabels": "",
"shareCost": None,
"shareSplit": "weighted", # 共享成本的拆分方法,weight 加權拆分,even 均分
})
resp_json = resp.json()
print(resp_json['code'])
result = resp_json['data']
print(result[0])
查詢結果中有這幾種特殊成本類別:
__idle__
: 未被佔用的空閒資源消耗的成本__unallocated_
: 不含有aggregate
對應維度的成本,比如按label:app
進行聚合,不含有app
這個 label 的 pod 成本就會被分類到此標籤__unmounted__
: 未掛載 PV 的成本
此外如果使用 kubecost 可視化面板,可能還會看到一個 other
類別,這是爲了方便可視化,把成本太低的一些指標聚合展示了。
進階用法
- 集成 AWS CUR 賬單:https://github.com/kubecost/docs/blob/b7e9d25994ce3df6b3936a06023588f2249554e5/aws-cloud-integrations.md
- 其他文檔:https://github.com/kubecost/docs
參考
- kubecost: kubecost 應該是目前最優秀的開源成本分析工具了,self-hosted 是免費的,也提供收費的雲上版本,值得研究。
- crane: 騰訊開源的一款 Kubernetes 成本優化工具,支持成本報表以及 EHPA 兩個功能,纔剛開源幾個月,目前還比較簡陋。
- Calculating Container Costs - FinOps