|
| 1 | +--- |
| 2 | +title: Running Automated Tasks with a CronJob |
| 3 | +min-kubernetes-server-version: v1.21 |
| 4 | +reviewers: |
| 5 | +- chenopis |
| 6 | +content_type: task |
| 7 | +weight: 10 |
| 8 | +--- |
| 9 | + |
| 10 | +<!-- overview --> |
| 11 | + |
| 12 | +CronJobs was promoted to general availability in Kubernetes v1.21. If you are using an older version of |
| 13 | +Kubernetes, please refer to the documentation for the version of Kubernetes that you are using, |
| 14 | +so that you see accurate information. Older Kubernetes versions do not support the `batch/v1` CronJob API. |
| 15 | + |
| 16 | +You can use a {{< glossary_tooltip text="CronJob" term_id="cronjob" >}} to run {{< glossary_tooltip text="Jobs" term_id="job" >}} on a time-based schedule. |
| 17 | +These automated jobs run like [Cron](https://en.wikipedia.org/wiki/Cron) tasks on a Linux or UNIX system. |
| 18 | + |
| 19 | +Cron jobs are useful for creating periodic and recurring tasks, like running backups or sending emails. |
| 20 | +Cron jobs can also schedule individual tasks for a specific time, such as if you want to schedule a job for a low activity period. |
| 21 | + |
| 22 | +Cron jobs have limitations and idiosyncrasies. |
| 23 | +For example, in certain circumstances, a single cron job can create multiple jobs. |
| 24 | +Therefore, jobs should be idempotent. |
| 25 | + |
| 26 | +For more limitations, see [CronJobs](/docs/concepts/workloads/controllers/cron-jobs). |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +## {{% heading "prerequisites" %}} |
| 31 | + |
| 32 | + |
| 33 | +* {{< include "task-tutorial-prereqs.md" >}} |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +<!-- steps --> |
| 38 | + |
| 39 | +## Creating a Cron Job |
| 40 | + |
| 41 | +Cron jobs require a config file. |
| 42 | +This example cron job config `.spec` file prints the current time and a hello message every minute: |
| 43 | + |
| 44 | +{{< codenew file="application/job/cronjob.yaml" >}} |
| 45 | + |
| 46 | +Run the example CronJob by using this command: |
| 47 | + |
| 48 | +```shell |
| 49 | +kubectl create -f https://k8s.io/examples/application/job/cronjob.yaml |
| 50 | +``` |
| 51 | +The output is similar to this: |
| 52 | + |
| 53 | +``` |
| 54 | +cronjob.batch/hello created |
| 55 | +``` |
| 56 | + |
| 57 | +After creating the cron job, get its status using this command: |
| 58 | + |
| 59 | +```shell |
| 60 | +kubectl get cronjob hello |
| 61 | +``` |
| 62 | +The output is similar to this: |
| 63 | + |
| 64 | +``` |
| 65 | +NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE |
| 66 | +hello */1 * * * * False 0 <none> 10s |
| 67 | +``` |
| 68 | + |
| 69 | +As you can see from the results of the command, the cron job has not scheduled or run any jobs yet. |
| 70 | +Watch for the job to be created in around one minute: |
| 71 | + |
| 72 | +```shell |
| 73 | +kubectl get jobs --watch |
| 74 | +``` |
| 75 | +The output is similar to this: |
| 76 | + |
| 77 | +``` |
| 78 | +NAME COMPLETIONS DURATION AGE |
| 79 | +hello-4111706356 0/1 0s |
| 80 | +hello-4111706356 0/1 0s 0s |
| 81 | +hello-4111706356 1/1 5s 5s |
| 82 | +``` |
| 83 | + |
| 84 | +Now you've seen one running job scheduled by the "hello" cron job. |
| 85 | +You can stop watching the job and view the cron job again to see that it scheduled the job: |
| 86 | + |
| 87 | +```shell |
| 88 | +kubectl get cronjob hello |
| 89 | +``` |
| 90 | +The output is similar to this: |
| 91 | + |
| 92 | +``` |
| 93 | +NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE |
| 94 | +hello */1 * * * * False 0 50s 75s |
| 95 | +``` |
| 96 | + |
| 97 | +You should see that the cron job `hello` successfully scheduled a job at the time specified in `LAST SCHEDULE`. There are currently 0 active jobs, meaning that the job has completed or failed. |
| 98 | + |
| 99 | +Now, find the pods that the last scheduled job created and view the standard output of one of the pods. |
| 100 | + |
| 101 | +{{< note >}} |
| 102 | +The job name and pod name are different. |
| 103 | +{{< /note >}} |
| 104 | + |
| 105 | +```shell |
| 106 | +# Replace "hello-4111706356" with the job name in your system |
| 107 | +pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath={.items[*].metadata.name}) |
| 108 | +``` |
| 109 | +Show pod log: |
| 110 | + |
| 111 | +```shell |
| 112 | +kubectl logs $pods |
| 113 | +``` |
| 114 | +The output is similar to this: |
| 115 | + |
| 116 | +``` |
| 117 | +Fri Feb 22 11:02:09 UTC 2019 |
| 118 | +Hello from the Kubernetes cluster |
| 119 | +``` |
| 120 | + |
| 121 | +## Deleting a Cron Job |
| 122 | + |
| 123 | +When you don't need a cron job any more, delete it with `kubectl delete cronjob <cronjob name>`: |
| 124 | + |
| 125 | +```shell |
| 126 | +kubectl delete cronjob hello |
| 127 | +``` |
| 128 | + |
| 129 | +Deleting the cron job removes all the jobs and pods it created and stops it from creating additional jobs. |
| 130 | +You can read more about removing jobs in [garbage collection](/docs/concepts/workloads/controllers/garbage-collection/). |
| 131 | + |
| 132 | +## Writing a Cron Job Spec |
| 133 | + |
| 134 | +As with all other Kubernetes configs, a cron job needs `apiVersion`, `kind`, and `metadata` fields. For general |
| 135 | +information about working with config files, see [deploying applications](/docs/tasks/run-application/run-stateless-application-deployment/), |
| 136 | +and [using kubectl to manage resources](/docs/concepts/overview/working-with-objects/object-management/) documents. |
| 137 | + |
| 138 | +A cron job config also needs a [`.spec` section](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status). |
| 139 | + |
| 140 | +{{< note >}} |
| 141 | +All modifications to a cron job, especially its `.spec`, are applied only to the following runs. |
| 142 | +{{< /note >}} |
| 143 | + |
| 144 | +### Schedule |
| 145 | + |
| 146 | +The `.spec.schedule` is a required field of the `.spec`. |
| 147 | +It takes a [Cron](https://en.wikipedia.org/wiki/Cron) format string, such as `0 * * * *` or `@hourly`, as schedule time of its jobs to be created and executed. |
| 148 | + |
| 149 | +The format also includes extended `vixie cron` step values. As explained in the |
| 150 | +[FreeBSD manual](https://www.freebsd.org/cgi/man.cgi?crontab%285%29): |
| 151 | + |
| 152 | +> Step values can be used in conjunction with ranges. Following a range |
| 153 | +> with `/<number>` specifies skips of the number's value through the |
| 154 | +> range. For example, `0-23/2` can be used in the hours field to specify |
| 155 | +> command execution every other hour (the alternative in the V7 standard is |
| 156 | +> `0,2,4,6,8,10,12,14,16,18,20,22`). Steps are also permitted after an |
| 157 | +> asterisk, so if you want to say "every two hours", just use `*/2`. |
| 158 | +
|
| 159 | +{{< note >}} |
| 160 | +A question mark (`?`) in the schedule has the same meaning as an asterisk `*`, that is, it stands for any of available value for a given field. |
| 161 | +{{< /note >}} |
| 162 | + |
| 163 | +### Job Template |
| 164 | + |
| 165 | +The `.spec.jobTemplate` is the template for the job, and it is required. |
| 166 | +It has exactly the same schema as a [Job](/docs/concepts/workloads/controllers/job/), except that it is nested and does not have an `apiVersion` or `kind`. |
| 167 | +For information about writing a job `.spec`, see [Writing a Job Spec](/docs/concepts/workloads/controllers/job/#writing-a-job-spec). |
| 168 | + |
| 169 | +### Starting Deadline |
| 170 | + |
| 171 | +The `.spec.startingDeadlineSeconds` field is optional. |
| 172 | +It stands for the deadline in seconds for starting the job if it misses its scheduled time for any reason. |
| 173 | +After the deadline, the cron job does not start the job. |
| 174 | +Jobs that do not meet their deadline in this way count as failed jobs. |
| 175 | +If this field is not specified, the jobs have no deadline. |
| 176 | + |
| 177 | +If the `.spec.startingDeadlineSeconds` field is set (not null), the CronJob |
| 178 | +controller measures the time between when a job is expected to be created and |
| 179 | +now. If the difference is higher than that limit, it will skip this execution. |
| 180 | + |
| 181 | +For example, if it is set to `200`, it allows a job to be created for up to 200 |
| 182 | +seconds after the actual schedule. |
| 183 | + |
| 184 | +### Concurrency Policy |
| 185 | + |
| 186 | +The `.spec.concurrencyPolicy` field is also optional. |
| 187 | +It specifies how to treat concurrent executions of a job that is created by this cron job. |
| 188 | +The spec may specify only one of the following concurrency policies: |
| 189 | + |
| 190 | +* `Allow` (default): The cron job allows concurrently running jobs |
| 191 | +* `Forbid`: The cron job does not allow concurrent runs; if it is time for a new job run and the previous job run hasn't finished yet, the cron job skips the new job run |
| 192 | +* `Replace`: If it is time for a new job run and the previous job run hasn't finished yet, the cron job replaces the currently running job run with a new job run |
| 193 | + |
| 194 | +Note that concurrency policy only applies to the jobs created by the same cron job. |
| 195 | +If there are multiple cron jobs, their respective jobs are always allowed to run concurrently. |
| 196 | + |
| 197 | +### Suspend |
| 198 | + |
| 199 | +The `.spec.suspend` field is also optional. |
| 200 | +If it is set to `true`, all subsequent executions are suspended. |
| 201 | +This setting does not apply to already started executions. |
| 202 | +Defaults to false. |
| 203 | + |
| 204 | +{{< caution >}} |
| 205 | +Executions that are suspended during their scheduled time count as missed jobs. |
| 206 | +When `.spec.suspend` changes from `true` to `false` on an existing cron job without a [starting deadline](#starting-deadline), the missed jobs are scheduled immediately. |
| 207 | +{{< /caution >}} |
| 208 | + |
| 209 | +### Jobs History Limits |
| 210 | + |
| 211 | +The `.spec.successfulJobsHistoryLimit` and `.spec.failedJobsHistoryLimit` fields are optional. |
| 212 | +These fields specify how many completed and failed jobs should be kept. |
| 213 | +By default, they are set to 3 and 1 respectively. Setting a limit to `0` corresponds to keeping none of the corresponding kind of jobs after they finish. |
| 214 | + |
| 215 | + |
0 commit comments