想象你是一家连锁餐厅的总厨,突然接到一个“全球AI美食节”的超级订单:三天内要训练出一个能写诗、会画画的“大模型大厨”。你不可能在自家后厨一口锅一口锅地炒——你需要租用一座“云端中央厨房”,里面有几百个顶级灶台(GPU),还要有个聪明的大堂经理,知道哪道菜该用哪个灶台、什么时候上菜、如何让每口锅都不闲着。这就是 GKE(Google Kubernetes Engine)GPU 集群要做的事:在 Google 云上搭建一座“AI 训练中央厨房”,自动排队、自动分灶、自动扩容,让成千上万个 GPU 灶台高效协作,把大模型的“菜”准时端上桌。

岗位关联

GKE GPU 集群管理是云原生 AI 工程师的核心技能——掌握它,你就能像调度一家云端大食堂一样,用最少的钱、最快的时间完成大模型训练,并成为团队里那个“会管算力的人”。

目录
  1. 可视化演示
  2. GKE初识:云端AI中央厨房
  3. GPU节点池配置:分灶台与备佐料
  4. 资源调度策略:总排单员的智慧
  5. 训练任务编排:密封餐盒里的菜谱
  6. 成本优化:精打细算的食堂老板
  7. 运维与生态:食堂的长久经营
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

GKE初识:云端AI中央厨房

你管理着传统餐厅后厨:每道菜需要专门的灶台,每个灶台要配专属厨师,忙时灶台不够用,闲时厨师干瞪眼。现在订单来了——要同时训练大模型、跑推荐系统、做视频推理。你需要一座“云端中央厨房”,而 GKE 就是这座厨房的承建商:它把 Google 云上的 GPU 服务器(灶台)组织成一个大集群,你只需要告诉它“我要几口锅、什么火候”,剩下的事它全包。

GKE 的全称是 Google Kubernetes Engine,是 Google 云上的托管 Kubernetes 服务。Kubernetes(简称 K8s)就像餐厅管理系统的标准协议:它定义“灶台”(节点 Node)、“餐盒”(容器 Container)和“总排单员”(调度器 Scheduler)的协作规则。GKE 的好处是不用自己搭建管理这套系统——Google 帮你把 Kubernetes 控制平面(厨房管理层)维护好,你只需要专注点菜和出菜。

在 GKE 中,GPU 是作为节点的“扩展能力”存在的。节点是一台虚拟机(相当于一个料理台),GPU 就是装在料理台上的专业灶头。容器是打包好的训练程序,它运行在节点上,占用节点的 CPU、内存和 GPU。整个集群由三部分组成:控制平面(负责管理和调度)、节点池(一组相同配置的节点)和容器网络(连接各个灶台的传菜通道)。

理解 GKE 的关键,是记住它把“厨房”变成了“服务”:你不需要关心哪台服务器在哪儿、GPU 驱动装没装,只需要说“我要一个 4 卡 A100 的厨房分区”。这座云端中央厨房,就是你训练大模型的第一站。

集群可用GPU=∑i=1n节点i上的GPU数−系统预留\displaystyle \text{集群可用GPU} = \sum_{i=1}^{n} \text{节点}_i\text{上的GPU数} - \text{系统预留}
这个公式告诉你:一个 GKE 集群的算力上限,是所有节点 GPU 数量之和再减去系统自身占用的部分——就像中央厨房能同时做的菜数,是所有灶台数减去洗碗池、备料台占用的空间。
  1. 节点求和把集群中每一个节点的 GPU 数量加起来,得到理论总算力。
    ∑i=1n节点i上的GPU数\displaystyle \sum_{i=1}^{n} \text{节点}_i\text{上的GPU数}
  2. 扣除预留GKE 系统组件(如监控、网络代理)会占用少量资源,必须从可用算力中扣除。
    −系统预留\displaystyle - \text{系统预留}

GPU节点池配置:分灶台与备佐料

既然接了“AI 美食节”的订单,你不能把所有菜都在一口锅里炒。你得把厨房分成几个分区:有的区专做需要猛火快炒的菜(大模型预训练),有的区专做小火慢炖的菜(微调),有的区专做凉菜(推理服务)。在 GKE 中,这个“分区”就是节点池(Node Pool)——一组配置相同的节点,共享同一种 GPU 型号和机器规格。

