“At the altar of AI capex, Google is sacrificing the golden goose.” 这句评论在近两年生成式 AI 投资讨论中经常被引用。它的意思是,在 AI 资本开支(AI Capex)的巨大投入面前,Google 正拿自己最赚钱的核心业务去冒险,那只“下金蛋的鹅”就是搜索、广告等核心业务带来的稳定利润。这句话看起来属于财务和战略层面的讨论,但落到技术团队手中,它还有另一层非常现实的含义:当公司把预算、机房、GPU、电力和研发资源大规模倾斜给 AI 之后,核心业务是否仍然拥有足够的容量、优先级和稳定性保障。
这篇文章从工程视角回答这个问题。先拆解 AI Capex 的成本构成,再沿着“算清账、分好资源、做隔离、控成本、保稳定、能排障”这条主线,给出一个既支持 AI 项目扩张、又不让核心业务沦为牺牲品的资源治理方案。内容适合负责云基础设施、成本治理、MLOps 平台的开发者和架构师阅读;如果你所在团队正在经历“AI 项目增长很快,但核心业务扩缩容越来越难”的阶段,这篇会更贴近你的处境。
1. AI Capex 的工程代价:为什么烧钱不只是财务问题
1.1 AI 资本开支的钱主要花在哪里
AI Capex 与传统的机房扩容有交集,但也有明显差异。传统业务的资本开支更多落在服务器、网络设备、存储和机房改造上;AI 项目还要多出几块硬成本。
| 成本项 | 说明 | 与传统业务对比 |
|---|---|---|
| GPU/TPU 计算卡 | 单价高,采购周期长,是资本开支中占比最大的部分 | 传统业务不需要同等规模的加速卡 |
| 供电与散热 | 高功率设备密度带来更大的电费与散热改造需求 | 电费可以通过利用率反推,容易被低估 |
| 配套基础设施 | 液冷、机柜、网络带宽、存储 | 扩容需要提前数月规划 |
| 研发与调度平台 | 训练平台、推理平台、监控、成本系统 | 容易被忽视,但决定资源使用效率 |
从这个表格可以看出,AI 资本开支不只是“买几张卡”,而是一条从采购、机房到调度平台的长链路。技术团队感受到的往往不是一次性采购数字,而是后面几个月的容量压力、配额审批和成本账单。
1.2 为什么大厂愿意承担如此高的资本开支
从行业目前可见的信息看,搜索、广告和云业务仍是主要利润来源,而大模型相关的搜索增强、AI 编程、企业级推理服务又需要大量 GPU 支持。如果不投入,产品能力就会落后;如果投入过猛,就会拖累短期利润率。这是所有 AI 基础设施投入者都要面对的取舍。
对工程师来说,真正要解决的是两个问题。第一,AI 任务是突发性、可延迟的,还是持续、在线、延迟敏感的。第二,这些任务会不会侵占在线业务的资源池。问题想清楚,“资本开支”就不再只是财务数字,而是容量、优先级和稳定性之间的博弈。
1.3 技术层面的三种失衡现象
当 AI 投入开始挤压核心业务时,基础设施团队通常先看到以下现象:
- 核心业务 Pod 申请扩容被 ResourceQuota 拒绝,因为集群 GPU 命名空间的 request 已经占满大部分配额。
- GPU 节点故障或维护窗口出现时,训练任务反复重启,但没人能确定哪个任务优先级更高。
- 月底账单显示 GPU 费用翻倍,但按团队、按项目拆分不出来,成本责任无法落到具体负责人。
这三种现象分别对应容量不足、优先级缺失、成本归属不清。后面几章的内容,就是围绕这三类问题展开。
2. 先建立可解释的成本模型,再谈投入产出
2.1 单张计算卡的月成本怎么估算
成本模型要解决的问题是:一个 AI 任务到底花了多少钱。如果连这个数都说不清,就谈不上平衡。
先把单卡月成本的固定部分拆开:
# 单卡月度固定成本估算示例 def monthly_gpu_cost( card_price_usd: float, # 单卡采购成本 server_share_price_usd: float, # 服务器、机箱分摊成本 power_kw: float, # 单卡平均功率,单位 kW daily_hours: float = 24.0, days_per_month: float = 30.0, electricity_price_usd: float = 0.10, # 每度电价格 depreciation_months: int = 36, # 折旧周期 ): hardware_cost = (card_price_usd + server_share_price_usd) / depreciation_months power_cost = power_kw * daily_hours * days_per_month * electricity_price_usd return hardware_cost + power_cost cost = monthly_gpu_cost( card_price_usd=25000, server_share_price_usd=5000, power_kw=0.7, ) print(f"single GPU fixed monthly cost: {cost:.2f} USD")这只是一个简化模型,实际账单里还要加上机房租金、运维人力、网络带宽、监控和调度平台成本。它的意义不在于精确到个位数,而是让团队有一个可以讨论的“分母”,知道一张卡挂在界面上即使什么都不跑,也会产生固定支出。
2.2 算力利用率是成本模型中真正的分母
假设一张卡每月固定成本是 1000 美元,任务 A 每天实际跑 4 小时,任务 B 每天跑 20 小时,两者单次运行成本相差很大。下面这张表说明了利用率对单位算力成本的影响。
| 平均利用率 | 每月有效算力小时 | 单位有效算力小时成本 | 对成本的影响 |
|---|---|---|---|
| 20% | 144 小时 | 约 6.9 美元 | 费用高但产出少 |
| 50% | 360 小时 | 约 2.8 美元 | 需要继续优化 |
| 80% | 576 小时 | 约 1.7 美元 | 较为健康 |
这里要注意一个常见误区:不要只看“GPU 显存有没有被占用”,还要看“计算单元是否真的在跑有效算子”。很多任务把显存占满,但计算单元大量空转,这种状态同样会造成成本浪费。
2.3 训练任务和推理任务的成本结构完全不同
训练任务通常是短期的、可排队的、失败后可以重新调度的;推理任务则是长期运行的、延迟敏感的、并发会波动的。两者不能共用同一套成本优化策略。
| 维度 | 训练任务 | 在线推理任务 |
|---|---|---|
| 运行时间 | 分钟到数天不等 | 7x24 小时 |
| 延迟要求 | 低,允许排队等待 | 高,必须响应在线请求 |
| 成本优化重点 | 控制空闲等待,提高批次效率 | 控制冗余副本,提升单卡并发 |
| 典型故障影响 | 多花时间,多花重训成本 | 用户请求超时,核心业务受损 |
理解了这两类任务的差异,容量规划时才能设置不同的优先级和弹性策略。训练任务可以等,在线推理不能等。
2.4 用成本标签和 Showback 让花销可归属
成本模型不等于成本分摊。如果账单上的 GPU 费用无法对应到团队和项目,责任人就不会重视优化。常见做法是给云资源和 Kubernetes 工作负载强制打标签,然后按月出成本报告。
# 以标注示例说明成本标签的用途,实际字段取决于平台 kubectl label namespace ml-platform team=ml cost-center=ai-infra owner=model-platform kubectl label namespace online-biz team=commerce cost-center=core-biz owner=commerceShowback(成本回显)和 Chargeback(成本结转)的区别在于:Showback 只向业务方展示费用,Chargeback 会把费用真正计入预算。大多数团队建议先做 Showback,避免为了分摊成本而消耗过多管理成本。
3. 容量规划与预算分配:确保 AI 投资不挤压核心业务
3.1 从“按需扩容”变成“按预算申请”
传统在线业务扩容往往看重性能和可用性,GPU 资源则更依赖预算和配额。核心变化是:先有预算,再有容量;先有优先级,再决定谁能抢占。可以把容量池拆成三个层次:
- 在线核心池:只能给核心业务和有 SLO 要求的 AI 推理服务使用。
- 弹性训练池:接收可延迟、可排队的训练任务,支持缩容和抢占。
- 备用池:用于应对突发流量、新模型灰度上线和故障切换。
3.2 用节点池表达不同类型容量
以云厂商托管 Kubernetes 为例,可以把 GPU 节点和 CPU 节点分开,再进一步把 GPU 节点按业务类型分成独立节点池。
# 节点池划分思路,字段以实际平台为准 apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: gpu-training handler: nvidia --- apiVersion: v1 kind: NodeSelectorTerm metadata: name: node-pool-term spec: matchExpressions: - key: workload operator: In values: - ai-training - ai-inference实际在云厂商创建节点时,通常会使用命令行或控制台创建带标签的多套节点池。以 Google Cloud GKE 为例,可以这样创建带上workload=ai-inference标签的节点池,具体实例型号和参数以云厂商当前控制台为准。
# 创建 AI 推理节点池,节点带 workload=ai-inference 标签 gcloud container node-pools create ai-inference \ --machine-type=g2-standard-24 \ --accelerator=type=nvidia-l4,count=1,install-gpu-driver \ --node-labels=workload=ai-inference \ --num-nodes=1这里的关键不是记住命令,而是理解节点池隔离的目的:训练任务哪怕写错了调度配置,也不能直接抢占在线推理节点的资源。
3.3 用 PriorityClass 定义任务优先级
同一个集群里,在线推理任务和离线训练任务同时抢 GPU 时,调度器必须知道谁更重要。Kubernetes 的 PriorityClass 可以做这件事。
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: online-critical value: 1000000 globalDefault: false description: "在线核心业务与 AI 在线推理服务使用" --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: ml-training value: 500000 globalDefault: false description: "可排队、可抢占的 AI 训练任务"PriorityClass 的值只代表相对高低。在线核心业务的优先级应该明显高于训练任务,这样当节点资源不足时,调度器会优先保证高优先级 Pod 的调度,必要时驱逐低优先级 Pod。
注意:PriorityClass 可以让高优先级 Pod 抢占低优先级 Pod,但它不是万能的。如果训练任务和在线任务共用同一个节点池,驱逐依然会造成节点抖动,所以优先级策略必须和节点隔离一起使用。
3.4 容量规划的关键指标
| 指标 | 作用 | 预警值建议 |
|---|---|---|
| GPU 资源分配率 | 表示集群是否还有可分配容量 | 超过 80% 需要关注 |
| GPU 实际利用率 | 表示算力是否真正被使用 | 长期低于 40% 需要治理 |
| 训练任务排队时间 | 表示弹性容量是否不足 | 超过业务预期即告警 |
| 在线服务 P99 延迟 | 表示资源争抢是否影响核心业务 | 超阈值即时告警 |
| 空闲节点占比 | 表示是否有成本浪费 | 持续超过 20% 需要回收 |
这些指标要按环境和业务区分阈值。学习环境可以允许空闲,生产环境必须设置更严格的容量审视节奏。
4. 与核心业务共享集群时的隔离与配额设计
4.1 用 ResourceQuota 限制命名空间的资源边界
如果一个集群要同时承载 AI 和核心业务,第一步是给命名空间配额,确保任意一方都不能无限占用节点资源。
apiVersion: v1 kind: ResourceQuota metadata: name: quota-ai-training namespace: ml-training spec: hard: requests.nvidia.com/gpu: "8" requests.cpu: "64" requests.memory: "256Gi" limits.cpu: "128" limits.memory: "512Gi"配额的作用是让业务方明确自己的资源上限。上限设置得过大,保护作用会失效;设置得过小,又会影响业务扩张。建议先参照过去 30 天的实际用量和增长趋势来定。
4.2 用 LimitRange 管理单容器资源规格
ResourceQuota 控制命名空间总量,LimitRange 控制单个 Pod 或容器的规格上限。两者配合,才能防止某个异常任务把整个命名空间的额度吃光。
apiVersion: v1 kind: LimitRange metadata: name: limit-range-ml-training namespace: ml-training spec: limits: - type: Container defaultRequest: cpu: "1" memory: "2Gi" default: cpu: "4" memory: "8Gi" max: cpu: "8" memory: "32Gi" maxLimitRequestRatio: cpu: "2"maxLimitRequestRatio是一个容易忽略的字段,它限定了单容器 limit 与 request 的比值,避免用户把 request 写得很小、limit 写得很大,导致资源超卖。
4.3 用节点污点实现物理级隔离
任何资源管理策略都可能被误配置绕过。对于在线核心业务,建议再加一层节点污点隔离,只允许打了对应容忍度的 Pod 调度到专用节点。
# 给在线核心节点打污点 apiVersion: v1 kind: Node metadata: name: node-a-online spec: taints: - key: workload value: online effect: NoSchedule# 在线业务 Pod 添加 toleration apiVersion: v1 kind: Pod metadata: name: online-pod spec: tolerations: - key: workload value: online operator: Equal effect: NoSchedule没有对应 toleration 的训练任务即使提交到集群,也无法调度到这些节点上。这就是物理级隔离的意思。
4.4 GPU 共享模式选型
GPU 资源不总是需要整卡独占。根据目前常见的 GPU 和云厂商能力,可以按场景选择不同的使用模式。
| 模式 | 特点 | 适用场景 |
|---|---|---|
| 整卡独占 | 最简单,性能稳定 | 训练任务、高可用推理 |
| MIG 切分 | 把 GPU 显存和计算单元按比例切分 | 多个小规模推理服务共享 |
| 时间片共享 | 共享显存但交替使用计算单元 | 实验环境、开发测试 |
| 虚拟化透传 | 隔离性更好,但配置复杂 | 多租户隔离要求高的场景 |
选择共享模式时,要关注延迟波动。时间片共享适合对 P99 延迟不敏感的任务,不适合在线核心业务。
4.5 推荐的多级容量池结构
一个比较稳妥的结构是:在线核心业务独占一组节点池,AI 推理服务使用带独立 PriorityClass 的节点池,AI 训练任务使用可被抢占的弹性节点池,并通过 ResourceQuota 和 LimitRange 控制每个命名空间。这样即使训练任务投入巨大,也不会因为调度问题把在线业务拉入故障。核心目标不是禁止 AI 使用资源,而是让每一类资源都有明确边界和逃生路径。
5. 用工程手段削减 AI 推理与训练成本
5.1 推理侧:模型小一点,成本低一截
推理成本的最大驱动因素是 GPU 占用和在线副本数。不要一上来就按最大模型、最大并发设计,优先做模型轻量化。
| 优化手段 | 适用场景 | 注意事项 |
|---|---|---|
| 模型蒸馏 | 允许精度小幅下降的任务 | 需要准备训练数据和评估集 |
| 量化(INT8/FP16) | 对数值精度不过度敏感的任务 | 需要验证输出质量 |
| 批量推理(batching) | 离线批量、非实时场景 | 在线场景要控制排队时间 |
| 结果缓存 | 重复请求比例高的任务 | 设计好缓存键和过期策略 |
| 模型裁剪 | 结构冗余明显的模型 | 需要重新评估效果 |
一个常见的错误是只做量化,不留评估集。量化后模型上线,线上效果下降,却排查不出来是模型问题还是数据问题。任何模型压缩手段都应该配套一批固定的回归样本。
5.2 训练侧:让任务排队,而不是立即抢占
训练任务通常允许延迟。把训练任务放进队列,由调度平台统一控制启动时间,可以有效削峰。
apiVersion: scheduling.incubator.kubernetes.io/v1alpha1 kind: Queue metadata: name: ml-training-queue spec: capacity: 4上面的 Queue 资源只是一个示意,不同训练平台字段差异很大。重点是设计“排队-启动-中断恢复”