最近经常有人问我:阿里云 ACK 这种容器平台,到底能不能扛住大模型的训练和推理?问的人有做基础架构的,也有刚把业务云原生化的小团队。大家下意识觉得,AI 任务动辄几十张 GPU,跑的是分布式批处理,底层应该用高性能计算那一套,普通 K8s 平台看着不够“硬核”。这个想法放在几年前还说得通,现在基本可以放下了。阿里云 ACK(容器服务 Kubernetes 版)这轮升级,核心就是把云原生底座延伸到智算场景,做一个真正面向智算时代的现代化应用平台。下面我不会抄发布会的宣传文案,而是从实际使用者的角度,把升级后在调度、弹性、成本、安全几个维度的变化,以及在迁移落地中踩过的坑,一次讲清楚。这篇文章适合正在规划 AI 基础设施、准备从自建集群迁到托管集群、或者已经在 ACK 上跑微服务但想扩展 GPU 能力的开发者和平台工程师。
1. 智算时代为什么需要一个“能算”的应用平台
1.1 大模型任务不是特殊物种,而是一群更挑剔的容器
分布式训练任务跑起来之后,你会发现它本质上还是那套容器编排逻辑:一个 Job 启动若干个 Worker,不同角色之间通过网络通信,任何一个实例挂了都要自动重启。问题在于,传统 K8s 对 GPU 资源的概念非常粗糙,默认把一张卡当成一个只能整体分配的资源,没办法按显存切分,也没办法在多个小任务之间共享。这就导致很多 AI 团队拿到 K8s 集群后,第一反应是“这平台跑微服务可以,跑训练够呛”。
我自己的体验是,在物理机上直接跑训练,最大的痛点是环境一致性。Python 版本、CUDA、cuDNN、依赖库稍有差异,复现就变成灾难。容器把这些问题压缩成一个镜像,而 Kubernetes 解决了“这个镜像应该在哪里跑、死了之后谁能拉起来”的问题。所以大模型训练和推理,本质上还是一大群容器任务的组合,只是它们对资源、网络、存储的要求更极端。ACK 的升级思路,不是把 K8s 推翻重来,而是在 K8s 的框架里补上这些极端场景需要的调度能力。
1.2 托管版到底比自建强在哪
自建 K8s 集群的苦,只有维护过的人懂:Master 节点高可用、etcd 备份、证书轮换、版本升级、集群故障恢复,每一项都是实打实的运维负担。ACK 托管版把这层全部收走,控制面由阿里云负责,包括 API Server、etcd 的高可用和监控。对中小团队来说,这几乎是决定性的选择——省出来的精力可以全部用来打磨业务应用。
另一个容易被低估的点是云产品集成。ACK 跟底层 VPC、SLB、ECS、云盘、日志服务是原生打通的,很多能力直接通过 CRD 和 Annotation 暴露出来,不需要自己写一堆 controller。比如给 Service 挂一个 SLB,只需要声明loadBalancerIP或service.beta.kubernetes.io/alicloud-loadbalancer-*注解。这种“云原生 + 阿里云基础设施”的粘合度,是自建环境很难复制的。
1.3 平台要同时服务两类人
智算平台上的用户至少有两类:一类是跑微服务的业务研发,另一类是跑训练和推理的算法工程师。这两类人对平台的诉求完全不同。业务研发要稳定、便捷、好排查;算法团队要高性能、高弹性、好调度。ACK 这次升级里,一个很重要的变化是允许在同一个集群或一组节点池上同时服务两类负载,而不是要求你为 AI 单独再搭一套平台。
这个设计理念很关键。如果平台分裂成“微服务集群”和“AI 集群”两套,运维模型会非常痛苦:多一套集群就多一套监控、多一套告警、多一套权限管理。混部之后,在线业务和白天的 CPU 峰值、训练任务和晚上的 GPU 长尾需求能互相错峰,资源利用率提升明显。当然,混部要搭配完善的资源隔离和驱逐机制,这一点我在后面成本治理的章节会具体展开。
2. 升级后最值得关注的四个能力变化
2.1 从“按卡独占”到“按显存细粒度共享”的 GPU 调度
以前想在一张 GPU 上跑多个小模型,基本得手动设置CUDA_VISIBLE_DEVICES,或者在物理机上做内核态隔离,操作繁琐且容易出问题。ACK 的 GPU 共享调度把显存定义成可调度的扩展资源,你在 Deployment 里声明需要多少显存,调度器负责分配。比如一张 32GB 的卡,跑两个需要 8GB 显存的推理服务,各占一份,不再需要为一个小模型独占整卡。
我实际使用中比较典型的写法是这样的:
apiVersion: apps/v1 kind: Deployment metadata: name: gpu-share-demo spec: replicas: 1 selector: matchLabels: app: gpu-share-demo template: metadata: labels: app: gpu-share-demo spec: containers: - name: inference image: registry.cn-hangzhou.aliyuncs.com/your-app/inference:latest resources: limits: aliyun.com/gpu: 1 aliyun.com/gpu-mem: 8这里aliyun.com/gpu-mem是请求显存大小,调度器会根据节点上剩余的 GPU 资源决定 Pod 落在哪台机器。要注意的是,这种共享方式不等于性能隔离。如果不同推理服务对延迟特别敏感,我还是建议用整卡或 MIG 方式,避免因互相争抢算力导致 P99 延迟抖动。
2.2 弹性扩容从“先扩容后跑”变成“边扩边跑”
弹性伸缩有两种节奏。第一种是节点池层面的伸缩,第二种是工作负载层面的 HPA。以往遇到突发算力时,要等 ECS 实例创建出来、加入集群、再把 Pod 调度上去,整体耗时经常在 3 到 8 分钟。对于在线推理服务来说,这种分钟级的伸缩基本意味着流量已经损失了。
ACK 升级后,节点池弹性扩容和 ECI 的配合明显更顺滑了。ECI 可以理解为 Serverless 容器,它不需要你预先创建 ECS 节点,Pod 创建之后直接运行在托管的计算资源上。当节点池扩容速度跟不上工作负载扩容速度时,队列里超出的 Pod 会自动调度到 ECI 上。我实测过同时拉起 200 个推理 Pod 做并发评测,体感不到 1 分钟全部就绪。这个能力对压测、评测、周期性数据处理任务非常友好。
2.3 运维视角从“看资源”走向“看业务”
以前看 GPU 使用率,只能看到节点层面的平均利用率。但训练任务卡住时,GPU 利用率可能还在 90% 以上,因为计算一直在空转,loss 不降。运维同学看着监控面板,很难判断这到底是“正在计算”还是“死循环”。
ACK 的云原生 AI 套件默认带上任务级监控,可以看到训练进度、日志、GPU 利用率、显存、网络吞吐,还能直接查看几个 worker 是否健康。算法同学不用再 SSH 到容器里到处翻日志,平台团队也能直接回答“这个训练任务什么时候能跑完”,而不是只能说“有几张卡在用”。这个维度的切换,对整个团队的协作方式有实打实的改善。
2.4 安全隔离从“网络边界”下沉到“调度边界”
智算平台最怕的是多团队共享时,某个镜像或某个任务把宿主机搞挂。以往靠 Namespace 做软隔离,效果有限。ACK 升级后,Pod 安全策略、RuntimeClass 安全沙箱、镜像签名和供应链扫描、RAM OIDC 以及细粒度 RBAC 都变成了推荐配置。
我服务过一个金融客户,他们内部要求不可信镜像必须在安全沙箱里运行。做法是在 RuntimeClass 里指定安全沙箱,然后通过策略强制某些命名空间下的 Pod 必须使用这个 RuntimeClass。这样即使镜像里有恶意代码,也无法直接影响宿主机。对合规要求严格的行业来说,这是决定能不能上生产的关键能力。
2.5 与阿里云全栈能力的粘合度更高
ACK 的价值从来不只是 K8s 本身。升级之后,计算侧可以对接 ECS、ECI、超级计算集群;存储侧支持 OSS、NAS、CPFS、云盘;网络侧支持 Terway ENI 直通;安全合规可以直接接 ActionTrail、云安全中心。再往上,还有阿里云百炼负责模型服务,PAI 负责建模实验。ACK 在中间扮演通用算力编排的角色。
平台团队如果只想选一个底座,同时又想留出后续接入上层 AI 平台的空间,那 ACK 是接受度最高的方案。它不会逼你在早期就把模型部署方案定死,而是先把容器编排、资源调度、弹性伸缩这些底层能力打好,后续再逐步演进。
3. 从自建 K8s 迁移到 ACK 的实操路径与排坑记录
3.1 迁移前必须回答的四个设计问题
第一个问题,一个集群还是多个集群?我的建议是生产集群和测试集群分开,AI 和微服务可以共用生产集群,但用节点池做物理隔离。我们最终采用的方式是生产集群 + 测试集群,AI 和微服务在同一个生产集群内,但通过节点池拆分:CPU 节点池给微服务,GPU 节点池给训练和推理。原因是这两类负载的峰值时间不同,混部能错峰共享资源。
第二个问题,容器网络选 Terway 还是 Flannel?ACK 默认推荐 Terway,它基于 ENI 给 Pod 分配独立网卡,网络延迟更低,还能配合安全组做 Pod 粒度的访问控制。自建集群如果还在用 Flannel,迁移前最好先规划好 VPC 和交换机网段,避免和现有业务网段冲突。
第三个问题,存储怎么选?不同存储类型对应不同场景,我整理了一个常用对照表:
| 存储类型 | 典型场景 | 注意事项 |
|---|---|---|
| 云盘 | 数据库、有状态服务的本地数据 | 单节点读写,容量固定,不能多 Pod 共享 |
| NAS | 多 Pod 共享文件、代码、日志 | 吞吐比 CPFS 低,适合普通共享场景 |
| OSS | 模型文件、数据集的低频归档 | 大量小文件性能差,需要配合缓存 |
| CPFS | 大规模分布式训练 | 成本高,性能要求极高时使用 |
我们实践中比较顺手的组合是:代码和配置放 ACR 和 ConfigMap,数据集放 OSS + Fluid 缓存,模型权重放 OSS,训练 checkpoint 写 NAS,日志直接走 SLS。
第四个问题,安全策略怎么设?提前定义 Namespace、ResourceQuota、LimitRange,避免一个团队的任务把集群资源全部占完。特别是 GPU 资源,一定要给每个团队设置上限,否则某个团队一个误操作就能把集群的 GPU 全抢走。
3.2 迁移中容易被忽视的四个坑
坑一,镜像拉取超时。自建环境直接从 Docker Hub 拉镜像很快,上了 ACK 后经常遇到ImagePullBackOff。原因是集群节点访问公网镜像源不稳定。解决办法很简单:把业务镜像同步到 ACR,集群通过 VPC 内网拉取。如果是第三方基础镜像,先转存到 ACR 再同步。
坑二,GPU 驱动和 runtime 版本不匹配。新建 GPU 节点池后,Pod 创建成功,但容器内执行nvidia-smi直接报错。排查下来是节点池基础镜像里的驱动版本和容器内 CUDA 版本对不上。建议直接用 ACK 官方推荐的 GPU 镜像,并保持 aliyun-acn 插件版本和集群版本兼容,不要自己手工处理驱动。
坑三,RDS 连接被打满。微服务迁入集群后,大量 Pod 同时连接 RDS,连接数很快到上限,业务开始报错。代码里要使用连接池,给数据库实例预留足够连接数,必要时加一层数据库代理。另外,数据库密码不要写死在环境变量里,用 K8s Secret 配合 KMS 或 external-secrets 管理。
坑四,存储性能不达预期。早期我们把 OSS 直接当训练数据目录,跑小文件密集的 dataloader 时性能低到怀疑人生。后来用 Fluid 做数据集缓存,把热数据缓存到节点本地盘,训练速度提升了 4 倍以上。这个经验值得记下来:OSS 不是不能用来训练,而是要用对方式。
3.3 一次实际迁移的时间线备忘
以一套 30 个微服务加 2 个训练任务的自建集群为例,我们的节奏大致是:第一周做资源清单和元数据梳理,包括所有 Deployment、Service、ConfigMap、StatefulSet;第二周搭建 ACK 测试集群,同步镜像,改造 YAML;第三周做业务灰度迁移和压测,重点验证存储和网络性能;第四周正式割接。
如果想压缩时间,最值得提前做的是把 YAML 里的旧版 API 升级到新版本,比如extensions/v1beta1的 Ingress 全部改成networking.k8s.io/v1。另一个提前要验证的是 GPU 节点池的插件状态,先在测试环境把 GPU 跑通,比什么都重要。
4. 把 ACK 用出性价比:弹性伸缩、成本治理和“省钱三板斧”
4.1 弹性伸缩策略要分层设计,别只靠一个 HPA
很多团队一说到弹性,第一反应是配一个 HPA,实际上这远远不够。我的经验是至少分三层:第一层是工作负载 HPA,按 CPU、内存或 QPS 伸缩;第二层是集群节点自动伸缩,工作负载扩容后节点不够时要能自动扩;第三层是 ECI 喷发,当节点池扩容跟不上时,用 Serverless 容器承接临时算力。
一个常见的 HPA 配置长这样:
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: online-inference spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: online-inference minReplicas: 2 maxReplicas: 20 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70这里一定要关注behavior里的stabilizationWindowSeconds,也就是缩容稳定窗口。如果不设置,流量一抖动,副本数会频繁增减,反而影响稳定性。我见过不止一次因为 HPA 频繁伸缩导致发布时 Pod 反复重建的案例。
4.2 Spot 实例专门承接“跑挂了也无所谓”的任务
AI 训练中有很多任务是可以容忍失败的,比如模型评估、批量评测、数据清洗、超参搜索。这些任务天然适合用抢占式实例。ACK 节点池支持 Spot 实例,配合 Pod 的restartPolicy和任务的 checkpoint 机制,即使节点被回收,任务也能从最近一次保存的状态继续。
但要注意,不是所有任务都适合 Spot。不间断的主训练任务,或者对显存连续性要求很高的推理服务,建议还是用包年包月或按量付费的 GPU 实例。否则节点被回收后,任务频繁重试,浪费时间成本,反而得不偿失。
4.3 成本分析别到月底再看账单,要实时盯
ACK 自带成本分析功能,可以按集群、命名空间、工作负载聚合资源消耗,并生成对应的成本报告。我们给每个业务线一个独立的 Namespace,并统一打上team、project标签。月底导出成本报告,哪个团队用了多少 GPU、多少 CPU、多少存储,一目了然。
这才叫成本治理落到人。否则平台团队每个月只能对着账单总数一脸懵,不知道成本是从哪儿涨起来的。
4.4 混部是省钱的大头,但要控制资源争抢
在线微服务的波峰一般在上下午,训练任务更多在晚上。如果各建一套集群,资源利用率很难上去。我们把训练任务设置为低优的 BestEffort 或 Burstable,通过 CPU 亲和性、弹性配额和 GPU 节点池错峰调度,把在线业务的空闲资源利用起来。
混部的前提是监控体系足够完善。一旦在线业务出现明显时延升高,平台必须能快速定位是不是被低优任务抢了 CPU,然后立刻驱逐或降级。我们一开始混部时踩过坑,低优任务把宿主机 CPU 跑满,导致在线服务 P99 延迟翻倍。后来给低优任务加了 CPU 和内存限额,并开启抢占优先级,情况才稳定下来。
5. 生产环境的安全底线:多租户隔离、镜像供应链和审计
5.1 多租户隔离:Namespace、ResourceQuota、NetworkPolicy 三件套
K8s 的 Namespace 只是逻辑边界,真正要落地隔离,必须配合 ResourceQuota 限制资源占用,配合 NetworkPolicy 限制 Pod 间通信。比如不同业务线的 Pod 不能互相访问,默认拒绝所有东西向流量,只放行同一命名空间内的必要访问。
在 ACK 上启用 NetworkPolicy 之后,我们可以把默认策略设置成拒绝,再按业务需求逐条放开。这个过程要在一开始就做好,等业务上线再补策略,会频繁出现“网络不通”的投诉,团队心态很容易崩。
5.2 镜像供应链:扫描、签名、白名单
镜像来源越杂,风险越高。生产环境一定要在 ACR 上开启镜像扫描,并把高危漏洞的镜像加入拉取拦截。重要业务最好使用镜像签名,K8s 端通过策略强制执行。
我见过一个案例,某团队为了省事,从公网仓库拉取了一个好久没更新的基础镜像,结果内部扫描发现存在多个高危漏洞。虽然短期内没出事,但这种风险谁也不想赌。建议把镜像同步和扫描阶段放进 CI 流水线,每一次构建都自动扫描,高危直接阻断发布。
5.3 审计与合规:ActionTrail 加 Kubernetes API 审计
平台团队最怕的是出了事说不清楚是谁改的。ACK 控制面的操作会写入 ActionTrail,集群内部的 API 操作可以通过开启 Kubernetes 审计日志,写入日志服务。建议把审计日志长期归档,平时不查,出问题时它就是唯一的还原手段。
有一次我们排查线上配置被意外修改,就是靠审计日志定位到某个同学在某时刻执行了一条kubectl scale命令。没有这个日志,很难追责,更别提复盘和改流程。
6. 组建平台工程团队,让 ACK 从“能用”走向“好用”
6.1 给算法工程师提供自助式体验
ACK 底层能力再强,如果算法工程师每次跑任务都要提工单让平台同学执行命令,平台一定会成为瓶颈。我们基于 ACK 做了一层自服务入口,提供几个常用的工作负载模板,算法同学填写资源需求、镜像地址、副本数,点击提交就自动生成对应的 Deployment、Service、Ingress,同时自动注入监控和日志采集的注解。
这层封装不复杂,核心是把最佳实践固化到模板里,比如统一加resources.requests和limits、统一加健康检查探针、统一加 Pod 反亲和性。这样既保留 K8s 的灵活性,又大幅降低使用门槛。
6.2 GitOps 是配置管理的兜底
所有集群配置、工作负载 YAML、Helm Release 都统一放在 Git 仓库里,通过 Argo CD 或阿里云 flow 对接 CI/CD。一旦出问题,可以快速回滚到上一个可用 commit。
我们经历过一次事故:有人手动改了线上 Deployment 的副本数,结果忘记回滚,凌晨流量高峰时资源不足,业务直接报警。上了 GitOps 之后,这类问题基本绝迹,因为仓库里的 YAML 才是唯一真实状态,手动改动会被自动覆盖。
6.3 可观测性要一开始就建好
APM、日志、监控、链路追踪这四类能力,如果不在项目一开始选型,后面再补会非常痛苦。ACK 本身的 Metrics 和事件可以通过 ARMS、SLS 和 Prometheus 接入。强烈建议把集群事件、审计日志、应用指标接入同一个看板,排查问题时不用反复切换控制台。
另外,告警规则一定要结合实际场景设计,不要全平台只配一个“节点 CPU 高”的通用告警。我们后来把告警收敛成三类:可用性告警、性能告警、成本告警,每一类都有明确的负责人,告警量少了,处理效率反而高了。
最后分享一个我自己的习惯:每次 ACK 控制台或组件有新版发布,我都会先在测试集群里升级,重点看 GPU 插件、Terway 和 CNI 的兼容性说明,再决定是否滚动到生产。生产集群的升级尽量选在业务低峰,并且提前做好快照和回退方案。智算时代给云原生带来的不是另一套新概念,而是把已有的调度和弹性能力用到极致。如果你也正在纠结要不要把 AI 负载放到 ACK 上,建议先从一个评测任务或推理服务开始,跑通后再逐步扩大边界,这条路比想象中要平滑很多。