Jenkins Kubernetes Plugin: Dynamic Agents in Pods, and What That Costs You
Jenkins plugin to run dynamic agents in a Kubernetes/Docker environment
At a glance
- What is it?
- The Jenkins Kubernetes plugin creates one pod per agent and deletes it after the build. It fits teams whose Jenkins controller already has a Kubernetes API to talk to, and it is a poor fit for anyone who needs agents to survive a build or who has not sized the API server for the pod churn.
- Who is it for?
- Adopt it if your controller can reach a Kubernetes 1.14+ cluster, your builds tolerate a fresh pod each time, and you can grant a ServiceAccount the privileges in the plugin's example manifest. Do not adopt it if agents must persist state between builds, if your Kubernetes API server cannot absorb pod creation and deletion on every build, or if you need a non-Java agent container without a compatible JRE.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: idle agents that you pay for anyway
A conventional Jenkins setup keeps a fixed pool of agents online. They sit idle between builds, they need patching, and adding capacity means provisioning machines ahead of demand. The Kubernetes plugin replaces that pool with a per-build pod. The README states the model directly: the plugin creates a Kubernetes Pod for each agent started, and stops it after each build. Capacity therefore tracks build volume rather than a pre-provisioned headcount. The intended audience is a team that already runs a Kubernetes cluster and wants the Jenkins controller to consume it as an elastic agent source. The README is explicit that the controller itself does not have to live in Kubernetes, which means the plugin is not a packaging decision for Jenkins as a whole. It is a scheduling decision for builds.
Inbound agents and the environment variables that make them connect
The mechanism is inbound rather than SSH-based. Agents launch as inbound agents, so the container is expected to connect back to the Jenkins controller on its own. The plugin injects JENKINS_URL, JENKINS_SECRET, and JENKINS_AGENT_NAME into the container so the agent process knows where to dial and how to authenticate. A fourth variable, JENKINS_NAME, is still injected for backwards compatibility and is marked deprecated in the README. Because the connection is outbound from the pod, the controller does not need a route into the cluster. That single design choice is what makes the plugin workable when the controller sits outside the cluster, behind a reverse proxy, or behind an ingress resource. The README notes that checking WebSocket makes agents connect over HTTP(S) instead of the Jenkins service TCP port, and points to JEP-222 for the reasoning. Inside the pod, one container always runs the Jenkins agent. Its name defaults to jnlp, which the README calls a historical name kept for backward compatibility. You can rename it. Other containers in the same pod run whatever you want, and pipeline jobs can execute commands in any of them through the container step.
Getting a cloud configured without hand-editing XML
Configuration starts in the Jenkins UI: Manage Jenkins, then Manage Nodes and Clouds, then Configure Clouds, then Add a new cloud, then Kubernetes. You supply a Kubernetes URL and a Jenkins URL. If Jenkins runs inside the cluster, the README says the defaults work. Credentials can be a username and password pair, a Secret File holding a kubeconfig, secret text for token-based authentication (the README lists OpenShift here), a Google Service Account from private key for GKE, or an X.509 client certificate. The Test Connection button checks that Jenkins can talk to the cluster before you build anything on top of the assumption. Pod templates are then defined in the Kubernetes Pod Template section, where you give the template a name and a Docker image. The template name becomes a prefix for the generated agent names. A template also declares a label, and a freestyle or pipeline job that calls node('some-label') with a matching label causes the Kubernetes Cloud to allocate a new pod. If you want to limit which jobs may consume a cloud, the advanced configuration has a Restrict pipeline support to authorized folders checkbox, and the job must then be listed in the folder's configuration. The README also recommends against baking the agent JAR into your image, pointing instead at the Inject Jenkins agent in agent container checkbox, on the grounds that it avoids drift between controller and agent. Whatever image you supply must carry a JRE compatible with the Java version your controller requires.
The garbage collection default is a deliberate trade
The README describes an exceptional case: agent pods can be left behind with no corresponding Jenkins agent declared in the controller. Those pods retry the connection repeatedly until something deletes them. The plugin ships a garbage collection mechanism for exactly this, but it is disabled by default because it can generate extra load on the Kubernetes API server. That is an honest default and a real cost. Turning it on trades API server load for orphan cleanup. Leaving it off means you own the cleanup problem yourself, and the README does not prescribe how. This is the kind of setting that looks like a checkbox and behaves like an operational commitment. The same API server load argument applies to the plugin's core loop: creating and deleting a pod per build is more API traffic than keeping agents around. The README does not quantify that traffic, and this article will not invent a number for it.
Where a pod-per-build model stops fitting
State is the first casualty. A pod is created for a build and stopped after it, so anything written outside a mounted volume does not survive to the next build. Teams that rely on warm caches, pre-pulled images, or toolchains installed once on a long-lived agent will find that model inverted. Container start time is now part of every build's wall clock, and the README offers no guidance on mitigating it beyond choosing images carefully. The second limitation is the agent container itself. It must have a JRE compatible with the controller's Java version, and the README's tested configuration is the jenkins/inbound-agent image. If your build needs a container that cannot carry a compatible JRE, the plugin's default agent container is the wrong place to run it. The third is privilege. The README points at an example ServiceAccount manifest at src/main/kubernetes/service-account.yml and describes it only as needing sufficient privileges. It does not enumerate them, so the scope of what the plugin can do in your cluster is something you determine by reading that file against your own policies, not by trusting a summary. Finally, the README warns that a controller outside the cluster using a self-signed HTTPS certificate needs additional configuration, with a link to a WebSocket section. That is a known rough edge, not a footnote.
Kubernetes pods versus a static SSH agent pool
The obvious alternative is the long-standing model of registering agents over SSH and keeping them online. The difference is not cosmetic. An SSH agent is a machine you maintain, with a fixed toolchain and a persistent filesystem, and Jenkins simply sends work to it. The Kubernetes plugin inverts the lifecycle: the agent is a pod, the pod is the unit of allocation, and the pod disappears when the build ends. That gives you per-build isolation and capacity that follows demand, at the price of cold starts and no persistence. It also changes your failure surface. With SSH agents, a broken agent is a broken machine. With this plugin, a broken agent is a Kubernetes scheduling or networking problem, and the plugin's own garbage collection exists precisely because pods can outlive their Jenkins-side agent record. If your builds are long and few, the pod churn buys you little. If they are short and numerous, or if you already run Kubernetes and want to stop maintaining a separate agent fleet, the trade tilts the other way.
Maintenance, release cadence, and the licence
The repository is not archived, and the recent release list shows three releases between late July and mid August 2026, with names in the Jenkins versioning style such as 4547.v52f3080db_8cd. That cadence suggests active maintenance, though the material here does not describe what changed in any of those releases, so upgrade risk per version is not something this article can assess. The licence is Apache-2.0, which is a permissive licence, but nothing here is legal advice and the plugin's dependencies carry their own terms. Practically, the upgrade cost is the usual Jenkins plugin cost: you update through the plugin manager, and a controller upgrade that raises the required Java version can invalidate your agent images, because the README requires the agent container's JRE to match the controller's Java version. That coupling is the maintenance item to watch. It is not a one-time setup detail; it recurs every time the controller's Java baseline moves.
A short note on what the README does not settle
Several things a reader would want are absent from the supplied material. There is no sizing guidance for the Kubernetes API server under pod-per-build churn, no recommended image pull policy or caching strategy, and no list of the ServiceAccount privileges the example manifest grants. The inheritance and declarative pipeline sections are named in the table of contents but their contents are not reproduced here, so pod template inheritance behaviour cannot be described from this material. The Windows support and minikube sections are likewise only referenced. Anyone evaluating the plugin for a production controller should read those sections in the repository rather than infer from the overview. The parts that are documented clearly, the inbound connection model, the injected variables, the garbage collection default, and the credential types, are enough to decide whether the architecture fits. They are not enough to decide whether your cluster will be happy with the resulting API traffic.
Editorial conclusion
Adopt it if your controller can reach a Kubernetes 1.14+ cluster, your builds tolerate a fresh pod each time, and you can grant a ServiceAccount the privileges in the plugin's example manifest. Do not adopt it if agents must persist state between builds, if your Kubernetes API server cannot absorb pod creation and deletion on every build, or if you need a non-Java agent container without a compatible JRE. Before rolling it out, verify the connection with the Test Connection button, confirm the injected JENKINS_URL and JENKINS_SECRET reach the controller from inside a pod, and decide explicitly whether to enable garbage collection, which the documentation says is off by default because it adds load on the Kubernetes API server.
Community notes