分布式构建
分布式构建是 Jenkins 的核心能力之一,它允许将构建任务分发到多个节点上并行执行,从而提高构建效率、实现环境隔离,并支持跨平台构建。本章将详细介绍 Jenkins 分布式构建的架构、配置和管理。
架构概述
Jenkins 采用 Master-Agent(主从)架构进行分布式构建。理解这个架构的各个组件是正确配置分布式构建的基础。
核心组件
Jenkins Controller(控制器/主节点):Jenkins 的核心服务,负责任务调度、配置管理、插件协调和 Web 界面服务。控制器本身也是一个节点(内置节点),可以执行构建任务,但出于安全性和性能考虑,生产环境通常不在控制器上执行构建。
Agent(代理/从节点):执行实际构建任务的工作节点。Agent 是一个轻量级的 Java 客户端程序(约 170KB),连接到控制器并执行分配给它的任务。Agent 可以运行在任何支持 Java 的操作系统上。
Executor(执行器):执行器是 Agent 上的构建槽位。每个执行器是一个独立的工作线程,可以执行一个构建任务。Agent 上配置的执行器数量决定了它可以同时运行的构建数量。
Node(节点):节点的概念涵盖了控制器和 Agent。在 Jenkins 中,节点是能够执行 Pipeline 的机器的抽象表示。
为什么需要分布式构建?
性能和可扩展性:单个节点能够承载的构建负载有限。通过添加更多 Agent,可以线性扩展构建能力,支持更多并发构建。当构建需求增长时,只需添加新的 Agent 即可,无需升级控制器硬件。
环境隔离:不同的项目可能需要不同的构建环境。例如,一个项目需要 Java 11,另一个需要 Java 21;一个需要 Windows 环境,另一个需要 Linux。通过为不同环境配置专门的 Agent,可以实现环境隔离,避免版本冲突。
安全性:构建过程中执行的代码可能来自外部贡献者(如开源项目的 PR),存在潜在的安全风险。将构建任务隔离在 Agent 上执行,即使构建过程被恶意代码利用,也不会影响控制器的安全。控制器通常存储着敏感的凭据和配置,不应暴露在构建环境中。
资源利用优化:通过标签和约束,可以将构建任务分配到最合适的节点上。例如,将 I/O 密集型任务分配到 SSD 节点,将 CPU 密集型任务分配到高性能 CPU 节点。
静态 Agent 配置
静态 Agent 是手动配置并持久存在的 Agent,适合稳定、长期使用的构建环境。
添加新 Agent
通过 Jenkins Web 界面添加 Agent:
- 导航到 Manage Jenkins → Nodes
- 点击 New Node
- 输入节点名称,选择 Permanent Agent
- 配置节点参数:
名称:Agent 的唯一标识符,建议使用有意义的命名,如 linux-build-01、windows-server-01。
描述:对 Agent 的简要说明,可包含用途、维护人员等信息。
执行器数量:该 Agent 可以并行执行的构建数量。设置建议:
- 1 个执行器:最安全的配置,避免资源竞争
- CPU 核心数:适合轻量级任务
- 需要根据实际内存、CPU、I/O 资源和构建任务的特点来确定
远程工作目录:Agent 上的工作空间根目录,如 /home/jenkins/agent 或 C:\jenkins\agent。确保 Agent 用户对该目录有读写权限。
标签:用于标识 Agent 特性的标签,多个标签用空格分隔,如 linux docker java17 maven。Pipeline 可以通过标签选择特定类型的 Agent。
启动方式:Agent 连接到控制器的方式,详见下文。
Agent 启动方式
Launch agent by connecting it to the controller(推荐)
Agent 主动连接到控制器,适用于 Agent 位于防火墙后的场景。这是最常用的启动方式,无需在控制器上开放额外的端口。
配置步骤:
- 在节点配置中选择此启动方式
- 记录显示的连接命令,格式如下:
java -jar agent.jar -url http://jenkins.example.com:8080/ -secret <secret-key> -name <agent-name>
- 在 Agent 机器上下载
agent.jar文件 - 运行连接命令
下载 agent.jar:
# 从 Jenkins 服务器下载
curl -o agent.jar http://jenkins.example.com:8080/jnlpJars/agent.jar
# 运行 Agent
java -jar agent.jar -url http://jenkins.example.com:8080/ \
-secret <secret-key> \
-name linux-agent-01
Launch agents via SSH
控制器通过 SSH 连接到 Agent,适用于控制器可以访问 Agent 的场景。需要在控制器上配置 SSH 凭据。
配置步骤:
- 在 Agent 节点创建 Jenkins 专用用户
- 配置 SSH 密钥认证
- 在 Jenkins 中配置 SSH 凭据(Manage Jenkins → Credentials)
- 选择 "Launch agents via SSH"
- 填写主机地址和凭据
Agent 配置示例:
# 在 Agent 上创建用户
sudo useradd -m -s /bin/bash jenkins
sudo mkdir -p /home/jenkins/.ssh
sudo chmod 700 /home/jenkins/.ssh
# 添加控制器的公钥
sudo nano /home/jenkins/.ssh/authorized_keys
sudo chmod 600 /home/jenkins/.ssh/authorized_keys
sudo chown -R jenkins:jenkins /home/jenkins/.ssh
Let Jenkins control this Windows agent as a Windows service
通过 Windows 服务管理 Agent,仅适用于 Windows 系统。需要在 Agent 上启用 WinRM 并配置远程管理。
将 Agent 注册为系统服务
为了 Agent 能够开机自启和后台运行,需要将其注册为系统服务。
Linux systemd 服务
创建 systemd 服务文件:
sudo nano /etc/systemd/system/jenkins-agent.service
服务配置内容:
[Unit]
Description=Jenkins Agent
After=network.target
[Service]
Type=simple
User=jenkins
Group=jenkins
WorkingDirectory=/home/jenkins/agent
ExecStart=/usr/bin/java -jar /home/jenkins/agent/agent.jar \
-url http://jenkins.example.com:8080 \
-secret <secret-key> \
-name linux-agent-01
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
启用和启动服务:
sudo systemctl daemon-reload
sudo systemctl enable jenkins-agent
sudo systemctl start jenkins-agent
sudo systemctl status jenkins-agent
Windows 服务
使用 Windows 任务计划程序或第三方工具(如 NSSM)将 Agent 注册为服务:
# 使用 NSSM 安装服务
nssm install JenkinsAgent
# 在弹出的对话框中配置:
# Application Path: C:\Program Files\Eclipse Adoptium\jdk-21\bin\java.exe
# Arguments: -jar C:\jenkins\agent.jar -url http://jenkins.example.com:8080 -secret <secret-key> -name windows-agent-01
# Startup directory: C:\jenkins
# 启动服务
nssm start JenkinsAgent
动态 Agent 配置
动态 Agent 根据构建需求自动创建和销毁,适合云环境和容器化场景。
Docker Agent
使用 Docker 插件动态创建容器作为 Agent。
安装插件:Docker Plugin
配置步骤:
- 导航到 Manage Jenkins → Nodes → Configure Clouds
- 添加 Docker 云配置
- 配置 Docker 主机连接(Unix socket 或 TCP)
Docker Agent 模板配置:
// Pipeline 中使用 Docker Agent
pipeline {
agent {
docker {
image 'maven:3.9-eclipse-temurin-21'
args '-v $HOME/.m2:/root/.m2 -e MAVEN_OPTS="-Xmx1024m"'
label 'docker'
}
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
}
Docker 云配置示例:
# Docker Cloud 配置
Docker URI: unix:///var/run/docker.sock
# 或远程 Docker 主机
Docker URI: tcp://docker-host:2375
# Agent 模板
Labels: docker linux java
Docker Image: jenkins/agent:latest
Remote FS Root: /home/jenkins/agent
Instance Capacity: 5
Kubernetes Agent
在 Kubernetes 集群中动态创建 Pod 作为 Agent。
安装插件:Kubernetes Plugin
配置步骤:
- 导航到 Manage Jenkins → Nodes → Configure Clouds
- 添加 Kubernetes 云配置
- 配置 Kubernetes 集群连接
Kubernetes 云配置:
Kubernetes URL: https://kubernetes.default
Kubernetes Namespace: jenkins
Jenkins URL: http://jenkins:8080
Jenkins Tunnel: jenkins:50000
Pipeline 中使用 Kubernetes Agent:
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
metadata:
labels:
app: jenkins-agent
spec:
containers:
- name: maven
image: maven:3.9-eclipse-temurin-21
command: ['cat']
tty: true
volumeMounts:
- name: m2-cache
mountPath: /root/.m2
- name: docker
image: docker:24.0
command: ['cat']
tty: true
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: m2-cache
persistentVolumeClaim:
claimName: maven-cache
- name: docker-sock
hostPath:
path: /var/run/docker.sock
'''
}
}
stages {
stage('Build') {
steps {
container('maven') {
sh 'mvn clean package'
}
}
}
stage('Docker Build') {
steps {
container('docker') {
sh 'docker build -t myapp .'
}
}
}
}
}
云平台 Agent
主流云平台都有对应的 Jenkins 插件支持动态创建 Agent。
Amazon EC2:EC2 Plugin 支持根据构建需求启动 EC2 实例作为 Agent,构建完成后自动终止。
Azure VM:Azure VM Agents Plugin 支持在 Azure 中动态创建虚拟机作为 Agent。
Google Cloud:Google Compute Engine Plugin 支持在 GCP 中动态创建 VM 实例。
Agent 管理最佳实践
标签命名规范
良好的标签命名可以简化 Agent 选择逻辑:
# 操作系统标签
linux, windows, macos
# 架构标签
amd64, arm64
# 工具标签
java11, java17, java21, maven, gradle, node20, python312
# 能力标签
docker, kubernetes, android, ios
# 环境标签
production, staging, testing
# 资源标签
high-memory, high-cpu, gpu
使用标签组合选择 Agent:
pipeline {
agent { label 'linux && docker && java17' }
stages {
// ...
}
}
执行器数量规划
执行器数量的设置需要考虑多个因素:
CPU 资源:CPU 密集型任务(如编译)建议一个执行器对应一个 CPU 核心;I/O 密集型任务(如下载依赖)可以设置更多执行器。
内存资源:需要评估每个构建任务的内存占用,确保并发构建不会导致内存不足。
磁盘 I/O:大量并发构建可能导致磁盘 I/O 瓶颈,需要根据存储性能调整。
网络带宽:需要大量网络传输的任务(如下载大型依赖)应适当减少并发数。
推荐配置:
- 小型项目:1-2 个执行器
- 中型项目:2-4 个执行器
- 大型项目:4-8 个执行器(或更多,需根据资源评估)
离线节点处理
当 Agent 离线时,可能会导致构建排队等待。建议配置:
pipeline {
agent {
label 'linux'
// 设置离线超时
offlineTimeout: 5 // 5分钟后放弃等待
}
}
定期检查节点状态:
// 使用 Pipeline 脚本检查节点状态
def nodes = Jenkins.instance.nodes
nodes.each { node ->
if (!node.toComputer().online) {
println "Warning: Node ${node.name} is offline"
}
}
工具配置
为 Agent 预配置常用工具,或使用容器镜像确保环境一致性:
全局工具配置(Manage Jenkins → Global Tool Configuration):
- JDK:配置多个版本(Java 11, 17, 21)
- Maven:配置常用版本(3.9.x)
- Gradle:配置常用版本(8.x)
- Node.js:配置 LTS 版本(20.x)
Pipeline 中引用工具:
pipeline {
agent { label 'linux' }
tools {
jdk 'JDK-17'
maven 'Maven-3.8'
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
}
工作空间管理
Agent 上的工作空间会随着构建累积占用磁盘空间,需要定期清理:
Pipeline 中清理:
post {
always {
cleanWs() // 清理工作空间
}
}
配置工作空间清理策略:
在 Agent 配置中设置:
- Workspace Root Directory:自定义工作空间目录
- Disable workspace auto-cleanup:禁用自动清理(不推荐)
Agent 故障排查
连接问题
Agent 无法连接到控制器:
- 检查网络连通性:
# 测试控制器端口可达性
telnet jenkins.example.com 8080
curl -I http://jenkins.example.com:8080
- 检查防火墙配置:
# Linux (firewalld)
sudo firewall-cmd --list-ports
sudo firewall-cmd --add-port=8080/tcp --permanent
# Linux (ufw)
sudo ufw allow 8080/tcp
# Windows
netsh advfirewall firewall add rule name="Jenkins" dir=in action=allow protocol=tcp localport=8080
- 检查 Agent JAR 版本是否与控制器兼容
性能问题
Agent 执行器全部繁忙:
- 检查构建队列:
http://jenkins.example.com:8080/queue - 增加执行器数量或添加新 Agent
- 分析构建耗时,优化长时间运行的构建
磁盘空间不足:
# 检查磁盘使用
df -h
# 查找大文件
du -sh /home/jenkins/agent/workspace/* | sort -hr | head -20
# 清理工作空间
rm -rf /home/jenkins/agent/workspace/*
日志分析
查看 Agent 日志:
# systemd 服务日志
journalctl -u jenkins-agent -f
# 直接运行时的输出
java -jar agent.jar -url ... -secret ... -name ...
查看控制器端的 Agent 日志:
- 导航到 Agent 页面,点击 "Log" 按钮
高级配置
多容器 Pod
在 Kubernetes Agent 中使用多个容器协同工作:
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.9-eclipse-temurin-21
command: ['cat']
tty: true
- name: kubectl
image: bitnami/kubectl:latest
command: ['cat']
tty: true
- name: helm
image: alpine/helm:latest
command: ['cat']
tty: true
'''
}
}
stages {
stage('Build') {
steps {
container('maven') {
sh 'mvn clean package'
}
}
}
stage('Deploy') {
steps {
container('helm') {
sh 'helm upgrade --install myapp ./chart'
}
}
}
}
}
Agent 资源限制
在 Kubernetes Agent 中设置资源限制:
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.9-eclipse-temurin-21
command: ['cat']
tty: true
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2"
'''
}
}
优先级和抢占
配置 Agent 的优先级,确保关键任务优先获得资源:
options {
// 设置高优先级
priority(100) // 数值越高优先级越高
}
小结
分布式构建是 Jenkins 扩展性的关键,合理配置和管理 Agent 可以显著提高构建效率:
- 架构理解:理解 Controller、Agent、Executor 的概念和职责分工
- 静态 Agent:适合稳定环境,配置简单,适合固定工作负载
- 动态 Agent:适合云环境和容器化场景,弹性扩展,按需创建
- 标签管理:使用标签组织 Agent,简化 Pipeline 配置
- 监控维护:定期检查 Agent 状态,及时处理离线和性能问题
下一步
- 多分支 Pipeline - 自动化多分支构建
- 共享库 - 封装和复用 Pipeline 代码
- 安全配置 - Agent 安全和权限管理