[Kubernetes] Job & CronJob
이번 포스팅에서는 k8s의 Job과 CronJob에 대해 알아보려고 한다.
Job
Job은 하나 이상의 Pod가 지정된 수의 Pod가 정상적으로 종료하는 것을 관리한다. 때문에 Job이 생성되는 시점에 같이 만들어지는 Pod에 문제가 발생했을 때 (Physical resource 및 Node 등) Pod가 정상적인 상태가 되도록 새롭게 다시 만든다. (내부 정책에 따라 Pod 생성 실패시 수행하는 작업이 다르다.)
또한 Job은 생성된 Pod의 작업이 끝났음에도 Pod를 삭제하지 않아 해당 로그 및 결과 등을 분석할 수 있게 한다.
apiVersion: batch/v1 kind: Job metadata: name: pi spec: template: spec: containers: - name: pi image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never backoffLimit: 4 |
Job을 생성하는 매니페스트 파일이다. 해당 파일을 실행시키면 아래 그림과 같이 Job이 생성된 것을 확인 할 수 있다.
그림 1. Job
Job 실행 방법을 매니페스트 파일에서 설정할 수 있는데 2가지 타입으로 나뉜다.
- .sepc.parallelism
- .spec.completions
먼저 parallelism은 말 그대로 병렬로 실행하는 Pod의 수이다. 1 이상의 값으로 (Default는 1이다.) 값에 따라 Pod의 생성 갯수가 결정된다.
예를 들어 parallelism의 값이 3이면 Pod는 3개가 실행되어 동작하게 된다.
completion은 Job이 작업을 끝내야하는 Pod의 수이다. 즉 Job에 있는 모든 Pod의 실행이 끝났을 때, 실행 완료된 (생성된 Pod) Pod의 갯수이다.
때문에 parallelism과 completions를 섞어서 사용 할 수 있다.
그림 2. Parallelism & Completions
그림 2를 바탕으로 간단한 예시를 보면
- .sepc.parallelism : 2 - .spec.completions : 5 |
Pod는 동시에 2개가 생성되어 동작한다. 즉, Job 내부에서는 최대 2개까지 Pod가 동작한다.
그런데 4개가 완료된 시점에서는 Pod를 한 개만 실행시켜 completions 값을 맞춘다.
- .sepc.parallelism : 5 - .spec.completions : 1 |
parallelism이 5개로 최대 Pod를 5까지 동작시킬 수 있지만 completions 값이 1이기 때문에 1개만 실행한다.
이 예시를 바탕으로 다시 그림 2를 확인해보면 parallelism과 completions의 값에 따라 Pod가 어떻게 수행되는지 이해 할 수 있다.
그래서 Job을 정의할 때 역할에 따라 달라지겠지만 parallelism과 completions을 적절히 혼합해서 사용해야 한다.
매니페스트 파일에서 볼 수 있는 속성 중 restartPolicy가 있다. 해당 속성은 Pod의 재시작 여부를 결정하며 3가지 값이 존재한다.
- Always : Pod가 종료되면 재실행한다. 하지만 Job의 특징상 Always 값은 사용 할 수 없다.
- Never : 실패한 Pod를 재생성하여 시작한다. (Recreate & Start)
- OnFailure : 실패한 Pod를 재시작한다. (Restart)
backoffLimit은 Pod 실패시 재시도 횟수를 의미한다. 기본 값은 6이며 실패 할 때마다 backoff 방식 (10s, 20s, 40s ...)으로 backoffLimit의 값의 횟수 만큼 재시도를 한다.
Job은 내부적으로 Pod를 병렬적으로 사용하긴하지만 IPC와 같은 병렬 프로세스 간의 통신을 지원하지 않는다. 다만 독립적인 작업을 병렬적으로 수행할 뿐이다. 그래서 일반적으로 batch 작업을 하는데 많이 사용된다.
cronJob
cronJob은 주기적으로 (Time based scheduler) Job을 실행시킨다. crontab과 거의 흡사하다.
apiVersion: batch/v1beta1 kind: CronJob metadata: name: pingpong spec: schedule: "*/1 * * * *" // 스케줄링 설정 jobTemplate: spec: template: // Job 설정과 동일 metadata: labels: app: pingpong spec: containers: - name: pingpong image: ... command: ["/bin/sh"] args: ... restartPolicy: OnFailure |
위의 파일은 cronJob에 대한 메니패스트 파일이다. Job의 메니패스트 파일과 비슷하지만 cronJob의 기능상 스케줄링하는 부분이 추가된다.
그림 3. cronJob
위의 매니페스트 파일에 정의되어 있지는 않지만 cronJob에는 중요한 2가지 속성이 있다.
- startingDeadlineSeconds : cronJob controller가 지금으로부터 설정된 값이전까지 실패한 Job 생성 갯수를 세기 위한 값
그림 4. startingDeadlineSeconds
그림 4를 확인해보면 cronJob controller에 의해 발생하였고 startingDeadlineSeconds 값을 수정하라는 로그 메시지를 확인 할 수 있다.
startingDeadlineSeconds의 기본값은 100으로 만약 매니페스트 파일에 아무것도 정의하지 않았으면 지난 100초 동안 실패한 스케줄링 개수를 확인한다. (200으로 설정되어 있으면 지난 200초 동안 확인한다.) 때문에 해당 로그 메시지는 정해진 시간 동안 100개 이상의 스케줄링이 실패해서 startingDeadlinSeconds의 값을 조정해야 한다는 의미이다.
그림 5. cronJob Architecture in Google
추가로 그림 5를 통해 cronJob & Job의 아키텍처를 확인 할 수 있다.
Reference
- https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
- https://www.slideshare.net/DanielSmith272/whats-new-in-kubernetes
- https://medium.com/google-cloud/kubernetes-cron-jobs-455fdc32e81a