跳过正文
  1. 博客文章/

企业级 Jenkins CI/CD 平台部署与配置完整指南

·4484 字·22 分钟·
DevOps Jenkins CI/CD Devops Automation Pipeline
Zayn
作者
Zayn
专注 Kubernetes、CI/CD、可观测性等云原生技术栈,记录生产环境中的实战经验与踩坑复盘。
目录

推荐阅读
#

Jenkins 平台简介
#

什么是 Jenkins
#

Jenkins 是世界领先的开源自动化服务器,由 Kohsuke Kawaguchi 于 2004 年创建。作为 DevOps 工具链的核心组件,Jenkins 为软件开发生命周期提供了强大的自动化能力。

核心特性
#

  • 持续集成(CI):自动化代码构建、测试和集成流程
  • 持续部署(CD):自动化应用程序部署到各种环境
  • 丰富的插件生态:超过 1800+ 插件,支持几乎所有开发工具和平台
  • 分布式架构:支持主从节点架构,可水平扩展构建能力
  • Pipeline as Code:通过 Jenkinsfile 实现流水线即代码
  • 多平台支持:支持 Windows、Linux、macOS 等多种操作系统

应用场景
#

  • 代码质量管控:集成 SonarQube、ESLint 等代码质量检查工具
  • 自动化测试:单元测试、集成测试、端到端测试的自动化执行
  • 多环境部署:开发、测试、预生产、生产环境的自动化部署
  • 微服务 CI/CD:支持容器化应用和微服务架构的持续交付
  • 基础设施即代码:集成 Terraform、Ansible 等基础设施管理工具

架构设计
#

单机架构
#

flowchart TB
    subgraph JenkinsMaster[Jenkins Master]
        A[Web UI]
        B[Job Scheduler]
        C[Plugin Management]
        D[Build Executors]
        E[Workspace]
        F[Build History]
        G[Logs]
    end

分布式架构
#

flowchart TB
    M[Jenkins Master
Web UI / Job Scheduler / Plugin] A1[Agent 1
Linux] A2[Agent 2
Windows] A3[Agent 3
Docker] M --> A1 M --> A2 M --> A3

环境准备
#

系统要求
#

硬件要求
#

环境类型CPU内存存储网络
开发环境2 核4GB50GB100Mbps
测试环境4 核8GB200GB1Gbps
生产环境8 核16GB500GB+1Gbps+

软件要求
#

组件最低版本推荐版本说明
操作系统CentOS 7.6CentOS 7.9 / RHEL 8+64位系统
JavaOpenJDK 8OpenJDK 11Jenkins 运行环境
内存2GB8GB+推荐配置
存储10GB100GB+构建历史和工作空间
网络端口8080自定义Web 界面访问端口

网络端口规划
#

端口协议用途是否必需
8080TCPJenkins Web UI
50000TCPAgent 连接端口是(分布式)
22TCPSSH 连接可选
443/80TCPHTTPS/HTTP 代理可选

环境检查脚本
#

cat > check-jenkins-env.sh << 'EOF'
#!/bin/bash

echo "=== Jenkins 环境检查脚本 ==="
echo "检查时间: $(date)"
echo

# 检查操作系统
echo "=== 系统信息 ==="
cat /etc/redhat-release
uname -a
echo

# 检查内存
echo "=== 内存信息 ==="
free -h
echo

# 检查磁盘空间
echo "=== 磁盘空间 ==="
df -h
echo

# 检查 Java 环境
echo "=== Java 环境检查 ==="
if command -v java >/dev/null 2>&1; then
    java -version
    echo "✓ Java 已安装"
else
    echo "✗ Java 未安装"
fi
echo

# 检查网络端口
echo "=== 端口检查 ==="
if netstat -tlnp | grep :8080 >/dev/null 2>&1; then
    echo "✗ 端口 8080 已被占用"
    netstat -tlnp | grep :8080
else
    echo "✓ 端口 8080 可用"
fi
echo

# 检查防火墙状态
echo "=== 防火墙状态 ==="
systemctl status firewalld --no-pager
echo

# 检查 SELinux 状态
echo "=== SELinux 状态 ==="
getenforce
echo

echo "=== 环境检查完成 ==="
EOF

chmod +x check-jenkins-env.sh
./check-jenkins-env.sh

Jenkins 安装部署
#

方案一:YUM 包管理器安装(推荐)
#

步骤 1:安装 Java 环境
#

Jenkins 需要 Java 运行环境,推荐使用 OpenJDK 11:

# 安装 OpenJDK 11(推荐)
yum install -y java-11-openjdk java-11-openjdk-devel

# 或安装 OpenJDK 8(兼容性考虑)
yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel

# 验证 Java 安装
java -version
javac -version

# 设置 JAVA_HOME 环境变量
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk' >> /etc/profile
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile
source /etc/profile

预期输出

openjdk version "11.0.16" 2022-07-19 LTS
OpenJDK Runtime Environment (Red_Hat-11.0.16.0.8-1.el7_9) (build 11.0.16+8-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-11.0.16.0.8-1.el7_9) (build 11.0.16+8-LTS, mixed mode, sharing)

步骤 2:配置 Jenkins YUM 源
#

# 添加 Jenkins 官方 YUM 仓库
sudo wget -O /etc/yum.repos.d/jenkins.repo \
    https://pkg.jenkins.io/redhat-stable/jenkins.repo

# 导入 Jenkins GPG 密钥
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

# 更新 YUM 缓存
yum clean all && yum makecache

步骤 3:安装 Jenkins
#

# 安装 Jenkins
yum install -y jenkins

# 查看 Jenkins 版本
rpm -qa | grep jenkins

# 查看 Jenkins 服务状态
systemctl status jenkins

步骤 4:配置 Jenkins 服务
#

# 启动 Jenkins 服务
systemctl start jenkins

# 设置开机自启动
systemctl enable jenkins

# 检查服务状态
systemctl status jenkins

# 查看 Jenkins 日志
journalctl -u jenkins -f

步骤 5:防火墙配置
#

# 开放 Jenkins 端口(8080)
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload

# 验证端口开放
firewall-cmd --list-ports

# 检查端口监听状态
netstat -tlnp | grep 8080

方案二:Docker 容器化部署
#

基础 Docker 部署
#

# 创建 Jenkins 数据目录
mkdir -p /data/jenkins_home
chown -R 1000:1000 /data/jenkins_home

# 运行 Jenkins 容器
docker run -d \
  --name jenkins \
  --restart unless-stopped \
  -p 8080:8080 \
  -p 50000:50000 \
  -v /data/jenkins_home:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /usr/bin/docker:/usr/bin/docker \
  jenkins/jenkins:lts

# 查看初始管理员密码
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Docker Compose 部署
#

cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins
    restart: unless-stopped
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker
    environment:
      - JENKINS_OPTS=--httpPort=8080
      - JAVA_OPTS=-Xmx2048m -Xms1024m
    user: root

volumes:
  jenkins_home:
    driver: local
EOF

# 启动服务
docker-compose up -d

# 查看日志
docker-compose logs -f jenkins

