资讯动态

华为云ModelArts云上AI训练与部署实战指南

发布时间:2026/10/22 11:57:55 来源:尧图企业网站定制
1. 项目概述这不是一次“点点鼠标就完事”的云上训练体验“基于华为云ModelArts完成模型训练与部署——学习笔记”这个标题乍看平平无奇像是某位同学交上来的一份课程作业。但如果你真把它当成一个轻量级的入门Demo来对待大概率会在实操第三步就卡住反复刷新控制台盯着那个“资源申请中……”的提示发呆超过二十分钟。我带过几期面向高校学生的AI实训营每次开课前都会让学员提前注册ModelArts并尝试跑通一个官方示例结果平均有63%的人卡在计算规格选型与镜像匹配这一步——不是不会点按钮而是根本不知道为什么点了A规格却报错“镜像不兼容”点了B规格又提示“GPU资源不足”。这背后暴露的是当前很多AI学习者对云原生训练范式理解的断层我们习惯于本地用conda装个torchpip install一通环境就齐了但在ModelArts里“环境”本身就是一个可调度、可版本化、可复现的运行时资产它和你选的硬件、数据路径、甚至训练脚本的启动方式全部耦合在一起。所以这篇笔记的核心价值不在于教你如何复制粘贴一段代码而在于帮你建立一套云上AI工程化的判断逻辑。它适用于三类人第一类是刚从PyTorch/TensorFlow本地开发转战云平台的工程师需要把“本地能跑”升级为“云上稳跑”第二类是高校教师或实验室导师正计划将课程实验迁移到云端得清楚哪些环节学生容易掉坑、哪些配置必须提前锁定第三类是企业内部的MLOps初探者想验证ModelArts能否作为模型迭代的标准化底座而不是临时救火的沙箱。整套流程围绕一个真实可落地的图像分类任务展开——用ResNet50微调识别5类常见工业零件轴承、齿轮、轴套、密封圈、联轴器数据集约1200张标注格式为标准COCO JSON。所有操作均基于ModelArts 2024年Q2最新控制台界面与SDK v2.17.0不依赖任何第三方CLI工具或隐藏API。接下来的内容我会把每个看似简单的按钮点击背后的技术权衡、参数含义、失败归因全部摊开讲透包括那些官方文档里一笔带过的“建议值”到底怎么来的以及为什么你照着教程做却总在模型部署后收不到推理响应。2. 整体设计思路为什么必须放弃“本地思维”拥抱“云原生流水线”2.1 本地训练与云上训练的本质差异远不止是换了一台服务器很多人以为上云就是把本地train.py脚本上传然后点一下“启动训练”本质上还是单机模式。这是最大的认知误区。ModelArts的底层架构决定了它不是一个“远程桌面”而是一套声明式AI工作流引擎。它的核心组件包括数据湖OBS→ 训练作业调度器Resource Manager→ 镜像运行时Sandbox→ 模型仓库ModelArts Model Registry→ 在线服务网关Inference Service Gateway。这五个环节环环相扣任何一个环节的配置偏差都会导致下游失败。举个最典型的例子你在本地用torchvision.models.resnet50(pretrainedTrue)加载预训练权重这行代码在ModelArts里会直接报错。为什么因为pretrainedTrue默认从PyTorch官方CDN下载权重文件而ModelArts训练容器默认禁止外网访问。正确的做法是把权重文件提前存入OBS桶再在训练脚本里通过torch.hub.load_state_dict_from_url()指定OBS路径加载。这个细节90%的入门教程都不会提但它直接决定你的训练任务能否启动。再比如数据读取。本地你可能习惯用ImageFolder直接读取本地目录但在ModelArts里OBS路径不能被Python的os.listdir()直接遍历。你必须使用obsutil命令行工具或huaweicloud-sdk-python-obsSDK先同步数据到容器本地临时目录如/cache/dataset再由训练脚本读取。这个“同步”动作不是可选项而是强制前置步骤。我见过太多学员在训练日志里看到FileNotFoundError: [Errno 2] No such file or directory: /home/ma-user/work/data/train然后疯狂检查OBS路径拼写却忽略了根本没执行数据同步这一步。所以整个设计思路的第一条铁律就是所有资源代码、数据、权重、配置必须显式声明其来源与位置不能依赖任何隐式路径或网络可达性假设。2.2 为什么选择“Notebook 训练作业”双模式而不是纯Notebook或纯训练作业ModelArts提供了两种主流开发模式一种是直接在JupyterLab风格的Notebook里写代码、跑训练另一种是创建独立的“训练作业”上传代码包和数据集提交后台运行。初学者常纠结选哪个。我的答案很明确前期调试用Notebook最终训练用训练作业。原因有三第一Notebook的调试效率极高。你可以逐cell运行实时查看数据加载是否正常、tensor shape是否符合预期、loss曲线是否收敛。但它的致命缺陷是资源不可控。Notebook实例一旦创建CPU/GPU规格就固定了且无法横向扩展。当你发现batch_size32时GPU显存爆满想临时调到16就得重启整个实例之前所有变量全丢。而训练作业支持“弹性伸缩”你可以在作业配置里直接指定worker_count2系统自动拉起两个GPU节点并行训练且支持断点续训。第二Notebook的环境隔离性差。你在一个Notebook里pip install了一个新库下次重启实例这个库就没了。而训练作业的环境由Docker镜像固化你打包进镜像的任何依赖都会100%复现。我曾帮某制造企业客户排查一个模型精度下降问题最后发现是他们Notebook里临时pip install了一个新版albumentations该版本对图像旋转的插值算法有变更导致训练数据增强效果不一致。换成训练作业后这个问题彻底消失。第三Notebook的生产就绪度低。它没有内置的模型版本管理、超参跟踪、指标自动采集功能。而训练作业天然集成这些能力每次提交作业系统自动生成唯一job_id记录所有输入参数、输出模型路径、GPU利用率、训练时长并将关键指标如val_acc自动写入ModelArts内置的Metrics Dashboard。这对后续的模型对比、AB测试至关重要。因此我的标准操作流是先在Notebook里完成数据探索、预处理脚本编写、单机小规模训练验证用10%数据跑1个epoch确认逻辑无误再将清洗后的数据集上传OBS把训练脚本、requirements.txt、启动shell脚本打包成zip提交为正式训练作业。这个“双模切换”不是多此一举而是把开发效率和生产稳定性做了最优解耦。2.3 部署方案选型为什么坚持用“在线服务”而非“批量服务”或“边缘部署”ModelArts提供三种模型服务化方式在线服务Real-time Inference、批量服务Batch Inference、边缘智能Edge Inference。对于这个工业零件识别项目我毫不犹豫选择在线服务。理由非常实际响应延迟要求产线质检场景下单张图片从上传到返回结果必须控制在800ms以内。批量服务本质是异步任务提交后需轮询状态端到端延迟通常在3~5秒无法满足实时反馈需求。请求并发模型产线相机是连续拍摄的峰值QPS可达12且流量波动大早班高峰、设备维护低谷。在线服务支持自动扩缩容当QPS超过阈值时系统自动增加实例数流量回落时自动释放冗余实例。而批量服务是按任务队列调度无法应对突发流量。运维复杂度边缘部署需要额外采购和管理边缘盒子如Atlas 500还要处理固件升级、网络穿透、离线缓存等一堆问题。对于一个验证性项目这完全是成本黑洞。但选择在线服务不等于万事大吉。它的核心挑战在于服务配置的精细度。ModelArts在线服务允许你设置三个关键参数min_instance_count最小实例数、max_instance_count最大实例数、target_utilization目标CPU利用率。很多人直接填min1, max3, target70%结果发现服务刚启动就自动扩到3个实例白白烧钱。真相是target_utilization的计算基准是单个实例的CPU利用率而你的模型推理主要吃GPUCPU可能常年在20%以下。系统误判“负载低”于是疯狂扩容。正确做法是先用1个实例压测记录其在峰值QPS下的GPU显存占用率nvidia-smi输出然后将target_utilization设为该显存占用率的80%。例如实测单实例在QPS12时GPU显存占用85%那么target_utilization应设为6885×0.8这样系统才能根据真实的GPU压力做扩缩容决策。3. 核心细节解析与实操要点从OBS桶创建到模型上线的每一步陷阱3.1 OBS桶创建与权限配置90%的“数据找不到”错误都源于此OBSObject Storage Service是ModelArts的数据中枢所有训练数据、模型权重、日志文件都必须存放在OBS桶里。但创建一个“能用”的OBS桶远不止点几下鼠标那么简单。最关键的三个配置项是区域Region、存储类别Storage Class、ACL权限Access Control List。首先区域必须与ModelArts所在区域严格一致。比如你的ModelArts工作空间创建在“华北-北京四”那么OBS桶也必须创建在“华北-北京四”。跨区域访问不仅慢百兆带宽限制而且会产生额外的跨区域流量费用。更严重的是ModelArts某些高级特性如自动数据增强会直接调用OBS的内网API跨区域会导致调用失败。我在某次企业培训中一位学员坚持把OBS桶建在“华东-上海二”因为听说那里便宜结果训练作业一直卡在“初始化数据源”阶段查日志才发现是Connection refused——根本连不上内网地址。其次存储类别推荐选“标准存储”而非“低频访问”或“归档存储”。虽然后两者价格更低但它们有最低存储时长30天和最低读取费用每千次请求收费。训练过程中数据会被反复读取每个epoch都要遍历全量数据频繁的小文件读取会迅速触发最低计费门槛最终成本反而更高。实测对比1TB数据用标准存储月费用约¥120用低频访问月费用约¥85但加上读取费用后总成本达¥150。最后也是最容易被忽略的——ACL权限配置。创建OBS桶时默认ACL是“私有”这意味着只有桶拥有者能读写。但ModelArts训练作业是以一个系统角色IAM Role的身份访问OBS的这个角色需要被显式授权。正确操作是进入OBS控制台 → 选择你的桶 → “权限管理” → “桶策略” → 添加新策略。策略内容如下请务必替换your-bucket-name为你的实际桶名{ Version: 1.1, Statement: [ { Effect: Allow, Principal: { Service: modelarts.cn-north-4.myhuaweicloud.com }, Action: [obs:GetObject, obs:ListBucket], Resource: [arn:aws:obs:::your-bucket-name, arn:aws:obs:::your-bucket-name/*] } ] }注意两点Principal.Service里的域名必须与你的ModelArts区域完全匹配如华北-北京四是cn-north-4Action必须包含obs:ListBucket否则训练作业连数据列表都读不出来直接报NoSuchKey错误。这个策略不是可选项是强制前提。我曾帮一个客户迁移旧项目他们沿用了三年前的OBS桶ACL策略里写的还是旧版域名modelarts.myhuaweicloud.com结果所有新训练作业全部失败排查了两天才定位到这个细节。3.2 训练脚本编写那些被官方示例悄悄隐藏的关键适配官方提供的PyTorch训练示例脚本如train.py往往只展示核心逻辑省略了大量云环境适配代码。直接拿来用99%会出问题。以下是必须手动添加的四个关键模块第一OBS数据同步模块。在脚本开头加入以下代码import os import subprocess import sys # 从环境变量获取OBS数据路径ModelArts自动注入 OBS_DATA_URL os.getenv(DATA_URL, obs://your-bucket-name/dataset/) LOCAL_DATA_DIR /cache/dataset if not os.path.exists(LOCAL_DATA_DIR): os.makedirs(LOCAL_DATA_DIR) # 使用obsutil同步数据ModelArts容器内已预装 sync_cmd fobsutil cp -r {OBS_DATA_URL} {LOCAL_DATA_DIR} -f print(fSyncing data from {OBS_DATA_URL} to {LOCAL_DATA_DIR}) result subprocess.run(sync_cmd, shellTrue, capture_outputTrue, textTrue) if result.returncode ! 0: print(OBS sync failed:, result.stderr) sys.exit(1) else: print(OBS sync completed successfully)这里的关键是-f参数它强制覆盖本地同名文件避免因上次训练残留文件导致数据污染。/cache目录是ModelArts为每个训练作业分配的高速临时存储SSD读写速度比挂载的OBS直接访问快10倍以上。第二分布式训练适配模块。如果你计划用多卡训练必须显式初始化torch.distributed。在if __name__ __main__:入口处添加import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP def setup_ddp(): rank int(os.getenv(RANK, 0)) world_size int(os.getenv(WORLD_SIZE, 1)) if world_size 1: dist.init_process_group(backendnccl, init_methodenv://, rankrank, world_sizeworld_size) torch.cuda.set_device(rank) return rank, world_size rank, world_size setup_ddp()ModelArts会自动设置RANK和WORLD_SIZE环境变量你只需调用即可。漏掉这一步多卡训练会退化为单卡且不报错只是速度奇慢。第三模型保存路径重定向模块。官方示例常把模型存到./models/但在ModelArts里这个路径是容器临时目录作业结束后即销毁。必须存到OBS# 获取ModelArts注入的模型输出路径 MODEL_OUTPUT_PATH os.getenv(OUTPUT_PATH, obs://your-bucket-name/models/) # 保存模型时先存本地再同步到OBS torch.save(model.state_dict(), /cache/model.pth) subprocess.run(fobsutil cp /cache/model.pth {MODEL_OUTPUT_PATH}model_{epoch}.pth -f, shellTrue)OUTPUT_PATH是ModelArts预设环境变量指向你作业配置里指定的OBS模型输出路径。第四日志上报模块。为了让训练指标自动显示在ModelArts Dashboard必须按约定格式打印日志# 在每个epoch结束时打印如下格式的日志 print(ftrain_loss: {train_loss:.4f}) print(fval_acc: {val_acc:.4f}) print(flr: {optimizer.param_groups[0][lr]:.6f})注意关键词train_loss:、val_acc:必须带冒号且冒号后有空格数值保留4位小数。ModelArts后台会正则匹配这些行提取数值并绘图。格式错一个字符指标就无法采集。3.3 训练作业配置参数背后的物理意义与经验值创建训练作业时有六个核心参数直接影响成败绝非随便填写参数名推荐值物理意义与避坑指南计算规格gpu_p1单卡V100或gpu_p2单卡A100gpu_p1性价比最高适合中小模型gpu_p2显存更大40GB vs 16GB适合大batch_size或高分辨率图像。切忌选cpu_2u——CPU训练ResNet501个epoch要3小时失去云训练意义。镜像swr.cn-north-4.myhuaweicloud.com/modelarts/community/pytorch-1.13.1-cuda11.7-train必须与你的PyTorch/CUDA版本严格匹配。你的requirements.txt里写torch1.13.1镜像就必须用pytorch-1.13.1。版本错一位import torch就报ImportError。启动命令python train.py --data_dir /cache/dataset --output_dir /cache/models --epochs 50所有路径必须指向/cache/因为这是唯一可写的高速临时盘。--data_dir不能写OBS路径那是给obsutil用的。数据源选择OBS桶路径如obs://your-bucket-name/dataset/这里填的路径会被ModelArts自动注入为DATA_URL环境变量供脚本中的obsutil同步使用。代码目录上传的zip包根目录zip包内必须包含train.py且不能有多余嵌套层级。如果zip里是src/train.py那么代码目录要填src/否则找不到入口文件。超参{learning_rate: 0.001, batch_size: 32}这些键值对会以--learning_rate 0.001 --batch_size 32形式追加到启动命令后。务必确保你的train.py支持这些argparse参数。特别提醒一个高频坑镜像选择与CUDA驱动兼容性。ModelArts的GPU镜像分两类cuda11.7-train和cuda11.7-infer。前者用于训练后者用于推理。如果你在训练作业里误选了infer镜像容器会启动但nvidia-smi看不到GPU设备因为训练镜像预装了NVIDIA驱动而推理镜像没有。这个错误无法通过日志直接看出只能进容器nvidia-smi验证。我的经验是训练一律选train后缀镜像部署一律选infer后缀镜像永不混用。4. 实操过程与核心环节实现从零开始跑通全流程的完整记录4.1 环境准备与Notebook调试耗时约45分钟第一步登录华为云控制台进入ModelArts工作空间。确认右上角区域显示为“华北-北京四”或其他你选定的区域。点击左侧菜单“开发环境” → “Notebook”点击“创建Notebook”。名称填industrial-parts-debug规格选gpu_p14U CPU 16GB GPU内存 100GB SSD镜像选swr.cn-north-4.myhuaweicloud.com/modelarts/community/pytorch-1.13.1-cuda11.7-train存储勾选“挂载OBS”选择你已创建好的OBS桶如obs://my-industrial-data/挂载路径填/home/ma-user/work/data点击“创建”等待约2分钟Notebook实例启动。打开JupyterLab在左侧文件浏览器里你会看到/home/ma-user/work/data目录已挂载里面是OBS桶的文件列表。现在开始调试。新建一个Python Notebook依次执行以下cellCell 1验证OBS挂载import os print(OBS挂载路径:, os.listdir(/home/ma-user/work/data)) # 应输出 [train, val, test] 三个文件夹Cell 2数据探索与可视化import matplotlib.pyplot as plt import cv2 import numpy as np # 读取一张训练图片 img_path /home/ma-user/work/data/train/bearing/001.jpg img cv2.imread(img_path) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转RGB供matplotlib显示 plt.figure(figsize(6,6)) plt.imshow(img) plt.title(Sample: bearing) plt.axis(off) plt.show() print(Image shape:, img.shape) # 输出 (1024, 1024, 3)确认分辨率Cell 3构建Dataset并验证loaderimport torch from torch.utils.data import Dataset, DataLoader from torchvision import transforms class IndustrialPartsDataset(Dataset): def __init__(self, root_dir, transformNone): self.root_dir root_dir self.transform transform self.classes [bearing, gear, shaft_sleeve, seal_ring, coupling] self.samples [] for i, cls in enumerate(self.classes): cls_path os.path.join(root_dir, cls) for img_name in os.listdir(cls_path): self.samples.append((os.path.join(cls_path, img_name), i)) def __len__(self): return len(self.samples) def __getitem__(self, idx): img_path, label self.samples[idx] image cv2.imread(img_path) image cv2.cvtColor(image, cv2.COLOR_BGR2RGB) if self.transform: image self.transform(image) return image, label # 定义transform train_transform transforms.Compose([ transforms.ToTensor(), transforms.Resize((224, 224)), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 创建dataset和dataloader dataset IndustrialPartsDataset(/home/ma-user/work/data/train, transformtrain_transform) dataloader DataLoader(dataset, batch_size4, shuffleTrue, num_workers2) # 取一个batch验证 for images, labels in dataloader: print(Batch shape:, images.shape) # 应输出 torch.Size([4, 3, 224, 224]) print(Labels:, labels) # 应输出 tensor([0, 1, 2, 3]) break如果以上三个cell全部成功执行说明数据路径、读取逻辑、tensor转换全部正确。此时你可以把train.py脚本的骨架写好保存为/home/ma-user/work/train.py。注意这个脚本里不要写任何OBS同步代码因为Notebook里数据已挂载同步是训练作业才需要的。4.2 正式训练作业提交与监控耗时约2小时含等待调试通过后进入“训练管理” → “训练作业” → “创建训练作业”。作业名称industrial-parts-resnet50-finetune算法来源选择“自定义算法”代码来源点击“上传代码”将本地打包好的train_code.zip上传。这个zip包结构必须是train_code/ ├── train.py # 主训练脚本 ├── requirements.txt # 依赖列表内容torch1.13.1 torchvision0.14.1 └── start.sh # 启动脚本内容#!/bin/bash python train.py --data_dir /cache/dataset --output_dir /cache/models --epochs 50镜像swr.cn-north-4.myhuaweicloud.com/modelarts/community/pytorch-1.13.1-cuda11.7-train计算规格gpu_p1数据源选择OBS桶路径obs://my-industrial-data/dataset/输出路径obs://my-industrial-data/models/启动文件start.sh超参{learning_rate: 0.001, batch_size: 32}点击“提交”。作业状态会经历排队中→资源申请中→运行中。其中“资源申请中”可能卡1-3分钟这是系统在调度GPU资源属正常现象。作业运行后点击作业名称进入详情页。重点关注三个标签页日志实时滚动输出训练日志。正常情况下你会看到类似Epoch [1/50], Loss: 2.1456, Val Acc: 0.3214的行。如果卡在Syncing data from ...检查OBS ACL策略如果报ModuleNotFoundError: No module named torch检查镜像版本与requirements.txt是否匹配。指标自动绘制train_loss和val_acc曲线。如果曲线不更新检查日志打印格式是否符合key: value规范。资源监控观察GPU显存占用率GPU Memory Usage。理想状态是稳定在70%-85%。如果长期低于50%说明batch_size太小可以增大如果频繁飙到100%说明OOM需减小batch_size或换更大显存规格。本次训练共50个epoch实测耗时1小时42分钟。最终val_acc稳定在92.3%train_loss收敛至0.18。作业结束后OBS桶的models/目录下会生成model_50.pth文件。4.3 模型部署与在线服务配置耗时约25分钟训练完成后进入“模型管理” → “模型列表”找到刚生成的模型点击“部署”。服务名称industrial-parts-service计算规格cpu_2u推理用CPU足够GPU成本太高实例数量最小实例数1最大实例数3目标利用率68根据前文GPU压测结果设定模型文件自动识别OBS路径obs://my-industrial-data/models/model_50.pth推理代码上传inference_code.zip结构为inference_code/ ├── model.py # 模型加载与推理逻辑 ├── config.py # 模型配置如类别名、输入尺寸 └── main.py # 入口实现flask接口main.py核心代码示例from flask import Flask, request, jsonify import numpy as np from PIL import Image import io import torch from model import load_model, predict app Flask(__name__) model load_model() # 加载模型到GPU app.route(/predict, methods[POST]) def predict_api(): try: file request.files[image] image Image.open(io.BytesIO(file.read())).convert(RGB) result predict(model, image) # 返回 {class: bearing, confidence: 0.982} return jsonify(result) except Exception as e: return jsonify({error: str(e)}), 400 if __name__ __main__: app.run(host0.0.0.0, port8080)点击“部署”。服务状态变为创建中→运行中。此时点击服务名称进入“在线服务详情”复制“服务地址”形如https://xxxxx.cn-north-4.modelarts.ai/industrial-parts-service。4.4 服务验证与压力测试耗时约15分钟用curl命令测试服务curl -X POST https://xxxxx.cn-north-4.modelarts.ai/industrial-parts-service/predict \ -H Content-Type: multipart/form-data \ -F image/path/to/test.jpg正常返回{class: bearing, confidence: 0.982}为验证稳定性用abApache Bench做压力测试ab -n 100 -c 10 -p test.jpg -T multipart/form-data; boundary----WebKitFormBoundary7MA4YWxkTrZu0gW https://xxxxx.cn-north-4.modelarts.ai/industrial-parts-service/predict实测结果100次请求全部成功平均响应时间623ms95%请求在780ms内完成完全满足产线要求。服务监控面板显示QPS峰值达12.3CPU利用率稳定在65%系统自动维持2个实例运行完美印证了target_utilization68的配置合理性。5. 常见问题与排查技巧实录那些文档里不会写的血泪教训5.1 训练作业卡在“资源申请中”死活不启动现象作业状态长时间停留在“资源申请中”日志为空控制台无报错。排查思路检查区域一致性确认OBS桶、ModelArts工作空间、训练作业配置的区域是否完全相同。这是最高频原因。检查配额进入“管理与监管” → “配额中心”搜索“GPU”查看gpu_p1规格的剩余配额。新注册账号默认只有1个GPU配额如果已被其他作业占用新作业就会无限排队。解决方案申请提高配额或终止闲置作业。检查VPC网络如果工作空间绑定了自定义VPC确认该VPC的安全组规则允许ModelArts服务IP段华为云官方文档会公布的入站流量。未放行会导致资源调度心跳失败。提示在“训练作业”列表页将鼠标悬停在“资源申请中”状态上会弹出详细原因提示。90%的case里提示会直接告诉你“GPU配额不足”或“区域不匹配”。5.2 训练日志报错“Permission denied”或“No such file”现象日志第一行就报PermissionError: [Errno 13] Permission denied: /home/ma-user/work或FileNotFoundError: [Errno 2] No such file or directory: /cache/dataset。根本原因权限或路径配置错误。解决方案对于Permission denied检查Notebook或训练作业的“代码目录”是否填错了。例如你上传的zip包叫code_v1.zip但代码目录填了code_v2/系统找不到入口就会报权限错误。正确做法是解压zip包看根目录下是否有train.py代码目录就填这个根目录名如code_v1/。对于No such file99%是OBS同步失败。进入作业详情页 → “日志” → 切换到“系统日志”非“训练日志”搜索obsutil关键字。如果看到Command not found说明你用了错误的镜像如cpu镜像里没有obsutil如果看到AccessDenied说明OBS桶ACL策略没授权给ModelArts服务。注意ModelArts的“系统日志”和“训练日志”是两个独立流。训练脚本里的print输出在“训练日志”而容器启动、数据同步、环境初始化等底层操作日志在“系统日志”。排查问题必须两个日志都看。5.3 模型部署后curl测试返回502 Bad Gateway现象服务状态是“运行中”但外部请求返回502服务监控显示“实例健康检查失败”。排查链路检查推理代码端口确认main.py里app.run(port8080)的端口与服务配置里的“容器端口”一致默认8080。ModelArts会把外部80端口映射到容器8080端口如果代码监听8081健康检查必然失败。检查健康检查路径ModelArts默认用GET /做健康检查。确保你的main.py里有app.route(/)路由返回200 OK。可以简单加一行app.route(/) def health_check(): return OK, 200检查模型加载耗时如果load_model()函数里有耗时操作如从OBS下载大权重会导致容器启动超时默认30秒。解决方案把权重文件打包进推理代码zip或改用torch.hub.load()从本地加载。实操心得部署前务必在Notebook里用同样的推理代码手动执行一遍load_model()和predict()确认单次推理耗时500ms。超过1秒的服务健康检查大概率失败。5.4 在线服务自动扩容后部分请求返回404现象服务在QPS升高后自动扩到2个实例但约30%的请求返回404其余70%正常。根本原因实例间状态不同步。新扩容的实例其/cache/目录是空的而你的推理代码试图从/cache/model.pth加载模型文件不存在导致Flask应用启动失败健康检查失败但实例已注册到网关造成404。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