【基于 SSH 与 JNLP 协议的 Jenkins 分布式构建方案】

提示:本文原创作品,良心制作,干货为主,简洁清晰,一看就会

文章目录

  • 前言
  • 一、jenkins分布式
    • [1.1 什么是jenkins分布式](#1.1 什么是jenkins分布式)
    • [1.2 Master 如何确定将任务下发至哪个 Agent?](#1.2 Master 如何确定将任务下发至哪个 Agent?)
    • [1.3 Master与Agent通信常用方式](#1.3 Master与Agent通信常用方式)
  • 二、基于SSH协议实现Jenkins分布式
    • [2.1 安装jenkins agent](#2.1 安装jenkins agent)
    • [2.2 下载jdk](#2.2 下载jdk)
    • [2.3 下载插件](#2.3 下载插件)
    • [2.4 添加凭证](#2.4 添加凭证)
    • [2.5 发送公钥](#2.5 发送公钥)
    • [2.6 添加节点](#2.6 添加节点)
    • [2.7 创建项目](#2.7 创建项目)
  • 三、基于JNLP协议实现Jenkins分布式
    • [3.1 安装jenkins agent](#3.1 安装jenkins agent)
    • [3.2 下载jdk](#3.2 下载jdk)
    • [3.3 配置端口](#3.3 配置端口)
    • [3.4 添加节点](#3.4 添加节点)
    • [3.5 发送公钥](#3.5 发送公钥)
    • [3.6 创建项目](#3.6 创建项目)

前言

我的实验环境

主机名 IP地址 运行服务 作用
gitlab 192.168.13.136 GitLab 托管 Git 仓库,为 developer 提供推送,为 Jenkins Agent 提供源码
developer 192.168.13.144 Git、Maven、JDK 17 模拟开发者编写代码并推送到 GitLab
jenkins-controller 192.168.13.143 Docker + Docker-Compose + Jenkins(容器版 2.516.2,UI 8080,内置 JDK 21) Jenkins 调度中心 :提供 Web UI、管理用户权限和凭据、将构建任务调度给 Agent 节点执行(注:本身不建议跑构建)
harbor 192.168.13.138 Harbor(HTTP 80,项目 myapptest) 私有镜像仓库,接收 Agent 推送的镜像,供 backend 节点拉取
backend1 192.168.13.139 Docker 拉取 Harbor 镜像,运行 myapp 容器(宿主机 80 映射容器 8080),对外提供服务
backend2 192.168.13.140 Docker 拉取 Harbor 镜像,运行 myapp 容器(宿主机 80 映射容器 8080),对外提供服务
jenkins-agent-ssh 192.168.13.145 JDK 17、OpenSSH-Server、Docker、Git SSH 代理节点 1 :供 Controller 通过 SSH 协议远程登录并下发 remoting.jar 启动。负责执行具体的项目构建、打包镜像等任务
jenkins-agent-ssh-02 192.168.13.146 JDK 17、OpenSSH-Server、Docker、Git SSH 代理节点 2:同上,用于并发构建或环境隔离
jenkins-agent-jnlp 192.168.13.147 JDK 17、Docker、Git JNLP/Inbound 代理节点:由 Agent 主动通过 WebSocket(或 50000 端口)连接 Controller 并接收任务。负责执行具体的项目构建、打包镜像等任务

由于我目前已有一套配置完整、包含全流程 CI/CD 的 Jenkins 项目,本次将在现有项目基础上进行改造,搭建 Jenkins 分布式架构

现有项目:https://blog.csdn.net/m0_63756214/article/details/167388905?spm=1001.2014.3001.5501

一、jenkins分布式

1.1 什么是jenkins分布式

Jenkins分布式由 Master主节点 + Agent代理节点 组成

Master负责任务调度、管理Web界面、保存项目配置与构建结果;真正的编译、打包、测试等构建任务分发到Agent执行

优势:分担Master压力;支持多环境(Linux/Windows/Docker)并行构建,横向扩展并发任务;或者可以按语言环境调度任务:Java 项目调度到预装 Java 环境的 Agent,Go 项目调度到预装 Go 环境的 Agent,实现环境隔离

1.2 Master 如何确定将任务下发至哪个 Agent?

通过为 Agent 节点配置标签(例如java、go、python),同时在项目中指定所需标签;当项目标签与 Agent 标签匹配时,该项目就会调度到对应的 Agent 上执行

再结合节点负载、可用性等策略,从中挑选一个 Agent,下发构建任务

1.3 Master与Agent通信常用方式

SSH 方式

Master 主动通过 SSH 连接 Agent;

JNLP 方式

Agent 主动连接 Master

旧版Jenkins:需要开放 50000 TCP 端口

新版复用 Jenkins Web 端口(8080/https),不再需要单独放行 50000 端口

二、基于SSH协议实现Jenkins分布式

各公司 Master 部署方式不同,此处仅提供一种参考路径:

  • 安装 Docker 和 Docker Compose,以容器方式运行 Jenkins Agent(容器自带 JDK 21)
  • 在 Agent宿主机 上安装 JDK 17,用于启动 Controller 通过 SSH 下发到 Agent 的 remoting.jar
  • Agent需具备可被 Controller SSH 登录的账户和足够的工作目录权限 Controller 生成 SSH 密钥对
  • 将Controller 的公钥 写入 Agent 的 /root/.ssh/authorized_keys(或目标用户的
    authorized_keys),实现免密登录
  • Agent 的公钥配置到后端服务器
  • 在 Controller 中添加凭证,私钥填 Controller自己的私钥,Username 填 Agent 的 SSH 登录用户
  • 在 Controller 上新建节点,配置Agent地址、Labels等
  • 创建 Job/Pipeline 时,通过 agent { label '匹配的标签' } 指定 Agent标签,任务即会调度到对应 Agent 执行

2.1 安装jenkins agent

yaml 复制代码
## 1. 准备docker、docker-compose
root@jenkins-agent-ssh:~# docker --version
Docker version 29.1.3, build 29.1.3-0ubuntu3~24.04.2
root@jenkins-agent-ssh:~# docker-compose --version
Docker Compose version v2.38.0

## 2. 创建jenkins容器文件存放目录
root@jenkins-agent-ssh:~# mkdir jenkins/
root@jenkins-agent-ssh:~# cd jenkins/

## 3. 自制Dockerfile,将原jenkins镜像中封装上docker命令
root@jenkins-agent-ssh:~/jenkins# vim Dockerfile 
FROM jenkins/jenkins:lts-jdk21

USER root

RUN apt-get update && \
    apt-get install -y ca-certificates curl gnupg && \
    install -m 0755 -d /etc/apt/keyrings && \
    curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
    chmod a+r /etc/apt/keyrings/docker.gpg && \
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list && \
    apt-get update && \
    apt-get install -y docker-ce-cli=5:28.1.1-1~debian.12~bookworm docker-compose-plugin && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

USER jenkins
yaml 复制代码
## 4. 创建docker-compose文件
root@jenkins-agent-ssh:~/jenkins# vim docker-compose.yml 
version: "3.8"
services:
  jenkins:
    build: .
    image: my-jenkins:lts-jdk21
    container_name: jenkins
    group_add:
      - "110" 
    restart: unless-stopped
    ports:
      - 8080:8080
      - 50000:50000
    environment:
      - TZ=Asia/Shanghai
      - JAVA_OPTS=-Duser.timezone=Asia/Shanghai
    volumes:
      - ./data/:/var/jenkins_home/
      - /var/run/docker.sock:/var/run/docker.sock
yaml 复制代码
## 5. 创建jenkins容器映射工作目录,并修改所属主、所属组为jenkins
root@jenkins-agent-ssh:~/jenkins# mkdir data/
root@jenkins-agent-ssh:~/jenkins# chown -R 1000:1000 data

## 6. 构建镜像,启动容器
root@jenkins-agent-ssh:~/jenkins# docker-compose bulid
root@jenkins-agent-ssh:~/jenkins# docker-compose up -d

jenkins agent运行起来后不用登录网页版下载插件或者配置之类的,网页上的配置操作都在jenkins master网页上完成

2.2 下载jdk

在 Agent 宿主机上安装 JDK 17,专门用于启动 Master 下发到 Agent 上的 remoting.jar,这是 Agent 节点能上线的前提

yaml 复制代码
root@jenkins-agent-ssh:~# java --version
java 17.0.17 2025-10-21 LTS
Java(TM) SE Runtime Environment (build 17.0.17+8-LTS-360)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.17+8-LTS-360, mixed mode, sharing)
root@jenkins-agent-ssh:~# which java
/usr/local/java/bin/java
root@jenkins-agent-ssh:~# ln -s /usr/local/java/bin/java /usr/bin/java

2.3 下载插件

jenkins controller上安装agent插件,不然不能添加agent节点

2.4 添加凭证

jenkins controller上添加凭证

2.5 发送公钥

yaml 复制代码
## 1. jenkins controller的公钥发送到agent
root@jenkins:~/jenkins# cat data/.ssh/id_ed25519.pub 
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXk7TCZEPRqnzOi3bQ6068MbybqD26U19LGylyF75ry jenkins@ci

root@jenkins-agent-ssh:~# cat /root/.ssh/authorized_keys 
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXk7TCZEPRqnzOi3bQ6068MbybqD26U19LGylyF75ry jenkins@ci
yaml 复制代码
## 2. agent生成密钥
root@jenkins-agent-ssh:~/jenkins# cd data/
root@jenkins-agent-ssh:~/jenkins/data# mkdir .ssh/
root@jenkins-agent-ssh:~/jenkins/data# ssh-keygen -t ed25519 -C "jenkins@ci" -f .ssh/id_ed25519 -N ""
root@jenkins-agent-ssh:~/jenkins/data# ls .ssh/
id_ed25519  id_ed25519.pub
root@jenkins-agent-ssh:~/jenkins/data# cat .ssh/id_ed25519.pub 
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQn7vY+fvD1Ayz92Y9ZHQfBcd/gm2wIoWbYZtAjC5fl jenkins@ci

## 3. 修改权限
root@jenkins-agent-ssh:~/jenkins/data# chown -R 1000:1000 .ssh/
root@jenkins-agent-ssh:~/jenkins/data# chmod 700 .ssh/
root@jenkins-agent-ssh:~/jenkins/data# chmod 600 .ssh/id_ed25519
root@jenkins-agent-ssh:~/jenkins/data# chmod 644 .ssh/id_ed25519.pub 

## 4. 后端服务器添加jenkins agent的公钥
root@backend1:~# cat .ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXk7TCZEPRqnzOi3bQ6068MbybqD26U19LGylyF75ry jenkins@ci
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQn7vY+fvD1Ayz92Y9ZHQfBcd/gm2wIoWbYZtAjC5fl jenkins@ci  # 追加的一行
root@backend2:~# cat .ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXk7TCZEPRqnzOi3bQ6068MbybqD26U19LGylyF75ry jenkins@ci
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQn7vY+fvD1Ayz92Y9ZHQfBcd/gm2wIoWbYZtAjC5fl jenkins@ci  # 追加的一行

2.6 添加节点

jenkins controller上添加节点

添加好之后的节点没有报错

如果有报错可以看节点相关日志,具体原因具体分析

查看agent端口和程序,可以agent配置成功

我这里又添加了一个节点,并打上了和刚才不同的标签

至此,我创建了两个agent,分别是

节点一:jenkins-agent-ssh 标签是jack和tom

节点二:jenkins-agent-ssh-02 标签是alice

2.7 创建项目

接下来jenkins controller上创建项目,这里我之前复制了现有的项目,然后添加了项目标签

给该项目打"jack"标签

运行项目,可以看到该项目(带有jack标签)被jenkins-agent-ssh节点(带有jack和tom标签)运行

yaml 复制代码
## 查看jenkins-agent-ssh节点的jenkins的家目录,可以看到项目
root@jenkins-agent-ssh:~/jenkins# ls /var/jenkins_home/
remoting  remoting.jar  workspace
root@jenkins-agent-ssh:~/jenkins# ls /var/jenkins_home/workspace/
jenkins-agent-ssh-demo  jenkins-agent-ssh-demo@tmp

## 查看jenkins-agent-ssh-02节点的jenkins家目录下没有项目也侧面证明项目运行到了第一个节点
root@jenkins-agent-ssh02:~# ls /var/jenkins_home/
remoting  remoting.jar

网页访问后端服务器网页成功!

三、基于JNLP协议实现Jenkins分布式

与ssh协议不同的是,jnlp 协议通过 secret 令牌进行认证,整个流程不涉及 ssh 密钥对的交换,因此自然不需要把 master 的公钥配置到 agent 上

3.1 安装jenkins agent

和上面安装方法一致,都是容器安装

3.2 下载jdk

在 Agent 宿主机上安装 JDK 17,专门用于启动 Master 下发到 Agent 上的 remoting.jar,这是 Agent 节点能上线的前提

yaml 复制代码
root@jenkins-agent-ssh:~# java --version
java 17.0.17 2025-10-21 LTS
Java(TM) SE Runtime Environment (build 17.0.17+8-LTS-360)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.17+8-LTS-360, mixed mode, sharing)
root@jenkins-agent-ssh:~# which java
/usr/local/java/bin/java
root@jenkins-agent-ssh:~# ln -s /usr/local/java/bin/java /usr/bin/java

3.3 配置端口

从 Jenkins 2.217 版本开始,使用jnlp协议的agent就可以配置为通过 WebSocket 进行连接,从而不再需要开启传统的 TCP 50000 端口

如果是老版则需要在jenkins controller上开启50000端口

3.4 添加节点

jenkins controller添加节点

保存之后我们还需要在该agent上下载 jenkins 代理程序,启动jnlp从节点,让这台机器作为 agent 接收主节点下发的构建任务

yaml 复制代码
root@jenkins-agent-jnlp:~# curl -sO http://192.168.13.143:8080/jnlpJars/agent.jar
root@jenkins-agent-jnlp:~# ls
agent.jar  jenkins
root@jenkins-agent-jnlp:~# java -jar agent.jar -url http://192.168.13.143:8080/ -secret 47347f13c17d95f81dfc19288a3ab7af6ca7fe001bb02f79a22d1527e573de7e -name "jenkins-agent-jnlp" -webSocket -workDir "/var/jenkins_home"
yaml 复制代码
## 查看端口,jenkins Agent(192.168.13.147)已经成功和 Jenkins Master(192.168.13.143:8080)建立 WebSocket 长连接
root@jenkins-agent-jnlp:~# ss -nt
State         Recv-Q         Send-Q                           Local Address:Port                             Peer Address:Port         Process         
ESTAB         0              0                               192.168.13.147:22                             192.168.13.143:42484                        
ESTAB         0              0                               192.168.13.147:22                               192.168.13.1:14257                        
ESTAB         0              52                              192.168.13.147:22                               192.168.13.1:17877                        
ESTAB         0              0                               192.168.13.147:22                               192.168.13.1:13793                        
ESTAB         0              0                      [::ffff:192.168.13.147]:45200                 [::ffff:192.168.13.143]:8080 

观察jenkins controller上配置的jnlp节点显示正常

3.5 发送公钥

虽然jenkins controller不用给agent发送公钥了,但是由于我的项目后端用的ssh协议,所以agent需要给后端服务器发送公钥,这里先让agent生成公钥,参考2.5,然后再给后端服务器发送公钥

yaml 复制代码
## 1. agent端生成的公钥
root@jenkins-agent-jnlp:~/jenkins/data# cat .ssh/id_ed25519.pub 
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAyJSD6Yx/X4awQBX/plsv0K92Q41upoE16fij2E9w4e jenkins@ci

## 2. 配置到后端服务器
root@backend1:~# cat /root/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXk7TCZEPRqnzOi3bQ6068MbybqD26U19LGylyF75ry jenkins@ci
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQn7vY+fvD1Ayz92Y9ZHQfBcd/gm2wIoWbYZtAjC5fl jenkins@ci
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAyJSD6Yx/X4awQBX/plsv0K92Q41upoE16fij2E9w4e jenkins@ci

root@backend2:~# cat /root/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXk7TCZEPRqnzOi3bQ6068MbybqD26U19LGylyF75ry jenkins@ci
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQn7vY+fvD1Ayz92Y9ZHQfBcd/gm2wIoWbYZtAjC5fl jenkins@ci
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAyJSD6Yx/X4awQBX/plsv0K92Q41upoE16fij2E9w4e jenkins@ci

3.6 创建项目

jenkins controller创建项目

这里我直接复制2.7小节的项目,然后改标签

构建项目

可以看到该项目在jenkins-agent-jnlp节点上运行

yaml 复制代码
## 查看jenkins家目录,生成内容
root@jenkins-agent-jnlp:~# ls /var/jenkins_home/
remoting  remoting.jar  workspace
root@jenkins-agent-jnlp:~# ls /var/jenkins_home/workspace/
jenkins-agent-jnlp-demo  jenkins-agent-jnlp-demo@tmp

后端服务器访问网页成功

注:

文中若有疏漏,欢迎大家指正赐教。

本文为100%原创,转载请务必标注原创作者,尊重劳动成果。

求赞、求关注、求评论!你的支持是我更新的最大动力,评论区等你~

相关推荐
PingCAP17 小时前
善战者无赫赫之功:消费金融核心系统的数据库选型与升级路径
数据库·分布式·架构
库库的数据库笔记18 小时前
金融核心交易系统的数据库国产信创改造该如何做?
大数据·数据库·分布式·mysql·oracle·金融·数据库架构
爱吃火鸡面呀1 天前
深入理解 Spark RDD:五大特性与实战解析
大数据·分布式·spark
Norris Huang1 天前
Kafka Connect 与 Flink CDC 写入 Iceberg:Upsert 的代价,以及 S3 Tables 的真正价值
分布式·flink·kafka
我就是不信1 天前
集群高并发环境下如何保证分布式唯一全局ID生成?
分布式
黄俊懿2 天前
【架构师从入门到进阶】第六章:服务集群优化——第八节:线程数公式
java·服务器·数据库·分布式·性能优化·架构·系统架构
大菠萝爱上小西瓜2 天前
基于 Spark + Iceberg 湖仓一体的 Netflix 流媒体用户行为全链路数仓与 ALS 智能推荐决策系统(含穿透下钻大屏)
大数据·分布式·spark
吴建旭 智宅焕2 天前
智能家居售后服务体系的架构设计:分布式售后风险的集中式兜底方案
分布式·智能家居
lisanmengmeng2 天前
Ganglia分布式集群监控系统安装手册
分布式