配置 GPU 节点池的第一步是选 GPU 型号。Google 云提供多种 GPU:T4(适合推理和轻量训练,相当于家用燃气灶)、L4(视频推理和中等负载,相当于商用猛火灶)、A100(大模型训练旗舰,相当于餐厅中央火力集成灶)、H100(超大模型专用,相当于工厂级工业灶台)。选型的原则很简单:训练任务看显存和算力,推理任务看性价比和延迟。

第二步是创建独立节点池。好的实践是:不同 GPU 型号绝不混在同一个节点池里。就像你不能让粤菜师傅和川菜师傅共用同一个调料台——A100 池专注于大模型训练,T4 池专注于推理服务,互不干扰。创建节点池时,GKE 会自动安装 GPU 驱动(相当于灶台安装完成后自动通气点火),这是托管服务的核心优势。

第三步是给节点池打标签(Label)和污点(Taint)。标签就像厨房分区门口的招牌:“A100 大模型区”“T4 推理区”;污点则像门禁——只有携带对应“门禁卡”(Toleration)的任务才能进入这个分区。这保证了重训练任务不会被调度到推理分区,互相不抢资源。

节点池配置的本质是“物理隔离 + 逻辑隔离”:物理隔离保证不同任务不抢灶台,逻辑隔离保证调度器知道把菜送到哪个区。配置好节点池,你的云端中央厨房就真正开张了。

适合GPU=arg⁡max⁡g∈{T4,L4,A100,H100}(任务需求显存GPU显存×算力匹配度)\displaystyle \text{适合GPU} = \arg\max_{g \in \{T4, L4, A100, H100\}} \left( \frac{\text{任务需求显存}}{\text{GPU显存}} \times \text{算力匹配度} \right)
选 GPU 就像买菜刀:切片用轻便的,剁骨用厚重的。这个公式是在四个选项中找出“显存够用 + 算力匹配”的最优解,而不用每次都买最贵的。
  1. 候选集合从 GKE 支持的 GPU 型号中圈定候选范围。
    g∈{T4,L4,A100,H100}\displaystyle g \in \{T4, L4, A100, H100\}
  2. 显存满足度任务需要加载的模型和数据,能否装进 GPU 显存。
    任务需求显存GPU显存\displaystyle \frac{\text{任务需求显存}}{\text{GPU显存}}
  3. 取最优综合显存满足度和算力匹配度,选出最合适的 GPU。
    arg⁡max⁡\displaystyle \arg\max

资源调度策略:总排单员的智慧

厨房开张后,几十个订单同时涌来:有的要 A100 灶台训练 3 小时,有的要 T4 灶台推理 10 分钟,有的说“我要 8 个 A100 灶台”。谁来安排?是调度器——GKE 里的“总排单员”。

Kubernetes 调度器的工作流程很简单:看需求、找节点、做决定。当一个训练任务(Pod)被提交时,调度器会先看任务需求的资源(几个 GPU、多少内存),然后扫描所有节点,筛选出满足条件的节点(Filtering),再给候选节点打分(Scoring),最后选择最优节点绑定(Binding)。就像排单员接到订单后,先看哪些灶台空闲、火候匹配,再选最顺手的那个。

但 GPU 调度有个特殊之处:GPU 是稀缺资源,必须排他性分配。一个 GPU 在同一时间只能给一个容器使用(除非启用 MIG 或时间分片)。所以,调度器必须精确记录每个节点的 GPU 分配情况——这个节点有 4 个 A100,用了 2 个,还剩 2 个。Kubernetes 通过 Device Plugin 机制来实现这一点:GPU 驱动以插件形式向调度器上报“我有几口锅”。

你还可以控制调度策略:节点亲和性(Node Affinity)让任务只调度到有特定标签的节点;Pod 反亲和性(Anti-Affinity)让训练任务尽量分散到不同节点,避免单点故障。排队(Queue)和抢占(Preemption)机制则保证:高优先级任务可以插队,但低优先级任务不会被饿死。

