Armada iconArmada text
Docs

Submitting jobs

Write an Armada job, submit it, and follow it to the end. Also shows how to reprioritize or cancel jobs, and lists every job field.

Before you start

You need a working armadactl. On your laptop, follow Getting started first. On your team's Armada, ask your platform team for the server address and how to log in.

mkdir -p ~/armada-guide
cd ~/armada-guide

1. Create a queue

Every job goes into one queue. Queues are how Armada shares resources fairly between teams. These guides use a queue called my-team.

armadactl create queue my-team --priority-factor 1

Success: Created queue my-team.

Creating a queue requires the create_queue permission. On a laptop install you have it. On a team installation you usually don't: ask your platform team to create the queue for you.

Wait about 10 seconds before the next step. Armada checks for new queues every 10 seconds. Submitting to a brand-new queue straight away fails with could not find queue.

2. Write a job file

A job file describes one or more jobs. Create job.yaml:

cat > job.yaml <<'EOF'
queue: my-team
jobSetId: demo-1
jobs:
  - namespace: default
    priority: 0
    podSpec:
      terminationGracePeriodSeconds: 0
      restartPolicy: Never
      containers:
        - name: sleeper
          image: alpine:3.21
          command: ['sh', '-c']
          args: ['echo hello from Armada; sleep 30']
          resources:
            requests:
              cpu: 200m
              memory: 128Mi
            limits:
              cpu: 200m
              memory: 128Mi
EOF

This job starts a small Linux container, prints hello from Armada, waits 30 seconds, and exits.

TermMeaning
queueThe queue the job goes into.
jobSetIdA label you choose to group related jobs, so you can watch or cancel them together.
namespaceThe Kubernetes namespace the pod runs in. Required. default always exists; on a team installation, ask which to use.
priorityOrder within your queue. Lower runs first.
podSpecA normal Kubernetes pod spec, for exactly one pod.
terminationGracePeriodSeconds: 0Fine for a demo. Real jobs need time to shut down cleanly.

Armada rejects the whole file if any job breaks one of these rules:

  • Each job has exactly one pod. To start several pods together, use a gang.
  • namespace is required.
  • Every container has resources with both requests and limits, and by default they're equal. Operators can allow limits above requests with a server setting: see Operator setup.
  • Node affinity is supported only in its required... form. preferred... node affinity is rejected.
  • priorityClassName, if set, must be on the cluster's allowed list. See Priority and preemption.

3. Check the file

Dry-run for a quick check. It only checks, on your computer, that the file is valid YAML and has at least one job; the rules above are checked by the server when you really submit:

armadactl submit job.yaml --dry-run

Success: it prints nothing and returns to the prompt.

4. Submit the job

JOB_ID=$(armadactl submit job.yaml | awk '{print $5}')
echo "Job ID: $JOB_ID"

This submits the job and keeps its ID in JOB_ID for the rest of this terminal session. You'll need the ID to read the job's output and to cancel it.

Success: it prints the job's ID:

Without the variable, armadactl submit job.yaml prints Submitted job with id <job-id> to job set demo-1. Use one command or the other, not both: each one submits a new job.

Output
Job ID: <job-id>

If you open a new terminal, set it again with JOB_ID=<job-id>, using your own ID. If you lose the ID, it's in every watch line for the job, and in Lookout.

5. Watch it run

armadactl watch my-team demo-1

You'll see the lifecycle as a stream of events. Each line carries a timestamp and running state counts, then the event:

Watching job set demo-1
Oct  2 18:34:13 | Queued:   0, Leased:   0, ... | JobSubmittedEvent, job id: 01m3...
Oct  2 18:34:13 | Queued:   1, Leased:   0, ... | JobQueuedEvent, job id: 01m3...
Oct  2 18:34:17 | Queued:   0, Leased:   1, ... | JobLeasedEvent, job id: 01m3...
Oct  2 18:34:24 | ... | JobPendingEvent, job id: 01m3... pod: 0
Oct  2 18:34:27 | ... | JobRunningEvent, job id: 01m3... pod: 0
Oct  2 18:34:59 | ... | JobSucceededEvent, job id: 01m3... pod: 0

Success: the last event is JobSucceededEvent.

A job moves through this sequence: Queued (waiting for the scheduler), Leased (cluster and node chosen), Pending (pod being created), Running, then Succeeded, Failed, or Cancelled.