方案三:Kubernetes 部署
#

创建 Jenkins 部署文件
#

cat > jenkins-k8s.yaml << 'EOF'
apiVersion: v1
kind: Namespace
metadata:
  name: jenkins

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: jenkins

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins
subjects:
- kind: ServiceAccount
  name: jenkins
  namespace: jenkins

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: jenkins
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      serviceAccountName: jenkins
      containers:
      - name: jenkins
        image: jenkins/jenkins:lts
        ports:
        - containerPort: 8080
        - containerPort: 50000
        volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home
        env:
        - name: JAVA_OPTS
          value: "-Xmx2048m -Xms1024m"
        resources:
          requests:
            cpu: 1000m
            memory: 2Gi
          limits:
            cpu: 2000m
            memory: 4Gi
      volumes:
      - name: jenkins-home
        persistentVolumeClaim:
          claimName: jenkins-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: jenkins
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30080
  - port: 50000
    targetPort: 50000
    nodePort: 30050
  selector:
    app: jenkins
EOF

# 部署到 Kubernetes
kubectl apply -f jenkins-k8s.yaml

# 查看部署状态
kubectl get pods -n jenkins
kubectl get svc -n jenkins

初始化配置
#

获取初始管理员密码
#

# YUM 安装方式
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

# Docker 方式
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

# Kubernetes 方式
kubectl exec -n jenkins deployment/jenkins -- cat /var/jenkins_home/secrets/initialAdminPassword

Web 界面初始化
#

  1. 访问 Jenkins:打开浏览器访问 http://your-server-ip:8080
  2. 输入管理员密码:使用上面获取的初始密码
  3. 安装插件:选择 “安装推荐的插件” 或 “选择插件来安装”
  4. 创建管理员用户:设置用户名、密码、邮箱等信息
  5. 实例配置:确认 Jenkins URL 配置
  6. 开始使用:完成初始化,进入 Jenkins 主界面

推荐插件列表
#

基础插件

  • Git Plugin
  • Pipeline Plugin
  • Blue Ocean
  • Build Timeout
  • Timestamper
  • Workspace Cleanup

高级插件

  • Kubernetes Plugin
  • Docker Plugin
  • LDAP Plugin
  • Role-based Authorization Strategy
  • SonarQube Scanner

Jenkins 系统配置优化
#

基础配置优化
#

修改服务端口
#

Jenkins 默认使用 8080 端口,如遇端口冲突需要修改:

# YUM 安装方式修改端口
sudo vim /etc/sysconfig/jenkins

# 修改以下配置项
JENKINS_PORT="18080"

# 或使用 sed 命令批量替换
sed -i 's/JENKINS_PORT="8080"/JENKINS_PORT="18080"/g' /etc/sysconfig/jenkins

# 重启 Jenkins 服务
systemctl restart jenkins

# 验证端口变更
netstat -tlnp | grep 18080

image-20210302194914456

JVM 参数优化
#

# 编辑 Jenkins 配置文件
sudo vim /etc/sysconfig/jenkins

# 优化 JVM 参数
JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Xms2048m -Xmx4096m -XX:+UseG1GC -XX:+UseStringDeduplication -Djava.net.preferIPv4Stack=true -Duser.timezone=Asia/Shanghai"

# 重启服务使配置生效
systemctl restart jenkins

工作目录配置
#

# 默认工作目录:/var/lib/jenkins
# 如需修改工作目录,编辑配置文件
sudo vim /etc/sysconfig/jenkins

# 修改工作目录
JENKINS_HOME="/data/jenkins"

# 创建新目录并设置权限
sudo mkdir -p /data/jenkins
sudo chown jenkins:jenkins /data/jenkins

# 迁移现有数据(可选)
sudo rsync -av /var/lib/jenkins/ /data/jenkins/

# 重启服务
systemctl restart jenkins

反向代理配置
#

Nginx 反向代理
#

安装 Nginx
#

# 安装 Nginx
yum install -y nginx

# 启动并设置开机自启
systemctl start nginx
systemctl enable nginx

配置虚拟主机
#

# 创建 Jenkins 虚拟主机配置
cat > /etc/nginx/conf.d/jenkins.conf << 'EOF'
upstream jenkins {
    server 127.0.0.1:8080 fail_timeout=0;
}

server {
    listen 80;
    server_name jenkins.your-domain.com;

    # 安全头设置
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    # 日志配置
    access_log /var/log/nginx/jenkins.access.log;
    error_log /var/log/nginx/jenkins.error.log;

    # Jenkins 代理配置
    location / {
        proxy_set_header Host $http_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;
        proxy_set_header X-Forwarded-Port $server_port;

        proxy_pass http://jenkins;
        proxy_read_timeout 90;
        proxy_redirect http://jenkins https://jenkins.your-domain.com;

        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 大文件上传支持
        client_max_body_size 100m;
    }
}
EOF

# 测试 Nginx 配置
nginx -t

# 重新加载 Nginx 配置
systemctl reload nginx

HTTPS 配置(推荐)
#

# 安装 Certbot
yum install -y certbot python2-certbot-nginx

# 获取 SSL 证书
certbot --nginx -d jenkins.your-domain.com

# 自动续期设置
echo "0 12 * * * /usr/bin/certbot renew --quiet" | crontab -

Apache 反向代理(备选)
#

# 安装 Apache
yum install -y httpd

# 启用必要模块
cat > /etc/httpd/conf.d/jenkins.conf << 'EOF'
<VirtualHost *:80>
    ServerName jenkins.your-domain.com

    ProxyPreserveHost On
    ProxyRequests Off
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    # 安全配置
    Header always set X-Frame-Options SAMEORIGIN
    Header always set X-Content-Type-Options nosniff
    Header always set X-XSS-Protection "1; mode=block"
</VirtualHost>
EOF

# 启动 Apache
systemctl start httpd
systemctl enable httpd

Traefik 反向代理(容器环境)
#

cat > traefik-jenkins.yml << 'EOF'
version: '3.8'

