<p>I'm looking for a way to quickly run/restart a Job/Pod from the command line and override the command to be executed in the created container.</p>
<p>For context, I have a Kubernetes Job that gets executed as a part of our deploy process. Sometimes that Job crashes and I need to run certain commands <em>inside the container the Job creates</em> to debug and fix the problem (subsequent Jobs then succeed).</p>
<p>The way I have done this so far is:</p>
<ul>
<li>Copy the YAML of the Job, save into a  file</li>
<li>Clean up the YAML (delete Kubernetes-managed fields)</li>
<li>Change the <code>command:</code> field to <code>tail -f /dev/null</code> (so that the container stays alive)</li>
<li><code>kubectl apply -f job.yaml &amp;&amp; kubectl get all &amp;&amp; kubectl exec -ti pod/foobar bash</code></li>
<li>Run commands inside the container</li>
<li><code>kubectl delete job/foobar</code> when I am done</li>
</ul>
<p>This is very tedious. I am looking for a way to do something like the following</p>
<pre><code>kubectl restart job/foobar --command &quot;tail -f /dev/null&quot;

# or even better
kubectl run job/foobar --exec --interactive bash
</code></pre>
<hr />
<p>I cannot use the <code>run</code> command to create a Pod:</p>
<pre class="lang-sh prettyprint-override"><code>kubectl run --image xxx -ti
</code></pre>
<p>because the Job I am trying to restart has certain <code>volumeMounts</code> and other configuration I need to reuse. So I would need something like <code>kubectl run --from-config job/foobar</code>.</p>
<hr />
<p>Is there a way to achieve this or am I stuck with juggling the YAML definition file?</p>
<hr />
<p>Edit: the Job YAML looks approx. like this:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: batch/v1
kind: Job
metadata:
    name: database-migrations
    labels:
        app: myapp
        service: myapp-database-migrations
spec:
    backoffLimit: 0
    template:
        metadata:
            labels:
                app: myapp
                service: myapp-database-migrations
        spec:
            restartPolicy: Never
            containers:
                - name: migrations
                  image: registry.example.com/myapp:977b44c9
                  command:
                      - &quot;bash&quot;
                      - &quot;-c&quot;
                      - |
                          set -e -E
                          echo &quot;Running database migrations...&quot;
                          do-migration-stuff-here
                          echo &quot;Migrations finished at $(date)&quot;
                  imagePullPolicy: Always
                  volumeMounts:
                      -   mountPath: /home/example/myapp/app/config/conf.yml
                          name: myapp-config-volume
                          subPath: conf.yml
                      -   mountPath: /home/example/myapp/.env
                          name: myapp-config-volume
                          subPath: .env
            volumes:
                - name: myapp-config-volume
                  configMap:
                      name: myapp
            imagePullSecrets:
                -   name: k8s-pull-project
</code></pre>

Martin Melka
<p>The commands you suggested don't exist. Take a look at <a href="https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands" rel="noreferrer">this reference</a> where you can find all available commands.</p>
<p>Based on <a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" rel="noreferrer">that documentation</a> the task of the <a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" rel="noreferrer"><em>Job</em></a> is to create one or more Pods and continue retrying execution them until the specified number of successfully terminated ones will be achieved. Then the <em>Job</em> tracks the successful completions. You cannot just update the Job because these fields are not updatable. To do what's you want you should delete current job and create one once again.</p>
<hr />
<p>I recommend you to keep all your configurations in files. If you have a problem with configuring job commands, practice says that you should modify these settings in yaml and apply to the cluster - if your deployment crashes - by storing the configuration in files, you have a backup.</p>
<p>If you are interested how to improve this task, you can try those 2 examples describe below:</p>
<p>Firstly I've created several files:</p>
<p>example job  (<code>job.yaml</code>):</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: batch/v1
kind: Job
metadata:
  name: test1
spec:
  template:
    spec:
      containers:
      - name: test1
        image: busybox
        command: [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;sleep 300&quot;]
        volumeMounts:
        - name: foo
          mountPath: &quot;/script/foo&quot;
      volumes:
      - name: foo
        configMap:
          name: my-conf
          defaultMode: 0755
      restartPolicy: OnFailure
</code></pre>
<p><code>patch-file.yaml</code>:</p>
<pre class="lang-yaml prettyprint-override"><code>spec:
  template:
    spec:
      containers:
      - name: test1
        image: busybox
        command: [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;echo 'patching test' &amp;&amp; sleep 500&quot;]
</code></pre>
<p>and  <code>configmap.yaml</code>:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: ConfigMap
metadata:
  name: my-conf
data:
  test: |
    #!/bin/sh
    echo &quot;skrypt test&quot;
</code></pre>
<hr />
<ol>
<li>If you want to automate this process you can use <a href="https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/" rel="noreferrer"><code>plugin</code></a></li>
</ol>
<blockquote>
<p>A plugin is a standalone executable file, whose name begins with <code>kubectl-</code>. To install a plugin, move its executable file to anywhere on your <code>PATH</code>.</p>
<p>There is no plugin installation or pre-loading required. Plugin executables receive the inherited environment from the <code>kubectl</code> binary. A plugin determines which command path it wishes to implement based on its name.</p>
</blockquote>
<p>Here is the file that can replace your job</p>
<blockquote>
<p>A plugin determines the command path that it will implement based on its filename.</p>
</blockquote>
<p><code>kubectl-job</code>:</p>
<pre class="lang-sh prettyprint-override"><code>#!/bin/bash
kubectl patch -f job.yaml -p &quot;$(cat patch-job.yaml)&quot; --dry-run=client -o yaml | kubectl replace --force -f - &amp;&amp; kubectl wait --for=condition=ready pod -l job-name=test1 &amp;&amp; kubectl exec -it $(kubectl get pod -l job-name=test1 --no-headers -o custom-columns=&quot;:metadata.name&quot;) -- /bin/sh
</code></pre>
<p>This command uses an additional file (<code>patch-job.yaml</code>, see this <a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/" rel="noreferrer">link</a>) - within we can put our changes for <code>job</code>.</p>
<p>Then you should change the permissions of this file and move it:</p>
<pre><code>sudo chmod +x .kubectl-job
sudo mv ./kubectl-job /usr/local/bin
</code></pre>
<p>It's all done. Right now you can use it.</p>
<pre><code>$ kubectl job
job.batch &quot;test1&quot; deleted
job.batch/test1 replaced
pod/test1-bdxtm condition met
pod/test1-nh2pv condition met
/ #
</code></pre>
<p>As you can see <code>Job</code> has been replaced (deleted and created).</p>
<hr />
<ol start="2">
<li>You can also use single-line command, here is the example:</li>
</ol>
<pre><code>kubectl get job test1 -o json | jq &quot;del(.spec.selector)&quot; | jq &quot;del(.spec.template.metadata.labels)&quot; | kubectl patch -f - --patch '{&quot;spec&quot;:  {&quot;template&quot;:  {&quot;spec&quot;:  {&quot;containers&quot;: [{&quot;name&quot;: &quot;test1&quot;, &quot;image&quot;: &quot;busybox&quot;, &quot;command&quot;: [&quot;/bin/sh&quot;, &quot;-c&quot;,  &quot;sleep 200&quot;]}]}}}}' --dry-run=client -o yaml | kubectl replace --force -f -
</code></pre>
<p>With this command you can change your job entering parameters &quot;by hand&quot;. Here is the output:</p>
<pre><code>job.batch &quot;test1&quot; deleted
job.batch/test1 replaced
</code></pre>
<p>As you can see this solution works as well.</p>
