第十一章:最佳实践

Jenkins 使用最佳实践,包括 Pipeline 编写、插件管理、安全加固、性能优化。

最后更新: 2024-01-15
页面目录

Jenkins 最佳实践

本章汇总 Jenkins 使用中的最佳实践,帮助您构建高效、可靠、安全的 CI/CD 系统。

Pipeline 最佳实践

1. 使用声明式 Pipeline

// ✅ 推荐:声明式 Pipeline
pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

// ❌ 避免:纯脚本式 Pipeline(除非必要)
node {
    stage('Build') {
        sh 'mvn clean package'
    }
}

2. 阶段命名规范

pipeline {
    stages {
        // ✅ 清晰的阶段名称
        stage('Checkout Source Code') { }
        stage('Install Dependencies') { }
        stage('Run Unit Tests') { }
        stage('Run Integration Tests') { }
        stage('Build Docker Image') { }
        stage('Deploy to Staging') { }
        stage('Smoke Test') { }
        stage('Deploy to Production') { }
        
        // ❌ 模糊的名称
        stage('Build') { }
        stage('Test') { }
        stage('Deploy') { }
    }
}

3. 错误处理

pipeline {
    stages {
        stage('Build') {
            steps {
                script {
                    try {
                        sh 'mvn clean package'
                    } catch (Exception e) {
                        echo "构建失败: ${e.message}"
                        // 可以发送通知
                        slackSend channel: '#alerts', 
                                  message: "构建失败: ${env.JOB_NAME}"
                        throw e
                    }
                }
            }
        }
    }
    
    post {
        always {
            // 总是清理资源
            cleanWs()
        }
        success {
            // 构建成功时执行
        }
        failure {
            // 构建失败时执行
        }
    }
}

4. 超时控制

pipeline {
    options {
        timeout(time: 1, unit: 'HOURS')
    }
    
    stages {
        stage('Long Running Task') {
            steps {
                timeout(time: 30, unit: 'MINUTES') {
                    sh './long-running-script.sh'
                }
            }
        }
    }
}

5. 参数化 Pipeline

// ✅ 良好的参数设计
parameters {
    choice(
        name: 'ENVIRONMENT',
        choices: ['dev', 'staging', 'production'],
        description: '部署环境'
    )
    string(
        name: 'VERSION',
        defaultValue: '',
        description: '版本号(留空自动生成)'
    )
    booleanParam(
        name: 'SKIP_TESTS',
        defaultValue: false,
        description: '跳过测试阶段'
    )
}

6. 环境变量管理

pipeline {
    environment {
        // ✅ 使用 credentials() 获取敏感信息
        API_KEY = credentials('api-key')
        DOCKER_REGISTRY = 'registry.example.com'
    }
    
    stages {
        stage('Build') {
            environment {
                // ✅ stage 级别的环境变量
                BUILD_MODE = 'release'
            }
            steps {
                sh 'echo $API_KEY' // 凭据会被自动屏蔽输出
            }
        }
    }
}

7. 并行执行

pipeline {
    stages {
        stage('Test') {
            stages {
                stage('Unit Tests') {
                    steps {
                        parallel(
                            backend: { sh 'mvn test -Dtest=Backend*' },
                            frontend: { sh 'npm test' },
                            api: { sh './test-api.sh' }
                        )
                    }
                }
            }
        }
    }
}

代码管理最佳实践

1. Jenkinsfile 放在代码库根目录

project/
├── Jenkinsfile          ✅ 根目录
├── src/
├── pom.xml
└── README.md

2. 多分支 Pipeline

// GitLab/GitHub 配置
// project 配置 - 扫描所有分支
// Branch Sources: Git
//     Project Repository: https://github.com/org/repo
//     Behaviors: 
//         - Discover branches
//         - Discover pull requests
//         - Build origin branches
//         - Build origin pull requests

3. 使用共享库

shared-library/
├── vars/
   ├── buildApp.groovy        可从 Pipeline 调用
   ├── deploy.groovy
   └── sendNotification.groovy
├── src/
   └── com/example/           工具类
       └── Utils.groovy
└── resources/
    └── templates/             资源文件

使用共享库:

@Library('shared-library') _

// 使用 vars 中的函数
buildApp image: 'maven:3.8', version: '1.0.0'

// 使用 src 中的类
script {
    def utils = new com.example.Utils()
    utils.helper()
}

插件管理

1. 最小化插件数量

建议 说明
只安装必需的 定期审查插件必要性
避免重复功能 不同插件可能有冲突
关注维护状态 选择活跃维护的插件

2. 插件版本管理

# 插件更新策略
# - 生产环境:使用 LTS 版本
# - 测试环境:验证新版本
# - 记录变更:维护插件变更日志

3. 推荐的核心插件

类别 插件
Pipeline pipeline-stage-view, workflow-aggregator
源码 git, github, gitlab
构建工具 maven-integration, gradle
通知 email-ext, slack
容器 docker-workflow, kubernetes
代码质量 sonar, checkstyle, pmd
测试报告 junit, coverage

