{"id":11625,"date":"2025-08-17T15:54:38","date_gmt":"2025-08-17T15:54:38","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=11625"},"modified":"2025-08-17T15:54:38","modified_gmt":"2025-08-17T15:54:38","slug":"kubernetes-jobs-one-off-tasks","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/kubernetes-jobs-one-off-tasks\/","title":{"rendered":"Kubernetes Jobs (one off tasks)"},"content":{"rendered":"<p>In the last <a href=\"https:\/\/putridparrot.com\/blog\/kubernetes-cronjobs\/\" target=\"_blank\">post<\/a> I create a simple application to be used within a schedule, i.e. a CronJob in Kubernetes. <\/p>\n<p>We can also create one off tasks (or a Job) which might be used to migrations or some batch processing. We&#8217;ve going to use everything from the previous post to build, containerize and push our imager to a container registry. The only change is to use the supplied job.yaml file, listed below<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\napiVersion: batch\/v1\r\nkind: Job\r\nmetadata:\r\n  name: one-time-job\r\n  namespace: dev\r\nspec:\r\n  template:\r\n    spec:\r\n      containers:\r\n      - name: one-time-jobb\r\n        image: putridparrotreg\/putridparrot\/crj:1.0.0\r\n      restartPolicy: Never\r\n<\/pre>\n<p>Running the following &#8220;kubectl get jobs -n dev&#8221; results in something like this<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nNAME           STATUS     COMPLETIONS   DURATION   AGE\r\none-time-job   Complete   1\/1           5s         41s\r\n<\/pre>\n<p>and if we get the pods using &#8220;kubectl get jobs -n dev&#8221; we get something like<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nNAME           STATUS     COMPLETIONS   DURATION   AGE\r\none-time-job   Complete   1\/1           5s         83s\r\n<\/pre>\n<p>and if we check the pods with &#8220;kubectl get pods -n dev&#8221; we&#8217;ll see something like this<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nNAME                 READY   STATUS      RESTARTS   AGE\r\none-time-job-h5dvf   0\/1     Completed   0          3m23s\r\n<\/pre>\n<p>and ofcourse we can see the logs of this run via &#8220;kubectl logs one-time-job-h5dvf -n dev&#8221; and we get our application output, i.e. the date\/time it was run<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nCurrent date and time: 2025-08-17 15:39:53.114962479 +00:00\r\n<\/pre>\n<p>You&#8217;ll note that the pod remained in the cluster, this allowed us to view the logs etc. and it&#8217;s down to the developer\/devops to delete the job and pod unless&#8230;<\/p>\n<p>We can actually set up automate deletion of the pod using the &#8220;ttlSecondsAfterFinished&#8221; option in the yaml file, i.e. <\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\napiVersion: batch\/v1\r\nkind: Job\r\nmetadata:\r\n  name: one-time-job\r\n  namespace: dev\r\nspec:\r\n  ttlSecondsAfterFinished: 300  # Deletes Job and its Pods 5 minutes after completion\r\n  template:\r\n    spec:\r\n      containers:\r\n      - name: one-time-jobb\r\n        image: putridparrotreg\/putridparrot\/crj:1.0.0\r\n      restartPolicy: Never\r\n<\/pre>\n<p>We also have the option of &#8220;activeDeadlineSeconds&#8221;, this does not delete or clean up anything but it can be used in the &#8220;spec:&#8221; section like &#8220;ttlSecondsAfterFinished&#8221; to denote that the job will be killed off it not finished. So for example<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\napiVersion: batch\/v1\r\nkind: Job\r\nmetadata:\r\n  name: one-time-job\r\n  namespace: dev\r\nspec:\r\n  ttlSecondsAfterFinished: 300  # Deletes Job and its Pods 5 minutes after completion\r\n  activeDeadlineSeconds: 600 # Job will be killed even if not finished, in 10 minutes\r\n  template:\r\n    spec:\r\n      containers:\r\n      - name: one-time-jobb\r\n        image: putridparrotreg\/putridparrot\/crj:1.0.0\r\n      restartPolicy: Never\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>In the last post I create a simple application to be used within a schedule, i.e. a CronJob in Kubernetes. We can also create one off tasks (or a Job) which might be used to migrations or some batch processing. We&#8217;ve going to use everything from the previous post to build, containerize and push our [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[314],"tags":[],"class_list":["post-11625","post","type-post","status-publish","format-standard","hentry","category-kubernetes"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11625","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=11625"}],"version-history":[{"count":4,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11625\/revisions"}],"predecessor-version":[{"id":11629,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11625\/revisions\/11629"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=11625"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=11625"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=11625"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}