Skip to main content
☘️ Septvean's Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Jenkins JNLP Agent

JNLP Agent(Java Network Launch Protocol Agent)是 Jenkins 中一种将 远程节点(Agent/Slave)连接到 Jenkins 主节点(Master/Controller)的方式。它允许你将构建任务分发到其他机器上执行,实现分布式构建,提升并发能力和资源利用率。


🔧 一、什么是 JNLP Agent?

JNLP(Java Network Launch Protocol)是 Java 提供的一种机制,允许通过 Web 启动远程 Java 应用程序。

在 Jenkins 中,JNLP Agent 是一个运行在远程机器上的 Java 进程,通过 JNLP 协议连接到 Jenkins 主节点,并接收构建任务。

也称为 “Inbound Agent”(入站代理),因为是 Agent 主动连接 Master(与 SSH Agent 的“出站”方式相对)。

✅ 适合场景:

  • 你无法从 Jenkins 主机直接 SSH 到构建机器(如 Windows 机器、容器、受限网络环境)。
  • 构建节点在防火墙/NAT 后,只能主动向外连接。
  • 需要临时启动的 Agent(如 Kubernetes Pod、Docker 容器)。

📦 二、JNLP Agent 的工作原理

  1. 通过 Manage Jenkins -> Nodes -> New node -> Type: Permanent Agent 创建一个永久节点。

  2. Jenkins 为主机生成一个唯一的 Agent 名称密钥(secret)。

  3. 在目标机器上执行以下命令启动 Agent。

  4. Agent 通过 HTTP/HTTPS 连接到 Jenkins 主节点,建立持久连接。

  5. Jenkins 主节点可向该 Agent 分配 Job 构建任务。

⚠️ 注意:

  • agent.jar 是 Jenkins 提供的客户端 JAR 文件,可从 http://<jenkins-url>/jnlpJars/agent.jar 下载。
  • 必须安装 Java 运行环境(JRE 或 JDK)在 Agent 机器上。

🛠 三、配置 JNLP Agent 的步骤

进入 Manage Jenkins -> Nodes -> New node

  • Node name:build-node-01(节点名称)
  • Type:选择 Permanent Agent (类型:永久代理)
  • 配置
    • Number of executors:2 (并发构建数)
    • Remote root directory:/data/jenkins/data (远程工作目录)
    • Labels:agent(标签,用于 Pipeline 中 agent { label 'xxx' } 调度)
    • Launch method:选择 Launch agent by connecting it to the controller

保存后,进入该节点页面,你会看到:

build-node-01
Built-In Node

点击 build-node-01,会给出相关的命令。

登录 Jenkins Agent 节点服务器,执行相关操作:

# 创建用户
# 注意: jenkins 用户的 home 目录不要设置在 /home 目录下 !!
# 原因: podman 打包的镜像保存在 ~/.local/share/containers 目录下, 会导致 / 或者 /home 空间不足
useradd -r -m -d /data/jenkins/home jenkins

# 创建目录
mkdir -p /data/jenkins/{app,data,log}

# 进入目录
cd /data/jenkins/app

# 创建密钥文件
echo ea388ed70f35857f98c23d73f8bc75b5f81a8ecef9ea93842ae4b6fae4c6a7b2 > secret-file

# 下载 JNLP Agent
curl -sO http://192.168.101.201:8200/jnlpJars/agent.jar

# 设置权限
chown -R jenkins:jenkins /data/jenkins

# 启动 JNLP Agent
# java -jar agent.jar -url http://192.168.101.201:8200/ -secret @secret-file -name "build-node-01" -webSocket -workDir "/data/jenkins/data"

# 创建服务
tee /etc/systemd/system/jenkins-agent.service <<'EOF'
[Unit]
Description=Jenkins Agent
After=network.target

[Service]
Type=simple
User=jenkins
Group=jenkins

# 工作目录
WorkingDirectory=/data/jenkins/app

# 启动命令
ExecStart=/usr/local/jdk/21.0.9/bin/java -jar agent.jar -url http://192.168.101.201:8200/ -secret @secret-file -name "build-node-01" -webSocket -workDir "/data/jenkins/data"

# 日志输出到文件
StandardOutput=append:/data/jenkins/log/run.log
StandardError=append:/data/jenkins/log/error.log

# 自动重启策略
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

# 启动服务
systemctl daemon-reload
systemctl start jenkins-agent
systemctl status jenkins-agent

