Jenkins agents can be instructed to shut themselves down from within a pipeline, but it’s not as simple as just calling a shutdown command.
Let’s see this in action. Imagine you have a pipeline that needs to spin up a temporary agent, run some tests, and then cleanly shut down that agent to save costs.
pipeline {
agent any
stages {
stage('Provision and Test') {
agent {
kubernetes {
label 'my-ephemeral-pod'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: jenkins-agent
image: jenkins/inbound-agent:latest
command: ['/bin/agent', '--url', 'http://jenkins.example.com', '--tunnel', 'jenkins.example.com:50000', '--credentials', 'jenkins-agent-credentials', '--work-dir', '/home/jenkins/agent']
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "200m"
"""
}
}
steps {
script {
// Agent is now running and connected to Jenkins
echo "Agent is ready. Running tests..."
// Simulate some work
sleep 60
echo "Tests complete. Initiating agent shutdown."
// How do we tell this pod to shut down?
}
}
}
}
}
The problem here is how to signal the specific agent pod provisioned by the Kubernetes agent plugin to terminate. It’s not a direct command you run on the agent itself in the traditional sense. Instead, Jenkins manages the lifecycle of these ephemeral agents.
Here’s how you actually achieve it, broken down by the common ways Jenkins manages agents:
1. Kubernetes Pod Agents (as in the example above):
- Diagnosis: The Kubernetes plugin creates and manages the lifecycle of pods. To shut down an agent pod, you don’t execute a command inside the pod; you instruct the Jenkins controller to delete the pod.
- Cause: The agent is provisioned as a Kubernetes Pod. Its existence is managed by the Kubernetes API.
- Command/Check: You can’t directly
kubectl delete pod <pod-name>from within the pipeline script that’s running on that pod, as it would likely fail due to permissions or race conditions. Instead, the pipeline needs to interact with the Jenkins controller, which then interacts with Kubernetes. - Fix: Use the
podTemplateconfiguration in your Jenkinsfile andagent { kubernetes { ... } }block. To terminate it, the pipeline should exit gracefully. When the pipeline finishes its stages and theagentblock scope ends, the Jenkins controller will automatically delete the associated Kubernetes pod if it was provisioned for that specific pipeline run. If you need to force an early shutdown, you can do so by cancelling the build from the Jenkins UI. The plugin is designed to clean up resources when the build is no longer active. - Why it works: The Kubernetes plugin tracks the pods it creates for ephemeral agents. When a build using such an agent completes or is cancelled, the plugin’s cleanup logic triggers the deletion of the corresponding pod via the Kubernetes API.
2. Docker Agents (via Docker Pipeline plugin):
- Diagnosis: When using
agent { docker { ... } }, Jenkins starts a Docker container. To stop it, you need to tell Jenkins to stop the container it launched. - Cause: The agent is a Docker container managed by the Docker Pipeline plugin.
- Command/Check: You can use the
docker.image('your-image').inside { ... }syntax. When theinsideblock finishes, the container is automatically stopped and removed by the plugin. - Fix: Structure your pipeline stages within the
docker.image('your-image').inside { ... }block.
When this stage completes, the container is automatically stopped.stage('Run in Docker') { agent { docker { image 'maven:3.8.5-openjdk-11' args '-v /var/run/docker.sock:/var/run/docker.sock' } } steps { sh 'echo "Running inside Docker container"' sh 'mvn --version' } } - Why it works: The Docker Pipeline plugin manages the lifecycle of containers it launches for pipeline stages. Upon completion of the
insideblock, the plugin executesdocker stopanddocker rmon the container it created.
3. JNLP Agents (Classic, "Swarm" agents):
- Diagnosis: These are agents that connect to Jenkins using the JNLP protocol. They are typically long-running processes. Shutting them down from a pipeline requires a specific mechanism.
- Cause: The agent is a dedicated Jenkins agent process (often a
slave.jaroragent.jar) that connects to the Jenkins controller. - Command/Check: You can use the
Jenkinsglobal configuration to label nodes and check their status. To shut down a specific JNLP agent programmatically, you often need to execute a command on the Jenkins controller that targets the agent. - Fix: The most reliable way is to use the Jenkins API or a plugin that exposes agent management functions. A common method involves using the Jenkins CLI or Groovy scripts executed on the controller. For example, you could have a pipeline on a different agent execute a Groovy script:
Or, if the JNLP agent has access to// On a different agent or controller: Jenkins.instance.getNode('my-jnlp-agent-name').terminate()jenkins-cli.jar:
Note:java -jar jenkins-cli.jar -s http://jenkins.example.com/ -auth YOUR_USER:YOUR_API_TOKEN delete-node my-jnlp-agent-nameterminate()is for shutting down the agent process itself,delete-noderemoves it from Jenkins configuration. - Why it works: Jenkins holds a reference to connected agents. The
terminate()method on aNodeobject signals the agent process to shut down its connection and exit.delete-noderemoves the agent’s configuration from Jenkins.
4. SSH Agents (via SSH Agent plugin):
- Diagnosis: Similar to JNLP agents, these are typically long-running processes.
- Cause: The agent is a remote machine that Jenkins connects to via SSH to execute builds.
- Command/Check: The SSH Agent plugin typically uses
sshcommands to execute steps. Shutting down the remote machine from within a pipeline running on that machine is usually not feasible or advisable due to permissions and the risk of cutting off the connection. - Fix: Similar to JNLP agents, you’d typically manage the lifecycle of the remote machine externally or via a separate administrative pipeline. If you must shut down the remote machine from a pipeline running on it, you would need to ensure the SSH user Jenkins uses has sufficient privileges to execute a shutdown command (e.g.,
sudo shutdown -h now). This is highly discouraged for security and reliability reasons. A better approach is to use ephemeral SSH agents (e.g., provisioned by Terraform/Ansible and then deleted) or use Kubernetes/Docker agents. - Why it works: If the SSH user has privileges, the
shutdowncommand directly instructs the operating system on the remote machine to halt.
5. Cloud Provisioned Agents (EC2, etc.):
- Diagnosis: Agents launched by cloud plugins (like EC2) are virtual machines.
- Cause: The agent is an instance in a cloud provider (AWS, Azure, GCP) managed by a Jenkins plugin.
- Command/Check: The plugin automatically terminates the instance when the build is done. If you need to trigger it early, cancelling the build from the Jenkins UI is the standard way.
- Fix: Ensure your cloud agent configuration is set up correctly to allow automatic termination. When a build using a dynamically provisioned cloud agent finishes, the plugin’s cleanup routine will signal the cloud provider to terminate the instance.
- Why it works: The cloud plugins are designed to provision and de-provision resources. They track the instances they launch and, upon build completion or cancellation, use the cloud provider’s API to terminate them.
The next thing you’ll likely run into is managing credentials for these dynamic agent provisioning and cleanup operations.