Jenkins 概述
什么是 Jenkins?
Jenkins 是一个开源的持续集成和持续部署(CI/CD)工具,帮助开发团队自动化构建、测试和部署应用程序。
🔄 持续集成
自动化代码集成,及早发现问题,提高代码质量
🚀 持续部署
自动化部署流程,快速交付应用到生产环境
🔌 丰富插件
超过1000个插件,支持各种工具和平台集成
📊 可视化流水线
图形化界面管理复杂的构建和部署流程
核心特性
- 易于安装和配置
- Web界面简单易用
- 支持分布式构建
- 强大的插件生态系统
- 支持多种版本控制系统
- 丰富的通知和报告功能
Jenkins 安装
方法一:使用 Docker 安装(推荐)
Docker 安装是最快速和简单的方式:
# 拉取 Jenkins 镜像
docker pull jenkins/jenkins:lts
# 创建数据卷
docker volume create jenkins_home
# 运行 Jenkins 容器
docker run -d \
--name jenkins \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
jenkins/jenkins:lts
方法二:Ubuntu/Debian 安装
# 更新系统包
sudo apt update
# 安装 Java 8 或 11
sudo apt install openjdk-11-jdk -y
# 添加 Jenkins 仓库密钥
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
# 添加 Jenkins 仓库
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
# 更新包列表并安装 Jenkins
sudo apt update
sudo apt install jenkins -y
# 启动 Jenkins 服务
sudo systemctl start jenkins
sudo systemctl enable jenkins
方法三:CentOS/RHEL 安装
# 安装 Java
sudo yum install java-11-openjdk-devel -y
# 添加 Jenkins 仓库
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
# 安装 Jenkins
sudo yum install jenkins -y
# 启动服务
sudo systemctl start jenkins
sudo systemctl enable jenkins
注意: 安装完成后,Jenkins 默认运行在 8080 端口。确保防火墙允许此端口的访问。
初始化设置
1. 访问 http://localhost:8080
2. 获取初始管理员密码:
# Docker 安装
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
# 系统安装
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
3. 输入密码并按照向导完成初始化设置
Jenkins 基础配置
1. 系统配置
访问 "系统管理" → "系统配置" 进行基本设置:
- Jenkins URL:设置 Jenkins 的访问地址
- 系统管理员邮件地址:配置管理员邮箱
- 邮件通知:配置 SMTP 服务器
2. 全局工具配置
配置构建工具:
Java (JDK)
配置 Java 开发工具包路径
# 查找 Java 路径
which java
echo $JAVA_HOME
Git
配置 Git 工具路径
# 安装 Git
sudo apt install git -y # Ubuntu/Debian
sudo yum install git -y # CentOS/RHEL
Maven
Java 项目构建工具
# 下载并配置 Maven
wget https://downloads.apache.org/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz
tar -xvf apache-maven-3.9.4-bin.tar.gz
sudo mv apache-maven-3.9.4 /opt/maven
3. 节点管理
配置 Jenkins 构建节点:
- 主节点:Jenkins 服务器本身
- 从节点:额外的构建机器
- 云节点:动态创建的构建环境
最佳实践:
- 定期备份 Jenkins 配置
- 使用环境变量管理敏感信息
- 配置适当的日志级别
- 设置合理的构建历史保留策略
插件管理
1. 插件安装
访问 "系统管理" → "插件管理" → "可选插件"
必备插件
- Git Plugin
- Pipeline Plugin
- Blue Ocean
- Build Pipeline Plugin
通知插件
- Email Extension
- Slack Notification
- Telegram Bot
- Microsoft Teams
集成插件
- Docker Plugin
- Kubernetes Plugin
- AWS Plugin
- SonarQube Plugin
测试插件
- JUnit Plugin
- Cobertura Plugin
- Cucumber Reports
- Performance Plugin
2. 插件配置示例
Git 插件配置
# 配置 Git 凭据
1. 系统管理 → 凭据管理
2. 添加凭据 → Username with password 或 SSH Username with private key
3. 在项目中使用配置的凭据ID
Docker 插件配置
# Docker 守护进程配置
{
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"],
"tls": true,
"tlscert": "/path/to/cert.pem",
"tlskey": "/path/to/key.pem",
"tlsverify": true,
"tlscacert": "/path/to/ca.pem"
}
3. 插件管理最佳实践
- 定期更新插件到最新版本
- 删除不使用的插件
- 在测试环境验证插件更新
- 备份插件配置
- 监控插件的安全公告
安全提示: 只安装来自可信源的插件,避免安装过多不必要的插件,这可能增加安全风险和系统复杂性。
创建和管理任务
1. 自由风格项目
最基本的 Jenkins 任务类型:
# 创建步骤:
1. 点击"新建任务"
2. 输入任务名称
3. 选择"构建一个自由风格的软件项目"
4. 配置源码管理、构建触发器、构建步骤
源码管理配置示例:
# Git 仓库配置
Repository URL: https://github.com/username/project.git
Credentials: 选择之前配置的凭据
Branch: */main 或 */master
2. 构建触发器
轮询 SCM
定期检查代码变更
# 每5分钟检查一次
H/5 * * * *
GitHub Webhook
代码推送时自动触发
# GitHub 设置
URL: http://jenkins-url/github-webhook/
Content type: application/json
定时构建
按计划执行构建
# 每天午夜执行
0 0 * * *
# 工作日上午9点执行
0 9 * * 1-5
上游项目触发
其他任务完成后触发
# 配置上游项目名称
upstream-project-name
3. 构建步骤示例
Java Maven 项目:
# 清理和编译
mvn clean compile
# 运行测试
mvn test
# 打包
mvn package
# 跳过测试打包
mvn package -DskipTests
Node.js 项目:
# 安装依赖
npm install
# 运行测试
npm test
# 构建项目
npm run build
# 启动应用
npm start
Docker 构建:
# 构建镜像
docker build -t myapp:${BUILD_NUMBER} .
# 推送到仓库
docker push myregistry/myapp:${BUILD_NUMBER}
# 清理本地镜像
docker rmi myapp:${BUILD_NUMBER}
4. 构建后操作
- 归档构建产物
- 发布测试结果报告
- 发送邮件通知
- 触发下游项目
- 部署到测试环境
Jenkins Pipeline 流水线
1. 声明式 Pipeline 基础语法
pipeline {
agent any
environment {
// 环境变量
DOCKER_IMAGE = "myapp"
VERSION = "${BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'https://github.com/username/project.git'
}
}
stage('Build') {
steps {
sh 'mvn clean compile'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Package') {
steps {
sh 'mvn package'
archiveArtifacts artifacts: 'target/*.jar'
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
sh 'docker build -t ${DOCKER_IMAGE}:${VERSION} .'
sh 'docker push ${DOCKER_IMAGE}:${VERSION}'
}
}
}
post {
success {
echo '构建成功!'
emailext (
subject: "构建成功: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
body: "构建成功完成。",
to: "team@company.com"
)
}
failure {
echo '构建失败!'
emailext (
subject: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
body: "构建失败,请检查日志。",
to: "team@company.com"
)
}
always {
cleanWs()
}
}
}
2. 脚本式 Pipeline
node {
try {
stage('Checkout') {
checkout scm
}
stage('Build') {
sh 'make build'
}
stage('Test') {
parallel (
"Unit Tests": {
sh 'make test-unit'
},
"Integration Tests": {
sh 'make test-integration'
}
)
}
stage('Deploy') {
if (env.BRANCH_NAME == 'main') {
sh 'make deploy'
}
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
throw e
} finally {
// 清理工作
deleteDir()
}
}
3. 多分支 Pipeline
自动为每个分支创建 Pipeline:
# Jenkinsfile 示例
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
if (env.BRANCH_NAME == 'develop') {
sh 'make build-dev'
} else if (env.BRANCH_NAME == 'main') {
sh 'make build-prod'
} else {
sh 'make build-feature'
}
}
}
}
stage('Deploy') {
when {
anyOf {
branch 'main'
branch 'develop'
}
}
steps {
script {
if (env.BRANCH_NAME == 'main') {
sh 'make deploy-prod'
} else {
sh 'make deploy-staging'
}
}
}
}
}
}
4. Pipeline 高级特性
条件执行:
stage('Deploy to Production') {
when {
allOf {
branch 'main'
environment name: 'DEPLOY_TO_PROD', value: 'true'
}
}
steps {
sh 'kubectl apply -f k8s-prod/'
}
}
并行执行:
stage('Parallel Tests') {
parallel {
stage('Unit Tests') {
steps {
sh 'npm run test:unit'
}
}
stage('Integration Tests') {
steps {
sh 'npm run test:integration'
}
}
stage('Security Scan') {
steps {
sh 'npm audit'
}
}
}
}
输入确认:
stage('Manual Approval') {
when {
branch 'main'
}
steps {
input message: '是否部署到生产环境?',
ok: '部署',
submitterParameter: 'APPROVER'
echo "Approved by ${APPROVER}"
}
}
应用部署
1. Docker 部署
pipeline {
agent any
environment {
DOCKER_REGISTRY = "registry.company.com"
IMAGE_NAME = "myapp"
CONTAINER_NAME = "myapp-container"
}
stages {
stage('Build Docker Image') {
steps {
script {
def image = docker.build("${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}")
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-registry-credentials') {
image.push()
image.push("latest")
}
}
}
}
stage('Deploy') {
steps {
sh """
docker stop ${CONTAINER_NAME} || true
docker rm ${CONTAINER_NAME} || true
docker run -d --name ${CONTAINER_NAME} \
-p 8080:8080 \
${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}
"""
}
}
}
}
2. Kubernetes 部署
# Kubernetes 部署清单
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: registry.company.com/myapp:${BUILD_NUMBER}
ports:
- containerPort: 8080
env:
- name: ENV
value: "production"
---
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
Jenkins Pipeline 中的 Kubernetes 部署:
stage('Deploy to Kubernetes') {
steps {
script {
kubernetesDeploy(
configs: 'k8s/*.yaml',
kubeconfigId: 'kubeconfig-credentials'
)
}
}
}
3. AWS 部署
# 部署到 AWS EC2
stage('Deploy to AWS') {
steps {
withAWS(region: 'us-west-2', credentials: 'aws-credentials') {
sh '''
# 上传应用包到 S3
aws s3 cp target/myapp.jar s3://deploy-bucket/myapp-${BUILD_NUMBER}.jar
# 创建 CodeDeploy 部署
aws deploy create-deployment \
--application-name myapp \
--deployment-group-name production \
--s3-location bucket=deploy-bucket,key=myapp-${BUILD_NUMBER}.jar,bundleType=zip
'''
}
}
}
# 部署到 AWS ECS
stage('Deploy to ECS') {
steps {
withAWS(region: 'us-west-2', credentials: 'aws-credentials') {
script {
def taskDefinition = readJSON text: sh(
script: "aws ecs describe-task-definition --task-definition myapp --query 'taskDefinition'",
returnStdout: true
)
taskDefinition.containerDefinitions[0].image = "registry.company.com/myapp:${BUILD_NUMBER}"
writeJSON file: 'task-definition.json', json: taskDefinition
sh '''
aws ecs register-task-definition --cli-input-json file://task-definition.json
aws ecs update-service --cluster production --service myapp --force-new-deployment
'''
}
}
}
}
4. 蓝绿部署
pipeline {
agent any
stages {
stage('Deploy to Green Environment') {
steps {
sh '''
# 部署到绿色环境
kubectl apply -f k8s/green-deployment.yaml
kubectl wait --for=condition=available deployment/myapp-green
'''
}
}
stage('Health Check') {
steps {
script {
def healthCheck = sh(
script: 'curl -f http://green.myapp.com/health',
returnStatus: true
)
if (healthCheck != 0) {
error '健康检查失败'
}
}
}
}
stage('Switch Traffic') {
steps {
input message: '切换到绿色环境?', ok: '切换'
sh '''
# 切换流量到绿色环境
kubectl patch service myapp-service -p '{"spec":{"selector":{"version":"green"}}}'
# 等待一段时间确保稳定
sleep 60
# 删除蓝色环境
kubectl delete deployment myapp-blue
'''
}
}
}
}
部署最佳实践:
- 使用滚动更新策略
- 实施健康检查
- 准备回滚方案
- 监控部署过程
- 自动化测试验证
监控和维护
1. Jenkins 系统监控
🖥️ 系统信息
CPU、内存、磁盘使用情况
# 查看系统信息
系统管理 → 系统信息
📊 构建统计
构建成功率、平均构建时间
# 安装插件
Build Monitor Plugin
Build Pipeline Plugin
📈 性能监控
插件性能、JVM 状态
# JVM 监控
-Xms2G -Xmx4G
-XX:+UseG1GC
🔍 日志分析
系统日志、构建日志
# 日志位置
/var/log/jenkins/jenkins.log
2. 构建监控 Pipeline
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
def startTime = System.currentTimeMillis()
// 构建步骤
sh 'make build'
def buildTime = System.currentTimeMillis() - startTime
echo "构建耗时: ${buildTime}ms"
// 记录构建指标
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'reports',
reportFiles: 'build-metrics.html',
reportName: 'Build Metrics'
])
}
}
}
stage('Test Coverage') {
steps {
sh 'mvn jacoco:report'
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'target/site/jacoco',
reportFiles: 'index.html',
reportName: 'Code Coverage Report'
])
}
}
stage('Quality Gate') {
steps {
script {
def coverage = sh(
script: "grep -o 'Total.*[0-9]*%' target/site/jacoco/index.html | grep -o '[0-9]*%' | head -1 | sed 's/%//'",
returnStdout: true
).trim() as Integer
if (coverage < 80) {
error "代码覆盖率 ${coverage}% 低于要求的 80%"
}
echo "代码覆盖率: ${coverage}%"
}
}
}
}
post {
always {
// 收集测试结果
junit 'target/surefire-reports/*.xml'
// 发送通知
script {
def buildResult = currentBuild.result ?: 'SUCCESS'
def buildTime = currentBuild.duration
slackSend(
channel: '#builds',
color: buildResult == 'SUCCESS' ? 'good' : 'danger',
message: """
构建 ${buildResult}: ${env.JOB_NAME} #${env.BUILD_NUMBER}
耗时: ${buildTime}ms
分支: ${env.BRANCH_NAME}
提交: ${env.GIT_COMMIT[0..7]}
"""
)
}
}
}
}
3. 外部监控集成
Prometheus 监控:
# Prometheus 配置 (prometheus.yml)
scrape_configs:
- job_name: 'jenkins'
static_configs:
- targets: ['jenkins:8080']
metrics_path: /prometheus
scrape_interval: 15s
# Jenkins Prometheus Plugin 配置
系统管理 → 系统配置 → Prometheus
Path: /prometheus
Grafana 仪表板:
# 常用指标
- jenkins_builds_duration_milliseconds_summary
- jenkins_builds_last_build_result_ordinal
- jenkins_executor_count_value
- jenkins_job_count_value
- jenkins_queue_size_value
4. 维护任务
定期清理
# 清理旧构建
pipeline {
options {
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30'
))
}
}
# 清理工作空间
pipeline {
post {
always {
cleanWs()
}
}
}
备份策略
#!/bin/bash
# Jenkins 备份脚本
JENKINS_HOME="/var/lib/jenkins"
BACKUP_DIR="/backup/jenkins"
DATE=$(date +%Y%m%d_%H%M%S)
# 创建备份目录
mkdir -p $BACKUP_DIR
# 备份配置文件
tar -czf $BACKUP_DIR/jenkins_config_$DATE.tar.gz \
$JENKINS_HOME/config.xml \
$JENKINS_HOME/jobs/ \
$JENKINS_HOME/users/ \
$JENKINS_HOME/plugins/
# 删除30天前的备份
find $BACKUP_DIR -name "jenkins_config_*.tar.gz" -mtime +30 -delete
安全配置
1. 用户权限管理
# 基于角色的访问控制 (RBAC)
系统管理 → 全局安全配置 → 授权策略
# 推荐使用 Role-based Authorization Strategy 插件
- 管理员:完全控制权限
- 开发者:构建、部署权限
- 测试者:查看、触发构建权限
- 访客:只读权限
🔐 认证方式
- Jenkins 自带数据库
- LDAP/Active Directory
- SAML 单点登录
- OAuth (GitHub, Google)
👥 用户管理
- 创建用户组
- 分配角色权限
- 定期审查权限
- 禁用不活跃用户
2. 凭据管理
# 凭据类型
1. Username with password - 用户名密码
2. SSH Username with private key - SSH 私钥
3. Secret text - 密钥文本
4. Secret file - 密钥文件
5. Certificate - 证书
# Pipeline 中使用凭据
pipeline {
stages {
stage('Deploy') {
steps {
withCredentials([
usernamePassword(
credentialsId: 'database-credentials',
usernameVariable: 'DB_USER',
passwordVariable: 'DB_PASS'
)
]) {
sh 'deploy.sh -u $DB_USER -p $DB_PASS'
}
}
}
}
}
3. 网络安全
HTTPS 配置:
# 使用 Nginx 反向代理
server {
listen 443 ssl;
server_name jenkins.company.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
防火墙配置:
# Ubuntu/Debian UFW
sudo ufw allow from 192.168.1.0/24 to any port 8080
sudo ufw enable
# CentOS/RHEL firewalld
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.0/24' port protocol='tcp' port='8080' accept"
sudo firewall-cmd --reload
4. 安全最佳实践
关键安全措施:
- 定期更新 Jenkins 和插件
- 使用最少权限原则
- 启用 CSRF 保护
- 配置安全的默认设置
- 监控异常登录活动
- 定期安全审计
安全脚本审批:
# 脚本安全配置
系统管理 → In-process Script Approval
# 审批脚本示例
@Grab('org.apache.commons:commons-lang3:3.12.0')
import org.apache.commons.lang3.StringUtils
// 需要管理员审批的脚本
def result = StringUtils.capitalize("hello world")
代理安全:
# 安全的代理配置
1. 使用专用的构建代理
2. 限制代理网络访问
3. 定期更新代理系统
4. 使用容器化代理环境
故障排除
1. 常见问题诊断
Jenkins 服务无法启动:
# 检查服务状态
sudo systemctl status jenkins
# 查看详细日志
sudo journalctl -u jenkins -f
# 检查端口占用
sudo netstat -tlnp | grep 8080
sudo lsof -i :8080
# 检查 Java 版本
java -version
# 检查磁盘空间
df -h /var/lib/jenkins
构建失败诊断:
# 常见构建失败原因
1. 环境变量未设置
2. 依赖包缺失
3. 权限不足
4. 网络连接问题
5. 资源不足
# 调试命令
echo "PATH: $PATH"
echo "JAVA_HOME: $JAVA_HOME"
echo "当前用户: $(whoami)"
echo "当前目录: $(pwd)"
ls -la
2. 性能问题解决
内存不足:
# 调整 JVM 参数
# /etc/default/jenkins (Ubuntu/Debian)
JAVA_ARGS="-Xmx4G -Xms2G -XX:+UseG1GC -XX:+UseStringDeduplication"
# 监控内存使用
free -h
top -p $(pgrep -f jenkins)
# 清理不必要的构建历史
pipeline {
options {
buildDiscarder(logRotator(numToKeepStr: '5'))
}
}
磁盘空间不足:
# 清理脚本
#!/bin/bash
JENKINS_HOME="/var/lib/jenkins"
# 清理旧的构建日志
find $JENKINS_HOME/jobs/*/builds/*/log -mtime +7 -delete
# 清理工作空间
find $JENKINS_HOME/workspace/ -maxdepth 2 -type d -mtime +3 -exec rm -rf {} \;
# 清理临时文件
find /tmp -name "jenkins*" -mtime +1 -delete
# Docker 清理
docker system prune -f
docker volume prune -f
3. 插件问题
插件冲突:
# 插件依赖检查
系统管理 → 插件管理 → 已安装 → 查看依赖关系
# 安全模式启动 Jenkins
java -jar jenkins.war --httpPort=8080 --enable-future-java
# 禁用有问题的插件
cd /var/lib/jenkins/plugins
mv problematic-plugin.jpi problematic-plugin.jpi.disabled
sudo systemctl restart jenkins
插件更新失败:
# 手动下载插件
wget https://updates.jenkins.io/download/plugins/plugin-name/version/plugin-name.hpi
# 手动安装
cp plugin-name.hpi /var/lib/jenkins/plugins/
sudo chown jenkins:jenkins /var/lib/jenkins/plugins/plugin-name.hpi
sudo systemctl restart jenkins
4. 网络和连接问题
Git 连接失败:
# 测试 Git 连接
git clone https://github.com/username/repo.git
ssh -T git@github.com
# SSH 密钥问题
ssh-keygen -t rsa -b 4096 -C "jenkins@company.com"
cat ~/.ssh/id_rsa.pub
# 代理设置
git config --global http.proxy http://proxy:port
git config --global https.proxy https://proxy:port
Docker 连接问题:
# 检查 Docker 状态
sudo systemctl status docker
docker version
# 权限问题
sudo usermod -aG docker jenkins
sudo systemctl restart jenkins
# Docker 守护进程配置
sudo systemctl edit docker
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376
5. 日志分析和调试
# Jenkins 系统日志
tail -f /var/log/jenkins/jenkins.log
# 特定任务日志
curl -u username:token http://jenkins-url/job/job-name/lastBuild/consoleText
# 开启调试模式
# 在系统管理 → 系统日志中添加记录器
Logger: hudson.model.Run
Level: FINE
# Pipeline 调试
pipeline {
agent any
stages {
stage('Debug') {
steps {
script {
echo "BUILD_NUMBER: ${BUILD_NUMBER}"
echo "JOB_NAME: ${JOB_NAME}"
echo "WORKSPACE: ${WORKSPACE}"
sh 'env | sort'
}
}
}
}
}
故障排除提示:
- 保持 Jenkins 和插件更新
- 定期备份配置和数据
- 监控系统资源使用
- 建立日志收集和分析机制
- 准备灾难恢复计划