# ● jenkins-agent.service - Jenkins Agent
#      Loaded: loaded (/etc/systemd/system/jenkins-agent.service; disabled; preset: disabled)
#      Active: active (running) since Sat 2026-01-03 23:32:17 CST; 13s ago
#    Main PID: 1456 (java)
#       Tasks: 41 (limit: 209715)
#      Memory: 59.5M (peak: 60.1M)
#         CPU: 2.761s
#      CGroup: /system.slice/jenkins-agent.service
#              └─1456 /usr/local/jdk/21.0.9/bin/java -jar agent.jar -url http://192.168.101.201:8200/ -secret @secret-file -name build-node-01 -webSocket -workDir /data/jenkins/data

# Jan 03 23:32:17 node-202.server.com systemd[1]: Started Jenkins Agent.

# 创建服务
systemctl enable jenkins-agent

刷新 build-node-01 页面,查看节点状态

以相同的方式添加 build-node-02,最终结果:

回到 Nodes 页面,点击 Built-In Node,选择 Configure,确保 Number of executors 设置为 0。


📦 四、Podman 设置 (重要‼️)

# 允许用户在无登录状态下运行
loginctl enable-linger jenkins

# 设置密码
echo 'wR5zxK2R' | passwd --stdin jenkins

# 禁止 jenkins 用户通过 SSH 登录
echo 'DenyUsers jenkins' >> /etc/ssh/sshd_config.d/99-deny-users.conf
systemctl restart sshd

# 设置 sudo 权限
echo 'jenkins ALL=(ALL) NOPASSWD: /usr/bin/podman,/usr/bin/docker' >> /etc/sudoers.d/jenkins
chmod 400 /etc/sudoers.d/jenkins

# 设置 UID 和 GID
usermod --add-subuids 100000-165535 --add-subgids 100000-165535 jenkins

# 去重 & 排序
awk -F: '{ res[$1] = $0 } END { for (u in res) print res[u] }' /etc/subuid | sort | sudo tee /etc/subuid
awk -F: '{ res[$1] = $0 } END { for (u in res) print res[u] }' /etc/subgid | sort | sudo tee /etc/subgid

# 切换用户
su - jenkins

# 检查配置
cat ~/.config/containers/containers.conf

# 如果配置文件不存在, 创建配置文件

# 强制 Podman 使用默认的 ulimit, 避免它尝试去设置过高的值
# 将其设置为一个 Jenkins 进程允许的值 (通常 4096 是比较安全的)
mkdir -p ~/.config/containers
cat > ~/.config/containers/containers.conf <<'EOF'
[containers]
default_ulimits = [ "nofile=1024:4096" ]
EOF

# 重置 podman
podman system migrate
podman system reset -f

# 查看镜像
podman images

# 拉取镜像
HTTP_PROXY=http://192.168.101.200:1080 HTTPS_PROXY=http://192.168.101.200:1080 podman pull custom/jdk:21.0.9-0

如果 jenkins 用户执行 docker build 始终有问题,则给 jenkins 用户创建 sudo 权限 ( /etc/sudoers.d/jenkins ),将 docker build 改为 sudo docker build


🔄 五、JNLP vs SSH Agent 对比

特性 JNLP Agent SSH Agent
连接方向 Agent -> Master(入站) Master -> Agent(出站)
防火墙友好 ✅ 适合 NAT/防火墙后 ❌ 需开放 SSH 端口
操作系统支持 跨平台(需 Java) 主要 Linux(需 SSH 服务)
启动方式 手动执行 Java 命令 Jenkins 自动 SSH 登录启动
资源开销 需常驻 Java 进程 按需启动,更轻量(一次性 Agent)

✅ 现代推荐:对于云环境或容器化场景,使用 Pod Template(Kubernetes Plugin)或 Docker Agent 更灵活,它们底层也常基于 JNLP。


🚀 六、常见问题排查

问题 可能原因 解决方案
Connection refused Jenkins URL 不可达 检查网络、防火墙、Jenkins 是否运行
Invalid secret 密钥错误或过期 重新复制 Secret,或在节点配置中点击 “Fix”
Unsupported protocol Java 版本不兼容 使用 Java 8/11,避免 Java 17+(除非 Jenkins 支持)
Agent 频繁断开 网络不稳定 增加重连脚本,或改用更稳定连接方式

✅ 总结

JNLP Agent 是 Jenkins 分布式构建的核心机制之一,特别适合:

  • 无法被主节点直接访问的构建机器
  • 需要灵活扩展构建资源的场景
  • Windows 或混合环境构建

虽然配置略复杂(需手动启动 Java 进程),但它是实现 横向扩展 Jenkins 能力 的关键一环。