调度策略的终极目标,是让每一口 GPU 灶台都“有事做、做对事、不闲着”——总排单员的智慧,决定了你的算力食堂是高效运转还是乱成一锅粥。

score(n)=∑f∈filterswf⋅f(n)+∑s∈scoresws⋅s(n)\displaystyle \text{score}(n) = \sum_{f \in \text{filters}} w_f \cdot f(n) + \sum_{s \in \text{scores}} w_s \cdot s(n)
排单员给每一个空闲灶台打分:亲和性匹配加分、资源碎片少加分、GPU 利用率高加分……分数最高的那个灶台赢得订单。
  1. 过滤器集合先排除不满足硬性条件的节点(如 GPU 数量不够)。
    f(n)∈{0,1}\displaystyle f(n) \in \{0, 1\}
  2. 打分器集合对通过过滤的节点进行软性评分(如亲和性匹配度)。
    s(n)∈[0,100]\displaystyle s(n) \in [0, 100]
  3. 加权求和不同策略的权重不同,最终得分决定节点被选中概率。
    ∑wf⋅f(n)+∑ws⋅s(n)\displaystyle \sum w_f \cdot f(n) + \sum w_s \cdot s(n)

训练任务编排:密封餐盒里的菜谱

在云端中央厨房里,每道菜的“菜谱 + 食材 + 厨具”都封在一个密封餐盒里,送到哪个灶台都能做。这个餐盒就是容器(Container),而容器在 Kubernetes 中的最小运行单位是 Pod。

为什么用容器封装训练任务?因为 AI 训练环境极其复杂:Python 版本、CUDA 版本、深度学习框架、各种依赖库……任何一环不匹配都出不了菜。容器把“环境”和“代码”打包在一起,就像餐盒里自带菜谱食材,送到 A100 灶台还是 H100 灶台都能做。Pod 是容器的“上菜托盘”——一个 Pod 中可以有一个或多个容器,共享网络和存储,但它们被调度到同一个节点上。

创建训练任务时,你需要在 Pod 的 spec 中声明资源需求:

这行配置的意思是:“这个任务要独占 4 个 GPU 灶台”。调度器看到这个声明后,就会去找有 4 个空闲 GPU 的节点。当声明与节点能力匹配时,任务才能被调度。

对于大模型训练,单个任务往往需要多个 GPU 甚至多台机器协作——这就是分布式训练。GKE 上有 Kubernetes 原生工作负载(如 tfjob、pytorchjob)来管理这类任务:它定义了“Worker“(炒菜师傅)和”Chief”(主厨)的角色,自动创建多个 Pod 并配置好相互通信的网络,让它们像一个团队一样协同训练。

资源请求和限制值的声明规范是:requests 表示最低保障(预留量),limits 表示上限。对于 GPU,推荐 requests=limits,因为 GPU 默认可抢占,如果上限和请求不一致,可能造成调度混乱。

容器编排的哲学是“一次封装,到处运行”。它让 AI 训练从“手工炒菜”变成了“标准化流水线”——你只管写好菜谱(训练代码),总排单员和密封餐盒会搞定一切。

世界批量大小=每GPU批量大小×GPU总数\displaystyle \text{世界批量大小} = \text{每GPU批量大小} \times \text{GPU总数}
分布式训练中,每个 GPU 灶台同时炒一锅同样的菜,最后主厨汇总。总批量就是单灶台的菜量乘以灶台数——这就是“全局批次大小”的由来。
  1. 每GPU批量大小每个 GPU 一次处理的数据样本数。
    每GPU批量大小\displaystyle \text{每GPU批量大小}
  2. GPU总数参与训练的 GPU 数量(一个任务请求的 GPU 数)。
    GPU总数\displaystyle \text{GPU总数}
  3. 相乘得到全局批量总吞吐量随之线性增长。
    ×\displaystyle \times
yaml3 行
resources:  limits:    nvidia.com/gpu: 4

成本优化:精打细算的食堂老板

