如何备份和恢复您的 Jenkins 实例

通过归档 JENKINS_HOME、保护密钥以及在实际需要前测试恢复,安全地备份和恢复 Jenkins。

如何备份和恢复您的 Jenkins 实例

Jenkins 通常成为您的构建、部署、凭据和发布历史的控制平面。如果在磁盘故障或不良迁移期间丢失了 $JENKINS_HOME,即使 Jenkins 软件包本身很容易重新安装,您的 CI/CD 流水线也可能停止。

本指南将向您展示需要备份什么、如何安全地创建文件系统归档,以及如何在不破坏凭据或文件所有权的情况下恢复 Jenkins。

理解核心:$JENKINS_HOME 目录

每个 Jenkins 实例都依赖于一个单一的根目录,称为 $JENKINS_HOME。此目录包含所有配置文件、插件、日志和作业数据。备份 Jenkins 本质上就是备份此目录的内容。

根据您的安装方法(例如,Linux 软件包、Docker 容器),$JENKINS_HOME 的位置通常有所不同:

  • Linux(软件包安装): /var/lib/jenkins
  • Docker: 通常挂载到一个卷,例如 /var/jenkins_home
  • 独立 JAR: 启动 Jenkins 进程的目录,除非通过环境变量指定。

识别关键数据组件

虽然备份整个 $JENKINS_HOME 目录是最简单的方法,但如果包含构建历史和工作区数据,它可能会导致归档文件非常大。为了进行快速高效的灾难恢复备份,您必须确保捕获以下目录和文件:

组件 $JENKINS_HOME 内的路径 用途
全局配置 config.xml Jenkins 根实例的主要配置文件。
作业定义 jobs/ 包含每个已配置作业的子目录,每个子目录都有自己的 config.xml
用户和凭据 users/credentials.xml 用户帐户、安全域设置和存储的密钥。
安全密钥 secrets/ 用于解密敏感数据(如存储的凭据)的加密密钥。
插件列表 plugins/ 包含所有已安装插件的 .hpi 文件。
节点定义 nodes/ 所有已连接构建代理的配置(如果已定义)。

方法 1:文件系统备份(推荐)

备份 Jenkins 最可靠的方法是在服务短暂停止时,创建必要文件的一致压缩归档。

步骤 1:停止 Jenkins 服务

为了确保数据一致性并防止备份过程中出现部分文件写入,必须停止 Jenkins 进程。未能停止服务可能会导致备份不完整或损坏。

# 对于使用 systemd 的系统(大多数现代 Linux 发行版)
sudo systemctl stop jenkins

# 或者,对于使用 service 命令的系统
sudo service jenkins stop

步骤 2:创建备份归档

导航到 $JENKINS_HOME 的父目录,并使用 tar 创建压缩归档。强烈建议排除大型构建工件以节省空间和时间。

假设 $JENKINS_HOME/var/lib/jenkins

JENKINS_HOME="/var/lib/jenkins"
BACKUP_TARGET="/mnt/backups/jenkins"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
ARCHIVE_NAME="jenkins_backup_${TIMESTAMP}.tar.gz"

# 如果目标目录不存在,则创建它
mkdir -p $BACKUP_TARGET

# 创建归档,排除构建历史和工作区
sudo tar -czvf "${BACKUP_TARGET}/${ARCHIVE_NAME}" \
    --exclude="${JENKINS_HOME}/workspace" \
    --exclude="${JENKINS_HOME}/caches" \
    --exclude="${JENKINS_HOME}/jobs/*/builds" \
    "${JENKINS_HOME}"

提示:包含构建历史

