Jenkins磁盘空间优化:Artifact Cleanup Plugin自动清理归档文件实战
1. 项目概述与核心价值
如果你是一位在 Jenkins 持续集成流水线中,长期与构建产物(Artifacts)打交道的工程师,那么你一定对“归档”这个动作又爱又恨。爱的是,它能将构建生成的 JAR、WAR、ZIP 等文件安全地保存下来,供后续部署、测试或审计使用;恨的是,随着项目迭代,这些归档文件会像滚雪球一样,迅速吞噬掉 Jenkins Master 宝贵的磁盘空间。手动清理?不仅繁琐,还容易误删重要历史构建。放任不管?最终的结果往往是 Jenkins 因磁盘写满而宕机,整个 CI/CD 流程陷入瘫痪。
今天要聊的这个 Jenkins 插件——mvanhorn/paperclip-plugin-acp,就是专门为解决这个“甜蜜的负担”而生的。它的核心功能,是为 Jenkins 内置的“归档构建产物”功能(通常由archiveArtifacts步骤实现)增加了一个自动化的、基于规则的清理策略。你可以把它理解为 Jenkins 归档文件的“智能管家”,它允许你为每个 Job 或整个系统配置一套规则,比如“只保留最近10次成功构建的产物”,或者“删除所有超过30天的构建产物”。一旦配置好,这个插件就会在后台默默工作,自动帮你清理掉那些不再需要的旧文件,从而从根本上解决磁盘空间管理的问题。
这个插件在社区中的正式名称是 “Artifact Cleanup Plugin”,缩写为 ACP。它并非 Jenkins 官方的核心插件,而是由社区开发者维护的一个开源项目。虽然名气可能不如一些大牌插件响亮,但对于那些构建频繁、产物体积庞大的团队来说,它几乎是一个“必需品”。我最初接触它,就是因为团队的一个微服务项目,每次构建都会生成一个近 200MB 的 Docker 镜像 Tar 包,一周下来,Jenkins Master 的硬盘就亮起了红灯。在尝试了手动写脚本、定时任务等多种方案后,最终发现 ACP 插件是最优雅、最集成化的解决方案。
2. 插件核心机制与工作原理拆解
要理解 ACP 插件如何工作,我们首先得回顾一下 Jenkins 原生的归档机制。当你在 Pipeline 脚本中写下archiveArtifacts ‘target/*.jar’时,Jenkins 会做两件事:一是将匹配的文件复制到 Jenkins Master 上一个特定的目录结构下(通常是$JENKINS_HOME/jobs/<job_name>/builds/<build_number>/archive/);二是在该次构建的页面中,生成一个可供下载的链接。这些文件的生命周期,默认是与构建记录绑定的——只有当你手动删除某次构建历史时,对应的归档文件才会被清除。
ACP 插件介入的,正是这个生命周期管理环节。它没有改变 Jenkins 归档文件的行为和存储位置,而是增加了一个“后置处理器”。这个处理器的触发时机非常关键:在每次构建完成之后。无论是构建成功、失败还是中止,只要构建动作结束,ACP 插件就会被激活,并根据你预先配置好的策略,对当前 Job 的历史构建归档文件进行一次扫描和清理。
2.1 策略引擎:规则如何被定义与执行
插件的核心是一个策略引擎。它允许你定义多种清理规则(Rule),这些规则可以组合使用。最常见的规则有以下几类:
数量型规则:这是最直观的策略。例如,“保留最近 N 次构建的产物”。这里的“构建”可以细分为“仅保留最近 N 次成功构建”、“仅保留最近 N 次稳定构建”(成功且测试通过)等。插件会按照构建号从大到小(即从新到旧)排序,只保留满足条件的最新 N 次构建的归档,其余的全部删除。
时间型规则:基于文件存在的时间长度。例如,“删除所有超过 N 天的构建产物”。插件会计算归档文件的最后修改时间(或根据构建时间推算),一旦超过设定的天数阈值,就会将其清理。这种规则非常适合用于清理那些“可能再也不会用到”的远古产物。
状态过滤型规则:这是 ACP 插件比较灵活的一点。你可以指定规则只针对特定构建状态的产物生效。比如,你可以配置一个规则:“对于所有失败的构建,立即删除其归档产物”。这基于一个常见的假设:失败构建的产物通常没有保留价值,反而占据了空间。当然,对于需要调试失败构建的团队,这条规则就需要慎用。
这些规则可以在两个层级进行配置:
- 系统全局配置:在 Jenkins 的 “Manage Jenkins” -> “Configure System” 页面中,可以找到 ACP 插件的配置区域。在这里设置的规则是默认规则,会对所有没有单独配置的 Job 生效。
- 单个 Job 配置:在 Freestyle 项目或 Pipeline 项目的配置页面中,通常可以找到 “Discard Old Builds” 或类似的区块,里面集成了 ACP 的规则配置。在这里设置的规则优先级高于全局规则,允许你为特定的、产物巨大的 Job 定制更激进的清理策略。
2.2 清理过程的安全性与原子性
作为直接删除文件的插件,其操作的安全性至关重要。ACP 插件在设计上考虑了以下几点:
- 基于构建记录的清理:插件是依据 Jenkins 的构建记录来决定删除哪些归档目录的,而不是简单地在文件系统上做模式匹配。这避免了误删其他插件或系统产生的、同样存放在
archive目录下的重要文件。 - 原子操作与日志记录:每次清理动作都会在对应构建的控制台输出日志或系统日志中留下记录,明确列出了被删除的文件路径。这为问题追溯提供了依据。
- 不影响进行中的构建:清理动作只针对已完成的构建,绝不会干扰正在运行的构建所产生的临时文件或归档过程。
理解了这个工作原理,我们就能明白,ACP 插件不是一个主动监控磁盘使用率的“看门狗”,而是一个基于事件的“清洁工”。它的效率取决于构建发生的频率。对于一天构建数十次的活跃项目,它能非常及时地维持空间整洁;对于几天才构建一次的项目,它可能无法应对单次构建产物就塞满磁盘的极端情况,这时就需要结合其他磁盘监控手段。
3. 插件安装与多场景配置实战
了解了原理,接下来我们进入实战环节。我将从安装开始,带你一步步配置 ACP 插件,并针对几种典型场景给出具体的配置方案。
3.1 插件安装与基础检查
安装 Jenkins 插件通常有两种方式:通过 Web 管理界面,或通过 Jenkins 的 CLI 工具。对于 ACP 插件,我们采用最通用的 Web 界面安装。
- 登录你的 Jenkins 管理后台,进入“Manage Jenkins” -> “Manage Plugins”。
- 切换到“Available”标签页。
- 在右上角的搜索框中输入“Artifact Cleanup”或“ACP”。你应该能找到名为 “Artifact Cleanup Plugin” 的插件,其插件 ID 通常就是
artifact-cleanup或显示为来自mvanhorn。 - 勾选该插件,点击页面底部的“Install without restart”或“Download now and install after restart”。建议选择不重启安装,如果安装后提示需要重启,再进行重启操作。
安装完成后,需要进行一个简单的验证:
- 进入任意一个 Freestyle 类型 Job 的配置页面。
- 滚动查找,你应该能看到一个名为“Discard Old Builds”的选项(对于较新的 Jenkins 版本和插件版本,这个选项可能被整合在构建后操作或单独的配置区块中)。勾选它,如果下面出现了关于清理构建产物(Artifacts)的详细规则配置项,并且有 “Artifact Cleanup” 相关的字样,就说明插件安装并启用成功了。
注意:对于 Pipeline 项目(Jenkinsfile),配置方式有所不同,我们会在后面专门讲解。插件安装后,系统全局配置默认可能是空的,即没有任何自动清理规则,需要你手动去设置。
3.2 全局策略配置:为所有Job设定安全基线
首先,我们来建立一个全局安全基线。这个策略应该相对保守,目的是防止一些被遗忘的、没有单独配置的 Job 无限度地占用空间。
进入“Manage Jenkins” -> “Configure System”,页面滚动到最下方,找到“Artifact Cleanup”配置区域(如果找不到,可能是插件版本或 Jenkins 主题问题,可以尝试在搜索框输入 “cleanup” 快速定位)。
这里你会看到可以添加多条规则。我们点击“Add”按钮,添加一条基础规则:
- 规则类型:选择
Keep the last X builds artifacts(保留最近 X 次构建的产物)。 - X 的值:填入一个较大的数字,例如
50。这意味着任何 Job,只要没有单独配置,都会自动保留最近 50 次构建的归档文件,更早的会被自动删除。 - 仅针对成功构建:通常,我会勾选
Apply to successful builds only。这样,失败构建的归档不受此规则限制,便于后续排查问题。失败构建的清理,我们可以用另一条更激进的规则,或者交给 Job 自身配置。
这样一条全局规则,对于大多数中小型项目来说已经足够。它保证了磁盘空间不会因为构建次数的单纯累积而被耗尽,同时也保留了足够的历史记录用于回滚和审计。
3.3 单Job精细配置:应对高负载与特殊需求
全局规则是保底策略,对于“重点户”,我们需要进行单独配置。这里分几种场景:
场景一:高频微服务构建假设有一个每日构建上百次的微服务 API 项目,每次构建产生一个 50MB 的 JAR 包。
- 策略:在该 Job 的配置页面,找到 “Discard Old Builds” 或 “Artifact Cleanup” 设置。
- 规则1:
Keep the last X builds artifacts,X=20, 不勾选“仅成功构建”。因为构建频率太高,保留20次已经包含了最近一小段时间的所有状态,便于追踪问题。 - 规则2:
Delete artifacts older than X days,X=3。这是一条时间兜底规则。即使某天构建次数没到20次,超过3天的产物也一律清除。因为对于快速迭代的微服务,3天前的版本几乎肯定已经被部署和替换掉了。
场景二:产出大型安装包的项目假设一个桌面客户端项目,每周发布一个 Alpha 版本,每次构建产生一个 1.5GB 的完整安装包。
- 策略:空间占用是主要矛盾,需要极其节俭。
- 规则1:
Keep the last X builds artifacts,X=5, 勾选Apply to successful builds only。只保留最近5个成功的安装包。 - 规则2:
Delete artifacts for failed builds immediately。立即删除所有失败构建的产物,因为失败构建产生的 1.5GB 文件纯属浪费空间。 - 规则3:
Delete artifacts older than X days,X=7。双重保障,超过一周的即使没满5个也删除。
场景四:Pipeline 项目配置在 Jenkinsfile 中配置 ACP,需要使用buildDiscarder指令和artifactCleanup属性。这提供了代码化、版本化的配置管理。
pipeline { agent any options { // 使用 buildDiscarder 来配置日志和产物的保留策略 buildDiscarder( logRotator( numToKeepStr: '30', // 保留最近30次构建的日志 artifactNumToKeepStr: '10' // 保留最近10次构建的产物 ) ) // 更精细的清理规则需要使用插件的 DSL // 注意:插件的 DSL 语法可能随版本变化,以下为常见写法 // 有些版本可能需要使用 `cleanup` 或 `artifactCleanup` 指令 } post { always { // 另一种方式是在 post 阶段使用 `artifactCleanup` 步骤(如果插件提供) // 示例(请查阅插件最新文档确认语法): // artifactCleanup( // rules: [ // [strategy: 'KEEP_LAST_X', number: 10], // [strategy: 'DELETE_OLDER_THAN', days: 30] // ] // ) // 目前更稳定通用的方式仍是依赖上述 `buildDiscarder` 中的 `artifactNumToKeepStr`。 // 对于复杂规则,可能仍需在 Job 的 Web 界面配置。 } } stages { stage('Build') { steps { sh 'mvn clean package' archiveArtifacts artifacts: 'target/*.jar', fingerprint: true } } } }实操心得:在 Pipeline 中,
buildDiscarder的artifactNumToKeepStr是最直接有效的标准方式。对于 ACP 插件更高级的时间规则、状态过滤规则,在 Jenkinsfile 中的原生 DSL 支持可能不完善或随版本变动。一个可靠的实践是:在 Pipeline 中只使用基础的artifactNumToKeepStr控制数量,如果需要复杂的时间策略,则在 Jenkins Master 上为该 Pipeline Job 通过 Web 界面进行配置。虽然混合配置稍显不纯粹,但在稳定性上更有保障。
4. 高级策略与性能调优指南
当你在生产环境大规模部署 ACP 插件后,可能会遇到一些复杂情况和性能考量。这一章我们深入探讨高级配置和优化技巧。
4.1 规则冲突与优先级解析
当你为同一个 Job 配置了多条规则时,比如“保留最近10次构建”和“删除超过7天的构建”,插件是如何工作的?它的执行逻辑是“或”关系。也就是说,只要某次构建的归档文件违反了任何一条规则,它就会被标记为待删除。
举个例子:你配置了规则A(保留最近10次)和规则B(删除7天前的)。假设现在有15次历史构建(#1到#15)。
- 根据规则A,构建#6到#15被保留,#1到#5被标记删除。
- 根据规则B,假设构建#11(8天前)也被标记删除。
- 最终,构建#1到#5以及#11的归档文件会被删除。构建#6到#10(虽然超过7天但属于最近10次中的前5次)和#12到#15会被保留。
这种“或”逻辑意味着规则是叠加生效的,清理会变得更激进。在配置时,你需要理解这种叠加效应,避免因规则过多过严而导致想保留的构建被意外清理。一个建议是:从简开始。通常,一条基于数量的规则和一条基于时间的兜底规则组合,已经能满足99%的需求。
4.2 处理特殊构建与指纹关联
Jenkins 有一个重要的特性叫“指纹”(Fingerprinting),用于跟踪文件的跨构建使用情况。例如,一个下游构建项目依赖了上游构建产出的某个 JAR 包,Jenkins 会为这个 JAR 文件生成一个唯一的指纹。当你尝试删除一个被其他构建指纹关联的归档文件时,Jenkins 默认会阻止删除,以防止破坏依赖关系。
ACP 插件在处理这类文件时,行为取决于 Jenkins 的底层逻辑。在大多数情况下,如果插件尝试删除一个被指纹关联的文件,这个删除操作会失败,并在日志中留下警告信息。这其实是一个安全特性。
但对于某些特殊情况,比如你明确知道所有下游构建都已不再需要这些历史文件,或者你使用制品库(如 Nexus、Artifactory)来管理正式依赖,Jenkins 内部的指纹只是冗余信息时,你可能希望强制清理。
警告:强制清理带指纹的归档文件是一个危险操作。ACP 插件本身不提供“强制忽略指纹”的选项。如果你确实需要这样做,可能需要在执行清理前,通过脚本或管理命令先清除相关的指纹记录,但这超出了插件的范畴,且极易出错,不建议在生产环境使用。正确的做法是,将正式发布的制品推送到专门的制品库,Jenkins 仅作为临时归档和测试使用,这样就不需要长期保留关联指纹。
4.3 监控、日志与故障排查
ACP 插件运行在后台,如何确认它工作正常?又如何在出现问题时进行排查?
1. 查看操作日志:最直接的日志位于每个构建的“Console Output”末尾。在构建完成后,如果 ACP 插件执行了清理动作,你会看到类似这样的记录:
[Artifact Cleanup] Starting cleanup for job ‘your-job-name’... [Artifact Cleanup] Applying rule ‘Keep last 10 builds artifacts’. [Artifact Cleanup] Deleting artifacts for build #123 ... [Artifact Cleanup] Cleanup completed. Freed approximately 1.2 GB.如果看不到这些日志,首先检查插件的全局和 Job 配置是否已启用并保存。其次,可以调整 Jenkins 的日志级别。
2. 调整日志级别:进入“Manage Jenkins” -> “System Log” -> “Log Levels”。 添加一个新的日志记录器,名称填入com.thoughtworks.jenkins.plugins.artifactcleanup(这是插件常见的包名,如果不对,请参考插件官方文档或查看已存在的类似记录器)。 将日志级别从INFO提升到FINE或FINEST。这样,在$JENKINS_HOME/logs目录下的相关日志文件中,你就会看到插件更详细的决策过程,例如每条规则如何评估每个构建。
3. 磁盘空间监控:插件本身不提供磁盘空间监控告警。你需要结合操作系统层面的监控(如 Zabbix, Prometheus + Node Exporter)或 Jenkins 的其他插件(如 “Disk Usage Plugin”)来监控$JENKINS_HOME的磁盘使用量。设置一个预警阈值(例如 80%),当触发预警时,再检查是否是 ACP 规则配置得不够激进,或者是否有某些 Job 未应用规则。
4. 常见问题排查表:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 构建产物完全没有被清理 | 1. 插件未正确安装或启用。 2. 全局和Job均未配置任何规则。 3. 规则配置后未保存。 | 1. 检查“Manage Plugins”中插件是否已安装且启用。 2. 检查系统配置和具体Job配置,确保至少有一条规则被添加并保存。 3. 查看构建日志,确认是否有清理日志输出。 |
| 部分预期外的构建产物被保留 | 规则之间存在“或”逻辑,导致满足任一条件的构建就被保留。 | 复核所有配置的规则。计算一下,在“保留最近N次”和“保留M天内”的规则叠加下,实际保留的构建数量可能多于你的预期。 |
| 控制台日志显示“跳过清理,因为构建正在运行” | 插件被配置在了构建过程中触发,而非构建后。 | ACP 设计为构建后清理。检查是否有其他插件或脚本错误地调用了它。确保配置在构建后步骤或作为Post-build action。 |
| 磁盘空间仍在持续增长 | 1. 归档的文件类型或路径未被正确纳入清理范围(如使用了自定义归档路径)。 2. 存在非归档文件占用了大量空间(如工作空间未清理、日志文件)。 | 1. 确认archiveArtifacts步骤匹配的文件确实被归档到了标准位置。2. 使用 du -sh $JENKINS_HOME/*命令分析磁盘占用大头,配合 “Disk Usage Plugin” 定位问题。同时考虑启用“工作空间清理”策略。 |
4.4 与“丢弃旧构建”功能的协同
Jenkins 本身有一个“Discard Old Builds”(丢弃旧构建)功能,它可以删除构建的历史记录(包括控制台日志、构建变量等信息)。ACP 插件专注于清理构建产物(archive/目录下的文件),而“丢弃旧构建”功能则清理构建的元数据。
这两者可以且应该配合使用:
- “丢弃旧构建”:设置一个相对宽松的规则,比如保留100次构建记录。这保证了 Jenkins 界面上的构建历史、趋势图、测试报告等有足够的数据。
- ACP插件:设置一个相对严格的规则,比如保留最近20次构建的产物。这解决了磁盘空间的核心压力,因为归档的二进制文件通常是空间占用主体。
这样配置的好处是,你既保留了较长的构建历史用于审计和分析,又避免了庞大的归档文件拖垮磁盘。两者通过不同的数字进行控制,实现了空间和信息的平衡管理。
5. 生产环境部署建议与避坑指南
将 ACP 插件部署到团队的生产 Jenkins 环境,不仅仅是一个技术动作,更是一个需要沟通和规划的管理过程。以下是我从多次部署中总结的经验和教训。
5.1 制定清晰的清理策略
在动手配置之前,先和团队达成共识:
- 保留期限:不同类型的项目,产物保留的需求不同。核心库的发布版本可能需要保留数月,而前端项目的每日构建可能只需保留几天。制定一个简单的分类标准(如:发布版本保留30天,快照构建保留7天)。
- 失败构建处理:团队是否需要保留失败构建的产物用于调试?如果不需要,配置立即删除可以节省大量空间(特别是编译失败常产生大量中间文件)。
- 审计要求:公司或行业是否有合规性要求,规定构建产物必须保留一定时长?确保你的策略符合这些要求。
5.2 分阶段灰度实施
切忌一刀切地在所有项目上立即应用激进的清理规则。建议分三步走:
- 监控阶段:先在所有项目上安装插件,但不配置任何清理规则,或者只配置一条非常保守的全局规则(如保留200次)。运行一两周,通过插件日志或磁盘分析,了解各个 Job 的产物生成速度和空间占用情况。找出“空间大户”。
- 试点阶段:挑选2-3个非核心的“空间大户”项目,应用设计好的清理规则。密切观察一段时间,确认规则按预期工作,没有误删团队需要的历史文件。同时收集项目组成员的反馈。
- 全面推广阶段:根据试点经验,微调规则模板。然后,通过 Jenkins 的脚本命令行(Script Console)或 Configuration as Code (JCasC) 工具,批量、自动化地将规则应用到所有目标 Job 上。对于 Pipeline 项目,推动在 Jenkinsfile 中固化规则。
5.3 关键的避坑点
- 坑点一:误删“发布”产物。有些团队可能直接将 Jenkins 归档的产物用于生产部署。如果 ACP 规则删除了这些文件,会导致部署失败。绝对禁止将 Jenkins 作为生产制品库。必须使用专业的制品库管理工具(如 Nexus, Artifactory, Container Registry)。Jenkins 只应保留用于即时测试和中间验证的临时产物。
- 坑点二:规则未生效。最常见的原因是配置在了错误的层级。记住:Job 级别的配置优先级高于全局配置。如果你在 Job 里勾选了“Discard Old Builds”但没配 ACP 规则,它可能使用的是 Jenkins 自带的仅删除元数据的策略。务必确认 ACP 的具体规则条目被添加并保存。
- 坑点三:清理时机带来的“惊群效应”。如果 Jenkins 上同时有数百个 Job 在短时间内密集完成构建,ACP 插件的清理任务可能会集中触发,导致磁盘 I/O 瞬间飙升。虽然这种情况不常见,但对于超大型实例,可以考虑在 Jenkins 系统配置中,为 ACP 插件的清理任务设置一个随机延迟执行,或者将其安排在系统负载较低的时段(但这需要修改插件代码或借助外部调度,非开箱即用功能)。
- 坑点四:符号链接(Symlink)问题。如果
archiveArtifacts步骤归档了指向工作空间外部的符号链接,ACP 插件在清理时,默认只会删除符号链接文件本身,而不会删除链接指向的真实文件。这可能导致空间并未真正释放。解决方案是,在构建脚本中避免归档符号链接,或者使用followSymlinks: false参数明确不跟踪链接(但这样归档的文件可能是无效的)。最好的实践是归档实际复制的文件。
5.4 作为代码的配置管理
对于追求运维自动化和版本控制的团队,建议将 ACP 的配置代码化。
- 对于 Pipeline:如前所述,尽可能使用
buildDiscarder指令在 Jenkinsfile 中定义规则。 - 对于传统 Job:可以使用Jenkins Configuration as Code (JCasC)插件。通过 YAML 文件定义全局和 Job 的清理策略。这样,所有的配置变更都可以通过 Git 进行版本管理、评审和回滚,实现了配置的可靠性和可追溯性。
# 示例 JCasC 配置片段 (具体语法需参考插件文档和JCasC支持程度) jenkins: systemMessage: “My Jenkins with ACP” # ... 其他配置 # 全局 ACP 规则可能通过特定配置项设置,或通过Job模板定义虽然初始设置有一定复杂度,但一旦落地,它将极大简化大规模 Jenkins 实例的配置管理工作。
ACP 插件就像一位沉默可靠的仓库管理员,在你专注于构建和交付价值时,它默默地维护着后台的秩序与整洁。一个配置得当的 Jenkins 环境,加上合理的归档清理策略,是 CI/CD 流水线稳定、高效运行的重要基石。