安全最佳实践

1. 凭据管理

// ✅ 正确使用凭据
withCredentials([string(credentialsId: 'my-secret', variable: 'SECRET')]) {
    sh 'curl -H "Authorization: Bearer $SECRET" https://api.example.com'
}

// ❌ 避免:硬编码凭据
environment {
    API_KEY = 'sk-1234567890'  // 绝对不要这样!
}

2. 最小权限原则

// ✅ Pipeline 使用最低必要权限
pipeline {
    // 在 Pipeline 中限制权限
    options {
        buildAuthorizationToken(
            useExpiredTokenAsAdmin: false
        )
    }
}

3. 安全的构建脚本

pipeline {
    stages {
        stage('Build') {
            steps {
                script {
                    // ✅ 验证输入
                    assert params.VERSION ==~ /^\d+\.\d+\.\d+$/
                    
                    // ✅ 避免命令注入
                    def safeVersion = params.VERSION.replaceAll(/[^a-zA-Z0-9.-]/, '')
                    sh "docker build -t app:${safeVersion} ."
                    
                    // ❌ 危险:直接使用用户输入
                    // sh "docker build -t app:${params.VERSION} ."  // 可能被注入
                }
            }
        }
    }
}

性能最佳实践

1. 减少构建时间

pipeline {
    stages {
        stage('Build') {
            steps {
                // ✅ 利用缓存
                sh '''
                    if [ -d ~/.m2/repository ]; then
                        echo "Using Maven cache"
                    fi
                    mvn clean package -o  # offline mode if possible
                '''
            }
        }
    }
}

2. 并行阶段设计

pipeline {
    stages {
        stage('Test') {
            stages {
                stage('Unit & Integration') {
                    parallel {
                        stage('Unit Tests') { steps { sh 'mvn test' } }
                        stage('Integration Tests') { steps { sh 'mvn verify' } }
                        stage('Code Analysis') { steps { sh 'mvn sonar:sonar' } }
                    }
                }
            }
        }
    }
}

3. 清理工作区

post {
    always {
        // ✅ 总是清理
        cleanWs(
            deleteDirs: true,
            notFailBuild: true,
            patterns: [
                [type: 'Exclude', pattern: '**/important/**'],
                [type: 'DeleteNone', excludePattern: '**/*.log']
            ]
        )
    }
}

4. 避免重复构建

pipeline {
    options {
        // ✅ 避免相同代码的并发构建
        disableConcurrentBuilds()
        
        // ✅ 跳过无变更的构建
        skipDefaultCheckout()
    }
    
    triggers {
        // ✅ 轮询间隔合理
        pollSCM('H/5 * * * *')  // 5分钟轮询
    }
}

监控与日志

1. 构建日志管理

pipeline {
    options {
        // ✅ 时间戳
        timestamps()
        
        // ✅ 限制日志大小
        logstash {
            enabled = true
            maxLines = 10000
        }
    }
}

2. 监控指标

post {
    always {
        // ✅ 记录关键指标
        script {
            def duration = currentBuild.duration / 1000
            metrics {
                metric('build.duration', duration)
                metric('build.result', currentBuild.result)
            }
        }
    }
}

组织与管理

1. 目录结构

Jenkins (视图)
├── 📁 开发环境
│   ├── backend-service
│   ├── frontend-app
│   └── mobile-app
├── 📁 测试环境
│   ├── backend-service
│   └── ...
├── 📁 生产环境
│   └── ...
├── 📁 基础设施
│   ├── backup
│   └── deployment
└── 📁 库 (Library)
    └── shared-pipeline

2. 视图管理

视图过滤器:
- 全部视图:显示所有项目
- 我的视图:显示我参与的项目
- 按环境:按 dev/staging/prod 分组
- 按团队:按团队/部门分组

3. 构建命名策略

// ✅ 清晰的构建名称
currentBuild.displayName = "#${BUILD_NUMBER} - ${BRANCH_NAME} - ${new Date().format('yyyy-MM-dd HH:mm')}"

配置即代码

1. Job 配置代码化

// 使用 Job DSL
job('example') {
    description 'Example job'
    scm {
        git 'https://github.com/org/repo.git'
    }
    steps {
        maven 'clean package'
    }
    publishers {
        junit 'target/surefire-reports/**/*.xml'
    }
}

2. 配置校验

// 测试 Job DSL 配置
job('test-job') {
    // 测试配置
}

// 在 CI 中验证

文档与培训

1. 文档内容

文档类型 内容
架构文档 系统设计、组件关系
操作手册 日常操作流程
故障处理 常见问题解决方案
API 文档 Jenkins API 使用方法

2. 团队培训

  • 新成员 onboarding
  • 安全意识培训
  • Pipeline 编写规范
  • 故障排查技巧

下一步

接下来让我们学习常见故障的排查和解决方法。

👉 故障排除


💡 提示:将最佳实践纳入团队规范,并定期审查更新。