# 크론잡(CronJob)으로 자동화된 작업 실행

LLMS index: [llms.txt](/llms.txt)

---

<!-- overview -->

<a class='glossary-tooltip' title='정기적인 일정으로 실행되는 반복 작업(잡).' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/concepts/workloads/controllers/cron-jobs/' target='_blank' aria-label='크론잡'>크론잡</a>을 이용하여
<a class='glossary-tooltip' title='완료를 목표로 실행되는 유한 또는 배치 작업.' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/concepts/workloads/controllers/job/' target='_blank' aria-label='잡(Job)'>잡(Job)</a>을 시간 기반의 스케줄에 따라 실행할 수 있다.
이러한 자동화된 잡은 리눅스 또는 유닉스 시스템의 [크론](https://ko.wikipedia.org/wiki/Cron) 작업처럼 실행된다.

크론 잡은 백업을 수행하거나 이메일을 보내는 것과 같이 주기적이고 반복적인 작업들을 생성하는 데 유용하다.
크론 잡은 시스템 사용이 적은 시간에 잡을 스케줄하려는 경우처럼 특정 시간에 개별 작업을 스케줄할 수도 있다.

크론 잡에는 제한 사항과 특이점이 있다.
예를 들어, 특정 상황에서는 하나의 크론 잡이 여러 잡을 생성할 수 있다.
따라서, 잡은 멱등성을 가져야 한다.

제한 사항에 대한 자세한 내용은 [크론잡](/ko/docs/concepts/workloads/controllers/cron-jobs/)을 참고한다.

## 시작하기 전에

* <p>쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와
통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고
있지 않다면,
<a href="/ko/docs/tasks/tools/#minikube">minikube</a>를 사용해서 생성하거나
다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.</p>
<ul>
<li><a href="https://labs.iximiuz.com/playgrounds?category=kubernetes&filter=all">iximiuz Labs</a></li>
<li><a href="https://killercoda.com/playgrounds/scenario/kubernetes">Killercoda</a></li>
<li><a href="https://kodekloud.com/public-playgrounds">KodeKloud</a></li>
</ul>


<!-- steps -->

## 크론잡(CronJob) 생성 {#creating-a-cron-job}

크론 잡은 구성 파일이 필요하다.
다음은 1분마다 간단한 데모 작업을 실행하는 크론잡 매니페스트다.

















<div class="highlight code-sample">
    <div class="copy-code-icon">
    <a href="https://raw.githubusercontent.com/kubernetes/website/main/content/ko/examples/application/job/cronjob.yaml" download="application/job/cronjob.yaml"><code>application/job/cronjob.yaml</code>
    </a><img src="/images/copycode.svg" class="icon-copycode" onclick="copyCode('application-job-cronjob-yaml')" title="Copy application/job/cronjob.yaml to clipboard"></img></div>
    <div class="includecode" id="application-job-cronjob-yaml"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">batch/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CronJob</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">hello</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;* * * * *&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">jobTemplate</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">hello</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">busybox:1.28</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l">IfNotPresent</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">command</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">/bin/sh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- -<span class="l">c</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">date; echo Hello from the Kubernetes cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">restartPolicy</span><span class="p">:</span><span class="w"> </span><span class="l">OnFailure</span><span class="w">
</span></span></span></code></pre></div></div>
</div>

다음 명령을 사용하여 크론잡 예제를 실행한다.

```shell
kubectl create -f https://k8s.io/examples/application/job/cronjob.yaml
```
출력 결과는 다음과 비슷하다.

```
cronjob.batch/hello created
```

크론 잡을 생성한 후, 다음 명령을 사용하여 상태를 가져온다.

```shell
kubectl get cronjob hello
```

출력 결과는 다음과 비슷하다.

```
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        <none>          10s
```

명령의 결과에서 알 수 있듯이, 크론 잡은 아직 잡을 스케줄하거나 실행하지 않았다.
약 1분 내로 잡이 생성되는지 확인한다.

```shell
kubectl get jobs --watch
```
출력 결과는 다음과 비슷하다.

```
NAME               COMPLETIONS   DURATION   AGE
hello-4111706356   0/1                      0s
hello-4111706356   0/1           0s         0s
hello-4111706356   1/1           5s         5s
```

이제 "hello" 크론 잡에 의해 스케줄된 실행 중인 작업을 확인했다.
잡 감시를 중지한 뒤에 크론 잡이 다시 스케줄되었는지를 확인할 수 있다.

```shell
kubectl get cronjob hello
```

출력 결과는 다음과 비슷하다.

```
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        50s             75s
```

크론 잡 `hello` 가 `LAST SCHEDULE` 열에 명시된 시간에 잡을 성공적으로 스케줄링한 것을 볼 수 있다.
현재는 0개의 활성 잡이 있고, 이는 작업이 완료되었거나 실패했음을 의미한다.

이제, 마지막으로 스케줄된 잡이 생성한 파드를 찾고 생성된 파드 중 하나의 표준 출력을 확인한다.


<div class="alert alert-info" role="note"><h4 class="alert-heading">참고:</h4>잡 이름과 파드 이름은 다르다.</div>


```shell
# "hello-4111706356"을 사용자의 시스템에 있는 잡 이름으로 바꾼다
pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath={.items[*].metadata.name})
```
파드의 로그를 출력한다.

```shell
kubectl logs $pods
```
출력 결과는 다음과 비슷하다.

```
Fri Feb 22 11:02:09 UTC 2019
Hello from the Kubernetes cluster
```

## 크론잡(CronJob) 삭제 {#deleting-a-cron-job}

더 이상 크론 잡이 필요하지 않으면, `kubectl delete cronjob <cronjob name>` 명령을 사용해서 삭제한다.

```shell
kubectl delete cronjob hello
```

크론 잡을 삭제하면 생성된 모든 잡과 파드가 제거되고 추가 잡 생성이 중지된다.
[가비지(garbage) 수집](/ko/docs/concepts/architecture/garbage-collection/)에서 잡 제거에 대해 상세한 내용을 읽을 수 있다.

## 크론잡(CronJob) 명세 작성 {#writing-a-cron-job-spec}

다른 모든 쿠버네티스 오브젝트들과 마찬가지로,
크론잡은 `apiVersion`, `kind` 그리고 `metadata` 필드가 반드시 필요하다.
쿠버네티스 오브젝트 및 그 <a class='glossary-tooltip' title='하나 이상의 쿠버네티스 API 오브젝트를 직렬화한 명세(specification).' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/reference/glossary/?all=true#term-manifest' target='_blank' aria-label='매니페스트'>매니페스트</a> 다루기에 대한
자세한 내용은 [리소스 관리하기](/ko/docs/concepts/cluster-administration/manage-deployment/)와
[kubectl을 사용하여 리소스 관리하기](/ko/docs/concepts/overview/working-with-objects/object-management/) 문서를 참고한다.

크론잡(CronJob)의 각 매니페스트에는 [`.spec`](/ko/docs/concepts/overview/working-with-objects/kubernetes-objects/#오브젝트-명세-spec-와-상태-status) 섹션도 필요하다.


<div class="alert alert-info" role="note"><h4 class="alert-heading">참고:</h4>크론잡(CronJob)을 수정한 경우, 수정 후 새로 실행하는 작업부터 적용된다.
이미 시작된 작업(및 해당 파드)은 변경 없이 계속 실행된다.
즉, 크론잡(CronJob)은 기존 작업이 계속 실행 중이라면, 작업을 변경하지 <em>않는다.</em></div>


### 스케줄

`.spec.schedule` 은 `.spec` 의 필수 필드이다.
이 필드는 `0 * * * *` 또는 `@hourly`와 같은 [크론](https://ko.wikipedia.org/wiki/Cron) 형식의 문자열을 받아, 
해당 잡이 생성 및 실행될 스케줄 시간으로 설정한다.

이 형식은 확장된 "Vixie cron" 스텝(step) 값도 포함한다. 이 내용은
[FreeBSD 매뉴얼](https://www.freebsd.org/cgi/man.cgi?crontab%285%29)에 설명되어 있다.

> 스텝 값은 범위(range)와 함께 사용할 수 있다. 범위 뒤에 `/<number>` 를
> 지정하여 범위 내에서 숫자만큼의 값을 건너뛴다. 예를 들어,
> 시간 필드에 `0-23/2` 를 사용하여 매 2시간마다 명령 실행을
> 지정할 수 있다(V7 표준의 대안은 `0,2,4,6,8,10,12,14,16,18,20,22`
> 이다). 별표(asterisk) 뒤에 붙이는 스텝도 허용되며,
> "2시간마다"라고 지정하고 싶으면, 간단히 `*/2` 를 사용하면 된다.


<div class="alert alert-info" role="note"><h4 class="alert-heading">참고:</h4>스케줄에서 물음표(<code>?</code>)는 별표 <code>*</code> 와 동일한 의미를 가지며,
주어진 필드에 대해 사용할 수 있는 모든 값을 나타낸다.</div>


### 잡 템플릿

`.spec.jobTemplate` 은 잡에 대한 템플릿이며, 이것은 필수 필드다.
이것은 중첩되어(nested) 있고 `apiVersion` 이나 `kind` 가 없다는 것을 제외하면,
[잡](/ko/docs/concepts/workloads/controllers/job/)과 정확히 같은 스키마를 가진다.
잡 `.spec` 을 작성하는 것에 대한 내용은 [잡 명세 작성하기](/ko/docs/concepts/workloads/controllers/job/#잡-사양-작성하기)를 참고한다.

### 시작 기한

`.spec.startingDeadlineSeconds` 필드는 선택 사항이다.
어떤 이유로든 스케줄된 시간을 놓친 경우 잡의 시작 기한을 초 단위로 나타낸다.
기한이 지나면, 크론 잡이 잡을 시작하지 않는다.
이러한 방식으로 기한을 맞추지 못한 잡은 실패한 작업으로 간주된다.
이 필드를 지정하지 않으면, 잡에 기한이 없다.

`.spec.startingDeadlineSeconds` 필드가 (null이 아닌 값으로) 설정되어 있다면,
크론잡 컨트롤러는 예상 잡 생성 시각과 현재 시각의 차이를 측정하고,
시각 차이가 설정한 값보다 커지면 잡 생성 동작을 스킵한다.

예를 들어, `200` 으로 설정되었다면,
예상 잡 생성 시각으로부터 200초까지는 잡이 생성될 수 있다.

### 동시성 정책

`.spec.concurrencyPolicy` 필드도 선택 사항이다.
이것은 이 크론 잡에 의해 생성된 잡의 동시 실행을 처리하는 방법을 지정한다.
명세는 다음의 동시성 정책 중 하나만 지정할 수 있다.

* `Allow`(기본값): 크론 잡은 동시에 실행되는 잡을 허용한다.
* `Forbid`: 크론 잡은 동시 실행을 허용하지 않는다.
  새로운 잡을 실행할 시간이고 이전 잡 실행이 아직 완료되지 않은 경우, 크론 잡은 새로운 잡 실행을 건너뛴다.
* `Replace`: 새로운 잡을 실행할 시간이고 이전 잡 실행이 아직 완료되지 않은 경우,
  크론 잡은 현재 실행 중인 잡 실행을 새로운 잡 실행으로 대체한다.

참고로 동시성 정책은 동일한 크론 잡에 의해 생성된 잡에만 적용된다.
크론 잡이 여러 개인 경우, 각각의 잡은 항상 동시에 실행될 수 있다.

### 일시 정지

`.spec.suspend` 필드도 선택 사항이다.
`true` 로 설정되면, 모든 후속 실행이 일시 정지된다.
이 설정은 이미 시작된 실행에는 적용되지 않는다.
기본값은 false이다.

<div class="alert alert-caution" role="note"><h4 class="alert-heading">주의:</h4>스케줄된 시간 동안 잡이 일시 정지되어 있다면 누락된 잡으로 간주한다.
<a href="#%EC%8B%9C%EC%9E%91-%EA%B8%B0%ED%95%9C">시작 기한</a> 없이 기존의 크론 잡에 대해 <code>.spec.suspend</code> 가 <code>true</code> 에서 <code>false</code> 로 변경되면,
누락된 잡들이 즉시 스케줄된다.</div>


### 잡 히스토리 한도

`.spec.successfulJobsHistoryLimit` 와 `.spec.failedJobsHistoryLimit` 필드는 선택 사항이다.
이들 필드는 기록을 보관해야 하는 완료 및 실패한 잡의 개수를 지정한다.
기본적으로, 각각 3과 1로 설정된다.
한도를 `0` 으로 설정하는 것은 잡 완료 후에 해당 잡 유형의 기록을 보관하지 않는다는 것이다.