watch keeps running until you press Ctrl-C. To stop it when every job in the job set has finished, add --exit-if-inactive. It counts only the jobs it has seen so far, so in a job set with older finished jobs it can stop before a newer job ends. If it's still running after the last job finishes, press Ctrl-C.

If watch says the job set does not exist, wait a few seconds and run it again.

You can also follow jobs in Lookout, Armada's web UI. On a laptop install it's at http://localhost:30000.

6. See the job's output

Read the output soon after the job finishes. Finished pods are cleaned up after a few minutes, and their output goes with them.

On a laptop install, use kubectl. Each job's pod is named armada-<job-id>-0:

kubectl logs -n default armada-$JOB_ID-0

(Or replace $JOB_ID with the ID itself.)

On your team's Armada, open the job in Lookout and choose the Logs tab. (This needs a log service that the laptop install doesn't include.)

Success: you see hello from Armada.

7. Reorder or cancel jobs

Change the priority of one job, or of every job in a job set. Lower numbers run first:

armadactl reprioritize job my-team demo-1 <job-id> 5
armadactl reprioritize job-set my-team demo-1 5

This changes the priority of every unfinished job, including running jobs. It does not interrupt a running job, but the new priority affects its order if it needs to run again.

The job you submitted earlier has already finished, so cancelling it does nothing. Submit a new copy first:

armadactl submit job.yaml

Then, within 30 seconds, before it ends, cancel every job in the job set:

armadactl cancel job-set my-team demo-1

To cancel only one job, use its ID: armadactl cancel job my-team demo-1 <job-id>.

Success: in watch or Lookout, the job moves to Cancelled. If you cancel a job while it's starting, watch may still print JobPendingEvent or JobRunningEvent after JobCancelledEvent; these are late updates, and the job stays cancelled.

Clean up

Nothing to do: finished pods are cleaned up automatically. Keep the my-team queue and the ~/armada-guide folder for the next guides.

Reference

Job file fields

Fields on each entry under jobs::

FieldMeaning
namespaceKubernetes namespace the pod runs in. Required.
priorityOrder within your queue. Lower runs first. No effect on other queues, and never causes preemption.
podSpecA standard Kubernetes pod spec, for one pod.
labels / annotationsAdded to the pod. The text {JobId} in any value is replaced with the job's ID.
clientIdA key that helps prevent duplicates, up to 100 characters. Submitting again with the same clientId to the same queue normally returns the original job instead of creating a new one. This is best effort: a database error can let a duplicate through, and saved keys can be removed after 7 days (the default).
ingress / servicesMake the job reachable over the network. See Interactive jobs and services.

The pod spec

Apart from the rules in Step 2, the pod spec is plain Kubernetes: imagePullSecrets, secret and config-map volumes, securityContext, init containers, nodeSelector, tolerations, activeDeadlineSeconds and serviceAccountName work as the Kubernetes docs describe.

Init containers have one extra rule: by default, Armada rejects a whole-number CPU value such as 1, so use a fractional value such as 900m.

Armada changes three things from a regular Kubernetes job launch:

  • It sets restartPolicy: Never, whatever you wrote. Armada handles retries, not Kubernetes.
  • It adds a node selector that pins the pod to the node the scheduler chose.
  • It adds the environment variables below.

Fields you leave empty may be filled in from server defaults:

FieldDefault
priorityClassNamearmada-default
activeDeadlineSeconds72 hours
terminationGracePeriodSeconds0 or unset becomes 1 second; the allowed range is 1 second to 5 minutes
A resource a container doesn't mentioncpu: 1, memory: 1Gi, ephemeral-storage: 8Gi
tolerationsArmada's own taint tolerations are added

Operators can change these.

Special annotations

AnnotationMeaning
armadaproject.io/gangIdMakes the job part of a gang, which starts all together or not at all.
armadaproject.io/gangCardinalityThe total number of jobs in the gang.
armadaproject.io/gangNodeUniformityLabelPlaces every gang member on nodes with the same value of this node label.
armadaproject.io/failFastWhen "true", Armada never retries the job: if a run fails or its node is lost, the job fails at once, even if the queue has a retry policy. Gang jobs get this automatically. "true" is the only allowed value.

Environment variables in every job

Armada adds these to every container, including init containers, unless you set a variable with the same name:

VariableValue
ARMADA_JOB_IDThe job's ID. It stays the same across runs.
ARMADA_JOB_RUN_IDThe ID of the current run. Each run has a different ID.
ARMADA_QUEUEThe job's queue
ARMADA_JOB_SET_IDThe job's job set
ARMADA_GANG_IDGang jobs only: the gang ID
ARMADA_GANG_CARDINALITYGang jobs only: the number of jobs in the gang
ARMADA_GANG_NODE_UNIFORMITY_LABEL_NAMEGang jobs only: the node label the gang is grouped by, if any
ARMADA_GANG_NODE_UNIFORMITY_LABEL_VALUEGang jobs only: that label's value on the gang's nodes

Getting data in and out

Armada runs pods. It doesn't move data.

  • Inputs come from your container image, or from volumes in the job's namespace (a PVC, or object storage your code reads).
  • Results must be written to storage outside the pod before the container exits. The pod's files are gone when the job ends.
  • Logs are normal container logs, readable while the pod exists (see Step 6). Finished pods are cleaned up after a few minutes. Lookout keeps the job's outcome: its state, error message and exit codes. To keep logs, write them to your own storage.

Operator setup

These settings control the rules and defaults above. They're in the Armada server's configuration, under submission:. On an Operator install, that's the ArmadaServer resource's spec.applicationConfig.submission.

SettingDefaultWhat it controls
allowedPriorityClassNamesarmada-default, armada-preemptible, armada-resilientWhich priorityClassName values jobs may use
defaultPriorityClassNamearmada-defaultThe class used when a job names none
defaultJobLimitscpu: 1, memory: 1Gi, ephemeral-storage: 8GiFilled in for any resource a container doesn't mention
minJobResourcesmemory: 1MiSmallest allowed request per resource
maxOversubscriptionByResourceRequestNot setHow far limits may exceed requests. Not set means they must be equal.
minTerminationGracePeriod / maxTerminationGracePeriod1s / 5mAllowed shutdown time. 0 or not set becomes the minimum.
defaultActiveDeadline72hTime limit for jobs that set none
defaultActiveDeadlineByResourceRequestnvidia.com/gpu: 336hTime limit by resource; the highest match wins
defaultJobTolerationsArmada's own taintsTolerations added to every pod, so operators can reserve nodes
restrictedTolerationKeysNot setToleration keys users may not set
maxPodSpecSizeBytes65535Largest allowed pod spec

Troubleshooting

What you seeCauseFix
PermissionDenied ... could not find queue "<name>"The queue is brand new, or doesn't existWait 10 seconds and try again. Check the name with armadactl get queues.
user ... cannot perform action submit on queue ...You don't have submit rights on the queueAsk your platform team to give you (or your group) the submit permission on the queue.
Error: Warning: You have provided no jobs to submit.The file has no jobs under jobs:Add at least one job.
Failed to parse file ... found character that cannot start any tokenThe YAML is broken, usually by a tabReplace tabs with spaces.
namespace is a required fieldThe job has no namespaceAdd namespace: default (or your team's namespace).
Job must contain at least one PodSpecThe job has no podSpecAdd one.
container <name> has no resources specifiedA container has no resourcesAdd requests and matching limits.
container <name> defines different resources for requests and limitsA container has requests but no limitsAdd limits equal to requests.
defines cpu with limits great than 1.00*requests or defines cpu with limits smaller than requestsA limit doesn't equal its requestMake each limit equal to its request.
preferredDuringSchedulingIgnoredDuringExecution node affinity is not supported by Armadapreferred... node affinityUse requiredDuringSchedulingIgnoredDuringExecution.
priority class X is not supportedThat class isn't allowed on this installationUse armada-default or armada-preemptible, or ask your platform team.
client id of length N is greater than max allowed length of 100clientId is too longUse 100 characters or fewer.
watch says the job set does not existThe job hasn't reached the event stream yetWait a few seconds and run watch again.
watch keeps running after the job endsWithout --exit-if-inactive, watch doesn't stop by itselfPress Ctrl-C.
The job is rejected with exceeds the total limit or insufficient resources availableThe job asks for more than its queue's limit or any single node allows, or the install has only just startedRead the full reason on the Job failed: line in watch, or in the job's Result tab in Lookout. On a new install, wait two minutes and submit again; otherwise lower the job's requests and limits.
The job stays QueuedA scheduling questionCheck why with armadactl get job-report <job-id>.
The job ran twiceTwo submits without a clientId create two jobsSet clientId to a stable, unique value.
zsh: no such file or directory: job-id (or bash: job-id: No such file or directory)A placeholder was pasted with its angle bracketsReplace <job-id>, including < and >, with the real value.
Edit on GitHub

Last updated on