使用 Triton Docker 镜像部署 FP16 与 INT8 多模型
解读
在国内云原生面试场景里,这道题考察的是“把 GPU 推理服务器装进容器并跑起来”的端到端能力。
Triton Inference Server 是 NVIDIA 官方推理框架,天然支持 FP16/INT8 混合精度、并发多模型、动态批处理。
Docker 化部署 的核心诉求是:镜像体积 < 5 GB、启动时间 < 30 s、GPU 驱动与 CUDA 版本对齐、国内网络可拉取、安全合规(非 root、最小权限、Secrets 不落盘)。
题目隐含三个得分点:
- 镜像选型与多阶段构建
- 模型仓库目录规范与配置文件写法
- 同一容器内同时服务 FP16 与 INT8 模型,且能热更新
知识点
- nvcr.io/nvidia/tritonserver:24.05-py3-min 国内加速拉取方案(阿里云 ACR 缓存或自建 Harbor proxy)
- 多阶段构建 把
tritonserver二进制与模型文件分离,最终镜像只保留/opt/tritonserver/bin与LD_LIBRARY_PATH所需 so,体积可压缩 40 % - 模型仓库目录树 必须严格遵循
其中model_repository/ ├── resnet50_fp16/ │ ├── 1/ │ │ └── model.pt │ └── config.pbtxt └── yolov5_int8/ ├── 1/ │ └── model.plan └── config.pbtxtconfig.pbtxt需显式指定platform: "tensorrt_plan"与precision_mode: INT8,并挂载校准表 - 同一进程加载多模型 依赖
--model-control-mode=poll与--load-model=*参数,避免启动顺序耦合 - GPU 显存隔离 使用
CUDA_VISIBLE_DEVICES与TRITON_SERVER_GPU_DEVICE环境变量,防止 FP16 模型抢占 INT8 模型显存 - 国内合规:镜像内禁止 root,USER 1001:1001;敏感 License 文件通过 Kubernetes Secrets 以
tmpfs挂载,不落容器可写层 - CI/CD:在 GitLab-Runner 或 GitHub Actions 国内节点做
docker buildx --cache-to type=registry缓存,加速后续构建
答案
- 准备最小 Dockerfile
# 第一阶段:拉取官方镜像作为构建缓存
FROM nvcr.io/nvidia/tritonserver:24.05-py3-min as builder
# 国内加速
RUN sed -i 's@http://.*.ubuntu.com@http://mirrors.aliyun.com@g' /etc/apt/sources.list
# 预装国内 pip 源
COPY pip.conf /etc/pip.conf
# 第二阶段:运行时镜像
FROM nvcr.io/nvidia/tritonserver:24.05-py3-min
COPY --from=builder /opt/tritonserver /opt/tritonserver
COPY model_repository /models
RUN groupadd -g 1001 triton && useradd -u 1001 -g triton -s /bin/false triton
USER 1001:1001
ENV LD_LIBRARY_PATH=/opt/tritonserver/lib:$LD_LIBRARY_PATH
ENTRYPOINT ["/opt/tritonserver/bin/tritonserver"]
CMD ["--model-repository=/models", "--model-control-mode=poll", "--load-model=*", "--strict-model-config=false"]
- 构建与推送
docker buildx build --platform linux/amd64 -t reg.xxx.cn/triton:fp16-int8-v1 \
--cache-to type=registry,ref=reg.xxx.cn/cache:triton \
--cache-from type=registry,ref=reg.xxx.cn/cache:triton --push .
- 运行验证
docker run --gpus all --rm -p 8000:8000 -p 8001:8001 -p 8002:8002 \
-e CUDA_VISIBLE_DEVICES=0,1 \
reg.xxx.cn/triton:fp16-int8-v1
使用 curl -X POST localhost:8000/v2/models/resnet50_fp16/ready 与 yolov5_int8/ready 返回 200,即表示多模型同时加载成功。
4. INT8 校准表热更新
把 *.calib 文件放在 yolov5_int8/1/ 目录,config.pbtxt 中增加
parameters: {
key: "INT8_CALIBRATION_TABLE"
value: { string_value: "/models/yolov5_int8/1/calib_yolov5.bin" }
}
Triton 轮询到文件变化会自动重载,无需重启容器。
拓展思考
- 动态批处理:在
config.pbtxt里打开dynamic_batching { max_queue_delay_microseconds: 500 },FP16 与 INT8 模型可共享同一调度器,但需评估 INT8 校准后的精度损失是否满足 SLA。 - A/B 灰度:利用 Triton 的
model_version_policy: { specific { versions: 2 } }与 Kubernetes Ingress 按 Header 分流,实现国内业务常见的“灰度 5 % 流量”需求。 - 国产化 GPU:在 Hygon、MTT 或 Moore Threads 环境,需把底层
libcuda.so替换为厂商提供的兼容库,重新编译 TensorRT plan,否则 INT8 校准阶段会报cudaErrorNotSupported。 - 镜像安全扫描:使用
trivy对最终镜像做 CVE 检测,国内银行客户要求 HIGH 级别漏洞为 0,可通过distroless或apko进一步裁剪系统库。