Sometimes we just want to restart a job. Unfortunately, Kubernetes does not have this feature implemented in version 1.15.

The solution is to get the job config, remove the labels kubernetes added to it and reapply it to the cluster:

kubectl get job my-job -n my-namespace -o json |
  jq 'del(.spec.selector)' |
  jq 'del(.spec.template.metadata.labels)' |
  kubectl replace --force -f - >/dev/null

kubectl wait --for=condition=complete job/my-job -n my-namespace --timeout 120s >/dev/null

If you use it a lot, you can create a script file for it

$ touch krestart.sh

krestart.sh:

#!/bin/bash

JOB=$1
NAMESPACE=$2

kubectl get job $JOB -n $NAMESPACE -o json |
  jq 'del(.spec.selector)' |
  jq 'del(.spec.template.metadata.labels)' |
  kubectl replace --force -f - >/dev/null
kubectl wait --for=condition=complete job/$JOB -n $NAMESPACE --timeout 120s >/dev/null

and run with

$ ./krestart.sh my-job my-namespace

Explanation

The first step is to get the job JSON output

$ kubectl get job my-job -n my-namespace -o JSON

When we get the job as JSON, the object will look something like this:

{
	"apiVersion": "batch/v1",
    "kind": "Job",
	//more stuff here
	"spec": {
		"selector": {
            "matchLabels": {
                "controller-uid": "6682047e-9d15-45b6-b324-c06ac8f323f6"
            }
        },
        "template": {
        	"metadata": {
        		"labels": {
                    "controller-uid": "6682047e-9d15-45b6-b324-c06ac8f323f6",
                    "job-name": "my-job"
                }
        	},
        }
	}
	//more stuff here
}

So, we use jq to get rid of spec.selector property and spec.template.metadata.labels, because these properties are created by kubernetes the moment we apply the job configuration in the cluster

$ jq 'del(.spec.selector)'

and

$ jq 'del(.spec.template.metadata.labels)'

Then, we reapply the result back to the cluster and redirect the output to /dev/null file, which is a special file in Linux that discards all data written to it but reports the write operation as succeeded.

$ kubectl replace --force -f - >/dev/null

In the end, we wait for the job to be finished with the status complete

$ kubectl wait --for=condition=complete job/my-job -n my-namespace --timeout 120s >/dev/null