services:
  traefik:
    image: traefik:v2.9
    container_name: traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/traefik.yml:ro
      - ./acme.json:/acme.json
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.your-domain.com`)"
      - "traefik.http.routers.dashboard.tls=true"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"

  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins
    restart: unless-stopped
    volumes:
      - jenkins_home:/var/jenkins_home
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.jenkins.rule=Host(`jenkins.your-domain.com`)"
      - "traefik.http.routers.jenkins.tls=true"
      - "traefik.http.routers.jenkins.tls.certresolver=letsencrypt"
      - "traefik.http.services.jenkins.loadbalancer.server.port=8080"

volumes:
  jenkins_home:
EOF

性能优化配置
#

系统级优化
#

# 创建性能优化脚本
cat > optimize-jenkins.sh << 'EOF'
#!/bin/bash

echo "=== Jenkins 性能优化脚本 ==="

# 1. 系统参数优化
echo "优化系统参数..."
cat >> /etc/sysctl.conf << 'SYSCTL'
# Jenkins 性能优化
vm.swappiness = 1
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
SYSCTL

sysctl -p

# 2. 文件描述符限制
echo "优化文件描述符限制..."
cat >> /etc/security/limits.conf << 'LIMITS'
jenkins soft nofile 65535
jenkins hard nofile 65535
jenkins soft nproc 32768
jenkins hard nproc 32768
LIMITS

# 3. Jenkins 用户环境优化
echo "优化 Jenkins 用户环境..."
sudo -u jenkins bash -c 'echo "ulimit -n 65535" >> ~/.bashrc'

# 4. 清理临时文件
echo "清理临时文件..."
find /var/lib/jenkins/workspace -name "*.tmp" -mtime +7 -delete
find /var/lib/jenkins/logs -name "*.log" -mtime +30 -delete

echo "=== 优化完成 ==="
EOF

chmod +x optimize-jenkins.sh
./optimize-jenkins.sh

Jenkins 内部优化
#

# 创建 Jenkins 配置优化脚本
cat > jenkins-config-optimize.groovy << 'EOF'
import jenkins.model.*
import hudson.model.*

// 设置执行器数量
Jenkins.instance.setNumExecutors(4)

// 设置构建历史保留策略
def jobs = Jenkins.instance.getAllItems(Job.class)
jobs.each { job ->
    if (job.getBuildDiscarder() == null) {
        job.setBuildDiscarder(new LogRotator(-1, 10, -1, 5))
        job.save()
    }
}

// 优化系统配置
def desc = Jenkins.instance.getDescriptor("hudson.model.DirectoryBrowserSupport")
desc.setCSP("default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';")

println "Jenkins 配置优化完成"
EOF

# 通过 Jenkins CLI 执行优化脚本
java -jar jenkins-cli.jar -s http://localhost:8080/ groovy = < jenkins-config-optimize.groovy

image-20210302195118303

image-20210302203954015

配置 Jenkins URL
#

完成反向代理配置后,需要在 Jenkins 中设置正确的 URL:

  1. 进入 Manage JenkinsConfigure System
  2. 找到 Jenkins Location 部分
  3. Jenkins URL 修改为代理地址(如:http://jenkins.your-domain.com
  4. 点击 Save 保存配置

这样可以解决反向代理的重定向问题。

插件管理优化
#

配置国内镜像源
#

由于网络原因,建议使用国内镜像源加速插件下载:

方法一:脚本自动配置
#

# 创建镜像源配置脚本
cat > setup-jenkins-mirror.sh << 'EOF'
#!/bin/bash

# 确定 Jenkins 工作目录
if [ -d "/var/lib/jenkins" ]; then
    JENKINS_HOME="/var/lib/jenkins"
elif [ -d "/var/jenkins_home" ]; then
    JENKINS_HOME="/var/jenkins_home"
else
    echo "未找到 Jenkins 工作目录"
    exit 1
fi

echo "Jenkins 工作目录: $JENKINS_HOME"

# 备份原始配置
cp "${JENKINS_HOME}/hudson.model.UpdateCenter.xml" "${JENKINS_HOME}/hudson.model.UpdateCenter.xml.bak" 2>/dev/null || true
cp "${JENKINS_HOME}/updates/default.json" "${JENKINS_HOME}/updates/default.json.bak" 2>/dev/null || true

# 配置清华大学镜像源
echo "配置清华大学镜像源..."
sed -i 's#https://updates.jenkins.io#https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates#g' "${JENKINS_HOME}/hudson.model.UpdateCenter.xml"

if [ -f "${JENKINS_HOME}/updates/default.json" ]; then
    sed -i 's#http://updates.jenkins-ci.org/download#https://mirrors.tuna.tsinghua.edu.cn/jenkins#g' "${JENKINS_HOME}/updates/default.json"
    sed -i 's#http://www.google.com#https://www.baidu.com#g' "${JENKINS_HOME}/updates/default.json"
fi

# 重启 Jenkins 服务
echo "重启 Jenkins 服务..."
systemctl restart jenkins

echo "镜像源配置完成!"
echo "请在 Web 界面中验证:Manage Jenkins → Manage Plugins → Advanced → Update Site"
echo "URL 应为: https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json"
EOF

chmod +x setup-jenkins-mirror.sh
./setup-jenkins-mirror.sh

方法二:Web 界面手动配置
#

  1. 进入 Manage JenkinsManage PluginsAdvanced
  2. Update Site 部分,将 URL 替换为:
    https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
    
  3. 点击 Submit 提交
  4. 重启 Jenkins 服务

image-20210302201455084

方法三:容器化部署环境变量
#

# Docker 运行时添加环境变量
docker run -d \
  --name jenkins \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  -e JENKINS_UC=https://mirrors.tuna.tsinghua.edu.cn \
  -e JENKINS_UC_DOWNLOAD=https://mirrors.tuna.tsinghua.edu.cn/jenkins \
  -e JENKINS_OPTS="-Djava.awt.headless=true -Duser.timezone=Asia/Shanghai -Dhudson.model.UpdateCenter.updateCenterUrl=https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json" \
  jenkins/jenkins:lts
# Docker Compose 配置
version: '3.8'
services:
  jenkins:
    image: jenkins/jenkins:lts
    environment:
      - JENKINS_UC=https://mirrors.tuna.tsinghua.edu.cn
      - JENKINS_UC_DOWNLOAD=https://mirrors.tuna.tsinghua.edu.cn/jenkins
      - JENKINS_OPTS=-Djava.awt.headless=true -Duser.timezone=Asia/Shanghai -Dhudson.model.UpdateCenter.updateCenterUrl=https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

批量插件安装
#

创建插件列表文件
#

cat > jenkins-plugins.txt << 'EOF'
# 基础插件
ant
build-timeout
credentials-binding
timestamper
ws-cleanup
gradle
workflow-aggregator
github-branch-source
pipeline-github-lib
pipeline-stage-view
git
ssh-slaves
matrix-auth
pam-auth
ldap
email-ext
mailer

# 高级插件
kubernetes
docker-workflow
docker-plugin
blueocean
sonar
role-strategy
rebuild
generic-webhook-trigger
http_request
ansicolor
build-user-vars-plugin
git-parameter
locale
localization-zh-cn
pipeline-utility-steps
simple-theme-plugin
periodicbackup
build-monitor-plugin
dingding-notifications
EOF

自动化插件安装脚本
#

cat > install-jenkins-plugins.sh << 'EOF'
#!/bin/bash

JENKINS_URL="http://localhost:8080"
JENKINS_USER="admin"
JENKINS_TOKEN="your-api-token"
PLUGIN_LIST="jenkins-plugins.txt"

# 检查 Jenkins CLI
if [ ! -f "jenkins-cli.jar" ]; then
    echo "下载 Jenkins CLI..."
    wget ${JENKINS_URL}/jnlpJars/jenkins-cli.jar
fi

# 安装插件
echo "开始安装插件..."
while IFS= read -r plugin; do
    # 跳过注释和空行
    [[ $plugin =~ ^#.*$ ]] && continue
    [[ -z "$plugin" ]] && continue

    echo "安装插件: $plugin"
    java -jar jenkins-cli.jar -s $JENKINS_URL -auth $JENKINS_USER:$JENKINS_TOKEN install-plugin $plugin
done < "$PLUGIN_LIST"

# 重启 Jenkins
echo "重启 Jenkins..."
java -jar jenkins-cli.jar -s $JENKINS_URL -auth $JENKINS_USER:$JENKINS_TOKEN restart

echo "插件安装完成!"
EOF

chmod +x install-jenkins-plugins.sh

Jenkins 版本管理
#

版本更新策略
#

Jenkins 提供两种发布版本:

  • LTS(长期支持版):每 12 周发布一次,稳定性更好,推荐生产环境使用
  • Weekly(周版本):每周发布,包含最新功能,适合测试环境

手动更新 Jenkins
#

方法一:YUM 包管理器更新
#

# 检查当前版本
java -jar /usr/lib/jenkins/jenkins.war --version

# 更新到最新 LTS 版本
yum update jenkins

# 重启服务
systemctl restart jenkins

方法二:WAR 包手动更新
#

# 创建更新脚本
cat > update-jenkins.sh << 'EOF'
#!/bin/bash

# 配置变量
JENKINS_HOME="/var/lib/jenkins"
JENKINS_WAR_DIR="/usr/lib/jenkins"
BACKUP_DIR="/backup/jenkins"
NEW_VERSION="2.414.1"  # 指定要更新的版本

# 创建备份目录
mkdir -p $BACKUP_DIR

echo "=== Jenkins 更新脚本 ==="
echo "当前版本: $(java -jar $JENKINS_WAR_DIR/jenkins.war --version)"
echo "目标版本: $NEW_VERSION"

# 停止 Jenkins 服务
echo "停止 Jenkins 服务..."
systemctl stop jenkins

# 备份当前版本
echo "备份当前版本..."
cp $JENKINS_WAR_DIR/jenkins.war $BACKUP_DIR/jenkins-$(date +%Y%m%d-%H%M%S).war.bak

# 下载新版本
echo "下载新版本..."
cd $JENKINS_WAR_DIR

# 优先使用国内镜像
if wget -q --spider https://mirrors.aliyun.com/jenkins/war/$NEW_VERSION/jenkins.war; then
    echo "使用阿里云镜像下载..."
    wget https://mirrors.aliyun.com/jenkins/war/$NEW_VERSION/jenkins.war -O jenkins.war.new
elif wget -q --spider https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/$NEW_VERSION/jenkins.war; then
    echo "使用清华镜像下载..."
    wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/$NEW_VERSION/jenkins.war -O jenkins.war.new
else
    echo "使用官方源下载..."
    wget https://updates.jenkins.io/download/war/$NEW_VERSION/jenkins.war -O jenkins.war.new
fi

# 验证下载
if [ -f "jenkins.war.new" ] && [ -s "jenkins.war.new" ]; then
    mv jenkins.war.new jenkins.war
    echo "WAR 包更新成功"
else
    echo "下载失败,恢复备份"
    cp $BACKUP_DIR/jenkins-$(date +%Y%m%d)*.war.bak jenkins.war
    exit 1
fi

# 启动 Jenkins 服务
echo "启动 Jenkins 服务..."
systemctl start jenkins

# 等待服务启动
sleep 30

# 验证更新
echo "验证更新结果..."
NEW_VERSION_CHECK=$(java -jar $JENKINS_WAR_DIR/jenkins.war --version)
echo "更新后版本: $NEW_VERSION_CHECK"

# 检查服务状态
if systemctl is-active --quiet jenkins; then
    echo "✓ Jenkins 服务运行正常"
    echo "✓ 更新完成!"
else
    echo "✗ Jenkins 服务启动失败,请检查日志"
    journalctl -u jenkins --no-pager -n 20
fi
EOF

chmod +x update-jenkins.sh

image-20210302201751849

自动化更新配置
#

配置自动更新检查
#

# 创建更新检查脚本
cat > check-jenkins-updates.sh << 'EOF'
#!/bin/bash

JENKINS_URL="http://localhost:8080"
CURRENT_VERSION=$(java -jar /usr/lib/jenkins/jenkins.war --version)

# 获取最新 LTS 版本信息
LATEST_LTS=$(curl -s https://updates.jenkins.io/stable/latestCore.txt)

echo "当前版本: $CURRENT_VERSION"
echo "最新 LTS: $LATEST_LTS"

if [ "$CURRENT_VERSION" != "$LATEST_LTS" ]; then
    echo "发现新版本,建议更新"
    # 可以在这里添加邮件通知或其他告警机制
else
    echo "已是最新版本"
fi
EOF

chmod +x check-jenkins-updates.sh

# 设置定期检查(每周检查一次)
echo "0 9 * * 1 /path/to/check-jenkins-updates.sh" | crontab -

容器化环境更新
#

Docker 容器更新
#

# 创建容器更新脚本
cat > update-jenkins-docker.sh << 'EOF'
#!/bin/bash

CONTAINER_NAME="jenkins"
NEW_IMAGE="jenkins/jenkins:lts"
BACKUP_DIR="/backup/jenkins"

echo "=== Docker Jenkins 更新脚本 ==="

# 创建数据备份
echo "备份 Jenkins 数据..."
mkdir -p $BACKUP_DIR
docker exec $CONTAINER_NAME tar czf /tmp/jenkins-backup-$(date +%Y%m%d).tar.gz -C /var/jenkins_home .
docker cp $CONTAINER_NAME:/tmp/jenkins-backup-$(date +%Y%m%d).tar.gz $BACKUP_DIR/

# 停止并删除旧容器
echo "停止旧容器..."
docker stop $CONTAINER_NAME
docker rm $CONTAINER_NAME

# 拉取新镜像
echo "拉取新镜像..."
docker pull $NEW_IMAGE

# 启动新容器
echo "启动新容器..."
docker run -d \
  --name $CONTAINER_NAME \
  --restart unless-stopped \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  $NEW_IMAGE

echo "更新完成!"
EOF

chmod +x update-jenkins-docker.sh

版本回滚
#

快速回滚脚本
#

cat > rollback-jenkins.sh << 'EOF'
#!/bin/bash

JENKINS_WAR_DIR="/usr/lib/jenkins"
BACKUP_DIR="/backup/jenkins"

echo "=== Jenkins 版本回滚脚本 ==="

# 列出可用备份
echo "可用的备份版本:"
ls -la $BACKUP_DIR/jenkins-*.war.bak

# 选择要回滚的版本
read -p "请输入要回滚的备份文件名: " BACKUP_FILE

if [ -f "$BACKUP_DIR/$BACKUP_FILE" ]; then
    echo "停止 Jenkins 服务..."
    systemctl stop jenkins

    echo "回滚到备份版本..."
    cp $BACKUP_DIR/$BACKUP_FILE $JENKINS_WAR_DIR/jenkins.war

    echo "启动 Jenkins 服务..."
    systemctl start jenkins

    echo "回滚完成!"
else
    echo "备份文件不存在: $BACKUP_DIR/$BACKUP_FILE"
fi
EOF

chmod +x rollback-jenkins.sh

企业级插件管理
#

核心插件分类
#

基础必备插件
#

插件名称功能说明使用场景
Git PluginGit 版本控制集成代码拉取和版本管理
Pipeline Plugin流水线核心功能Pipeline as Code
Credentials Plugin凭据管理安全存储密码、密钥等
Build Timeout构建超时控制防止构建无限期运行
Timestamper时间戳显示构建日志时间标记
Workspace Cleanup工作空间清理自动清理构建工作空间

用户界面增强
#

插件名称功能说明使用场景
Blue Ocean现代化 UI 界面更直观的流水线可视化
Simple Theme Plugin自定义主题企业品牌定制
Green Balls成功状态绿色显示更直观的状态显示
Build Monitor View构建状态监控面板大屏幕状态展示
AnsiColor彩色日志输出更易读的构建日志

源码管理集成
#

插件名称功能说明使用场景
GitHub PluginGitHub 集成GitHub 项目构建
GitLab PluginGitLab 集成GitLab 项目构建
Bitbucket PluginBitbucket 集成Bitbucket 项目构建
Git ParameterGit 参数化构建分支/标签选择构建
Generic Webhook Trigger通用 Webhook 触发器灵活的触发机制

构建工具集成
#

插件名称功能说明使用场景
Maven IntegrationMaven 构建支持Java 项目构建
Gradle PluginGradle 构建支持Gradle 项目构建
NodeJS PluginNode.js 环境管理前端项目构建
Docker PluginDocker 集成容器化构建和部署
Kubernetes PluginKubernetes 集成动态 Agent 和容器化部署

质量管控
#

插件名称功能说明使用场景
SonarQube Scanner代码质量检查静态代码分析
Checkstyle Plugin代码风格检查Java 代码规范检查
JUnit Plugin单元测试报告测试结果展示
Cobertura Plugin代码覆盖率测试覆盖率统计
Warnings Next Generation编译警告分析代码质量趋势分析

通知和集成
#

插件名称功能说明使用场景
Email Extension邮件通知增强构建结果邮件通知
Slack NotificationSlack 集成团队协作通知
DingTalk钉钉通知企业内部通知
WeChat Work Notification企业微信通知企业微信群通知
HTTP RequestHTTP API 调用第三方系统集成

安全和权限管理
#

插件名称功能说明使用场景
Role-based Authorization Strategy基于角色的权限管理细粒度权限控制
LDAP PluginLDAP 认证集成企业统一认证
Active Directory PluginAD 域认证Windows 域环境集成
GitLab AuthenticationGitLab OAuth 认证GitLab 用户认证
Matrix Authorization Strategy矩阵权限管理项目级权限控制

运维和监控
#

插件名称功能说明使用场景
Monitoring系统监控Jenkins 性能监控
Disk Usage Plugin磁盘使用统计存储空间管理
Build User Vars构建用户信息审计和追踪
Periodic Backup定期备份数据安全保护
Job Configuration History配置变更历史配置管理和审计

实用工具
#

插件名称功能说明使用场景
Pipeline Utility Steps流水线工具步骤文件操作、JSON 处理等
Rebuilder重新构建使用相同参数重新构建
Parameterized Trigger参数化触发复杂的构建触发逻辑
Copy Artifact构建产物复制跨项目产物共享
Archive Artifacts产物归档构建产物管理

国际化
#

插件名称功能说明使用场景
Locale Plugin语言环境控制界面语言设置
Localization: Chinese (Simplified)简体中文语言包中文界面支持

企业级安全配置
#

LDAP 统一认证集成
#

前置条件
#

  1. 安装 LDAP Plugin 插件
  2. 准备 OpenLDAP 服务器(参考 OpenLDAP 部署文档

配置步骤
#

步骤 1:启用 LDAP 认证
#

  1. 进入 Manage JenkinsConfigure Global Security
  2. Security Realm 部分选择 LDAP

步骤 2:配置 LDAP 服务器
#

# LDAP 配置参数示例
Server: ldap://ldap.your-domain.com:389
Root DN: dc=your-domain,dc=com
User search base: ou=people
User search filter: uid={0}
Group search base: ou=groups
Group search filter: (uniqueMember={0})
Manager DN: cn=admin,dc=your-domain,dc=com
Manager Password: your-admin-password
Display Name LDAP attribute: cn
Email Address LDAP attribute: mail

image-20210303100044191

步骤 3:高级 LDAP 配置
#

// Jenkins 配置脚本 (Groovy)
import jenkins.model.*
import hudson.security.*
import org.jenkinsci.plugins.ldap.*

def instance = Jenkins.getInstance()

// LDAP 配置
def ldapRealm = new LDAPSecurityRealm(
    "ldap://ldap.your-domain.com:389",  // server
    "dc=your-domain,dc=com",            // rootDN
    "ou=people,dc=your-domain,dc=com",  // userSearchBase
    "uid={0}",                          // userSearch
    "ou=groups,dc=your-domain,dc=com",  // groupSearchBase
    "(uniqueMember={0})",               // groupSearchFilter
    new LDAPSecurityRealm.LDAPGroupMembershipStrategy(), // groupMembershipStrategy
    "cn=admin,dc=your-domain,dc=com",   // managerDN
    "your-admin-password",              // managerPassword
    false,                              // inhibitInferRootDN
    false,                              // disableMailAddressResolver
    null,                               // cache
    null,                               // environmentProperties
    "cn",                               // displayNameAttributeName
    "mail",                             // mailAddressAttributeName
    IdStrategy.CASE_INSENSITIVE,        // userIdStrategy
    IdStrategy.CASE_INSENSITIVE         // groupIdStrategy
)

instance.setSecurityRealm(ldapRealm)
instance.save()

println "LDAP 配置完成"

步骤 4:测试 LDAP 连接
#

image-20210303100342139

LDAP 故障排除
#

# 创建 LDAP 连接测试脚本
cat > test-ldap-connection.sh << 'EOF'
#!/bin/bash

LDAP_SERVER="ldap.your-domain.com"
LDAP_PORT="389"
BASE_DN="dc=your-domain,dc=com"
ADMIN_DN="cn=admin,dc=your-domain,dc=com"
ADMIN_PASS="your-admin-password"

echo "=== LDAP 连接测试 ==="

# 测试基本连接
echo "测试 LDAP 服务器连接..."
ldapsearch -x -H ldap://$LDAP_SERVER:$LDAP_PORT -b "" -s base

# 测试管理员认证
echo "测试管理员认证..."
ldapsearch -x -H ldap://$LDAP_SERVER:$LDAP_PORT -D "$ADMIN_DN" -w "$ADMIN_PASS" -b "$BASE_DN" -s base

# 测试用户搜索
echo "测试用户搜索..."
ldapsearch -x -H ldap://$LDAP_SERVER:$LDAP_PORT -D "$ADMIN_DN" -w "$ADMIN_PASS" -b "ou=people,$BASE_DN" "(objectClass=inetOrgPerson)"

# 测试组搜索
echo "测试组搜索..."
ldapsearch -x -H ldap://$LDAP_SERVER:$LDAP_PORT -D "$ADMIN_DN" -w "$ADMIN_PASS" -b "ou=groups,$BASE_DN" "(objectClass=groupOfUniqueNames)"

echo "=== 测试完成 ==="
EOF

chmod +x test-ldap-connection.sh

基于角色的权限管理
#

安装和启用
#

  1. 安装 Role-based Authorization Strategy 插件
  2. 进入 Manage JenkinsConfigure Global Security
  3. Authorization 部分选择 Role-Based Strategy

image-20210303102611821

角色配置
#

步骤 1:定义全局角色
#

进入 Manage JenkinsManage and Assign RolesManage Roles

# 全局角色定义示例
admin       # 管理员角色 - 所有权限
developer   # 开发者角色 - 构建、查看权限
viewer      # 只读角色 - 仅查看权限
operator    # 运维角色 - 部署、监控权限

步骤 2:定义项目角色
#

# 项目角色模式示例
project-.*-admin     # 项目管理员
project-.*-developer # 项目开发者
project-.*-viewer    # 项目查看者

步骤 3:分配角色
#

进入 Manage JenkinsManage and Assign RolesAssign Roles

image-20210303103022143

权限配置脚本
#

// 自动化权限配置脚本
import jenkins.model.*
import hudson.security.*
import com.michelin.cio.hudson.plugins.rolestrategy.*

def instance = Jenkins.getInstance()

// 创建角色策略
def strategy = new RoleBasedAuthorizationStrategy()

// 定义全局角色
def globalRoles = [
    'admin': [
        'hudson.model.Hudson.Administer',
        'hudson.model.Hudson.Read'
    ],
    'developer': [
        'hudson.model.Hudson.Read',
        'hudson.model.Item.Build',
        'hudson.model.Item.Read',
        'hudson.model.Item.Workspace'
    ],
    'viewer': [
        'hudson.model.Hudson.Read',
        'hudson.model.Item.Read'
    ]
]

// 添加全局角色
globalRoles.each { roleName, permissions ->
    def role = new Role(roleName, permissions as Set)
    strategy.addRole(RoleBasedAuthorizationStrategy.GLOBAL, role)
}

// 定义项目角色
def projectRoles = [
    'project-admin': [
        'hudson.model.Item.Build',
        'hudson.model.Item.Cancel',
        'hudson.model.Item.Configure',
        'hudson.model.Item.Create',
        'hudson.model.Item.Delete',
        'hudson.model.Item.Read',
        'hudson.model.Item.Workspace'
    ],
    'project-developer': [
        'hudson.model.Item.Build',
        'hudson.model.Item.Cancel',
        'hudson.model.Item.Read',
        'hudson.model.Item.Workspace'
    ]
]

// 添加项目角色
projectRoles.each { roleName, permissions ->
    def role = new Role(roleName, "project-.*", permissions as Set)
    strategy.addRole(RoleBasedAuthorizationStrategy.PROJECT, role)
}

// 应用策略
instance.setAuthorizationStrategy(strategy)
instance.save()

println "权限配置完成"

主题和界面定制
#

现代化主题配置
#

方法一:Simple Theme Plugin
#

  1. 安装 Simple Theme Plugin 插件
  2. 进入 Manage JenkinsConfigure System
  3. 找到 Theme 部分
/* Jenkins Material Theme CSS */
@import url('https://cdn.jsdelivr.net/gh/afonsof/jenkins-material-theme@master/dist/material-blue.css');

/* 自定义样式 */
.jenkins-header {
    background-color: #1976d2 !important;
}

.jenkins-logo {
    content: url('https://your-domain.com/logo.png');
    width: 120px;
    height: 40px;
}

/* 侧边栏样式 */
#side-panel {
    background-color: #f5f5f5;
}

/* 构建状态颜色 */
.build-status-success {
    color: #4caf50 !important;
}

.build-status-failed {
    color: #f44336 !important;
}

方法二:Blue Ocean 现代界面
#

# 安装 Blue Ocean 插件套件
jenkins-cli.jar -s http://localhost:8080/ install-plugin blueocean

# 重启 Jenkins
systemctl restart jenkins

image-20210303104809646

企业品牌定制
#

<!-- 自定义 HTML 头部 -->
<style>
/* 企业 Logo */
.logo img {
    content: url('/userContent/company-logo.png');
    max-height: 40px;
}

/* 企业色彩主题 */
:root {
    --primary-color: #your-brand-color;
    --secondary-color: #your-secondary-color;
}

/* 自定义页脚 */
.footer {
    background-color: var(--primary-color);
    color: white;
    text-align: center;
    padding: 10px;
}

.footer::after {
    content: "© 2024 Your Company Name. All rights reserved.";
}
</style>

<script>
// 自定义 JavaScript
document.addEventListener('DOMContentLoaded', function() {
    // 添加企业信息
    const footer = document.createElement('div');
    footer.className = 'footer';
    document.body.appendChild(footer);

    // 自定义页面标题
    document.title = 'Your Company CI/CD Platform';
});
</script>

image-20210303105432114

响应式设计优化
#

/* 移动端适配 */
@media (max-width: 768px) {
    #main-panel {
        margin-left: 0;
    }

    #side-panel {
        transform: translateX(-100%);
        transition: transform 0.3s ease;
    }

    #side-panel.show {
        transform: translateX(0);
    }
}

/* 大屏幕优化 */
@media (min-width: 1920px) {
    .container {
        max-width: 1800px;
        margin: 0 auto;
    }
}

备份与恢复
#

自动化备份策略
#

完整备份脚本
#

cat > jenkins-backup.sh << 'EOF'
#!/bin/bash

# 配置变量
JENKINS_HOME="/var/lib/jenkins"
BACKUP_DIR="/backup/jenkins"
RETENTION_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="jenkins-backup-$DATE"

# 创建备份目录
mkdir -p $BACKUP_DIR

echo "=== Jenkins 备份脚本 ==="
echo "开始时间: $(date)"
echo "备份目录: $BACKUP_DIR"

# 停止 Jenkins 服务(可选,用于一致性备份)
read -p "是否停止 Jenkins 服务进行一致性备份?(y/N): " STOP_SERVICE
if [[ $STOP_SERVICE =~ ^[Yy]$ ]]; then
    echo "停止 Jenkins 服务..."
    systemctl stop jenkins
    RESTART_NEEDED=true
fi

# 创建备份
echo "创建备份: $BACKUP_NAME"
tar -czf "$BACKUP_DIR/$BACKUP_NAME.tar.gz" \
    --exclude="$JENKINS_HOME/workspace/*" \
    --exclude="$JENKINS_HOME/logs/*" \
    --exclude="$JENKINS_HOME/war/*" \
    --exclude="$JENKINS_HOME/.m2/repository/*" \
    -C "$(dirname $JENKINS_HOME)" \
    "$(basename $JENKINS_HOME)"

# 重启服务(如果之前停止了)
if [[ $RESTART_NEEDED == true ]]; then
    echo "重启 Jenkins 服务..."
    systemctl start jenkins
fi

# 验证备份
if [ -f "$BACKUP_DIR/$BACKUP_NAME.tar.gz" ]; then
    BACKUP_SIZE=$(du -h "$BACKUP_DIR/$BACKUP_NAME.tar.gz" | cut -f1)
    echo "✓ 备份完成: $BACKUP_NAME.tar.gz ($BACKUP_SIZE)"
else
    echo "✗ 备份失败"
    exit 1
fi

# 清理过期备份
echo "清理 $RETENTION_DAYS 天前的备份..."
find $BACKUP_DIR -name "jenkins-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete

# 备份报告
echo "=== 备份报告 ==="
echo "备份文件: $BACKUP_DIR/$BACKUP_NAME.tar.gz"
echo "备份大小: $BACKUP_SIZE"
echo "完成时间: $(date)"
echo "当前备份列表:"
ls -lh $BACKUP_DIR/jenkins-backup-*.tar.gz | tail -5
EOF

chmod +x jenkins-backup.sh

增量备份脚本
#

cat > jenkins-incremental-backup.sh << 'EOF'
#!/bin/bash

JENKINS_HOME="/var/lib/jenkins"
BACKUP_DIR="/backup/jenkins/incremental"
FULL_BACKUP_DIR="/backup/jenkins"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# 查找最近的完整备份
LAST_FULL_BACKUP=$(ls -t $FULL_BACKUP_DIR/jenkins-backup-*.tar.gz 2>/dev/null | head -1)

if [ -z "$LAST_FULL_BACKUP" ]; then
    echo "未找到完整备份,请先执行完整备份"
    exit 1
fi

# 获取完整备份的时间戳
FULL_BACKUP_TIME=$(stat -c %Y "$LAST_FULL_BACKUP")

echo "=== Jenkins 增量备份 ==="
echo "基于完整备份: $(basename $LAST_FULL_BACKUP)"

# 创建增量备份
find $JENKINS_HOME -newer "$LAST_FULL_BACKUP" -type f | \
    tar -czf "$BACKUP_DIR/jenkins-incremental-$DATE.tar.gz" -T -

echo "✓ 增量备份完成: jenkins-incremental-$DATE.tar.gz"
EOF

chmod +x jenkins-incremental-backup.sh

定时备份配置
#

# 配置 crontab 定时备份
cat > setup-backup-cron.sh << 'EOF'
#!/bin/bash

# 添加定时任务
(crontab -l 2>/dev/null; cat << 'CRON'
# Jenkins 备份任务
# 每天凌晨 2 点执行完整备份
0 2 * * * /path/to/jenkins-backup.sh >> /var/log/jenkins-backup.log 2>&1

# 每 6 小时执行增量备份
0 */6 * * * /path/to/jenkins-incremental-backup.sh >> /var/log/jenkins-backup.log 2>&1

# 每周日执行深度清理
0 3 * * 0 find /var/lib/jenkins/workspace -type d -mtime +7 -exec rm -rf {} + 2>/dev/null
CRON
) | crontab -

echo "定时备份任务已配置"
crontab -l
EOF

chmod +x setup-backup-cron.sh
./setup-backup-cron.sh

数据恢复
#

完整恢复脚本
#

cat > jenkins-restore.sh << 'EOF'
#!/bin/bash

BACKUP_DIR="/backup/jenkins"
JENKINS_HOME="/var/lib/jenkins"

echo "=== Jenkins 恢复脚本 ==="

# 列出可用备份
echo "可用的备份文件:"
ls -lh $BACKUP_DIR/jenkins-backup-*.tar.gz | nl

# 选择备份文件
read -p "请输入要恢复的备份文件编号: " BACKUP_NUM
BACKUP_FILE=$(ls $BACKUP_DIR/jenkins-backup-*.tar.gz | sed -n "${BACKUP_NUM}p")

if [ ! -f "$BACKUP_FILE" ]; then
    echo "备份文件不存在: $BACKUP_FILE"
    exit 1
fi

echo "选择的备份文件: $BACKUP_FILE"
read -p "确认恢复?这将覆盖现有数据 (yes/no): " CONFIRM

if [ "$CONFIRM" != "yes" ]; then
    echo "恢复已取消"
    exit 0
fi

# 停止 Jenkins 服务
echo "停止 Jenkins 服务..."
systemctl stop jenkins

# 备份当前数据
echo "备份当前数据..."
mv $JENKINS_HOME ${JENKINS_HOME}.backup.$(date +%Y%m%d_%H%M%S)

# 恢复数据
echo "恢复数据..."
mkdir -p $(dirname $JENKINS_HOME)
tar -xzf "$BACKUP_FILE" -C $(dirname $JENKINS_HOME)

# 修复权限
echo "修复权限..."
chown -R jenkins:jenkins $JENKINS_HOME

# 启动 Jenkins 服务
echo "启动 Jenkins 服务..."
systemctl start jenkins

# 等待服务启动
echo "等待服务启动..."
sleep 30

# 验证恢复
if systemctl is-active --quiet jenkins; then
    echo "✓ Jenkins 恢复成功"
    echo "请访问 Web 界面验证功能"
else
    echo "✗ Jenkins 启动失败,请检查日志"
    journalctl -u jenkins --no-pager -n 20
fi
EOF

chmod +x jenkins-restore.sh

监控与告警
#

系统监控
#

Jenkins 性能监控脚本
#

cat > jenkins-monitor.sh << 'EOF'
#!/bin/bash

JENKINS_URL="http://localhost:8080"
JENKINS_HOME="/var/lib/jenkins"
LOG_FILE="/var/log/jenkins-monitor.log"

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}

# 检查 Jenkins 服务状态
check_service() {
    if systemctl is-active --quiet jenkins; then
        log "✓ Jenkins 服务运行正常"
        return 0
    else
        log "✗ Jenkins 服务异常"
        return 1
    fi
}

# 检查 Web 界面响应
check_web_response() {
    local response_code=$(curl -s -o /dev/null -w "%{http_code}" $JENKINS_URL/login)
    if [ "$response_code" = "200" ]; then
        log "✓ Web 界面响应正常"
        return 0
    else
        log "✗ Web 界面响应异常 (HTTP $response_code)"
        return 1
    fi
}

# 检查磁盘空间
check_disk_space() {
    local usage=$(df $JENKINS_HOME | awk 'NR==2 {print $5}' | sed 's/%//')
    if [ $usage -lt 80 ]; then
        log "✓ 磁盘空间充足 (${usage}%)"
        return 0
    elif [ $usage -lt 90 ]; then
        log "⚠ 磁盘空间不足 (${usage}%)"
        return 1
    else
        log "✗ 磁盘空间严重不足 (${usage}%)"
        return 2
    fi
}

# 检查内存使用
check_memory() {
    local jenkins_pid=$(pgrep -f jenkins.war)
    if [ -n "$jenkins_pid" ]; then
        local memory_mb=$(ps -p $jenkins_pid -o rss= | awk '{print int($1/1024)}')
        log "✓ Jenkins 内存使用: ${memory_mb}MB"

        if [ $memory_mb -gt 4096 ]; then
            log "⚠ 内存使用较高"
            return 1
        fi
        return 0
    else
        log "✗ 无法获取 Jenkins 进程信息"
        return 1
    fi
}

# 检查构建队列
check_build_queue() {
    local queue_length=$(curl -s "$JENKINS_URL/queue/api/json" | jq '.items | length' 2>/dev/null || echo "0")
    log "构建队列长度: $queue_length"

    if [ $queue_length -gt 10 ]; then
        log "⚠ 构建队列过长"
        return 1
    fi
    return 0
}

# 主监控函数
main() {
    log "=== Jenkins 监控检查开始 ==="

    local issues=0

    check_service || ((issues++))
    check_web_response || ((issues++))
    check_disk_space || ((issues++))
    check_memory || ((issues++))
    check_build_queue || ((issues++))

    if [ $issues -eq 0 ]; then
        log "✓ 所有检查通过"
    else
        log "⚠ 发现 $issues 个问题"
        # 这里可以添加告警通知
        send_alert "Jenkins 监控发现 $issues 个问题"
    fi

    log "=== Jenkins 监控检查完成 ==="
}

# 告警通知函数
send_alert() {
    local message="$1"

    # 邮件通知
    if command -v mail >/dev/null 2>&1; then
        echo "$message" | mail -s "Jenkins 监控告警" admin@your-domain.com
    fi

    # 钉钉通知(需要配置 webhook)
    if [ -n "$DINGTALK_WEBHOOK" ]; then
        curl -X POST "$DINGTALK_WEBHOOK" \
            -H 'Content-Type: application/json' \
            -d "{\"msgtype\": \"text\", \"text\": {\"content\": \"$message\"}}"
    fi
}

main "$@"
EOF

chmod +x jenkins-monitor.sh

# 设置定时监控
echo "*/5 * * * * /path/to/jenkins-monitor.sh" | crontab -

Prometheus 监控集成
#

# 安装 Prometheus Metrics Plugin
jenkins-cli.jar -s http://localhost:8080/ install-plugin prometheus

# 配置 Prometheus 抓取
cat > prometheus-jenkins.yml << 'EOF'
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'jenkins'
    static_configs:
      - targets: ['localhost:8080']
    metrics_path: '/prometheus'
    scrape_interval: 30s
EOF

故障排除
#

常见问题诊断
#

启动问题
#

# Jenkins 启动失败诊断脚本
cat > diagnose-jenkins.sh << 'EOF'
#!/bin/bash

echo "=== Jenkins 故障诊断 ==="

# 检查 Java 环境
echo "1. 检查 Java 环境"
java -version
echo "JAVA_HOME: $JAVA_HOME"

# 检查 Jenkins 服务状态
echo -e "\n2. 检查服务状态"
systemctl status jenkins --no-pager

# 检查端口占用
echo -e "\n3. 检查端口占用"
netstat -tlnp | grep 8080

# 检查日志
echo -e "\n4. 最近的错误日志"
journalctl -u jenkins --no-pager -n 20 | grep -i error

# 检查磁盘空间
echo -e "\n5. 检查磁盘空间"
df -h /var/lib/jenkins

# 检查权限
echo -e "\n6. 检查权限"
ls -la /var/lib/jenkins | head -5

# 检查配置文件
echo -e "\n7. 检查配置文件"
if [ -f /etc/sysconfig/jenkins ]; then
    grep -v "^#" /etc/sysconfig/jenkins | grep -v "^$"
fi

echo -e "\n=== 诊断完成 ==="
EOF

chmod +x diagnose-jenkins.sh

性能问题
#

# 性能分析脚本
cat > jenkins-performance-analysis.sh << 'EOF'
#!/bin/bash

JENKINS_PID=$(pgrep -f jenkins.war)

if [ -z "$JENKINS_PID" ]; then
    echo "Jenkins 进程未运行"
    exit 1
fi

echo "=== Jenkins 性能分析 ==="
echo "进程 ID: $JENKINS_PID"

# CPU 使用率
echo -e "\nCPU 使用率:"
ps -p $JENKINS_PID -o pid,ppid,cmd,%cpu,%mem

# 内存详情
echo -e "\n内存使用详情:"
cat /proc/$JENKINS_PID/status | grep -E "(VmSize|VmRSS|VmHWM)"

# 线程信息
echo -e "\n线程数量:"
cat /proc/$JENKINS_PID/status | grep Threads

# GC 信息(如果启用了 GC 日志)
if [ -f /var/log/jenkins/gc.log ]; then
    echo -e "\n最近的 GC 活动:"
    tail -10 /var/log/jenkins/gc.log
fi

# 网络连接
echo -e "\n网络连接:"
netstat -an | grep :8080

echo -e "\n=== 分析完成 ==="
EOF

chmod +x jenkins-performance-analysis.sh

总结
#

部署优势
#

通过本指南,您可以成功部署一个企业级的 Jenkins CI/CD 平台,具有以下优势:

技术优势
#

  • 多种部署方式:支持传统部署、容器化部署和 Kubernetes 部署
  • 高可用性:通过主从架构和负载均衡实现高可用
  • 安全可靠:集成 LDAP 认证和基于角色的权限管理
  • 可扩展性:支持分布式构建和动态 Agent
  • 监控完善:集成监控告警和自动化运维

运维优势
#

  • 自动化备份:完整的备份恢复策略
  • 性能优化:JVM 调优和系统级优化
  • 故障排除:完善的诊断和恢复机制
  • 企业集成:支持多种企业级认证和通知系统

最佳实践
#

生产环境建议
#

  1. 资源规划:根据团队规模和项目数量合理规划资源
  2. 安全配置:启用 HTTPS、配置防火墙、定期更新
  3. 备份策略:建立完善的备份和灾难恢复计划
  4. 监控告警:部署全面的监控和告警体系
  5. 权限管理:实施最小权限原则和定期权限审计

扩展建议
#

  • 分布式构建:配置多个 Agent 节点提高构建效率
  • Pipeline 优化:使用声明式 Pipeline 和共享库
  • 工具链集成:集成代码质量、安全扫描、部署工具
  • 容器化 CI/CD:结合 Docker 和 Kubernetes 实现现代化 CI/CD

持续改进
#

Jenkins 作为 DevOps 工具链的核心,需要持续优化和改进:

  • 定期更新:保持 Jenkins 和插件的最新版本
  • 性能监控:持续监控系统性能和构建效率
  • 安全审计:定期进行安全检查和权限审计
  • 流程优化:根据团队反馈持续优化 CI/CD 流程

通过本指南的配置和最佳实践,您可以构建一个稳定、高效、安全的企业级 Jenkins CI/CD 平台,为团队的软件开发和交付提供强有力的支撑。

相关文章

企业级 Nexus3 制品仓库平台部署与运维完整指南
·6475 字·31 分钟
Docker DevOps Nexus3 Docker Artifact-Repository Devops Package-Management
Docker 部署 OpenLDAP 统一身份认证服务
·2305 字·11 分钟
DevOps Openldap Docker Authentication Devops
Kubernetes 部署企业级 Kafka 集群完整指南
·3156 字·15 分钟
Kubernetes Kafka Zookeeper Helm Kubernetes Streaming