AI 训练最烧钱的不是人,是 GPU。一个 A100 灶台的单日租金可能高达数百美元。如何把每一分钱花在刀刃上?精明的食堂老板有三招。

第一招:用 Spot 实例做“临期食材”。 Spot 实例是 Google 云的闲置算力,价格比按需实例便宜 60%~80%,但有一个风险:Google 随时可能回收它(就像临期食材随时可能被更早的顾客买走)。对策是训练任务支持断点续训——每训练一段时间就保存检查点(checkpoint),Spot 被回收后换个灶台接着炒,不心疼。

第二招:自动扩缩容,让灶台数量跟着客流走。 GKE 的节点自动伸缩器(Cluster Autoscaler)会根据排队任务的数量动态增减节点:队列长了,自动加灶台;队列空了,自动关灶台。配合 Pod 水平自动扩缩(HPA),推理服务也可以根据请求量自动增减算力——就像食堂根据午餐和晚餐的客流调整开多少个窗口。

第三招:GPU 共享与分时。 不是所有任务都需要整块 GPU。GKE 支持时间分片(Time Slicing)和多实例 GPU(MIG):前者让多个任务轮流用一块 GPU(错峰炒菜),后者把一块物理 GPU 切成多个独立的小 GPU(一灶分多口锅)。推理场景常配合使用:

| 策略 | 适用场景 | 节省幅度 |

|------|----------|----------|

| Spot 实例 | 可中断的预训练/微调 | 60%~80% |

| 自动扩缩容 | 负载波动的推理/训练 | 30%~50% |

| GPU 共享 | 小模型推理/开发调试 | 50%+ |

成本优化的本质是“不买最贵的,不买最多的,买最合适的”。精打细算的食堂老板,用同样的预算做出了双倍的菜。

有效成本=按需价格×(1−折扣率)利用率\displaystyle \text{有效成本} = \frac{\text{按需价格} \times (1 - \text{折扣率})}{\text{利用率}}
成本优化的终极公式:降价格(Spot)、提利用率(共享/扩缩容),两头发力,让每美元买到最多的算力。
  1. 按需价格普通按需实例的小时单价,作为成本基准。
    按需价格\displaystyle \text{按需价格}
  2. 折扣率Spot 或承诺使用折扣带来的价格优惠比例。
    (1−折扣率)\displaystyle (1 - \text{折扣率})
  3. 利用率GPU 实际被有效使用的时间占比。
    利用率\displaystyle \text{利用率}

运维与生态:食堂的长久经营

新食堂开业容易,长期经营难。GPU 集群的运维,核心是四件事:看得见(监控)、扛得住(容灾)、省得心(托管)、用得顺(生态)。

监控与日志: GKE 深度集成 Cloud Monitoring 和 Cloud Logging。你可以实时查看集群 GPU 利用率、显存占用、温度功耗、任务状态等核心指标。就像在食堂监控墙上装了大屏幕:每个灶台的火力、每道菜的进度一目了然。推荐重点盯三个指标:GPU 利用率(灶台是否闲置)、排队等待时长(订单是否积压)、节点温度(是否过热降频)。

故障恢复: GPU 节点可能因硬件故障、网络抖动或 Spot 回收而挂掉。GKE 的健康检查机制会自动重启故障节点,Pod 会自动被调度到健康节点上。配合多可用区部署(把节点分散到多个机房),即使整个机房断电,训练任务也能在其他机房继续跑。

托管生态: GKE 之上还有 Vertex AI 等 AI 平台层服务,提供托管式 Jupyter Notebook、Pipeline 和模型注册中心。更关键的是一批开源工具:Kubeflow(MLOps 平台)、KServe(模型推理)、Ray(分布式计算),它们都已经在 GKE 上验证过——相当于给你的中央厨房配备了标准化的“中央实验室”和“配送体系”。

最佳实践沉淀: 成熟团队的运维经验通常沉淀为三份文档:集群规范(命名、标签、配额标准)、成本周报(每周 GPU 花费与利用率分析)、故障预案(GPU 掉卡、OOM、网络分区等常见故障的应对手册)。

运维的本质是“让意外成为计划的一部分”。监控让问题看得见,容灾让故障扛得住,生态让工作用得顺——云端中央食堂的长久经营之道,就在这四个字中。

