Expected Outcome
This article provides an overview of using the Nomad job API to create a new job, run a job plan (e.g. see actions to be taken by Nomad and the differences between the old and new job), and update your existing jobs. The Nomad API uses JSON, not HCL, as the input format, so you will want to convert your current jobspec before continuing. If you prefer to save some time (e.g. many files to convert), Nomad can perform the conversion by simply adding the -output flag to the 'nomad job run' command and directing the output to a file.
nomad job run -output example.nomad > example.json
Prerequisites
All API output is in JSON format; while it's not a requirement, having jq installed on your machine will aid in the reading/parsing of the API output.
Create a New Job Using the Jobs API
Procedure
-
Verify that the jobspec is in JSON format
-
Use curl to post the jobspec to the jobs API
Format
curl -s --request POST --data @<FILENAME>.json $NOMAD_ADDR/v1/jobs
Example
$ curl -s --request POST --data @example.json $NOMAD_ADDR/v1/jobs | jq
{
"EvalID": "79b5392a-07fc-fe2a-c224-2462db15c4a3",
"EvalCreateIndex": 250,
"JobModifyIndex": 250,
"Warnings": "",
"Index": 250,
"LastContact": 0,
"KnownLeader": false,
"NextToken": ""
}
View Nomad Actions Before Modifying a Job
When running a job plan via the API, you have the option for high-level update information only or detailed job differences can be included in the output as well. This section will cover the high-level output only.
Procedure
-
Verify the new jobspec is in JSON format and that the desired job updates (e.g. new image version) have been added.
-
Use curl to post the new jobspec to the job plan API
Format
curl -s --request POST --data @<FILENAME>.json $NOMAD_ADDR/v1/job/<JOB_NAME>/plan | jq
Example
$ curl -s --request POST --data @example.json $NOMAD_ADDR/v1/job/example/plan | jq
{
"Annotations": {
"DesiredTGUpdates": {
"cache": {
"Ignore": 0,
"Place": 0,
"Migrate": 0,
"Stop": 0,
"InPlaceUpdate": 0,
"DestructiveUpdate": 1,
"Canary": 0,
"Preemptions": 0
}
},
"PreemptedAllocs": null
},
"FailedTGAllocs": null,
"JobModifyIndex": 250,
"CreatedEvals": null,
"Diff": null,
"NextPeriodicLaunch": null,
"Warnings": "",
"Index": 250
}
In the example above, you can see that this change will cause Nomad to perform a DestructiveUpdate, meaning that the change to the jobspec will cause the current job container to be stopped, and a new container will take its place.
DesiredTGUpdates
Ignore | Allocations that require no upgrades |
Place | Place is the set of allocations to place by the scheduler |
Migrate | Migrate is used to indicate that this allocation should be stopped and migrated to another node |
Stop | Stop is the set of allocations to stop |
InPlaceUpdate | InplaceUpdate is the set of allocations to apply an inplace update to |
DestructiveUpdate | DestructiveUpdate is the set of allocations to apply a destructive update to |
Canary | The number of canaries to be created without stopping any previous allocations |
Preemptions | The number of allocations that would be preempted if the job plan is run |
View Nomad Actions Before Modifying a Job (Including Differences Between the Current Job & New Job)
This section covers the additional information needed in the new jobspec file to get detailed information (differences) between the current and new job.
Procedure
-
Verify the new jobspec is in JSON format and that the desired job updates (e.g. new image version) have been added.
-
Edit the jobspec and add ' "Diff": true ' before the closing } at the end of the JSON.
- Use curl to post the new jobspec to the job plan API
Before
{
"Job": {
"Region": null,
"Namespace": null,
"ID": "example",
"Name": "example",
"Type": null,
"Priority": null,
"AllAtOnce": null,
"Datacenters": [
"dc1"
],
... [MIDDLE TRUNCATED]
"VaultNamespace": null,
"NomadTokenID": null,
"Status": null,
"StatusDescription": null,
"Stable": null,
"Version": null,
"SubmitTime": null,
"CreateIndex": null,
"ModifyIndex": null,
"JobModifyIndex": null
}
}
After
{
"Job": {
"Region": null,
"Namespace": null,
"ID": "example",
"Name": "example",
"Type": null,
"Priority": null,
"AllAtOnce": null,
"Datacenters": [
"dc1"
],
... [MIDDLE TRUNCATED]
"VaultNamespace": null,
"NomadTokenID": null,
"Status": null,
"StatusDescription": null,
"Stable": null,
"Version": null,
"SubmitTime": null,
"CreateIndex": null,
"ModifyIndex": null,
"JobModifyIndex": null
},
"Diff": true
}
-
Use curl to post the new jobspec to the job API
Format
curl --request POST --data @<FILENAME>.json $NOMAD_ADDR/v1/job/<JOB_NAME>/plan | jq
Example
$ curl -s --request POST --data @example2.json $NOMAD_ADDR/v1/job/example/plan | jq
{
"Annotations": {
"DesiredTGUpdates": {
"cache": {
"Ignore": 0,
"Place": 0,
"Migrate": 0,
"Stop": 0,
"InPlaceUpdate": 0,
"DestructiveUpdate": 1,
"Canary": 0,
"Preemptions": 0
}
},
"PreemptedAllocs": null
},
"FailedTGAllocs": null,
"JobModifyIndex": 250,
"CreatedEvals": null,
"Diff": {
"Type": "Edited",
"ID": "example",
"Fields": [
{
"Type": "Added",
"Name": "Meta[DB]",
"Old": "",
"New": "true",
"Annotations": null
},
{
"Type": "Added",
"Name": "Meta[Production]",
"Old": "",
"New": "false",
"Annotations": null
},
{
"Type": "Added",
"Name": "Meta[Version]",
"Old": "",
"New": "7",
"Annotations": null
}
],
"Objects": null,
"TaskGroups": [
{
"Type": "Edited",
"Name": "cache",
"Fields": null,
"Objects": null,
"Tasks": [
{
"Type": "Edited",
"Name": "redis",
"Fields": null,
"Objects": [
{
"Type": "Edited",
"Name": "Config",
"Fields": [
{
"Type": "None",
"Name": "auth_soft_fail",
"Old": "true",
"New": "true",
"Annotations": null
},
{
"Type": "Edited",
"Name": "image",
"Old": "redis:3.2",
"New": "redis:7",
"Annotations": null
},
{
"Type": "None",
"Name": "ports[0]",
"Old": "db",
"New": "db",
"Annotations": null
}
],
"Objects": null
}
],
"Annotations": [
"forces create/destroy update"
]
}
],
"Updates": {
"create/destroy update": 1
}
}
]
},
"NextPeriodicLaunch": null,
"Warnings": "",
"Index": 250
}
In the example above, you can see that this change will cause Nomad to perform a DestructiveUpdate, meaning that the change to the jobspec will cause the current job container to be stopped, and a new container will take its place.
Additionally, you can see new meta has been added to the jobspec and that the redis image has been updated from 3.2 to 7.
Update an Existing Job
Procedure
-
Once you are satisfied with the job plan output, it's time to apply the new jobspec
-
Use curl to post the new jobspec to the job API
Format
curl -s --request POST --data @<FILENAME>.json $NOMAD_ADDR/v1/job/<JOB_NAME> | jq
Example
$ curl -s --request POST --data @example2.json $NOMAD_ADDR/v1/job/example | jq
{
"EvalID": "a4fb6c6b-93e5-0fe8-b056-cb65a10106c8",
"EvalCreateIndex": 373,
"JobModifyIndex": 373,
"Warnings": "",
"Index": 373,
"LastContact": 0,
"KnownLeader": false,
"NextToken": ""
}