The plugin manages Control Plane and Jenkins resource lifecycles and allows for efficient automated provisioning and unprovisioning of resources based on physical load.
git clone [email protected]:controlplane-com/cpln-jenkins-plugin.git
https://maven.apache.org/download.cgi
mvn clean install
Note: the plugin build currently supports Jenkins controller versions of 2.462.3+.
This option starts an empty controller with the Control Plane Plugin already installed.
mvnDebug hpi:run
mvnDebug hpi:run -Dhost=<hostip to bind to>
mvnDebug hpi:run -Dhost=<hostip> -Dorg.slf4j.simpleLogger.defaultLogLevel=info
mvnDebug hpi:run -Dhost=<hostip> -Dorg.slf4j.simpleLogger.defaultLogLevel=debug
This option starts a controller with the Control Plane Plugin already installed. In order to login follow the steps in (B).
If you don't need to attach a debugger, you can use only mvn instead of mvnDebug. If using mvnDebug, you can
attach your debugger to let the controller start.
Note: if you deploy with Option A, in the cloud instance config, you may need to set a Jenkins controller URL with a uri
of /jenkins/, e.g. http://public-address:port/jenkins/ (instead of http://public-address:port/)
https://www.jenkins.io/download/ (e.g. 2.516.3+)
- run either
java -jar jenkins.war(without debugger) or - run
java "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000" -jar jenkins.warif connecting a debugger is preferred - Get the generated password from the terminal and login (subsequent restarts/logins can use the account created);
- Click on the "Jenkins" picture if needed in the landing page;
- Install the recommended plugins (the config will be persisted under
<user>/.jenkins/); - Create an initial user account;
- Accept or update the controller (jenkins) url, e.g. use a canonical dns name instead of localhost etc.;
- Go to the configuration (
<url>/manage/); - Click
Plugins; - Click
Advanced; - In section
Deploy Plugin, clickFile Browseand select theHPIfile:<repo>/cpln-jenkins-plugin/target/cpln-jenkins-plugin/cpln-jenkins-plugin-2.0.0.hpi(this file is generated by themvnbuild step above but for simplifying the initial setup, this artifact is kept underdocs/artifacts, which can be used as is but should be removed later) - Click
Deploy; - Logout and restart the controller;
- Login with the account created above;
- Go to the configuration, click
Plugins -> Installed Plugins; - Verify that
Control Plane Pluginis available and enabled; - Go to configuration (
<url>/manage/) again, ClickSecurity, in the sectionAgents, selectRandomfor theTCP port for inbound agentsandSave;
Prepare your Jenkins instance for the plugin to provision / manage resources in Control Plane and Jenkins as needed.
- Go to the configuration (
/manage), clickNodes -> Built-In Node -> Configure;- Set the
Number of executorsto0in order to make sure that Jenkins will only use your clouds' agents to run jobs and not the local node, thenSave;
- Set the
- Go to the configuration (
/manage), clickClouds -> New cloud; - Create a new cloud, e.g.
MyCplnOne, select the type asControl Plane(the only available cloud provider), clickCreate; - In Control Plane, obtain (or create a new)
API Keyfor any available organization in your Control Plane Account; - Paste the key in the
API Keyfield (leave the field and the plugin will immediately fill theOrgfield with the available organization; - Select the org. This will update the available GVCs in the
gvcfield; - Although all GVCs are reported, only GVCs with one location will be accepted as only one agent (replica) per cloud config (and label) can be deployed per Jenkins requirements;
- Set the agent workload name, e.g.
west1-generic; - Optional. Set the volume set name from the available options in the selected gvc (volume set must be of type: shared). If the empty option is selected then the volume set path must also be empty;
- Optional. Set the volume set path (any valid path preferred in the agent workload container). If the empty option is selected in the volume set name then the path must also be empty;
- Optional. Set the workload identity from the available options in the selected gvc.
- Set zero or more labels (separated by space), the field content must follow the regex with:
()|(([a-z][-a-z0-9]+)( [a-z][-a-z0-9]+)*); - Check if this cloud supports unique agent workloads. When checked, Jenkins will create unique / dedicated agent workloads for each (or a small number) of job items instead of handling a larger set of job items with a specific cloud configuration. If checked, the plugin allows Jenkins to provision one agent for each job item, so they can be processed concurrently regardless of how many concurrent jobs are allowed on each agent. The # of executors setting for the cloud configuration still works the same way but new agents are allowed to be provisioned based on load. If a unique agent is always meant to process a single job item at a time, set the # of executors on the corresponding cloud configuration to 1. Note that Jenkins provisioning continuously evaluates different load factors based on moving averages of available or not-yet-available executors, job queue length etc. Some over-provisioning of agents may be expected on job burst, very short job executions, substantial agent startup delays etc. Unused agents will be unprovisioned based on the configured idle timeout and so, removed from both Jenkins and Control Plane GVC locations. If available / allowed cloud capacity falls short, new agents that failed provisioning will be removed from Jenkins and queued jobs will be processed as new / additional cloud capacity becomes available. It is recommended that you consult the Jenkins parameters MARGIN, MARGIN0 and MARGIN_DECAY, which can help fine tune Jenkins resource provisioning scenarios.
- Check if this cloud instance can pick up jobs without labels. If unchecked, only jobs with any one of the specified labels will be picked up;
- Set the # of executors ( >= 0 ). If 0, no jobs will be picked up, rendering the cloud instance disabled similar to the Built-In Node change above;
- Set the CPU and Memory resources as needed or accept the defaults (200 mcore and 512 MiB respectively);
- Set the idle timeout minutes or accept the default (it has to be min 1 minute). If the agent(s) associated with this cloud configuration have been idle for this long, both the Jenkins agent(s) and the correspoding Control Plane agent workloads will be deleted from the applicable GVCs;
- Accept the default (standard) Jenkins inbound agent docker image (https://hub.docker.com/r/jenkins/inbound-agent). If needed, a compatible agent image can be used but the Jenkins env variables are expected to be available with the same behavior;
- Set the
Jenkins controller URLas known to (and resolvable by) the agent workloads running on Control Plane. This url will be used to access the Jenkins controller from each agent workload (from the corresponding GVC's location). The agent workloads are configured to allow outgoing traffic. E.g. if the controller is running on the default port behind a nat gateway, the incoming connection from the agent's GVC must be routed to the host through the public url, which is configured here, say http://public-address:port/ -> has to route to the host atcontroller-host:8080; - Save the cloud instance;
- Go to
Jenkins -> New Item; - Set the item name, e.g.
job-west, selectFreestyle project, clickOk; - Uncheck
Restrict where this project can be run; - Click
Build Steps - Add build step - Execute shell; - Add
date; sleep 30;date;; - Go to Jenkins (the job is created and is listed in the
Allview); - Click the green arrow on the far right of the job to send a new instance of the job to the queue;
- The job is expected to show up in the queue and an agent for the cloud instance will be created with the agent workload being deployed in the selected GVC within a few seconds;
- In a few more seconds after that, the agent becomes active and ready to pick up the unlabeled job from the queue;
- After the job is processed, the agent will be allowed to run idle for approximately up to the configured idle time. After that, both the agent and the agent workload will be removed automatically;
- A new job item will restart the provisioning process based on the configuration of the available cloud and agent instances;
- CPU Minimum: 50 millicores (recommended: 200m or higher)
- Memory Minimum: 128 MiB (recommended: 256 MiB or higher)
- The Jenkins inbound-agent is a Java process that requires adequate resources to start. Setting values too low will cause agent startup failures or OOM kills.
- When using Volume Sets, the volume must be of type
shared - Volumes of type
ext4orxfsare NOT supported because they are not compatible on a standard workload
- The Provisioning Cooldown setting (default: 60 seconds) prevents over-provisioning when agents take time to connect
- For unique agents, this cooldown prevents Jenkins from creating multiple agents for the same job
- The cooldown is automatically cleared when an agent successfully connects
The plugin includes automatic cleanup mechanisms that handle various failure scenarios:
- Runs periodically (every 60 seconds by default) to detect and clean up orphan workloads
- Removes workloads that have no matching Jenkins node after a grace period
- Detects terminated, crashed, or OOM-killed workloads
- Detects agents that are online but have stalled JVMs (high response time, no channel activity)
- Automatically cleans up agents that have been stuck for the configured grace period
- Only affects unique agents with no running builds
- Detects builds where the script finished but Jenkins never received the completion event
- Triggers cleanup when: log output stops, channel becomes stale, and no progress for extended period
- Forces build interruption and agent cleanup to prevent indefinite hangs
These mechanisms ensure workloads are cleaned up regardless of:
- Handshake failures
- OOM kills
- Fast exits
- Abnormal websocket terminations
- Controller restarts
- Stalled JVMs due to CPU overload
The plugin uses Jenkins' standard label-based routing to control which jobs run on Control Plane agents. This is especially useful when you have multiple cloud providers configured (e.g., Control Plane, Kubernetes, EC2).
- Cloud Labels: Each cloud configuration has a
Labelsfield where you specify one or more labels (space-separated), e.g.,cpln linux-build - Job Restrictions: In job configurations, you can check "Restrict where this project can be run" and enter a label expression
- Allow Jobs Without Labels: Controls whether unlabeled jobs can run on this cloud
If you have multiple cloud providers:
| Cloud Provider | Labels | Allow Jobs Without Labels |
|---|---|---|
| Control Plane | cpln |
No |
| Kubernetes | k8s |
No |
| EC2 | ec2 |
Yes |
Then job routing works as follows:
| Job Label Expression | Where It Runs |
|---|---|
cpln |
Only Control Plane cloud |
k8s |
Only Kubernetes cloud |
linux |
Any cloud |
- Configure the cloud: Set a unique label on your Control Plane cloud (e.g.,
cpln) - Configure the job:
- Go to the job configuration
- Check "Restrict where this project can be run"
- Enter
cplnin the Label Expression field
- Only agents from the Control Plane cloud will pick up this job
- Give the Control Plane cloud a unique label (e.g.,
cpln) - Uncheck "Allow Jobs Without Labels" on the Control Plane cloud
- Ensure your job either:
- Has no label restriction (it won't match
cpln-only cloud), or - Requests a different label (e.g.,
k8sorec2)
- Has no label restriction (it won't match
For Pipeline jobs, use the agent directive with a label:
pipeline {
agent { label 'cpln' }
stages {
stage('Build') {
steps {
sh 'echo "Running on Control Plane agent"'
}
}
}
}Or for specific stages:
pipeline {
agent none
stages {
stage('Build on CPLN') {
agent { label 'cpln' }
steps {
sh 'echo "Running on Control Plane"'
}
}
stage('Build on K8s') {
agent { label 'k8s' }
steps {
sh 'echo "Running on Kubernetes"'
}
}
}
}- Authorization Requirements for the
API Keyin the Jenkins Cpln Cloud configuration:- list orgs
- list gvcs
- list volume sets (in the configured gvc(s))
- list identities (in the configured gvc(s))
- read workload(s) (in the configured gvc(s))
- create workloads (in the configured gvc(s))
- delete workloads (in the configured gvc(s))
- Jenkins agents can be removed manually at any point and removing the Jenkins agent will also request the Control Plane Jenkins Plugin to remove the underlying resources from the GVCs involved;
- If agent workloads are forcefully removed from the GVCs, the Plugin may recreate them at anytime based on the jobs in the Jenkins queue;
- Unlabeled jobs may be picked up and processed on any agent (and so any GVC) depending on the available cloud instances with one or more executors. This also implies that if no agent workloads are deployed/running, the may be (re)deployed due to the jobs queued;
- If the cloud instance is configured not to take unlabeled jobs, the created job will remain in the queue indefinitely or until the cloud instance is updated to allow unlabeled jobs again. Alternatively, the job item can be updated with one of the labels configured for the cloud instance with the waiting job removed;
- The agent workload is configured to use WebSockets to connect to the Jenkins controller;
- The sample implementation uses unsecured connection (no tls) between the Jenkins controller and the agent workloads. Configuring TLS support and generating public certificates on the Jenkins controller can follow the configuration steps unrelated to the Control Plane Jenkins Plugin. Some related configuration steps and options are discussed here:
- The provisioned agent containers are using standard Jenkins properties to provide agent secrets and additional connection properties to make inbound connections to the controller;













