🚀 Jenkins 完整指南

从安装到部署的全方位教程

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 和插件更新
- 定期备份配置和数据
- 监控系统资源使用
- 建立日志收集和分析机制
- 准备灾难恢复计划