跳到主要内容

分布式构建

分布式构建是 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:

  1. 导航到 Manage Jenkins → Nodes
  2. 点击 New Node
  3. 输入节点名称,选择 Permanent Agent
  4. 配置节点参数:

名称:Agent 的唯一标识符,建议使用有意义的命名,如 linux-build-01windows-server-01

描述:对 Agent 的简要说明,可包含用途、维护人员等信息。

执行器数量:该 Agent 可以并行执行的构建数量。设置建议:

  • 1 个执行器:最安全的配置,避免资源竞争
  • CPU 核心数:适合轻量级任务
  • 需要根据实际内存、CPU、I/O 资源和构建任务的特点来确定

远程工作目录:Agent 上的工作空间根目录,如 /home/jenkins/agentC:\jenkins\agent。确保 Agent 用户对该目录有读写权限。

标签:用于标识 Agent 特性的标签,多个标签用空格分隔,如 linux docker java17 maven。Pipeline 可以通过标签选择特定类型的 Agent。

启动方式:Agent 连接到控制器的方式,详见下文。

Agent 启动方式

Launch agent by connecting it to the controller(推荐)

Agent 主动连接到控制器,适用于 Agent 位于防火墙后的场景。这是最常用的启动方式,无需在控制器上开放额外的端口。

配置步骤

  1. 在节点配置中选择此启动方式
  2. 记录显示的连接命令,格式如下:
java -jar agent.jar -url http://jenkins.example.com:8080/ -secret <secret-key> -name <agent-name>
  1. 在 Agent 机器上下载 agent.jar 文件
  2. 运行连接命令

下载 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 凭据。

配置步骤

  1. 在 Agent 节点创建 Jenkins 专用用户
  2. 配置 SSH 密钥认证
  3. 在 Jenkins 中配置 SSH 凭据(Manage Jenkins → Credentials)
  4. 选择 "Launch agents via SSH"
  5. 填写主机地址和凭据

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

配置步骤

  1. 导航到 Manage Jenkins → Nodes → Configure Clouds
  2. 添加 Docker 云配置
  3. 配置 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

配置步骤

  1. 导航到 Manage Jenkins → Nodes → Configure Clouds
  2. 添加 Kubernetes 云配置
  3. 配置 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 无法连接到控制器

  1. 检查网络连通性:
# 测试控制器端口可达性
telnet jenkins.example.com 8080
curl -I http://jenkins.example.com:8080
  1. 检查防火墙配置:
# 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
  1. 检查 Agent JAR 版本是否与控制器兼容

性能问题

Agent 执行器全部繁忙

  1. 检查构建队列:http://jenkins.example.com:8080/queue
  2. 增加执行器数量或添加新 Agent
  3. 分析构建耗时,优化长时间运行的构建

磁盘空间不足

# 检查磁盘使用
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 状态,及时处理离线和性能问题

下一步