Skip to content

Jenkins Controller、Agent与构建执行全过程

Jenkins不是“网页上点一下,然后服务器执行Shell”。一次构建要经过触发、队列、节点匹配、Executor占用、Workspace准备、代码检出、Step执行、日志回传、制品归档和清理。理解这些对象后,才能解释为什么任务一直排队、为什么同一Job出现 workspace@2、为什么Controller磁盘满会让所有流水线异常。

学习目标

  1. 区分Controller、Node、Agent进程、Executor、Queue、Workspace、Job和Build。
  2. 解释Webhook到Build完成的完整链路。
  3. 说明Queue等待的所有常见原因。
  4. 解释Executor为什么不是CPU核,也不是线程池大小的直接映射。
  5. 说明Workspace的创建、复用、并发目录和污染风险。
  6. 区分Workspace、stash、archive、fingerprint、制品仓库和镜像仓库。
  7. 解释JENKINS_HOME保存什么,以及为什么Controller备份不能只复制Workspace。
  8. 区分现代Jenkins运行Java与业务项目构建JDK 7/8/17/21。
  9. 设计Controller不执行重构建、Agent最小权限和凭据边界。
  10. 定位Queue卡住、Agent离线、磁盘满、工具缺失和Workspace串扰。

一、核心对象关系

mermaid
flowchart TD
    A["用户、Webhook或定时器"] --> B["Jenkins Controller"]
    B --> C["Job配置与Jenkinsfile"]
    B --> D["Build Queue"]
    D --> E["Node标签与资源匹配"]
    E --> F["Agent进程"]
    F --> G["Executor槽位"]
    G --> H["Workspace"]
    H --> I["Git、Maven、测试、Docker等Step"]
    I --> J["日志、状态和测试结果"]
    I --> K["Jar、镜像或其他制品"]
    J --> B

二、Controller到底负责什么

Controller负责控制面:

  • Web UI和API。
  • 用户、权限和凭据元数据。
  • Job/Pipeline定义。
  • Webhook、定时和手动触发。
  • Queue调度。
  • Node与Agent管理。
  • Pipeline执行状态持久化。
  • Build历史、日志索引、测试结果和归档元数据。
  • 插件加载与系统配置。

Controller不应长期承担所有Maven编译、Docker构建和生产部署。重任务会竞争Controller的CPU、Heap、磁盘和线程,最终影响所有Job调度与UI。

常见安全起点是Controller内置节点Executor设为0,只通过明确Agent执行构建。是否能完全做到取决于系统任务和插件,需验证。

三、Agent、Node和Executor区别

概念含义
NodeJenkins中可调度计算资源的逻辑定义
Agent连接Controller并执行远程任务的进程/运行环境
ExecutorNode可同时占用的构建执行槽位

一台Linux机器可定义为一个Node,运行一个Agent进程,并配置多个Executor。但Executor不是CPU核,也不自动限制Maven线程、测试子进程或Docker容器资源。

四、Executor为什么不能盲目调大

若Node配置8个Executor,表示最多可让8个需要Executor的构建同时占用该Node。每个构建还可能启动:

  • Maven/Gradle并行线程。
  • Java测试JVM。
  • Node.js构建进程。
  • Docker BuildKit。
  • 集成测试数据库和中间件。
  • 压缩、扫描和上传进程。

因此:

text
Executor数 × 单Build峰值CPU/内存/磁盘IO

才接近容量。Executor过多会导致OOM、磁盘抖动、测试超时和构建整体变慢;过少则Queue等待。

五、Agent如何连接Controller

常见模式:

  • Controller通过SSH启动/管理远程Agent。
  • Agent主动连接Controller的Inbound模式。
  • WebSocket等穿越反向代理的连接方式。
  • Kubernetes插件动态创建Agent Pod。
  • 云插件按需创建虚拟机。