可用性=总时间−故障时间总时间×100%\displaystyle \text{可用性} = \frac{\text{总时间} - \text{故障时间}}{\text{总时间}} \times 100\%
可用性指标就是食堂的门面:一年 99.9% 的营业时间都在正常出菜,才算得上一家值得信赖的老店。
  1. 总时间一个观察周期内的总时长(如一年 8760 小时)。
    总时间\displaystyle \text{总时间}
  2. 故障时间集群不可用或任务中断的总时长。
    故障时间\displaystyle \text{故障时间}
  3. 计算比值可用时间占比乘百分比,得到 SLA 指标。
    ×100%\displaystyle \times 100\%

AI 应用场景

大模型分布式训练调度

阶段:模型训练

解决的问题:训练一个 70B 参数的大语言模型需要几百张 A100/H100 GPU,手工管理这些卡(分配、调度、故障恢复)几乎不可能。GKE 通过节点池隔离、调度器自动分配和分布式工作负载编排,让“一键发起千卡训练”成为现实:提交一个 PyTorchJob,GKE 自动创建几百个 Worker Pod,每个 Pod 占 8 张 GPU,自动配置分布式通信(NCCL),训练崩溃自动重启。

具体案例:某 AI 公司要基于 Llama 3 微调一个中文法律大模型。他们在 GKE 上创建了一个 32 卡 A100 节点池,提交 PyTorchJob,指定 4 个 Worker、每个 Worker 8 卡。调度器自动将 Worker 分散到不同节点(反亲和性),训练 3 天后完成微调,总花费比自建机房省了 40%。

弹性的推理服务自动扩缩

阶段:模型部署

解决的问题:线上推理服务的请求量波动大(白天峰值晚上低谷),固定 GPU 数量要么浪费、要么不够。GKE 的 HPA + Cluster Autoscaler 根据请求量自动增减 GPU 节点,请求多时加灶台,请求少时关灶台。Spot 实例进一步降低非峰值成本,配合 GPU 时间分片让小模型共享卡。

具体案例:一家电商公司的 AI 客服机器人部署在 GKE 上,使用 T4 池。工作日白天峰值 500 QPS,深夜仅 20 QPS。自动扩缩让节点数在 3~12 之间动态调整,月均 GPU 成本比固定 10 卡下降了 55%。

成本可视化与配额治理

阶段:成本管控

解决的问题:多个团队共用 GKE 集群时,“算力账单算不清、谁多用谁少用一团乱麻”。GKE 的 ResourceQuota 和 Cost Allocation 功能,为每个团队设定 GPU 配额上限,并按命名空间拆分账单。

具体案例:某数据科学团队、算法团队、推理团队共用一个 GKE 集群。平台组为每个团队设置了 A100 配额(数据科学 8 卡、算法 32 卡),超出则任务排队。每月成本报告自动按团队拆分,各部门成本透明。

Python 演示

