节点管理 #

Jenkins支持分布式构建,通过节点(Node)和代理(Agent)可以将构建任务分发到多台机器上执行,提高构建效率和资源利用率。

架构概述 #

text
┌─────────────────────────────────────────────────────────────┐
│                     Jenkins Master                           │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │   调度器     │  │  任务队列   │  │  配置管理   │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘
         │                │                │
         ▼                ▼                ▼
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│   Agent 1   │  │   Agent 2   │  │   Agent 3   │
│   (Linux)   │  │  (Windows)  │  │   (Docker)  │
│             │  │             │  │             │
│  执行器: 4  │  │  执行器: 2  │  │  执行器: 8  │
└─────────────┘  └─────────────┘  └─────────────┘

Master与Agent #

Master节点 #

  • 运行Jenkins主服务
  • 处理HTTP请求
  • 管理配置和任务
  • 调度构建任务
  • 通常不执行构建(推荐)

Agent节点 #

  • 执行构建任务
  • 可以是物理机、虚拟机或容器
  • 支持多种操作系统
  • 支持多种连接方式

配置节点 #

访问节点管理 #

  1. 进入 Manage Jenkins
  2. 点击 Manage Nodes

创建新节点 #

  1. 点击 New Node
  2. 输入节点名称
  3. 选择类型:
    • Permanent Agent:永久代理
    • Copy from existing node:从现有节点复制

节点配置 #

配置项 说明
Name 节点名称
Description 描述
Number of executors 执行器数量
Remote root directory 远程根目录
Labels 标签
Usage 使用策略
Launch method 启动方式
Availability 可用性

执行器数量 #

执行器数量决定节点可以并行执行的任务数:

text
建议值 = CPU核心数
最大值 = CPU核心数 * 2

启动方式 #

1. Launch agents via SSH #

通过SSH连接到Agent:

text
Host: agent-host.example.com
Credentials: ssh-credentials
Host Key Verification Strategy: Known hosts file

配置步骤:

  1. 在Agent机器上创建jenkins用户
  2. 配置SSH密钥认证
  3. 在Jenkins中配置SSH凭据
  4. 设置远程工作目录

2. Start agents via Java Web Start #

通过JNLP启动Agent:

text
Agent Jar: 从Master下载agent.jar
启动命令: java -jar agent.jar -jnlpUrl http://jenkins/computer/agent-name/slave-agent.jnlp

适用于:

  • Agent在防火墙后
  • 无法从Master直接SSH连接

3. Launch agent via execution of command on the master #

通过命令启动:

text
Launch command: ssh jenkins@agent-host java -jar /path/to/agent.jar

4. Let Jenkins control this Windows slave as a Windows service #

Windows服务方式:

text
适用于Windows Agent
需要配置Windows服务

标签(Labels) #

定义标签 #

标签用于对节点进行分组:

text
Labels: linux docker maven java11

标签命名约定 #

text
操作系统: linux, windows, macos
工具: docker, maven, gradle, nodejs
环境: production, staging, dev
能力: gpu, high-memory, ssd

使用标签 #

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

多标签匹配 #

groovy
agent { label 'linux' }           // 任一标签为linux
agent { label 'linux && docker' } // 同时有linux和docker标签
agent { label 'linux || macos' }  // 有linux或macos标签

使用策略 #

Use this node as much as possible #

尽可能使用此节点:

text
Usage: Use this node as much as possible

Only build jobs with label expressions matching this node #

只构建匹配标签的任务:

text
Usage: Only build jobs with label expressions matching this node

在Pipeline中使用Agent #

agent any #

使用任意可用节点:

groovy
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
    }
}

agent none #

在各Stage中指定:

groovy
pipeline {
    agent none
    
    stages {
        stage('Build') {
            agent { label 'build' }
            steps {
                sh 'mvn clean package'
            }
        }
        
        stage('Test') {
            agent { label 'test' }
            steps {
                sh 'mvn test'
            }
        }
        
        stage('Deploy') {
            agent { label 'production' }
            steps {
                sh 'deploy.sh'
            }
        }
    }
}

agent label #

使用标签指定节点:

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

agent node #

使用节点配置:

groovy
pipeline {
    agent {
        node {
            label 'linux'
            customWorkspace '/tmp/custom'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Docker Agent #

使用Docker镜像 #

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
            label 'docker'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Docker配置选项 #

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
            label 'docker'
            args '-v $HOME/.m2:/root/.m2 -e MAVEN_OPTS="-Xmx1024m"'
            registryUrl 'https://registry.example.com'
            registryCredentialsId 'docker-registry'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Dockerfile Agent #

groovy
pipeline {
    agent {
        dockerfile {
            filename 'Dockerfile.build'
            dir 'docker'
            additionalBuildArgs '--build-arg VERSION=1.0'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Kubernetes Agent #

动态Pod #

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 .'
                }
            }
        }
    }
}

使用YAML文件 #

groovy
pipeline {
    agent {
        kubernetes {
            yamlFile 'kubernetes/pod.yaml'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn clean package'
                }
            }
        }
    }
}

