你是否也经历过这样的场景:某天早上,你正悠闲地喝着咖啡,准备开始一天的工作,突然收到告警邮件或监控提示:“Jenkins主节点磁盘使用率超过90%”!顿时心头一紧。登录服务器一看,$JENKINS_HOME/jobs/your-project/builds/ 目录下,密密麻麻全是构建历史的文件夹,从 #1 到 #10086,每个都占据着宝贵的磁盘空间。这些历史记录,有些是几周甚至几个月前的,除了占地方,似乎已经失去了大部分参考价值。
这就像你家的储物间,东西只进不出,总有一天会塞满。今天,我们就来当一次“整理大师”,系统地探讨如何为Jenkins制定一套优雅的“大扫除”方案,既释放磁盘空间,又能保留有价值的历史信息。
一、问题根源:为什么Jenkins会“吃”掉那么多空间?
在动手清理之前,我们得先明白这些空间都被谁占用了。Jenkins的构建历史不仅仅是控制台日志文本那么简单,它是一个完整的“构建档案”。一次典型的构建可能会产生:
- 构建产物:比如你编译生成的JAR包、WAR包、Docker镜像tar文件等。这是通常的“空间大户”。
- 工作空间快照:如果你配置了“归档工作空间”,Jenkins会把整个构建时的工作目录打包保存下来,以便后续排查问题。这个操作非常消耗空间。
- 控制台日志:每一次构建的完整输出日志。日积月累,体积也不容小觑。
- 测试报告与覆盖率文件:生成的HTML、XML格式的报告。
- 插件数据:一些插件(如Pipeline历史、凭证记录等)也会将数据存储在构建目录下。
默认情况下,Jenkins会永久保留所有构建历史,因为它认为每一次构建都可能有回溯价值。但在资源有限的实际生产环境中,我们必须做出取舍,制定一个自动化的清理策略。
二、核心武器:Jenkins自带的“磁盘空间清理”插件
Jenkins社区提供了强大的官方插件来应对这个问题,最核心的就是 Disk-Clean Plugin。它允许我们为每个Job配置灵活的清理策略,决定保留什么、删除什么。
技术栈声明:本文所有示例均基于 Jenkins Pipeline (Declarative Syntax)。
这个插件主要通过 cleanWs() 和 deleteDir() 等指令,以及在Job配置中设置策略来工作。让我们先看一个最基础的在Pipeline脚本中清理工作空间的例子。
// 技术栈:Jenkins Pipeline (Declarative Syntax)
pipeline {
agent any
stages {
stage('构建') {
steps {
// 模拟构建过程,生成一些文件
sh '''
echo "模拟编译..."
mkdir -p target
dd if=/dev/zero of=target/big-dummy-file.bin bs=1M count=50
echo "构建产物已生成。"
'''
}
}
stage('清理工作空间') {
steps {
// 使用 cleanWs 插件清理当前构建的工作空间
cleanWs(
cleanWhenAborted: true, // 当构建被中止时也清理
cleanWhenFailure: true, // 当构建失败时也清理
cleanWhenNotBuilt: true, // 当构建未执行时也清理
cleanWhenSuccess: true, // 当构建成功时也清理
cleanWhenUnstable: true, // 当构建不稳定时也清理
deleteDirs: true, // 删除整个目录,而不仅仅是内容
// 可以设置排除模式,不删除某些重要文件
patterns: [
[pattern: 'target/*.jar', type: 'INCLUDE'] // 例如,保留所有的JAR包
]
)
// 注意:cleanWs() 主要清理的是本次构建的工作区(workspace)。
// 它不会删除构建历史(即 /builds/ 目录下的内容)。
}
}
}
}
注释:这个示例展示了在Pipeline的某个阶段结束后,立即清理工作空间。cleanWs() 功能强大,可以精细控制在不同构建状态下的清理行为,并支持通配符模式来保留关键文件。但请记住,它清理的是 workspace@tmp 之类的临时工作目录,对于已经归档到构建历史目录里的产物,它无能为力。
三、构建历史管理:制定你的保留策略
清理工作空间是“节流”,而管理构建历史才是“开源”的关键。我们需要告诉Jenkins:“嘿,别把所有东西都当宝贝存着,按我的规则来。”
这主要通过在Pipeline中配置 options 块,或者直接在自由风格Job的配置页面里设置。
策略一:按数量保留
这是最直接的方式,比如“只保留最近30次构建”。
// 技术栈:Jenkins Pipeline (Declarative Syntax)
pipeline {
agent any
// 在options中定义构建历史保留策略
options {
// 保留最近10次的构建历史记录
buildDiscarder(logRotator(numToKeepStr: '10'))
// 你也可以同时设置按天数保留,Jenkins会取两者中最严格的条件执行
// buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '7'))
}
stages {
stage('示例') {
steps {
echo "这个Job只会保留最近10次构建的历史记录和产物。"
}
}
}
}
注释:logRotator 是核心参数。numToKeepStr 定义了保留的构建个数。Jenkins会自动删除更早的构建,包括其对应的控制台日志、归档产物等所有数据。
策略二:按天数保留
适合那些构建频率不高,但需要按周期清理的场景,比如“只保留过去30天内的构建”。
// 技术栈:Jenkins Pipeline (Declarative Syntax)
pipeline {
agent any
options {
// 只保留最近7天内的构建历史
buildDiscarder(logRotator(daysToKeepStr: '7'))
// 同时,最多只保留20个,即使都在7天内
// buildDiscarder(logRotator(daysToKeepStr: '7', artifactDaysToKeepStr: '3', artifactNumToKeepStr: '5'))
}
stages {
stage('示例') {
steps {
echo "这个Job只会保留7天内的构建记录。"
}
}
}
}
注释:daysToKeepStr 指定了构建记录本身保留的天数。更有用的是 artifactDaysToKeepStr 和 artifactNumToKeepStr,它们可以单独控制构建产物的保留策略。例如,你可以让构建记录保留30天,但构建产物只保留7天或最新的5个,这能极大节省空间,因为产物通常是最大的。
策略三:高级清理与脚本化策略
对于更复杂的需求,比如只想清理特定分支的构建,或者根据构建状态(仅成功/仅失败)来清理,我们可以结合 script 块和Jenkins的API。
// 技术栈:Jenkins Pipeline (Declarative Syntax)
pipeline {
agent any
parameters {
choice(name: 'BRANCH_TO_CLEAN', choices: ['feature/*', 'hotfix/*', 'develop'], description: '选择要清理历史的分支模式')
}
stages {
stage('清理旧分支构建') {
steps {
script {
// 这是一个示例性脚本,实际使用可能需要根据你的多分支Pipeline结构调整
def jobName = env.JOB_NAME // 当前任务名
def maxAge = 7 // 保留天数
def branchPattern = params.BANCH_TO_CLEAN
echo "开始清理任务 ${jobName} 中,分支模式为 ${branchPattern},超过 ${maxAge} 天的构建..."
// 注意:直接操作Jenkins内部API删除构建需要管理员权限,且需谨慎。
// 更常见的做法是通过调用 Jenkins CLI 或使用 `buildDiscarder` 在Job层面配置。
// 此处示意逻辑:
// 1. 获取该Job下所有构建。
// 2. 遍历,检查构建的显示名称(通常包含分支信息)和创建时间。
// 3. 如果匹配分支模式且超过maxAge,则调用 build.delete()。
// 由于安全性和复杂性,生产环境建议使用下一节介绍的“文件夹级”或“全局”策略。
}
}
}
}
}
注释:这个示例展示了通过参数化Pipeline来触发定向清理的想法。但在生产环境中,直接在Pipeline脚本中删除历史构建需要极高的权限,且容易出错。对于跨Job、跨分支的复杂清理,更好的方式是使用Jenkins的“视图(View)”结合脚本控制台,或者使用后续提到的外部工具。
四、全局优化与进阶方案
除了针对单个Job的优化,我们还需要从全局视角看问题。
1. 为整个文件夹(Folder)设置默认策略 如果你使用“CloudBees Folders”插件来组织Job,可以为一个文件夹下的所有Job设置统一的构建历史保留策略。这非常高效,避免了逐个Job配置的繁琐。在文件夹的配置页面中,找到“Pipeline Libraries / Default Properties”,可以添加一个“构建丢弃策略”属性。
2. 定期清理全局的Workspace和临时文件
Jenkins主目录下,除了 jobs,还有 workspaces(所有Job的工作空间副本)和大量插件生成的临时文件、缓存。可以编写一个简单的系统定时任务(如Linux的cron job),定期清理这些目录中的老旧文件。
# 示例:一个简单的Bash清理脚本(需在Jenkins服务器上运行)
#!/bin/bash
JENKINS_HOME="/var/lib/jenkins"
# 清理所有工作空间中,超过7天未修改的目录
find $JENKINS_HOME/workspace -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;
# 清理插件产生的临时文件(具体路径因插件而异,请谨慎操作)
find $JENKINS_HOME -name "*.tmp" -mtime +1 -delete
find $JENKINS_HOME -name "*.log" -path "*/logs/*" -mtime +30 -delete
echo "全局临时文件清理完成。"
注释:此脚本需要根据你的实际目录和需求进行调整,尤其是 rm -rf 操作,务必先在测试环境验证。建议先使用 ls 命令替换 rm 来确认要删除的文件列表。
3. 监控与告警 预防胜于治疗。使用服务器监控工具(如Prometheus+Grafana,或Zabbix)对Jenkins主节点的磁盘使用率进行持续监控,并设置预警阈值(如80%)。这样你可以在问题爆发前,从容地启动清理计划。
4. 考虑分布式构建架构 将构建任务分散到多个代理节点(Agent)上执行。确保主节点(Master)只承担调度和存储核心数据(配置、构建记录元数据)的角色,而将产生大量中间文件和产物的构建过程放到Agent上。并配置Agent在工作完成后自动清理自己的本地工作空间。
五、应用场景、优缺点与注意事项
应用场景:
- 磁盘空间持续增长:Jenkins服务器磁盘使用率不断攀升,频繁告警。
- 构建速度变慢:磁盘IO成为瓶颈,因为需要从海量小文件中读取数据。
- 项目生命周期管理:需要清理已下线项目或长期不活跃分支的构建数据。
- 合规与审计:需要按照公司政策,只保留特定时长内的构建记录。
技术优缺点:
- 优点:
- 成本极低:主要利用Jenkins现有插件和功能,无需额外投入。
- 自动化程度高:一旦配置好策略,无需人工干预。
- 灵活精细:可以按Job、按文件夹、按天数、按数量、甚至按构建状态进行控制。
- 非侵入式:清理过程通常不会影响正在进行的构建。
- 缺点:
- 策略配置分散:如果Job数量多且最初没有统一规范,逐个配置会非常耗时。
- 清理非即时:
buildDiscarder策略通常在构建完成后触发,不会立即释放空间。 - 无法处理“僵尸”文件:对于插件异常、构建异常终止留下的孤立文件,可能需要手动或通过外部脚本清理。
- 历史数据丢失风险:策略设置过于激进可能导致需要回溯问题时找不到历史构建。
注意事项(非常重要!):
- 先备份,后操作:在执行任何全局性、批量性的删除脚本前,确保你有完整的Jenkins主目录备份。
- 循序渐进:不要一次性将保留策略从“永久”改为“保留1个”。可以先设置为保留30天或50次,观察一段时间。
- 区分环境:生产环境的Jenkins构建历史可能具有更高的审计价值,保留策略应比测试环境更保守。
- 沟通与通知:如果清理策略会影响团队其他成员(例如测试需要下载旧版本产物),务必提前沟通。
- 关注插件兼容性:某些插件(如Build Pipeline, Delivery Pipeline)可能会引用旧的构建号,过于激进的清理可能导致这些视图显示异常。
- 使用“立即丢弃旧构建”:在Job配置页面,配置好策略后,可以点击这个按钮手动触发一次清理,立即查看效果并释放空间。
六、总结
给Jenkins做磁盘空间优化,就像管理一个数字仓库,核心思路是 “自动化策略” 与 “精细化管理” 相结合。
- 对于日常构建:首要任务是为每个Job配置合理的
buildDiscarder策略,特别是利用artifactDaysToKeepStr和artifactNumToKeepStr来严格控制构建产物——这个空间消耗的主力军。 - 对于临时空间:在Pipeline中适时使用
cleanWs(),确保单次构建不留下垃圾。 - 对于全局管理:善用文件夹级策略和操作系统级的定时清理任务,处理散落的“边角料”。
- 对于长期健康:建立监控告警,并考虑通过增加Agent节点来分散存储压力。
记住,没有一劳永逸的万能配置。最好的策略是根据你团队的构建频率、产物大小、回溯需求以及服务器资源情况,量身定制一套组合拳。定期审视和调整这些策略,才能让你的Jenkins服务器始终保持轻盈、高效的状态,稳稳地托住团队的快速交付流程。
希望这篇指南能帮助你解决磁盘空间的困扰,让你的CI/CD流水线运行得更加顺畅!
评论