news 2026/9/20 9:09:59

MXNet 发布流水线实战:基于 Jenkins 的 Scala 构件自动化构建、测试与部署全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MXNet 发布流水线实战:基于 Jenkins 的 Scala 构件自动化构建、测试与部署全解析

MXNet 发布流水线实战:基于 Jenkins 的 Scala 构件自动化构建、测试与部署全解析

【免费下载链接】mxnetLightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more项目地址: https://gitcode.com/gh_mirrors/mx/mxnet

导读

本文围绕 MXNet 仓库中的 ci/publish 发布配置,系统讲解 MXNet 官方制品(Artifacts)的持续发布机制:从 Jenkins 三阶段流水线(构建 → 测试 → 部署)的编排逻辑,到 CentOS 7 + Developer Toolset 7 的统一构建环境选型,再到 Scala 包(Maven 构件)从密钥管理、静态编译到发布上线的完整链路。读完本文,你将掌握这套发布体系的目录结构、核心脚本的职责与调用关系,以及各环境变量与配置项的真实含义,可直接据此复现或迁移 MXNet 的制品发布流程。

一、发布体系总览:ci/publish目录做了什么

在 MXNet 仓库根目录下,ci/publish目录承载了所有面向「对外发布制品」的 Jenkins 配置与部署脚本。其内部结构如下:

ci/publish/ ├── Jenkinsfile # Jenkins 声明式/脚本式流水线定义 ├── README.md # 发布配置说明(本文主体依据) ├── scala/ # Scala(Maven)发布所需全部文件 │ ├── build.sh # 构建后端(libmxnet)与 Scala 包 │ ├── buildkey.py # 从密钥服务提取凭据并配置 Maven/GPG │ ├── deploy.sh # 执行 Maven 部署(nightly 仓库) │ ├── fullDeploy.sh # CI 一键完整发布(构建+测试+部署) │ └── test.sh # 对构建产物运行 Scala 测试 ├── python/ # Python 发布(README 标注为 TBD,目录当前为空) └── website/ # 网站发布(内部另有 README 与部署脚本)

从源码结构看,发布体系刻意将「脚本层」与「基础设施层」分离:ci/publish/只关注发布动作本身,而运行这些动作的 Docker 镜像与依赖安装脚本统一放在 ci/docker(所有发布用 Dockerfile 均以Dockerfile.publish为前缀,如 Dockerfile.publish.test.centos7)。README 同时指出:Python 构建发布当时仍处于 TBD(待定)状态,当前已完整支持的是 Linux 平台上的 Scala 发布。

二、Jenkins 流水线:三阶段并行发布模型

2.1 流水线骨架

ci/publish/Jenkinsfile 定义了发布作业的核心编排。整条流水线由三个顺序阶段组成,每个阶段内部对不同平台做并行处理:

utils.main_wrapper( core_logic: { stage('Build Packages') { parallel toBuild } stage('Test Packages') { parallel toTest } stage('Deploy Packages') { parallel toDeploy } } , failure_handler: { if (currentBuild.result == "FAILURE") { emailext body: 'Generating the nightly maven has failed. ...', subject: '[NIGHTLY MAVEN FAILED] Build ${BUILD_NUMBER}', ...} })
  • Build Packages:构建全部依赖,并产出 Scala 包(scala-package);
  • Test Packages:将上一阶段产物送入测试环境,专门执行制品级测试;
  • Deploy Packages:通过测试的包由对应节点执行部署(mvn deploy到 Maven 仓库)。

三个阶段在宏观上串行(先构建、再测试、后部署),但在每一阶段内部对 CPU/GPU 平台并行。failure_handler表明该作业是nightly maven发布:一旦失败,会通过邮件发送标题为[NIGHTLY MAVEN FAILED]的告警。

2.2 节点与平台映射

流水线先在一个restricted-utility工具节点上加载通用工具类ci/Jenkinsfile_utils.groovy,随后通过utils.assign_node_labels(...)为各平台分配带restricted-前缀的专用节点(restricted-mxnetlinux-cpurestricted-mxnetlinux-gpu-p3等)。核心的平台映射如下:

def nodeMap = ['cpu': NODE_LINUX_CPU, 'gpu': NODE_LINUX_GPU_P3] def scalaOSMap = ['cpu': 'linux-x86_64-cpu', 'gpu': 'linux-x86_64-gpu'] def scalaVariantMap = ['cpu': 'cpu', 'gpu': 'cu92']

其中scalaVariantMap是关键:cpu变体对应纯 CPU 构建,gpu变体对应 CUDA 9.2(cu92),该值会以$mxnet_variant形式传给 Scala 构建脚本。wrapStep封装器还确保每个阶段运行在独立 workspace 中,并设置120 分钟超时max_time = 120)。

2.3 触发机制与受支持测试系统

README 明确说明:该发布作业每 24 小时定时触发一次,运行在 Jenkins 的 restricted(受限)实例上,用于生成 nightly 制品。当前发布制品支持的测试系统包括:

系统说明
Ubuntu 16.04支持发布产物测试
Ubuntu 18.04支持发布产物测试
Cent OS 7支持发布产物测试(构建基准系统)

所有包统一在Cent OS 7 + Developer Toolset 7上构建。Developer Toolset 7 为 CentOS 7 提供GCC 7(含 C++17 支持),使构建出的二进制能兼容 2014 年之后发布的所有主流 Linux 发行版——这与 Python Enhancement Proposal 599(PEP 599,即 manylinux2014 规范)的时间口径一致。这一策略的实质是:在较老的 glibc 系统上构建,获得更低的运行时 glibc 依赖,从而让产物具备更广的发行版兼容面

三、发布用 Docker 与依赖安装

3.1Dockerfile.publish系列镜像

发布相关的 Dockerfile 全部位于 ci/docker,以Dockerfile.publish为前缀。以 Dockerfile.publish.test.centos7 为例,它通过动态ARG BASE_IMAGE(如centos:7nvidia/cuda:10.2-cudnn7-devel-centos7)构造测试镜像,并安装制品测试所需的最小依赖集:

ARG BASE_IMAGE FROM $BASE_IMAGE WORKDIR /work/deps RUN yum -y check-update || true && \ yum -y install epel-release centos-release-scl && \ yum -y install \ make \ # 运行 ci/publish/scala/test.sh 中的测试 gcc \ # 提供 libgomp.so.1(未来可能随 jar 分发而移除) unzip \ # 运行 org.apache.mxnetexamples.neuralstyle.NeuralStyleSuite rh-maven35 && # 运行 ci/publish/scala/test.sh 所需的 Maven yum clean all ENV PYTHONPATH=./python/ WORKDIR /work/mxnet COPY runtime_functions.sh /work/

Dockerfile 中的注释还揭示了各依赖的真实用途:unzip服务于 NeuralStyle 示例测试套件,gcc用于提供 OpenMP 运行时库libgomp.so.1(并注明未来可能改为随 jar 分发)。镜像的基础层配置可通过 docker-compose.yml 中的BASE_IMAGE参数动态指定不同版本组合(如nvidia/cuda:10.1-cudnn8-devel-centos7等 GPU 变体)。

3.2 环境安装脚本

README 指出,创建环境与执行发布的脚本位于ci/docker/install下,并特别提到ubuntu_base.sh用于安装运行已发布包所需的最小依赖。需要说明的是:在当前仓库快照中,ci/docker/install目录实际包含的是 deb_ubuntu_ccache.sh、docker_filepermissions.sh、requirements与 ubuntu_adduser.sh 等文件(ubuntu_base.sh未出现在快照中,可能已随版本演进被调整),因此该目录的职责可概括为:为发布/测试镜像提供最小化、可复现的系统级依赖安装,其中docker_filepermissions.sh还被Dockerfile.publish.test.centos7显式引用以修正工作目录权限。

四、Scala 发布全链路拆解

Scala 发布在 Linux 上已由 Jenkins 完整支持,ci/publish/scala/下的五个脚本构成一条闭环:密钥配置 → 构建 → 测试 → 部署,由fullDeploy.sh一键串起。

4.1fullDeploy.sh:CI 入口,一键完整发布

