分布式构建 #

分布式构建是Jenkins的核心特性之一,通过将构建任务分发到多个节点,可以显著提高构建效率和系统扩展性。

为什么需要分布式构建? #

单节点限制 #

  • 构建队列等待时间长
  • 资源竞争导致效率低下
  • 单点故障风险
  • 无法满足多样化环境需求

分布式优势 #

  • 并行构建提高效率
  • 资源隔离和专业化
  • 高可用性
  • 灵活扩展

架构模式 #

Master-Agent架构 #

text
                    ┌─────────────────┐
                    │  Jenkins Master │
                    │                 │
                    │  - 调度任务     │
                    │  - 管理配置     │
                    │  - 处理请求     │
                    └────────┬────────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
        ▼                    ▼                    ▼
┌───────────────┐    ┌───────────────┐    ┌───────────────┐
│   Agent 1     │    │   Agent 2     │    │   Agent 3     │
│   (Linux)     │    │  (Windows)    │    │   (macOS)     │
│               │    │               │    │               │
│  - Maven构建  │    │  - .NET构建   │    │  - iOS构建    │
│  - Docker     │    │  - IIS部署    │    │  - Xcode      │
└───────────────┘    └───────────────┘    └───────────────┘

职责分离 #

组件 职责
Master 任务调度、配置管理、用户界面、插件管理
Agent 执行构建、运行测试、部署应用

配置分布式构建 #

1. 配置Master #

禁用Master构建:

  1. 进入 Manage Jenkins → System
  2. 设置 # of executors 为 0

2. 添加Agent #

SSH Agent:

text
Name: linux-agent-01
Remote root directory: /home/jenkins/agent
Labels: linux docker maven
Launch method: Launch agents via SSH
Host: 192.168.1.100
Credentials: jenkins-ssh-key

JNLP Agent:

text
Name: windows-agent-01
Remote root directory: C:\jenkins\agent
Labels: windows dotnet
Launch method: Launch agent via Java Web Start

3. 配置标签 #

text
Agent 1: linux, docker, maven, java11
Agent 2: linux, docker, nodejs, angular
Agent 3: windows, dotnet, iis
Agent 4: macos, xcode, ios

任务调度策略 #

标签调度 #

groovy
pipeline {
    agent { label 'linux && docker' }
    
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp .'
            }
        }
    }
}

动态调度 #

groovy
pipeline {
    agent none
    
    stages {
        stage('Build') {
            parallel {
                stage('Linux') {
                    agent { label 'linux' }
                    steps {
                        sh 'build-linux.sh'
                    }
                }
                stage('Windows') {
                    agent { label 'windows' }
                    steps {
                        bat 'build-windows.bat'
                    }
                }
                stage('macOS') {
                    agent { label 'macos' }
                    steps {
                        sh 'build-macos.sh'
                    }
                }
            }
        }
    }
}

表达式调度 #

groovy
pipeline {
    agent {
        label 'linux && docker && !windows'
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp .'
            }
        }
    }
}

负载均衡 #

轮询调度 #

Jenkins默认使用轮询调度:

text
任务1 → Agent 1
任务2 → Agent 2
任务3 → Agent 3
任务4 → Agent 1
...

基于负载调度 #

groovy
options {
    retry(3)
    timeout(time: 30, unit: 'MINUTES')
}

自定义调度 #

groovy
def selectAgent(String label) {
    def nodes = jenkins.model.Jenkins.instance.nodes
    def candidates = nodes.findAll { node ->
        node.labelString.contains(label) && 
        node.toComputer().online && 
        node.toComputer().countBusy() < node.numExecutors
    }
    
    if (candidates.isEmpty()) {
        error "No available agent with label: ${label}"
    }
    
    return candidates.min { it.toComputer().countBusy() }.name
}

pipeline {
    agent { label selectAgent('linux') }
    
    stages {
        stage('Build') {
            steps {
                echo "Building on ${NODE_NAME}"
            }
        }
    }
}

高可用配置 #

多Agent冗余 #

text
Agent组: linux-build
├── linux-agent-01 (4 executors)
├── linux-agent-02 (4 executors)
└── linux-agent-03 (4 executors)

使用相同标签:

text
linux-agent-01: Labels: linux-build
linux-agent-02: Labels: linux-build
linux-agent-03: Labels: linux-build

故障转移 #