python112 行
import timefrom collections import deque  class GPUNode:    """模拟 GKE 节点池中的一个 GPU 节点"""     def __init__(self, name, gpu_type, total_gpus):        self.name = name        self.gpu_type = gpu_type        self.total_gpus = total_gpus        self.used_gpus = 0     def allocatable(self, request):        return self.used_gpus + request <= self.total_gpus     def allocate(self, request):        if not self.allocatable(request):            raise ValueError("GPU 数量不足")        self.used_gpus += request     def release(self, request):        self.used_gpus -= request  class TrainingTask:    """模拟一个需要 GPU 的训练任务"""     def __init__(self, name, gpu_request, duration):        self.name = name        self.gpu_request = gpu_request        self.duration = duration        self.remaining = duration  class GKEScheduler:    """模拟 GKE 调度器:把任务分配到 GPU 节点"""     def __init__(self, nodes):        self.nodes = nodes        self.queue = deque()        self.running = []        self.scheduled_count = 0        self.rejected_count = 0     def submit(self, task):        for node in self.nodes:            if node.allocatable(task.gpu_request):                node.allocate(task.gpu_request)                task.remaining = task.duration                self.running.append((node, task))                self.scheduled_count += 1                print(f"[调度] {task.name} -> {node.name} "                      f"({node.gpu_type} x {task.gpu_request})")                return        self.queue.append(task)        self.rejected_count += 1        print(f"[排队] {task.name} 等待空闲 GPU")     def tick(self, seconds=1):        finished = []        for item in self.running:            node, task = item            task.remaining -= seconds            if task.remaining <= 0:                finished.append(item)        for node, task in finished:            node.release(task.gpu_request)            self.running.remove((node, task))            print(f"[完成] {task.name} 释放 {node.name} "                  f"({node.gpu_type})")        if self.queue:            waiting = list(self.queue)            self.queue.clear()            for task in waiting:                self.submit(task)     def report(self):        print(f"\n=== 集群状态 ===")        for node in self.nodes:            usage = node.used_gpus / node.total_gpus * 100            print(f"{node.name}({node.gpu_type}): "                  f"{node.used_gpus}/{node.total_gpus} GPU "                  f"({usage:.0f}% 利用率)")        print(f"已调度: {self.scheduled_count}, "              f"仍在排队: {len(self.queue)}")  if __name__ == "__main__":    nodes = [        GPUNode("pool-a100-01", "A100", 8),        GPUNode("pool-t4-01", "T4", 4),    ]    scheduler = GKEScheduler(nodes)     tasks = [        TrainingTask("bert-finetune", 4, 3),        TrainingTask("llm-pretrain", 8, 4),        TrainingTask("sentiment-serve", 1, 2),        TrainingTask("vision-vit", 2, 2),        TrainingTask("gpt-inference", 4, 5),    ]     for task in tasks:        scheduler.submit(task)     print("\n--- 开始模拟时钟 ---")    for step in range(1, 8):        print(f"\n--- 第 {step} 秒 ---")        scheduler.tick()        scheduler.report()        time.sleep(0.3)
目的:用 Python 模拟 GKE 调度器如何将 GPU 需求不同的训练任务分配到不同型号的节点池,并处理排队与释放。
  1. class GPUNode模拟 GKE 的一个 GPU 节点,记录 GPU 型号与总卡数/已用卡数。
  2. def allocatable(self, request)核心资源判断:节点剩余 GPU 能否满足任务的请求。
  3. class TrainingTask封装训练任务的三要素:名字、所需 GPU 数、预计时长。
  4. def submit(self, task)调度主逻辑:先遍历节点找空闲 GPU,找不到就丢进队列等待。
  5. self.running.append((node, task))记录“哪个节点在跑哪个任务”,便于模拟完成释放。
  6. def tick(self, seconds=1)推进模拟时钟:任务剩余时间减少,完成后释放 GPU。
  7. def report(self)打印集群利用率,对应 GKE 控制台的 Dashboard。

常见误区

误区搞大模型训练当然选最贵的 H100/A100,贵的就是好的,一步到位免得以后升级麻烦。

正解就像你不会用工业剁骨刀去切葱花——任务小(比如微调小模型、跑推理服务),T4/L4 完全够用且成本低几倍。选 GPU 看三个维度:模型显存需求(模型参数 + 梯度 + 优化器状态能否放进显存)、算力需求(训练 vs 推理)、预算(每小时单价 × 预计时长)。先用显存估算公式算出需求,再对照 GPU 规格表选型。

为何常见:人对“贵的更好”有天然的认知捷径,且对 GPU 规格(显存、算力、带宽)缺乏量化感知,容易被厂商宣传带偏。

误区不同的任务都单独建一个节点池,互相隔离互不干扰,池子越多管理越精细。

正解节点池太多会带来三个问题:资源碎片化(A100 池剩 2 卡,但新任务要 4 卡,只能等着)、管理复杂(每个池要单独配置伸缩策略、监控告警)、成本上升(每个池都要预留 buffer 节点)。合理做法是:按 GPU 型号分池(不同卡不能混) + 按工作负载类型分池(在线推理和离线训练分离),池内允许多个团队共享。

为何常见:初学者对“隔离”的直觉是物理分割最安全,但忽略了资源池化的经济学——池子越大,碎片越少,利用率越高。