fullDeploy.sh 是整个流程的编排入口,内容极简但语义清晰:

set -ex ./ci/publish/scala/build.sh ./ci/publish/scala/test.sh ./ci/publish/scala/deploy.sh

它按顺序调用构建、测试、部署三个脚本,与 Jenkinsfile 的三个 stage 一一对应。set -ex保证任何一步失败立即中断,杜绝「带病发布」。

4.2build.sh:静态构建后端 + 生成 Scala 包

build.sh 是「构建」阶段的主执行脚本:

set -ex # MAVEN_PUBLISH_OS_TYPE: linux-x86_64-cpu|linux-x86_64-gpu|osx-x86_64-cpu # export MAVEN_PUBLISH_OS_TYPE=linux-x86_64-cpu source tools/staticbuild/build.sh $mxnet_variant cd scala-package mvn -B deploy -DskipTests=true

它首先sourcetools/staticbuild/build.sh 完成MXNet 后端的静态构建。该静态构建脚本接收<VARIANT> <BLAS>两个位置参数,并导出大量环境变量:

  • VARIANT:由$1转为小写(如cpucu92darwin);
  • PLATFORM:由uname探测(linux/darwin);
  • BLAS:默认open(OpenBLAS);
  • 编译标志统一追加-fPIC -mno-avx,保证产物具备良好的可移植性(不依赖 AVX 指令集);
  • NUM_PROC自动探测 CPU 核数,并行编译。

构建完成后进入scala-package目录执行mvn -B deploy -DskipTests=true:跳过单元测试、先生成并安装 Scala 包,为下一阶段的制品测试做准备。README 对它的定位是「构建后端以及 Scala 包的主可执行文件」,这里mxnet_variant正是来自 Jenkinsfile 中scalaVariantMap的映射值(cpu/cu92)。

4.3buildkey.py:从密钥服务安全装配 Maven 凭据

buildkey.py 负责在发布节点上安全地装配 Maven 与 GPG 凭据,是整个发布链路中唯一接触机密的环节。其工作流程分四步:

  1. 从 AWS Secrets Manager 拉取凭据:通过 boto3 客户端读取四个环境变量指定的密钥——
    • MAVEN_PUBLISH_SECRET_ENDPOINT_URL:Secrets Manager 端点;
    • MAVEN_PUBLISH_SECRET_NAME_CREDENTIALS:存放 Maven 账号/密码/GPG passphrase 的密钥名;
    • MAVEN_PUBLISH_SECRET_NAME_GPG:存放 GPG 私钥(key.asc)的密钥名;
    • DOCKERHUB_SECRET_ENDPOINT_REGION:区域名。 凭据以 JSON 形式返回,包含userpasswordmasterpassgpgPassphrase等字段。
  2. 导入 GPG 密钥:将key.asc写入~/.m2/key.asc,再用gpg2 --batch --yes --passphrase-fd 0 --import以管道方式传入 passphrase 完成导入,避免口令出现在命令行参数中。
  3. 生成加密口令:利用expect脚本自动化执行mvn --encrypt-master-passwordmvn --encrypt-password,把明文口令转为 Maven 加密密文。
  4. 落盘 Maven 配置
    • ~/.m2/settings-security.xml:写入 master 口令;
    • ~/.m2/settings.xml:写入两个 server(apache.snapshots.httpsapache.releases.https,即快照仓库与正式发布仓库)的用户名/加密口令,并配置gpgprofile(gpg.executable=gpg2gpg.passphrasegpg.skip=true)且设为激活 profile。

这套设计的核心价值在于:密钥不落盘于构建脚本,而是按需从云端密钥服务动态注入,且部署结束后会清理全部临时文件(见下文deploy.sh),最大限度降低凭据泄露面。

4.4deploy.sh:GPG 会话配置 + Maven 部署

deploy.sh 是「部署」阶段的执行脚本:

set -ex # On Jenkins, run python script to configure keys if [[ $BUILD_ID ]]; then python3 ci/publish/scala/buildkey.py fi # 配置 gpg-agent 缓存,避免长发布过程中口令失效 mkdir -p ~/.gnupg echo "default-cache-ttl 14400" > ~/.gnupg/gpg-agent.conf echo "max-cache-ttl 14400" >> ~/.gnupg/gpg-agent.conf echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf echo "pinentry-mode loopback" >> ~/.gnupg/gpg-agent.conf export GPG_TTY=$(tty) cd scala-package mvn -B deploy -Pnightly # On Jenkins, clear all password .xml files, exp files, and gpg key files if [[ $BUILD_ID ]]; then rm -rf ~/.m2/*.xml ~/.m2/key.asc ~/.m2/*.exp fi

几个值得注意的实现细节:

  • BUILD_ID是 Jenkins 环境标志:只有在 CI(Jenkins)环境中才执行密钥装配(buildkey.py)与部署后的凭据清理,本地手动运行时跳过,避免误删开发者本机配置;
  • gpg-agent 缓存调整:将默认缓存 TTL 提升到14400 秒(4 小时),并启用allow-loopback-pinentrypinentry-mode loopback,保证长耗时构建期间 GPG 签名不因口令过期而中断;
  • mvn -B deploy -Pnightly:激活nightlyprofile,将制品部署到 nightly(快照)Maven 仓库;
  • 部署后强制清理:删除~/.m2下所有*.xml*.asc*.exp临时文件,确保口令、密钥不残留。

4.5test.sh:制品级测试(含 GPU 分支)

test.sh 对应「测试」阶段,对已构建的 Scala 包运行集成测试:

set -ex if [ -z "$JAVA_HOME" ]; then source /etc/profile fi cd scala-package/packageTest if [[ $mxnet_variant == cu* ]]; then export SCALA_TEST_ON_GPU=1 make testlocal USE_CUDA=1 CI=1 else make testlocal CI=1 fi

脚本通过$mxnet_variant判断运行环境:凡是cu*前缀的变体(如cu92)即视为 GPU 构建,设置SCALA_TEST_ON_GPU=1并以USE_CUDA=1运行make testlocal;纯 CPU 变体则直接make testlocal CI=1CI=1标志使测试套件以 CI 模式执行(更严格的断言与退出码语义),testlocal目标则保证测试在本地目录运行、不污染外部环境。这与Dockerfile.publish.test.centos7中安装makerh-maven35unzip(NeuralStyle 示例套件需要)的依赖选择相互印证。

4.6 环境变量速查表

综合以上脚本,Scala 发布链路涉及的关键环境变量汇总如下:

环境变量取值示例作用
mxnet_variantcpu/cu92构建变体,决定静态编译目标与测试是否走 GPU 分支(Jenkinsfile 的scalaVariantMap注入)
MAVEN_PUBLISH_OS_TYPElinux-x86_64-cpu/linux-x86_64-gpu/osx-x86_64-cpu声明发布产物的操作系统与硬件类型(build.sh 头部注释说明)
MAVEN_PUBLISH_SECRET_ENDPOINT_URLSecrets Manager 端点buildkey.py 拉取密钥的端点
MAVEN_PUBLISH_SECRET_NAME_CREDENTIALS密钥名存放 Maven 账号/口令/GPG passphrase 的 Secret
MAVEN_PUBLISH_SECRET_NAME_GPG密钥名存放 GPG 私钥的 Secret
DOCKERHUB_SECRET_ENDPOINT_REGIONAWS 区域Secrets Manager 客户端区域
BUILD_IDJenkins 注入判定是否处于 CI 环境,控制密钥装配与清理逻辑
JAVA_HOMEJDK 路径test.sh 中若无 JAVA_HOME 则 source/etc/profile恢复环境

五、Python 发布与 Website 发布的现状

README 明确注明Python 构建发布仍为 TBD。对应地,ci/publish/python/目录在当前仓库中为空,表明 Python 制品的自动发布尚未接入这套流水线;Python 侧用户仍需依赖 tools/pip 等目录下的构建辅助工具人工处理。

至于网站发布,ci/publish/website/README.md仅给出指向 MXNet Developer Wiki(Building the New Website)的指引,仓库内该目录同时保留了 deploy.sh、beta-deploy.sh、publish_artifacts.sh 三个脚本,与 Jenkins 侧的网站发布作业(Jenkinsfile_website_*系列,见 ci/jenkins)配合使用,负责站点与文档制品的发布。

