2. Kubernetes成本模型基础

在 Kubernetes 里谈成本,不能只看节点账单。节点只是“物理或虚拟的容量池”,真正决定钱花在哪里的是工作负载如何声明资源、调度器如何放置 Pod、以及这些 Pod 被哪些命名空间和标签组织起来。理解这四层关系,是后续用 OpenCost 做成本分摊和优化的前提。

一、requests 与 limits:成本模型的计量起点

每个容器都可以声明两类资源参数:

  • requests:调度器用来判断“这个 Pod 能不能放到某个节点上”的依据,也是节点容量的预留量。只要 Pod 被调度成功,这部分资源就被该 Pod 占用,即使它实际几乎不用。
  • limits:容器运行时用来限制“这个容器最多能用多少”的上限。CPU 超过 limit 会被节流(throttle),内存超过 limit 会触发 OOMKill。

成本分摊的核心逻辑是:成本按 requests 分摊,而不是按实际用量分摊。原因是集群容量是按 requests 预留的——一个声明了 2 核 request 的 Pod,即使实际只用了 0.1 核,它仍然占着 2 核的调度空间,其他 Pod 无法使用。因此 OpenCost 默认以 requests 作为分摊权重,这样每个团队看到的成本才与它“占用的容量”一致。

下面这张图展示了从节点容量到成本归属的完整链路,以及 requests 在其中的关键位置:

节点容量池(Node Capacity) CPU: 8 核 / 内存: 32 GiB / 单价: ¥2.4/小时 已分配 requests: 5.5 核 空闲: 2.5 核 调度器按 requests 放置 Pod 调度单元(Scheduling Unit) Pod A(frontend) requests: 1核/2Gi · limits: 2核/4Gi Pod B(backend) requests: 2核/4Gi · limits: 4核/8Gi Pod C(cache) requests: 0.5核/1Gi · limits: 1核/2Gi 按 namespace + labels 归属 命名空间与标签(Namespace & Labels) ns: production labels: team=platform, env=prod ns: staging labels: team=platform, env=staging ns: monitoring labels: team=sre, env=prod OpenCost 聚合分摊 成本归属结果:team=platform → ¥1.68/h · team=sre → ¥0.72/h

二、调度单元:为什么成本按 Pod 而不是按容器算

Kubernetes 的最小调度单位是 Pod,不是容器。一个 Pod 内的多个容器共享网络命名空间和存储卷,调度器以 Pod 为单位计算 requests 总和,再决定放到哪个节点。因此成本分摊也以 Pod 为最小粒度:一个 Pod 的总成本 = 其所有容器 requests 之和 × 节点单位资源价格。

这里有一个容易忽略的点:Pod 的 requests 之和决定了它占用的“容量份额”。假设节点有 8 核,Pod A 声明 2 核 request,Pod B 声明 6 核 request,那么即使两者实际 CPU 使用率都只有 10%,成本也应按 2:6 分摊,而不是按实际用量 1:1 分摊。这就是“预留容量”与“实际消耗”的区别,也是成本工程中需要向业务团队解释清楚的核心概念。

三、命名空间:成本归属的第一层边界

命名空间(Namespace)是 Kubernetes 中天然的资源隔离边界,也是成本归属的第一层聚合维度。在 OpenCost 中,每个 Pod 都属于且仅属于一个命名空间,因此命名空间级别的成本汇总是最直接、最可靠的分摊方式。

实际落地时,建议按团队或业务线划分命名空间,而不是按技术组件划分。例如:

  • team-payment:支付团队的所有工作负载
  • team-search:搜索团队的所有工作负载
  • shared-infra:共享中间件(Ingress、DNS、监控等)

共享基础设施的成本需要额外处理:它服务于多个团队,不能简单归给某一个命名空间。常见做法是先按命名空间汇总,再将 shared-infra 的成本按各业务命名空间的 requests 占比进行二次分摊。

四、标签:成本归属的灵活维度

命名空间只能表达一层归属关系,但实际成本分析往往需要多维度:按环境(prod/staging/dev)、按成本中心(cost-center)、按应用(app)、按版本(version)等。这时就需要标签(Labels)。

OpenCost 支持通过标签进行成本聚合。关键标签建议在部署时就统一规划,例如:

标签键用途示例值
team归属团队platform、payment、search
env环境区分prod、staging、dev
app应用名称checkout、user-service
cost-center财务成本中心CC-1001、CC-2003

标签的挑战在于一致性:如果部分 Pod 有 team 标签、部分没有,成本汇总就会出现“未归属”的缺口。建议通过准入控制器(如 OPA Gatekeeper 或 Kyverno)强制要求关键标签,缺失时拒绝创建或自动补全默认值。

五、四层关系如何串成一条成本链

把上述概念串起来,就得到一条完整的成本归属链:

  1. 节点提供容量,按小时或按月产生费用;
  2. Pod通过 requests 占用节点容量,成为成本分摊的基本单元;
  3. 命名空间将 Pod 按团队/业务线聚合,形成第一层成本归属;
  4. 标签在命名空间之上提供多维切分,支持按环境、成本中心、应用等视角查看成本。

OpenCost 的工作方式正是沿着这条链:先采集节点价格和 Pod requests,再按命名空间和标签聚合,最终输出每个团队、每个应用、每个环境的成本数据。理解这条链,才能在后续章节中正确配置 OpenCost 的分摊规则,并在成本异常时快速定位是 requests 设置不合理、命名空间划分不当,还是标签缺失导致归属错误。

实践建议:在集群初始化阶段就确定命名空间划分规则和标签规范,比事后补标签要容易得多。一个可用的最小标签集是 team + env + app,这三个标签能覆盖大部分成本分析场景。
常见误区:不要用实际 CPU/内存使用率来分摊成本。实际用量波动大、采集延迟高,且与容量预留脱节。requests 才是与成本直接挂钩的稳定计量口径。