误区在 Pod 的 YAML 里只写 `limits.nvidia.com/gpu: 4` 就够了,调度器会按照需要的资源给我分配,不写 requests 也没关系。

正解Kubernetes 调度器依据 requests 而非 limits 做资源分配决策。如果只写 limits,调度器可能把多个 GPU 请求压到同一个节点上,导致 GPU 显存溢出(OOM)甚至节点崩溃。实践规范:requests 和 limits 必须相等(对 GPU),且 requests 值要基于实际显存需求。

为何常见:很多人把 limits 当作“我需要的资源”(直觉正确),但忽略了调度的底层机制是按 requests 处理——这是 Kubernetes 的内部契约。

误区Spot 便宜那么多,把所有训练任务都跑在 Spot 上,成本直接降到 20%。

正解Spot 随时可能被回收,如果任务不支持断点续训(定期保存 checkpoint),被回收一次可能损失数小时的计算进度,省下的钱全赔进去。正确策略是混合池:核心训练用按需实例保证稳定,可容错的任务(如超参数搜索、数据预处理、低优先级微调)跑 Spot,并配合 Workload 的优先级等级(PriorityClass)让 Spot 任务在回收时可被优雅终止。

为何常见:人容易被“高折扣 + 只要加个断点续训就行”的表面逻辑说服,忽视了断点续训在真实分布式训练中的实现成本很高。

误区GPU 利用率才 30%,说明算力浪费了,赶紧多塞几个训练任务把灶台填满。

正解GPU 利用率低要先诊断原因,盲目加任务可能适得其反。常见低利用率原因:(1) 数据加载瓶颈——数据搬得太慢,GPU 在等饭;(2) 小批量策略——batch size 太小,GPU 启动开销占比大;(3) 分布式通信开销——多卡同步频繁,等同伴;先看监控指标(数据加载时间、通信等待时间、kernel 执行时间),再对症下药。

为何常见:把“利用率”等同于“效率”,忽略了利用率只是结果指标,瓶颈可能在 GPU 之外。

面试题

Q1. 在 GKE 中,节点池(Node Pool)的主要作用是什么?

单选题 · easy

  • A.给节点做备份恢复
  • B.将相同配置的节点编组管理← 正确答案
  • C.自动编写 GPU 驱动程序
  • D.提供跨云厂商迁移能力

答案:B。节点池是把一组相同配置(GPU 型号、机器规格、镜像)的节点组成一个管理单元,就像食堂里的“川菜窗口”或“粤菜窗口”——入口统一、配置一致。B 正确。A 是数据恢复概念,C 是 GKE 自动安装驱动的能力但非节点池功能,D 是 Anthos 的能力而非节点池本身。

Q2. 在 GKE 上训练大模型,选择 GPU 型号时优先考虑什么?

单选题 · easy

  • A.越贵越好
  • B.显存满足模型需求且算力匹配← 正确答案
  • C.GPU 频率越高越好
  • D.只要能跑就行

答案:B。选 GPU 的核心约束是显存能否装下模型(模型参数+梯度+优化器状态),其次再考虑算力匹配和成本。B 正确。贵的 GPU(A 错)如果显存不够照样跑不起来,频率高(C 错)和能跑(D 错)都忽略了显存是第一硬约束。

Q3. Kubernetes 调度器将 GPU 任务分配到节点时,主要依据什么?

单选题 · mid

  • A.Pod 的 limits 资源声明
  • B.Pod 的 requests 资源声明← 正确答案
  • C.节点名称的字母顺序
  • D.镜像仓库的下载速度

答案:B。Kubernetes 调度器依据 requests 值进行节点筛选和打分,因为 requests 代表容器运行的最低资源保障。若按 limits 分配(A 错),多个 Pod 可能让节点超卖。C 和 D 与调度决策无关。

Q4. GKE 中给节点池设置 Taint(污点)的主要目的是?

单选题 · mid

  • A.防止节点被病毒攻击
  • B.限制只有特定 Pod 能调度到该节点← 正确答案
  • C.加快节点启动速度
  • D.降低 GPU 功耗