六、总结:一套可复制的「制品发布」参考范式

MXNet 的发布体系(ci/publish)提供了一套极具参考价值的制品发布范式,其要点可归纳为:

  1. 流水线分层:构建 → 测试 → 部署三阶段严格串行、阶段内平台并行,配合 120 分钟超时与失败邮件告警,保证发布过程可观测、可止损;
  2. 兼容性优先:统一在 CentOS 7 + GCC 7(C++17)上构建,对齐 PEP 599 的时间口径,用静态链接(tools/staticbuild/build.sh-fPIC -mno-avx)换取跨发行版兼容;
  3. 密钥安全:凭据全部动态注入(AWS Secrets Manager →buildkey.py→ Maven 加密配置),GPG 密钥与口令文件在部署完成后立即清理;
  4. 环境一致:发布与测试环境全部容器化(Dockerfile.publish*+docker-compose.ymlBASE_IMAGE参数化),依赖最小化且用途在注释中逐一说明;
  5. 变体驱动:以mxnet_variantcpu/cu92)单一变量贯穿构建、测试(GPU 分支)与部署,逻辑收敛、易于扩展新变体。

对于需要构建自己深度学习框架发布链路的团队,这套「受限节点 + 静态构建 + 密钥服务 + 制品测试 + nightly 部署」的组合,是一份可以直接借鉴的工程蓝图。相关全部源码均可从 ci/publish 与 ci/docker 目录继续深入查阅。

【免费下载链接】mxnetLightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more项目地址: https://gitcode.com/gh_mirrors/mx/mxnet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 9:06:27

向日葵远程听不到声音?从音频传输原理到配置排查全指南

先说个我自己的经历。去年年底我帮一个朋友远程调试家里的电脑&#xff0c;他装的是向日葵远程控制&#xff0c;配置好了识别码和密码&#xff0c;连上之后能看着桌面操作&#xff0c;但只要一打开视频网站&#xff0c;画面流畅&#xff0c;声音却死活传不过来。他在那头打字问…

作者头像 李华
网站建设 2026/9/20 9:06:17

大模型训练性能瓶颈如何定位?用Profile揪出GPU利用率低的真凶

训练一个大模型&#xff0c;跑了半天发现 loss 不掉&#xff0c;或者 GPU 利用率一直上不去&#xff0c;卡在某个数值下不来&#xff0c;这种体验我相信做训练的人都不会陌生。很多时候大家的第一反应是“显卡不够好”“显存不够大”&#xff0c;但真正用 Profile 扫过一遍之后…

作者头像 李华
网站建设 2026/9/20 9:05:04

Claude Pro订阅全攻略:价格、支付方式与高效使用技巧详解

1. 先聊清楚&#xff1a;Claude Pro 到底解决什么问题我最初接触 Claude Pro&#xff0c;纯粹是免费版不够用了。平时写代码、做方案、整理文档&#xff0c;每天都得跟大模型打交道&#xff0c;免费额度用得快&#xff0c;一旦触发限流就得停下来等窗口。这种断断续续的体验&am…

作者头像 李华
网站建设 2026/9/20 9:04:16

C++在实时系统中的性能优化与架构设计

1. 为什么C在实时数据处理中不可替代在金融交易系统里&#xff0c;每毫秒的延迟可能导致数百万的损失&#xff1b;在自动驾驶领域&#xff0c;30毫秒的决策延迟就能让车辆多冲出1米距离。这就是为什么华尔街高频交易公司和特斯拉的自动驾驶团队都在核心路径上使用C——当纳秒级…

作者头像 李华
网站建设 2026/9/20 8:59:43

chezmoi `azureKeyVault` 模板函数:从 Azure Key Vault 安全注入机密

开发工具CLI配置管理 【免费下载链接】chezmoi Manage your dotfiles across multiple diverse machines, securely. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ch/chezmoi 点击查看 免费下载 azureKeyVault 是 chezmoi 内置的模板函数&#xff0c;用于在渲染模板…

作者头像 李华