如果保留构建历史(jobs/*/builds)至关重要,您可以移除相应的 --exclude 标志。但是,请准备好归档大小可能达到数百 GB。

步骤 3:验证并异地存储

创建归档后,在信任它之前测试它是否可读:

tar -tzf "${BACKUP_TARGET}/${ARCHIVE_NAME}" >/dev/null

然后将其传输到外部存储位置,例如 S3 存储桶或网络备份系统,这样本地磁盘故障不会同时破坏 Jenkins 及其备份。

步骤 4:重启 Jenkins

sudo systemctl start jenkins

方法 2:利用 Jenkins 备份插件(部分解决方案)

虽然存在 ThinBackup 或 Backup Plugin 等插件,但它们通常只捕获配置文件(config.xml),并且可能无法稳健地处理大文件或所有必要的安全元素。这些通常仅适用于备份作业配置,不应依赖它们进行完整的、安全的灾难恢复策略。

恢复您的 Jenkins 实例

恢复涉及将备份数据复制到目标机器的 $JENKINS_HOME 目录,并在启动服务之前确保文件权限正确。

步骤 1:准备目标环境

确保目标系统(或修复后的系统)已安装 Jenkins,但保持服务停止。

sudo systemctl stop jenkins

步骤 2:清除现有 Jenkins 数据(可选但推荐)

如果您要恢复到之前托管 Jenkins 的机器,请清除现有的 $JENKINS_HOME 内容,以确保环境干净。

# 谨慎使用 'rm -rf' 命令!
sudo rm -rf /var/lib/jenkins/*

步骤 3:解压备份归档

将压缩归档(jenkins_backup_latest.tar.gz)复制到目标机器,并将其解压到 $JENKINS_HOME 目录。-C 标志指定解压的目标目录。

# 假设归档在 /tmp 中,JENKINS_HOME 是 /var/lib/jenkins
sudo tar -xzvf /tmp/jenkins_backup_latest.tar.gz -C /var/lib/

# 注意:如果 tar 命令在归档中包含了父目录,请调整路径。
# 结果应该是归档的内容替换 /var/lib/jenkins 的内容

步骤 4:验证并更正权限

这是恢复后最关键的步骤。如果文件所有权不正确,Jenkins 将无法启动或安全运行。您必须将所有权递归设置为 Jenkins 服务运行的用户和组(通常是 jenkins:jenkins)。

JENKINS_HOME="/var/lib/jenkins"
JENKINS_USER="jenkins"
JENKINS_GROUP="jenkins"

sudo chown -R $JENKINS_USER:$JENKINS_GROUP $JENKINS_HOME
sudo find "$JENKINS_HOME" -type d -exec chmod 755 {} \;
sudo find "$JENKINS_HOME" -type f -exec chmod 644 {} \;
sudo chmod -R go-rwx "$JENKINS_HOME/secrets" "$JENKINS_HOME/users" 2>/dev/null || true

步骤 5:启动 Jenkins 并验证

启动服务并监控日志以确保成功启动。

sudo systemctl start jenkins

# 监控启动日志
sudo tail -f /var/log/jenkins/jenkins.log

成功启动后,验证所有作业、用户和已安装的插件是否存在并正常运行。

自动化备份的最佳实践

为了超越手动备份,使用系统工具和外部配置管理实现自动化。

1. 利用 Cron 作业

使用 cron 或类似的调度程序,安排备份脚本(方法 1 中的步骤 1 和 2)每天或每晚运行。确保 cron 作业以具有适当权限的用户身份运行,以停止和启动 Jenkins 服务,并读取/写入 $JENKINS_HOME 目录。

2. 配置即代码 (CasC)

考虑采用 Jenkins 配置即代码 (CasC)。CasC 使用声明性 YAML 文件定义 Jenkins 设置、作业和插件。通过将这些 YAML 文件存储在单独的源代码控制存储库(如 Git)中,您的配置变得可移植且版本受控,从而大大简化了核心备份需求。

要点

只有在测试过恢复之后,才将 Jenkins 备份视为有用。一个好的恢复计划会保留 config.xmljobs/plugins/users/credentials.xmlsecrets/,然后验证作业是否可以在干净的实例上运行。

警告:保护凭据

恢复实例时,请确保 secrets/ 目录存在且正确。如果 Jenkins 找不到用于加密凭据(如 API 密钥或密码)的密钥,这些凭据将变得不可用,必须手动重新输入。