This is a very early release of this plugin!
There are still plenty of bugs a non-implemented features that you may depend on!
This is a plugin for Jenkins that runs Jenkins job into the Nomad scheduler, and allow the configuration of the Nomad jobs from Jenkins pipelines.
Sample job:
// Guarantee the node will use this template
def label = "job-${UUID.randomUUID().toString()}"
nomadJobTemplate(label: label) {
node(label) {
stage("Run shell command") {
echo "Hello world!"
}
}
}
You first need to install the plugin.
Then, follow the menu Jenkins → Manage Jenkins → Configure System.
In the Cloud section, click on Add a new cloud → Nomad to configure the Nomad cloud entry.
You will need to set:
- Name: this has to be set to
nomad
for now - Nomad URL: the URL to your Nomad cluster. It has to be reachable from the Jenkins master
- Region: the default Nomad region you want to launch your job in. See Regions and Datacenters in the Nomad documentation.
- Datacenters: the default Nomad datacenters you want to launch your job in. See Regions and Datacenters in the Nomad documentation.
You will then be ready to configure and start a new Jenkins job!
If your Nomad cluster has ACLs enabled, you can configure the plugin to authenticate using a dedicated Nomad token.
-
The minimum policy needed by the authenticated persona once connected is:
namespace "default" { capabilities = ["list-jobs", "read-job", "submit-job"] }
-
Once the token has been created and associated with this policy, it can be saved as a new
Secret text
credentials in Jenkins. The credentials can optionaly be associated to the domain of your Nomad cluster. -
Finally, in the plugin configuration panel in Jenkins → Manage Jenkins → Configure System, select the correct credentials in the Nomad Token select box.
The plugin creates a new Nomad job for each agent started and stops it after each build.
The plugin expects that the agent launched by Nomad will automatically connect to the Jenkins master via JNLP (see Distributed builds).
For that purpose, the following environment variables are automatically injected:
JENKINS_AGENT_NAME
: the name of the Jenkins agentJENKINS_JNLP_URL
: the URL for Jenkins agent JNLP configuration fileJENKINS_SECRET
: the secret key for authenticationJENKINS_URL
: the URL to Jenkins web interface
By default if not specified otherwise, the plugin launches the jenkins/jnlp-slave Docker image.
You can set a more complex configuration, as shown below:
// Guarantee the node will use this template
def label = "job-${UUID.randomUUID().toString()}"
nomadJobTemplate(
label: label,
taskGroups: [
taskTemplate(
name: 'jnlp',
image: 'jenkins/jnlp-slave:alpine',
resourcesMemory: 2048,
resourcesCPU: 1000,
envVars: [
envVar(key: 'my-super-var', value: '1234'),
envVar(key: 'OTHER_VAR', value: 'foobar'),
],
)
]
) {
node(label) {
stage("Run shell command") {
echo "Hello world!: ${env.OTHER_VAR}"
}
}
}
- Specify the Docker image to run your job in your job definition
- Adjust the resources needed in your job definition
- Configure environment variables for your whole job
- Optionally, automatically download the Jenkins agent from the Jenkins master
Current limitations:
- This is a very early version!
- Although it's possible to define multiple tasks within a job, this has not been tested yet
- Although it's possible to define multiple Nomad jobs in the same Jenkins pipeline, this has not been tested yet.
- It's currently not possible to configure the agent to receive SSH connection from the Jenkins master.
- It's not possible to use the plugin using a declarative
Jenkinsfile
configuration file (see #2) - Look at the issues!
TODO: complete me!
-
name
: name of Nomad task group to run. It specifies value forTaskGroups/Name
in Nomad Job definition. -
image
: image identifier to use for the job. Specifies value forTaskGroups/Tasks/Config/image
in Nomad Job definition.The value undergoes variable names expansion. Jenkins environment variables can be specified like this:
image: 'img-repo:5003/repo/my-image:${env.BRANCH_NAME}_${env.BUILD_ID}'
You can also specify container environment variables:
taskGroups: [ taskTemplate( name: 'my-task-grp', image: 'img-repo:5003/repo/my-image:${IMAGE_VERSION}' ) ], envVars: [ envVar(key: 'IMAGE_VERSION', value: '0.1') ]
-
resourcesMemory
: memory resources allocated for the job. Specifies value forTaskGroups/Tasks/Resources/MemoryMB
in Nomad Job definition. -
resourcesCPU
: cpu resources allocated for the job. Specifies value forTaskGroups/Tasks/Resources/CPU
in Nomad Job definition. -
command
: command to execute then running the container. Specifies value forTaskGroups/Tasks/Config/command
in Nomad Job definition.The value undergoes the same variable names expansion as in case of
image
setting. -
args
: arguments to pass to command then running the container. Specifies value for TaskGroups/Tasks/Config/args in Nomad Job definition.Each argument list entry undergoes the same variable names expansion as in case of
image
setting. -
downloadAgentJar
: default tofalse
. If set, download the slave agent from the Jenkins master at/jnlpJars/slave.jar
into/local/slave.jar
, prior to start the Nomad job.You can then start the worker using the following command:
java -jar /local/slave.jar -jnlpUrl $JENKINS_JNLP_URL -secret $JENKINS_SECRET'
Migrating from Nomad Plugin
There's another Jenkins plugin for Nomad which has a very different approach and doesn't support pipeline jobs defintion.
You can still use the same Docker image as you were using with the other plugin with a few adjustements:
-
The other plugin was downloading an agent
jar
file directly from the Jenkins master. This is not done automatically by default so you need to setdownloadAgentJar
totrue
to download it into/local/slave.jar
. -
The other plugin was starting the Jenkins agent on behalf of the Docker image.
You will now need to start this agent yourself by setting the right command line in the Nomad job.
def label = "job-${UUID.randomUUID().toString()}"
nomadJobTemplate(
label: label,
taskGroups: [
taskTemplate(
name: 'jnlp',
image: 'your/image', // Your previous Docker image
// Download the slave agent from the Jenkins master at
// http://jenkins-master/jnlpJars/slave.jar
downloadAgentJar: true,
command: 'sh',
args: [
'-c',
// Start the Jenkins agent:
// * /local/slave.jar is automatically downloaded by Nomad from
// the Jenkins master
// * The JNLP URL and the Jenkins secret is injected by the Jenkins
// Nomad plugin.
'java -jar /local/slave.jar -jnlpUrl $JENKINS_JNLP_URL -secret $JENKINS_SECRET',
],
)
]
) {
// your build here
}
mvn package
Easy way:
- download Nomad and run
nomad agent -dev
on your machine (you need Docker also). - then run:
mvn hpi:run -Djetty.consoleForceReload=false -Djava.util.logging.config.file=debug-plugin-logging.properties
- wait for Jenkins to start and connect on http://localhost:8080/jenkins/
- create a new pipeline job with the code from
test-config/test.Jenkinsfile
- configure Jenkins, add a new Cloud Provider and set the Server URL to http://localhost:4646
This plugin is heavily based on the kubernetes-plugin - it actually started as a fork of the Kubernetes code, replaced by calls to the Nomad API.
You may also want to have a look at the nomad-plugin:
nomad-pipeline
allows to define how to run a Jenkins worker directly from aJenkinsfile
build file, instead of referring to an external definition (configured in the Jenkins master). This give much finer grained opportunities to control the environment in which the build runs at the expense of preventing to have long-running Jenkins worker.- jenkinsci/nomad-plugin#20 is the initial issue which
prompted for the creation of
nomad-pipeline
.