大模型CI/CD流水线配置:从零搭建自动训练与部署流程
大模型项目的 CI/CD 和普通 Web 应用不太一样:除了代码检查和镜像构建,往往还要触发模型微调任务、管理大体积产物,并把新模型滚动到推理服务。
下面按零基础也能照做的顺序,讲清楚一条最小可用流水线怎么配、怎么验、怎么避坑。
先确认你的环境能跑流水线
这套配置适用于已有 GitLab 仓库、至少一台 Linux 服务器(建议 4 核 8G 以上,模型训练另算)的场景。
你需要准备:
- GitLab 项目仓库,并开启 CI/CD 功能
- 一台能访问 GitLab 的服务器,安装 Docker 和 GitLab Runner
- 一个容器镜像仓库(GitLab 自带的 Container Registry 或 Harbor 均可)
- 如果要跑微调,服务器需能访问 GPU 或训练集群
在服务器上安装 Runner 后,执行注册命令,把 Runner 挂到项目下:
docker run --rm -it \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
gitlab/gitlab-runner:latest register \
--non-interactive \
--url "https://gitlab.example.com/" \
--registration-token "你的项目TOKEN" \
--executor "docker" \
--docker-image "docker:24-cli" \
--description "llm-runner"
注册完成后回到 GitLab 项目,进入 Settings > CI/CD > Runners,确认 Runner 显示为绿色在线。
如果显示离线,优先检查服务器到 GitLab 的网络和防火墙。
编写 .gitlab-ci.yml 核心阶段
在项目根目录创建 .gitlab-ci.yml,先跑通“检查 → 构建 → 部署”三段。
下面是一个可调整的骨架:
stages:
- lint
- build
- deploy
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
lint-code:
stage: lint
image: python:3.11-slim
script:
- pip install ruff
- ruff check .
build-image:
stage: build
image: docker:24-cli
services:
- docker:24-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
only:
- main
deploy-infer:
stage: deploy
image: alpine:3.19
script:
- apk add --no-cache openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | ssh-add -
- ssh -o StrictHostKeyChecking=no $DEPLOY_USER@$DEPLOY_HOST "docker pull $IMAGE_TAG && docker stop llm-infer || true && docker rm llm-infer || true && docker run -d --name llm-infer -p 8000:8000 $IMAGE_TAG"
only:
- main
把 SSH_PRIVATE_KEY、DEPLOY_HOST、DEPLOY_USER 配到 Settings > CI/CD > Variables,
并勾选 Protected 和 Masked。CI_REGISTRY_* 是 GitLab 预置变量,
不用手动填。
提交代码后进入 CI/CD > Pipelines,应该能看到三个阶段依次变绿。
如果 build-image 报 Cannot connect to the Docker daemon,检查是否声明了 docker:24-dind 服务,以及 Runner 的 config.toml 中是否允许 privileged 模式。
接入模型微调任务
大模型 CI/CD 流水线配置的关键差异点在训练环节。
推荐把微调做成独立的手动触发 job,避免每次提交都消耗 GPU:
train-lora:
stage: deploy
image: python:3.11-slim
script:
- pip install -r requirements-train.txt
- python train.py --base-model ./base --data ./data/train.jsonl --output ./out/lora
artifacts:
paths:
- out/lora/
expire_in: 7 days
when: manual
only:
- main
提交后在流水线页面点击 train-lora 旁边的播放按钮即可触发。
训练产物会作为 artifact 保留 7 天,适合小体积 LoRA 权重;
如果产物超过几百 MB,建议改为上传到对象存储,避免 GitLab 存储压力。
避坑与验证清单
镜像体积失控:大模型项目容易把模型文件打进镜像,导致构建超时。
在 .dockerignore 中排除 *.bin、*.safetensors、data/、out/,模型文件通过挂载卷或对象存储提供。
部署脚本误删旧容器:上面的 docker stop ... || true 写法在容器不存在时不会中断流水线,但生产环境建议保留上一个版本镜像 tag,便于回滚。
变量没加保护:SSH_PRIVATE_KEY 这类敏感变量务必勾选 Masked,否则可能出现在 job 日志里。
验证时按顺序检查:流水线三个阶段是否全绿、镜像仓库是否有新 tag、目标服务器上 docker ps 是否显示新容器、推理接口 curl http://服务器IP:8000/health 是否返回正常。
任何一步失败,先看对应 job 的日志末尾,再回到本文对应小节排查。
如果你正在处理大模型CI/CD流水线配置,建议先按本文步骤跑通最小三段流水线,再逐步加入训练和回滚逻辑,不要一开始就把所有环节塞进同一个 job。