旧资料常把Inbound Agent统称JNLP Agent,现代界面和协议名称可能变化。实际加密、认证、端口和版本以当前Jenkins文档为准。

Agent连接只解决控制通道,不自动提供Maven、Docker、kubectl和业务网络。工具和权限仍需在Agent环境准备。

六、一次触发如何进入Queue

mermaid
flowchart TD
    A["Webhook/手动/定时触发"] --> B["创建Queue Item"]
    B --> C["检查Job是否允许并发"]
    C --> D["解析需要的Label/Node"]
    D --> E{"是否有在线且匹配的Node"}
    E -- "否" --> F["留在Queue并显示原因"]
    E -- "是" --> G{"是否有空闲Executor"}
    G -- "否" --> F
    G -- "是" --> H["分配Executor并创建Run"]
    H --> I["准备Workspace并执行"]

Queue Item还不是Build进程。只有满足调度条件并获得执行资源后,才进入实际运行。

七、Queue一直等待的常见原因

提示方向常见原因
Waiting for next available executor匹配Node的Executor都忙
Label不存在/不匹配Jenkinsfile要求的label没有Node
Node offlineAgent断连、磁盘阈值或人为下线
Waiting for builds to finish禁止并发、里程碑或锁
Throttle/Lock等待插件限制并发或共享资源
Flyweight/Controller任务等待Pipeline控制步骤或Controller压力
Quiet period配置了延迟合并触发

排查不能只“重启Jenkins”,应读取Queue原因、Node状态、Executor占用、标签表达式和上一个Build。

八、Label是能力声明,不应只是机器名

可以给Agent标注:

text
linux && jdk8 && docker
linux && jdk17 && kubectl
windows && node20

Pipeline:

groovy
agent { label 'linux && jdk8 && docker' }

Label表示能力与约束,比 agent-01更可维护。但Label不是事实自动探测:节点被错误打上 jdk8,实际没安装JDK 8,构建仍会失败。应在镜像、配置管理和启动验收中保证标签真实。

九、现代Jenkins与JDK 7/8业务构建边界

现代Jenkins Controller/Agent进程通常要求受支持的现代Java版本,具体基线随Jenkins LTS升级变化,不能假定仍能运行在JDK 8。

但这不妨碍构建JDK 7/8业务:

text
Controller/Agent运行时:使用Jenkins当前支持的Java
业务编译工具链:选择JDK 7、JDK 8、JDK 17或JDK 21

实现方式:

  • Jenkins Tool配置选择不同JDK。
  • Maven Toolchains。
  • 固定构建容器镜像。
  • 不同Label的Agent。

JDK 7/8构建还要固定具体更新版本、Maven/Gradle兼容性、TLS仓库访问和编译参数,不能只写“Java 8”。

十、动态Agent生命周期

Kubernetes动态Agent概念流程:

mermaid
flowchart TD
    A["Queue出现k8s-agent需求"] --> B["Jenkins Kubernetes插件请求创建Pod"]
    B --> C["调度Pod并启动Agent容器"]
    C --> D["Agent连接Controller"]
    D --> E["获得Executor并执行Build"]
    E --> F["上传日志、测试结果和制品"]
    F --> G["Pod按策略删除"]

动态Agent减少环境漂移和空闲成本,但要处理镜像拉取、Pod启动延迟、PVC、网络策略、ServiceAccount、缓存和失败现场保留。

十一、Workspace是什么

Workspace是某次Job在某个Node上的工作目录,通常包含:

  • 检出的源码。
  • 构建中间文件。
  • 测试输出。
  • 临时脚本。
  • 未归档产物。

它不是可靠长期存储,也不应成为部署事实源。Agent删除、Workspace清理、并发构建和Node迁移都可能让文件消失。

十二、为什么出现workspace@2

当同一Job允许并发,并在同一Node上同时执行时,Jenkins需要避免两个Build写同一目录,可能创建:

text
workspace/job-name
workspace/job-name@2
workspace/job-name@3