groovy
pipeline {
    agent { label 'linux-build' }
    
    options {
        retry(3)
        timeout(time: 30, unit: 'MINUTES')
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

容器化Agent #

Docker Agent #

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
            args '-v $HOME/.m2:/root/.m2'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Kubernetes Agent #

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command: ["cat"]
    tty: true
  - name: docker
    image: docker:latest
    command: ["cat"]
    tty: true
    volumeMounts:
    - name: docker-sock
      mountPath: /var/run/docker.sock
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
'''
        }
    }
    
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn clean package'
                }
            }
        }
        
        stage('Docker') {
            steps {
                container('docker') {
                    sh 'docker build -t myapp .'
                }
            }
        }
    }
}

跨平台构建 #

多平台矩阵 #

groovy
pipeline {
    agent none
    
    matrix {
        axes {
            axis {
                name 'OS'
                values 'linux', 'windows', 'macos'
            }
            axis {
                name 'JAVA_VERSION'
                values '8', '11', '17'
            }
        }
        
        stages {
            stage('Build') {
                agent { label "${OS}" }
                tools {
                    jdk "JDK ${JAVA_VERSION}"
                }
                steps {
                    script {
                        if (OS == 'windows') {
                            bat 'mvn clean package'
                        } else {
                            sh 'mvn clean package'
                        }
                    }
                }
            }
            
            stage('Test') {
                steps {
                    script {
                        if (OS == 'windows') {
                            bat 'mvn test'
                        } else {
                            sh 'mvn test'
                        }
                    }
                }
            }
        }
    }
}

资源管理 #

资源锁定 #

groovy
pipeline {
    agent any
    
    stages {
        stage('Deploy') {
            steps {
                lock(resource: 'production-server', quantity: 1) {
                    sh 'deploy.sh'
                }
            }
        }
    }
}

并发控制 #

groovy
pipeline {
    agent any
    
    options {
        disableConcurrentBuilds()
    }
    
    stages {
        stage('Deploy') {
            steps {
                sh 'deploy.sh'
            }
        }
    }
}

监控和诊断 #

节点状态 #

groovy
def checkNodes() {
    def nodes = jenkins.model.Jenkins.instance.nodes
    nodes.each { node ->
        def computer = node.toComputer()
        println "Node: ${node.name}"
        println "  Online: ${computer.online}"
        println "  Offline: ${computer.offline}"
        println "  Executors: ${node.numExecutors}"
        println "  Busy: ${computer.countBusy()}"
        println "  Idle: ${computer.countIdle()}"
    }
}

构建时间分析 #

groovy
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                script {
                    def start = System.currentTimeMillis()
                    sh 'mvn clean package'
                    def duration = System.currentTimeMillis() - start
                    echo "Build duration: ${duration}ms"
                }
            }
        }
    }
}

最佳实践 #

1. 专用Agent #

text
build-agent: 专门用于编译
test-agent: 专门用于测试
deploy-agent: 专门用于部署

2. 资源隔离 #

text
high-memory: 大内存任务
gpu: GPU任务
ssd: 高IO任务

3. 环境隔离 #

text
dev-agent: 开发环境
staging-agent: 预发布环境
prod-agent: 生产环境

4. 自动扩缩容 #

使用Kubernetes实现自动扩缩容:

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    resources:
      requests:
        memory: "2Gi"
        cpu: "1"
      limits:
        memory: "4Gi"
        cpu: "2"
'''
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

完整示例 #

groovy
pipeline {
    agent none
    
    environment {
        APP_NAME = 'myapp'
        VERSION = "${BUILD_NUMBER}"
    }
    
    stages {
        stage('Build') {
            parallel {
                stage('Backend') {
                    agent {
                        docker {
                            image 'maven:3.8-openjdk-11'
                            label 'docker'
                        }
                    }
                    steps {
                        sh 'mvn clean package -DskipTests'
                        stash includes: 'target/*.jar', name: 'backend'
                    }
                }
                
                stage('Frontend') {
                    agent {
                        docker {
                            image 'node:18'
                            label 'docker'
                        }
                    }
                    steps {
                        sh 'npm ci'
                        sh 'npm run build'
                        stash includes: 'dist/**', name: 'frontend'
                    }
                }
            }
        }
        
        stage('Test') {
            parallel {
                stage('Unit Tests') {
                    agent { label 'linux && test' }
                    steps {
                        unstash 'backend'
                        sh 'mvn test'
                    }
                    post {
                        always {
                            junit '**/target/surefire-reports/*.xml'
                        }
                    }
                }
                
                stage('Integration Tests') {
                    agent {
                        kubernetes {
                            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command: ["cat"]
    tty: true
  - name: postgres
    image: postgres:14
    env:
    - name: POSTGRES_PASSWORD
      value: test
'''
                        }
                    }
                    steps {
                        unstash 'backend'
                        container('maven') {
                            sh 'mvn verify -P integration'
                        }
                    }
                }
            }
        }
        
        stage('SonarQube') {
            agent { label 'sonar' }
            steps {
                unstash 'backend'
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar'
                }
            }
        }
        
        stage('Docker Build') {
            agent { label 'docker' }
            steps {
                unstash 'backend'
                unstash 'frontend'
                
                script {
                    docker.withRegistry('https://registry.example.com', 'docker-registry') {
                        def backendImage = docker.build("${APP_NAME}-backend:${VERSION}", '-f backend/Dockerfile .')
                        backendImage.push()
                        
                        def frontendImage = docker.build("${APP_NAME}-frontend:${VERSION}", '-f frontend/Dockerfile .')
                        frontendImage.push()
                    }
                }
            }
        }
        
        stage('Deploy') {
            matrix {
                axes {
                    axis {
                        name 'ENVIRONMENT'
                        values 'staging', 'production'
                    }
                }
                when {
                    anyOf {
                        branch 'main'
                        expression { ENVIRONMENT == 'staging' }
                    }
                }
                agent {
                    kubernetes {
                        yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: kubectl
    image: bitnami/kubectl:latest
    command: ["cat"]
    tty: true
'''
                    }
                }
                stages {
                    stage('Deploy') {
                        steps {
                            container('kubectl') {
                                lock(resource: "${ENVIRONMENT}-environment") {
                                    sh """
                                        kubectl set image deployment/${APP_NAME} \
                                            ${APP_NAME}=registry.example.com/${APP_NAME}:${VERSION} \
                                            -n ${ENVIRONMENT}
                                    """
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    post {
        always {
            node('linux') {
                echo "Build completed"
            }
        }
    }
}

下一步学习 #

小结 #

  • 分布式构建提高效率和扩展性
  • Master负责调度,Agent负责执行
  • 使用标签进行任务调度
  • 支持多种Agent类型
  • 容器化Agent提供动态扩展
  • 合理规划资源和环境隔离
最后更新:2026-03-28