Run Kubernetes Jobs

Updated 6 months ago by Michael Cretzman

Kubernetes Jobs create one or more pods to carry out commands. For example, a calculation or a backup operation.

In Harness Kubernetes deployments, you define Jobs in the Harness Service Manifests. Next you add the Apply step to your Harness Workflow to execute the Job.

In this topic, we will show you how to execute a Job in a Harness Kubernetes deployment as part of the main deployment.

Typically, Jobs are not part of the main deployment. You can exclude them from the main deployment and simply call them at any point in the Workflow using the Apply step. For steps on ignoring the Job as part of the main deployment and executing it separately, see Deploy Manifests Separately using Apply Step.

In this topic:

Before You Begin

  • ​Kubernetes Jobs — We assume you are familiar with Kubernetes Jobs.
  • Apply step — The Harness Workflow Apply step allows you to deploy any resource you have set up in the Service Manifests section at any point in your Workflow. See  Deploy Manifests Separately using Apply Step.
  • Ignoring Manifests — You can annotate a manifest to have Harness ignore it when performing its main deployment operations. Then you can use the Apply step to execute the manifest wherever you want to run it in the Workflow. See Ignore a Manifest File During Deployment.

Visual Summary

In this topic, we will walk through a simple Job deployment. Here is the completed deployment in Harness:

Review: Apply Step

Workflows include an Apply step that allows you to deploy any resource you have set up in the Service Manifests section.

Harness supports Deployment workloads in Canary and Blue/Green Workflows only. Rolling Workflows support all workloads except Jobs. The Apply step can deploy all workload types, including Jobs.

You can add an Apply step anywhere in your Harness Workflow. This makes the Apply step useful for running Kubernetes Jobs.

Here are some Job examples:

  • Run independent but related work items in parallel: sending emails, rendering frames, transcoding files, or scanning database keys.
  • Create a new pod if the first pod fails or is deleted due to a node hardware failure or node reboot. 
  • Create a Job that cleans up the configuration of an environment, to create a fresh environment for deployment.
  • Use a Job to spin down the replica count of a service, to save on cost.

Step 1: Add Job Manifest

For this topic, we will create a Service named Countdown of the Kubernetes Deployment Type.

The Job manifest is added to the Harness Service Manifests section.

Here is a Job that will countdown from 15 to 1 and print out the countdown when complete:

apiVersion: batch/v1
kind: Job
metadata:
name: {{.Values.name}}
spec:
template:
metadata:
name: {{.Values.name}}
labels:
app: {{.Values.name}}
spec:
containers:
- name: counter
image: {{.Values.image}}
command:
- "bin/bash"
- "-c"
- "for i in $(seq 1 15); do echo $((16-i)); sleep 1s; done"
restartPolicy: Never

In your Harness Service, in Manifests, you simply add the Job in a manifest file. Let's walk through adding the manifest and the values.yaml file.

First, we add a CentOS Docker Image as the Docker Registry Artifact Source for the Service.

Next, we create the countdown.yaml file in a templates folder. It contains the exact same countdown Job example listed above:

Next, edit values.yaml to contain the name and image labels only:

name: countdown
image: ${artifact.metadata.image}

Now that the Job is added to the Service, we can select the target cluster where the Job will be deployed.

Step 2: Define Target Cluster

Jobs do not require any changes to the way you specify the target cluster in Harness.

For steps on setting up the target cluster, see Define Your Kubernetes Target Infrastructure.

Step 3: Add the Job to the Workflow

For this topic, we will create a Harness Rolling Workflow for our Service, named Countdown.

  1. In the Workflow Deploy section, delete the Rollout Deployment step. We don't need the Rollout Deployment step because we will simply deploy the Job using the Apply step.
  2. In the Workflow Deploy section, click Add Step, and then select the Apply step.
  3. Set up the Apply step to use the Job manifest in the Service Manifests: templates/countdown.yaml.

That's all you have to do to add the Job to your Workflow. Next, we'll add some test and clean up steps.

Step 4: Add Test and Clean Up Steps

  1. In Workflow Variables, add a new variable named JobName and give it the value countdown. We will use this variable in a Shell Script step to check if the Job is complete.
  2. In the Verify section of the Workflow, click Add Step, and then select the Shell Script step.
  3. In the Shell Script step, in Script, add the following script to check if the Job completed:
kubectl wait --for=condition=complete --timeout=30s jobs/${workflow.variables.JobName} -n ${infra.kubernetes.namespace}

You can see the script uses the Workflow variable expression ${workflow.variables.JobName} to get the name of the Job, countdown.

Next, we'll add a Shell Script step to output the log for the Job. When we deploy, the log will display the countdown from 15 to 1 performed by the Job.

  1. In the Wrap Up section of the Workflow, add another Shell Script step. In Script, enter the following script:
kubectl logs -n ${infra.kubernetes.namespace} $(kubectl get pods -n ${infra.kubernetes.namespace} -l job-name=${workflow.variables.JobName} -o jsonpath='{.items[*].metadata.name}')

Finally, let's add a Delete step to remove the Job.

  1. In the Wrap Up section of the Workflow, after the Shell Script step, click Add Step. Select the Delete step.
  2. In Resources, enter the type and name of the resource, Job/countdown.

See Delete Kubernetes Resources for more information on how to reference resources.

Now that our Job deployment is set up, we can run it.

Step 5: Deploy the Job

  1. In the Workflow, click Deploy.
  2. In Start New Deployment, we enter countdown for the JobName Workflow variable, select a Build/Version for our CentOS artifact, and click Submit.

Let's look at the results of each step.

In the Apply step, in Wrap Up, you can see that the Job is run:

Wrapping up..


kubectl --kubeconfig=config describe --filename=manifests.yaml

Name: countdown
Namespace: default
Selector: controller-uid=aff025af-6ebe-11ea-b052-4201ac10c80b
Labels: app=countdown
controller-uid=aff025af-6ebe-11ea-b052-4201ac10c80b
job-name=countdown
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"batch/v1","kind":"Job","metadata":{"annotations":{"kubernetes.io/change-cause":"kubectl apply --kubeconfig=config --filenam...
kubernetes.io/change-cause: kubectl apply --kubeconfig=config --filename=manifests.yaml --record=true
Parallelism: 1
Completions: 1
Start Time: Wed, 25 Mar 2020 17:33:06 +0000
Completed At: Wed, 25 Mar 2020 17:33:22 +0000
Duration: 16s
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
Pod Template:
Labels: app=countdown
controller-uid=aff025af-6ebe-11ea-b052-4201ac10c80b
job-name=countdown
Containers:
counter:
Image: registry.hub.docker.com/library/centos:6.10
Port: <none>
Host Port: <none>
Command:
bin/bash
-c
for i in $(seq 1 15); do echo $((16-i)); sleep 1s; done
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 22s job-controller Created pod: countdown-wzph5

Done.

In the Shell Script step in Verify, we can see that our Job completed:

In the Shell Script step in Wrap Up, we can see the log for the Job pod:

Finally, in the Delete step, you can see the countdown Job deleted.

Summary

Using the Apply step, you are able to configure, manage, and deploy a Kubernetes Job.

One More Thing to Try

As we demonstrated, you can get the status of the Job using a simple script. In addition, you can output that status to a Jira, ServiceNow, or Email step using the Shell Script step Publish Variable Name.

For example, let's change the Shell Script that checks the success of the Job. We will add the output to a variable and then publish that variable:

Now you can obtain the output via the variable expression ${context.checkjob.jobstatus}. Here's an Email step using the published variable:

For information on these collaboration tools, see:


How did we do?