因此脚本不能硬编码绝对Workspace路径,也不能假定另一次Build会看到当前目录。

并发隔离仍不完整:两个Workspace可能共享同一Maven本地仓库、Docker daemon、固定端口、测试数据库和部署环境,仍会冲突。

十三、Workspace污染如何发生

text
Build 100生成旧class/配置
→ 未清理
→ Build 101切换分支
→ 工具增量构建复用旧文件
→ 产物混入上一版本内容

治理:

  • 构建工具执行clean或可靠增量策略。
  • 必要时 deleteDir()/Workspace Cleanup。
  • 不把凭据文件留在Workspace。
  • 动态Agent提供干净环境。
  • 缓存目录与源码目录分离。

清理不是越多越好:每次删除所有依赖缓存会显著拖慢构建,应区分可复用依赖缓存和必须隔离的业务输出。

十四、Checkout全过程

mermaid
flowchart TD
    A["Agent准备Workspace"] --> B["凭据访问Git"]
    B --> C["获取指定仓库和Ref"]
    C --> D["Checkout具体Commit"]
    D --> E["记录Commit、分支和变更集"]
    E --> F["后续Build只使用该Commit"]

正式发布应记录具体Commit SHA,不只记录分支名。分支在构建期间可能继续移动;同一Build必须绑定不可变Commit。

浅克隆、Reference仓库和缓存可以加速,但会影响Tag、历史、Changelog和某些版本插件,需要按流水线需求选择。

十五、Job、Build和Run

  • Job:长期任务定义。
  • Build/Run:Job的一次具体执行。
  • Build Number:Job内递增标识,不等于全局版本。
  • Result:SUCCESS、UNSTABLE、FAILURE、ABORTED等。
  • Cause:Webhook、用户、上游任务、定时器等触发原因。

UNSTABLE通常表示流水线完成但测试等质量门不完全通过,不应与SUCCESS混用。是否允许部署必须由明确策略决定。

十六、Workspace、stash、archive和制品仓库

存储方式用途生命周期/边界
Workspace当前Node构建工作目录可清理、不可长期依赖
stash/unstash同一Pipeline不同Node/Stage传小型文件Controller/制品管理链路有开销,不适合巨大文件
archiveArtifacts归档到Build记录受Controller/Artifact Manager存储与保留策略影响
Maven/Nexus制品库保存Jar等版本制品跨Pipeline、可审计、可推广
Registry保存OCI镜像使用Tag和Digest,适合部署

原则:制品一次构建,多环境推广;测试和生产不要分别重新编译同一Commit。

十七、fingerprint解决什么

Fingerprint通过文件摘要关联制品与Build,帮助追踪某Jar在哪次构建产生、被哪些下游任务使用。但它不是数字签名,也不证明制品没有恶意来源。供应链还需要签名、SBOM、扫描和制品仓库权限。

十八、JENKINS_HOME保存什么

常见包括:

  • 系统和Job配置。
  • 插件及版本。
  • 凭据加密数据与密钥材料。
  • Build记录和日志。
  • Pipeline执行状态。
  • 用户、节点和队列相关状态。
  • 归档产物,取决于Artifact Manager。

JENKINS_HOME是Controller关键状态,磁盘满或损坏会影响全站。备份必须保证一致性、加密、访问控制和恢复演练。

十九、为什么不能只备份Workspace

Workspace只是构建临时目录,不包含完整Job配置、插件、凭据密钥和Build状态。反过来,备份JENKINS_HOME也不等于备份外部Nexus、Registry、Git和云凭据系统。

恢复计划应覆盖:

  • Jenkins核心版本。
  • 插件锁定与兼容。
  • JENKINS_HOME。
  • Configuration as Code。
  • 外部数据库/制品库/Registry。
  • DNS、证书和Agent接入。

二十、日志和状态如何回传

