FinOps for Kubernetes - 如何拆分 Kubernetes 成本

本文獨立博客閱讀地址: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 的前提下提升資源利用率

多雲環境

上述討論的絕大部分策略,都適用於多雲環境。在這種涉及多個雲服務提供商的場景,最重要的一點是:搭建平臺無關的成本分析與管控平臺。而其核心仍然是文章最前面提到的兩點,只需要補充兩個字 一致

  • 一致的資源標籤規範: 從公司業務側需求出發,制定出跨平臺一致的標籤規範,這樣才能統一分析多雲成本。
  • 資源標籤的準確率: 隨着公司業務的發展,標籤規範的迭代,標籤的準確率總是會上下波動。而標籤準確率越高,我們對雲計算成本的管控能力就越強。

這樣就可以把不同雲服務商的數據轉換成統一的格式,然後在自有的成本平臺上進行統一的分析了。

搭建一個這樣的成本分析平臺其實並不難,許多大公司都是這麼幹的,小公司也可以從一個最小的平臺開始做起,再慢慢完善功能。

以我現有的經驗看,其實主要就包含這麼幾個部分:

  • 成本數據轉換模塊:將來自不同雲的成本數據,轉換成與雲服務無關的格式,方便統一處理
  • 折扣模塊:處理不同資源的折扣
    • 比如 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

查詢成本拆分結果的 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 類別,這是爲了方便可視化,把成本太低的一些指標聚合展示了。

進階用法

參考

  • kubecost: kubecost 應該是目前最優秀的開源成本分析工具了,self-hosted 是免費的,也提供收費的雲上版本,值得研究。
  • crane: 騰訊開源的一款 Kubernetes 成本優化工具,支持成本報表以及 EHPA 兩個功能,纔剛開源幾個月,目前還比較簡陋。
  • Calculating Container Costs - FinOps
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章