答案:B。Taint(污点)是节点上的门禁标记,只有声明了对应 Toleration(容忍)的 Pod 才能被调度上去。B 正确。它和安全(A 错)、性能(C 错)、功耗(D 错)无关,是纯调度层面的控制机制。

Q5. 以下哪些是 GKE 上降低 GPU 成本的有效手段?

多选题 · mid

  • A.使用 Spot 实例训练可容错任务← 正确答案
  • B.配置 Cluster Autoscaler 自动缩容← 正确答案
  • C.所有任务都用按需实例保证稳定
  • D.使用 GPU 时间分片让多个容器共享卡← 正确答案

答案:ABD。Spot 实例降低单价(A 对),自动缩容避免闲置扣费(B 对),GPU 共享提升利用率变相降本(D 对)。C 恰是成本高企的典型原因——安全和稳定性可以通过优先层级与 Spot 混合实现,没必要全用按需。

Q6. 关于 GPU 的 requests 与 limits 配置,以下说法正确的是?

多选题 · mid

  • A.调度器根据 requests 分配资源← 正确答案
  • B.GPU 建议 requests 等于 limits← 正确答案
  • C.limits 必须大于 requests
  • D.只写 limits 可能导致节点过载← 正确答案

答案:ABD。requests 用于调度决策,是 Pod 的资源保障底线(A 对)。GPU 不可超卖,请求与上限一致可避免调度器误判(B 对)。只写 limits 时调度器把多个大任务塞进同节点导致 OOM(D 对)。C 是与 CPU/内存的理念混淆——CPU 可超卖,GPU 不行。

Q7. 大模型分布式训练使用 PyTorchJob 工作负载时,8 个 Worker 各占 8 张 A100,总 batch size 为 512。每个 Worker 的 batch size 是多少?

单选题 · hard

  • A.16
  • B.64← 正确答案
  • C.128
  • D.512

答案:B。总 batch size(512)= 每 Worker batch size × Worker 数(8),所以每个 Worker 的 batch size 为 64。调度器只负责分配 GPU 资源,模型训练中“梯度累积”和“全局批量”的设定在训练代码中完成。

Q8. GKE 集群中启用 Cluster Autoscaler 后,以下哪种情况会触发节点缩容?

单选题 · hard

  • A.节点 GPU 利用率低于 20%
  • B.存在长时间无法调度的 Pod
  • C.所有 Pod 的资源需求可以在更少节点上满足← 正确答案
  • D.Spot 实例价格下降

答案:C。Cluster Autoscaler 的缩容依据是“资源是否冗余”——如果当前 Pod 的请求总量能被更少的节点容纳,就收缩节点。GPU 利用率低(A)只是业务指标,不等同于资源冗余;有不可调度 Pod 时应扩容而非缩容(B 错);Spot 价格波动(D)与伸缩逻辑无关。

Q9. 在 GKE GPU 集群中,排查“GPU 利用率低但任务在跑”的问题,应检查哪些方面?

多选题 · hard

  • A.数据加载管道是否成为瓶颈← 正确答案
  • B.分布式通信中是否存在等待← 正确答案
  • C.节点池的污点是否配置正确
  • D.batch size 是否过小导致启动开销大← 正确答案

答案:ABD。GPU 利用率低说明 GPU 在“等”数据或“等”同伴。数据加载慢(A)、通信等待(B)、batch size 太小(D)都是典型瓶颈。节点池污点配置(C)影响的是任务能否被调度到节点,与运行后的利用率无关。

Q10. GKE 的 Device Plugin 机制主要负责什么?

单选题 · easy

  • A.将你编写的模型部署到 GPU 上
  • B.向调度器上报节点的可用 GPU 资源← 正确答案
  • C.自动优化训练超参数
  • D.生成 GPU 使用账单

答案:B。Device Plugin 是一种 Kubernetes 插件,GPU 厂商通过它向 kubelet 上报“这个节点有几张卡、可用几张”,kubelet 再上报给调度器。它负责资源发现与上报,不负责模型部署(A 错)、超参优化(C 错)或计费(D 错)。