Agent执行Shell/Batch等Step,标准输出通过Agent通道回传并写入Build日志。网络中断时,运行中进程、日志和Pipeline状态取决于Agent类型、Step和持久化策略。

不要输出:

  • 密码和Token。
  • kubeconfig全文。
  • 私钥。
  • Docker登录配置。
  • 生产环境变量全集。

Credentials masking只是降低意外打印风险,不是绝对防泄漏;编码、分段输出或恶意脚本可能绕过。

二十一、Controller与Agent信任边界

Agent能执行仓库中的代码。若不可信PR可以在有生产凭据的Agent运行,就可能窃取Secret或控制部署环境。

应隔离:

  • 不可信PR Agent与生产部署Agent。
  • 开发凭据与生产凭据。
  • Docker Socket和宿主机权限。
  • Kubernetes ServiceAccount。
  • 出网和内网访问。
  • Workspace与缓存。

不要让普通构建Agent长期拥有生产集群管理员权限。

二十二、凭据什么时候注入

凭据应在最小Step范围内绑定:

groovy
withCredentials([string(credentialsId: 'deploy-token', variable: 'DEPLOY_TOKEN')]) {
    sh './deploy.sh'
}

边界:

  • 不写入Jenkinsfile。
  • 不写入镜像层。
  • 不归档到artifact。
  • 不输出到日志。
  • 不留在Workspace。
  • 不传给不可信子进程。
  • 使用后端最小权限和短期凭据。

二十三、插件为什么是核心风险

Jenkins大量能力由插件提供,插件运行在Controller或参与Agent执行,可能影响:

  • 安全漏洞。
  • Pipeline语义。
  • 凭据处理。
  • 页面和API。
  • 数据格式和升级。

不能在生产随意点击“全部更新”。应维护插件清单、依赖、兼容矩阵、测试环境、备份和回退方案。插件降级不一定兼容已升级的数据格式。

二十四、Controller高可用边界

Jenkins传统Controller是有状态系统。仅启动两个Controller指向同一JENKINS_HOME并不自动形成安全Active-Active,可能造成文件和任务状态冲突。

高可用通常依赖:

  • 快速恢复而非简单双写。
  • 可靠JENKINS_HOME存储与备份。
  • Configuration as Code。
  • 外部Artifact Manager。
  • 动态Agent。
  • DNS/LB切换。
  • 明确RPO/RTO和演练。

二十五、商业执行链:Spring Boot镜像发布

mermaid
flowchart TD
    A["Git Webhook携带仓库事件"] --> B["Controller创建Queue Item"]
    B --> C["匹配linux+jdk8+docker Agent"]
    C --> D["Executor分配Workspace"]
    D --> E["Checkout固定Commit"]
    E --> F["JDK 8编译与测试"]
    F --> G["构建镜像并记录Digest"]
    G --> H["推送受信Registry"]
    H --> I["部署测试环境并验证"]
    I --> J["审批后推广同一Digest到生产"]
    J --> K["健康、指标和回滚验证"]

重点是同一镜像Digest从测试推广到生产,而不是生产阶段重新构建。

二十六、Queue卡住Runbook

  1. 打开Queue Item查看原因。
  2. 检查Job是否禁用并发或等待锁。
  3. 检查Jenkinsfile要求的Label。
  4. 检查匹配Node是否在线。
  5. 检查Executor是否占满。
  6. 检查磁盘/临时空间监控是否自动下线Node。
  7. 检查Throttle、Lock和上游依赖。
  8. 检查Controller线程、Heap和插件异常。

二十七、Agent离线Runbook

检查:

  • Agent进程和Java版本。
  • Controller URL、DNS和TLS。
  • SSH/WebSocket/Inbound通道。
  • Agent Secret或认证。
  • 时钟与证书。
  • 防火墙、代理和反向代理超时。
  • Node磁盘和inode。
  • Remoting版本兼容。
  • Controller日志与Agent日志时间线。

不要只反复Reconnect,先确认断开原因和是否正在运行敏感部署。