节点环境变量 #

配置节点环境变量 #

text
Node Properties:
  ☑ Environment variables
  PATH+MAVEN=/opt/maven/bin
  JAVA_HOME=/usr/lib/jvm/java-11

在Pipeline中使用 #

groovy
pipeline {
    agent { label 'linux' }
    
    stages {
        stage('Build') {
            steps {
                echo "Node: ${NODE_NAME}"
                echo "Labels: ${NODE_LABELS}"
                sh 'mvn clean package'
            }
        }
    }
}

节点工具配置 #

配置节点工具 #

text
Node Properties:
  ☑ Tool Locations
  Maven: /opt/maven
  JDK: /usr/lib/jvm/java-11
  Git: /usr/bin/git

在Pipeline中使用 #

groovy
pipeline {
    agent { label 'linux' }
    
    tools {
        maven 'Maven 3.8'
        jdk 'JDK 11'
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

节点监控 #

状态检查 #

groovy
steps {
    script {
        def computer = jenkins.model.Jenkins.instance.getComputer(env.NODE_NAME)
        echo "Offline: ${computer.offline}"
        echo "Offline Cause: ${computer.offlineCause}"
        echo "Idle: ${computer.idle}"
        echo "Busy: ${computer.countBusy()}"
    }
}

磁盘空间监控 #

groovy
steps {
    script {
        def computer = jenkins.model.Jenkins.instance.getComputer(env.NODE_NAME)
        def diskSpace = computer.node.toComputer().getDiskSpace()
        echo "Disk Space: ${diskSpace}"
    }
}

最佳实践 #

1. 分离Master和Agent #

text
Master: 只负责调度和管理
Agent: 执行所有构建任务

2. 合理设置执行器数量 #

text
CPU密集型任务: 执行器数 = CPU核心数
IO密集型任务: 执行器数 = CPU核心数 * 2

3. 使用标签分组 #

text
linux, docker, maven, java11, production

4. 配置节点工具 #

text
每个节点配置自己的工具路径
避免依赖全局配置

5. 监控节点状态 #

text
定期检查节点是否在线
监控磁盘空间和内存使用

完整示例 #

groovy
pipeline {
    agent none
    
    environment {
        APP_NAME = 'myapp'
        VERSION = "${BUILD_NUMBER}"
    }
    
    stages {
        stage('Build') {
            agent {
                docker {
                    image 'maven:3.8-openjdk-11'
                    args '-v $HOME/.m2:/root/.m2'
                }
            }
            steps {
                sh 'mvn clean package -DskipTests'
                stash includes: 'target/*.jar', name: 'artifacts'
            }
        }
        
        stage('Test') {
            agent { label 'linux && test' }
            parallel {
                stage('Unit Tests') {
                    steps {
                        unstash 'artifacts'
                        sh 'mvn test'
                    }
                    post {
                        always {
                            junit '**/target/surefire-reports/*.xml'
                        }
                    }
                }
                stage('Integration Tests') {
                    steps {
                        unstash 'artifacts'
                        sh 'mvn verify -P integration'
                    }
                }
            }
        }
        
        stage('SonarQube') {
            agent { label 'sonar' }
            steps {
                unstash 'artifacts'
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar'
                }
            }
        }
        
        stage('Docker Build') {
            agent { label 'docker' }
            steps {
                unstash 'artifacts'
                script {
                    docker.withRegistry('https://registry.example.com', 'docker-registry') {
                        def image = docker.build("myapp:${VERSION}")
                        image.push()
                    }
                }
            }
        }
        
        stage('Deploy') {
            agent {
                kubernetes {
                    yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: kubectl
    image: bitnami/kubectl:latest
    command:
    - cat
    tty: true
'''
                }
            }
            when {
                branch 'main'
            }
            steps {
                container('kubectl') {
                    sh """
                        kubectl set image deployment/${APP_NAME} \
                            ${APP_NAME}=registry.example.com/${APP_NAME}:${VERSION}
                    """
                }
            }
        }
    }
    
    post {
        always {
            echo "Build completed on node: ${NODE_NAME}"
        }
    }
}

下一步学习 #

小结 #

  • 节点管理实现分布式构建
  • 支持多种连接方式
  • 使用标签分组节点
  • Docker和Kubernetes提供动态Agent
  • 合理设置执行器数量
  • 分离Master和Agent职责
最后更新:2026-03-28