本文独立博客阅读地址: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 网关费用
    • 如果 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 成本分析

前面讨论的内容都很「虚」,下面来点更「务实」的:使用 Kubecost 进行 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

FinOps for Kubernetes - 如何拆分 Kubernetes 成本的更多相关文章

  1. 傲视Kubernetes(一):Kubernetes简介

    前言 从上个月,因工作需要外加兴趣所知,博主开始学习Kubernetes,时至今日可以说是刚刚入门.独自学不如一起学,后面博主会一边学着一边将学习内容以博文的形式呈现出来,希望能跟各位园友有问题一起讨 ...

  2. kubernetes学习01—kubernetes介绍

    本文收录在容器技术学习系列文章总目录 一.简介 1.Kubernetes代码托管在GitHub上:https://github.com/kubernetes/kubernetes/. 2.Kubern ...

  3. Kubernetes系列02—Kubernetes设计架构和设计理念

    本文收录在容器技术学习系列文章总目录 1.Kubernetes设计架构 Kubernetes集群包含有节点代理kubelet和Master组件(APIs, scheduler, etc),一切都基于分 ...

  4. [原]CentOS7安装Rancher2.1并部署kubernetes (二)---部署kubernetes

    ##################    Rancher v2.1.7  +    Kubernetes 1.13.4  ################ ##################### ...

  5. Kubernetes 学习15 kubernetes 认证及serviceaccount

    一.概述 1.通过此前描述可以知道k8s是以后运行我们生产环境中重要应用程序的尤其是无状态程序的一个非常重要的平台.这里面能托管一些核心应用以及核心数据,很显然对于k8s对应接口的访问不是任何人都可以 ...

  6. Kubernetes入门(一)——Kubernetes v1.18.5 安装部署

    Kubernetes的安装有两种方式:一是使用各个厂商封装的Kubernetes发行版,优点是可以一键安装部署,操作简单,缺点也很明显,若安装过程中某一步骤出现问题,很难定位处理:二是使用官方提供的k ...

  7. linux(centos8):安装kubernetes worker节点并加入到kubernetes集群(kubernetes 1.18.3)

    一,安装kubernetes前的准备工作      安装前的准备工作(master\worker都要进行)      参见: https://www.cnblogs.com/architectfore ...

  8. 浅入kubernetes(1):Kubernetes 入门基础

    目录 Kubernetes 入门基础 Introduction basic of kubernetes What Is Kubernetes? Components of Kubernetes Kub ...

  9. 浅入kubernetes(2):Kubernetes 的组成

    目录 说明 Kubernetes集群的组成 What are containerized applications? What are Kubernetes containers? What are ...

随机推荐

  1. 关于 OOP 和设计模式?

    这部分包含 Java 面试过程中关于 SOLID 的设计原则,OOP 基础,如类,对象, 接口,继承,多态,封装,抽象以及更高级的一些概念,如组合.聚合及关联. 也包含了 GOF 设计模式的问题.

  2. 学习Kvm(一)

     背景介绍 传统数据中心面临的问题: 资源使用率低 资源分配不均 自动化能力差 初始化成本高   云计算: 云计算是一种按使用量付费的模式,这种模式提供可用的.便捷的.按需的网络访问, 进入可配置的计 ...

  3. 插值方法 - Lagrange插值多项式

    Lagrange插值多项式代码: 1 # -*- coding: utf-8 -*- 2 """ 3 Created on Wed Mar 25 15:43:42 202 ...

  4. 定时任务__@Xxl-JOB的使用

    概述xxl-job框架 ​ 首先我们要知道什么是XXL-JOB? ​ 官方简介:XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码并接入多家公司 ...

  5. element el-tree、el-table组件加载数据前闪现 暂无数据 清除

    相信很多人在使用element  el-tree.el-table组件加载数据前会显示一个" 暂无数据 ",体验很不友好,有没有办法处理不显示呢?答案是:有的.废话不多说直接上代码 ...

  6. 基于vue2.0的在线电影APP,

    基于vue2.0构建的在线电影网[film],webpack + vue + vuex + vue-loader + keepAlive + muse-ui + cordova 全家桶,cordova ...

  7. 【Android开发】简单好用的阴影库 ShadowLayout

    先来看一张使用 ShadowLayout 库实现的各种阴影的效果图,如下图所示: 如上图所示,通过使用 ShadowLayout 可以控制阴影的颜色.范围.显示边界(上下左右四个边界).x 轴和 y ...

  8. wx:key报错does not look like a valid key name

    把花括号去掉就行了,  现在改版了,  要注意了     wx:key="index"  

  9. MySQL安装配置教程(超级详细)

    一. 下载MySQL Mysql官网下载地址:https://downloads.mysql.com/archives/installer/ 1. 选择要安装的版本,本篇文章选择的是5.7.31版本, ...

  10. SpringMVC注解环境搭建

    基本步骤 新建Maven项目(Web) 导入依赖 配置web.xml 配置springmvc配置文件 编写Controller 创建view页面 部署并启动Tomcat 开始搭建 新建Maven项目( ...