二十八、Workspace磁盘满Runbook

text
Node磁盘满
→ Git checkout或构建写失败
→ Agent可能被标记临时离线
→ Queue继续堆积

检查Workspace、依赖缓存、Docker数据、测试容器、日志、归档和deleted-open文件。清理前按Job、Build和标签确认归属,不执行无条件全局删除。

二十九、工具存在但Job找不到

常见原因:

  • Agent非交互Shell不读取用户profile。
  • Jenkins服务用户PATH不同。
  • Tool配置没有应用。
  • Label选到另一台Node。
  • 容器Agent镜像缺工具。
  • Windows/Linux命令不同。
  • JDK版本被环境变量覆盖。

在Build中输出经过脱敏的:

bash
pwd
id
java -version
mvn -version
git --version

不要输出完整环境变量,因为可能含Secret。

三十、商业场景:@2目录导致部署错包

脚本硬编码 /var/lib/jenkins/workspace/order-service/target/app.jar。并发Build实际在 order-service@2构建,新脚本却部署了旧目录Jar。

修复:使用 $WORKSPACE和归档制品,不从固定Workspace路径部署;禁用同环境并发部署,制品按版本和Digest推广。

三十一、商业场景:Controller执行Docker构建后全站卡顿

多个Build在Controller执行Docker构建,占满CPU、磁盘IO和Docker Root Dir;UI、Queue和Pipeline持久化都变慢。

修复:Controller Executor设为受控值或0,构建迁移到隔离Agent;为Agent设置资源、日志和Docker清理策略,Controller只做控制面。

三十二、面试标准回答

Controller、Agent和Executor区别

Controller保存配置、调度Queue、管理凭据、插件和Pipeline状态;Agent是连接Controller并真正执行命令的运行环境;Executor是Node可同时承载的构建槽位,不等于CPU核。Executor过多会让多个Build的JVM、Docker和IO竞争资源。

Jenkins任务为什么一直排队

先看Queue Item的具体原因,常见是Label无匹配Node、Agent离线、Executor占满、禁止并发、Lock/Throttle等待、Quiet Period或Controller压力。不能只重启Jenkins,应结合Node、Executor、上一个Build和插件限制定位。

workspace@2是什么

同一Job在同一Node并发执行时,为隔离文件目录,Jenkins可能创建workspace、workspace@2等目录。脚本不能硬编码绝对Workspace路径;即使目录隔离,Maven缓存、Docker daemon、固定端口和部署环境仍可能冲突。

Workspace、stash和artifact区别

Workspace是Node临时工作目录;stash用于同一Pipeline跨Node传递相对小的文件;archive把产物关联到Build记录;正式Jar和镜像应进入Nexus/Registry等外部制品仓库。生产应一次构建、多环境推广同一不可变制品。

Jenkins运行JDK和业务编译JDK必须一样吗

不必。现代Jenkins Controller/Agent进程使用当前LTS支持的现代Java,而业务可通过Tool、Maven Toolchains、容器或不同Label Agent使用JDK 7/8/17/21编译。要固定具体版本并验证Maven、TLS和插件兼容。

三十三、学习验收

  1. 画出Webhook、Queue、Node、Agent、Executor和Workspace全过程。
  2. 制造Label不匹配、Agent离线和Executor占满三种Queue等待。
  3. 根据单Build峰值估算Executor,而不是按CPU核机械设置。
  4. 并发执行同Job并解释workspace@2和共享资源冲突。
  5. 用现代Agent运行时构建一个JDK 8项目并记录具体8u版本。
  6. 区分Workspace、stash、archive、Nexus和Registry。
  7. 从Commit到镜像Digest追踪一次发布。
  8. 设计JENKINS_HOME备份、插件清单和恢复演练。
  9. 隔离不可信PR Agent与生产部署凭据。
  10. 完成Queue、Agent离线和磁盘满Runbook。

关联知识点