job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
spec:
restartPolicy: Never
containers:
- name: hello
image: ubuntu:focal
command: ["sh", "-c", "echo Hello World!"]
- apiVersion에 batch 그룹으로 들어간다는 게 특징이다.
- Deployment와 마찬가지로 내부적으로 Pod를 감싸고 있기 때문에, template이라는 키워드를 사용한다.
- Deployment에는 selector 및 labels를 매칭하는 영역이 필수인데, 이 Job 메니페스트 파일엔 그런 영역이 필수는 아니다. Job 오브젝트가 생성될 때 Job 컨트롤러가, labels selector와 template(Pod)의 labels를 임의로 생성해서 넣어주기 때문이다.
- 다만 특수한 목적으로, 직접 커스텀하게 selector 및 labels를 설정하고 싶다면 기재해줘도 된다.
- Job을 명세할 때 주의할 점은 restartPolicy를 반드시 설정해줘야 한다는 것이다. restartPolicy에는 Always, Never, OnFailure가 있다. Job만들 때는 이 중에 Always 옵션은 사용을 안하는 것이 적절하다.
- command로 Hello World!라는 문자열을 출력하도록 지정하였다.
job-parallelism.yml
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
completions: 10
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: hello
image: ubuntu:focal
command: ["sh", "-c", "sleep 2; echo Hello World!"]
- job.yml과 달리 competions와 parallelism 옵션이 추가되어 있다.
- competions 옵션은 Job을 몇 번 성공시킬 것인지, parallelism은 최대 동시 실행 횟수를 지정하는 것이다.
- 그리고 결과를 제대로 보기 위해서 sleep 2를 넣어 2초간 기다리게 한다.
job-deadline.yml
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
activeDeadlineSeconds: 3
template:
spec:
restartPolicy: Never
containers:
- name: hello
image: ubuntu:focal
command: ["sh", "-c", "sleep 5; echo Hello World!"]
- activeDeadlineSeconds 옵션을 넣는다. Job이 최대 실행될 수 있는 타임아웃 시간을 주는 것이다.
- 즉 위 파일을 해석해보면, hello라는 Job이 Pod를 생성할 때 3초를 넘어가면 실패로 간주하겠다는 것이다.
- 실패 결과를 보기 위해 5초 슬립을 주었다.
cronjob.yml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello-every-minute
spec:
schedule: "*/1 * * * *"
successfulJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: hello
image: ubuntu:focal
command: ["sh", "-c", "echo Hello $(date)!"]
- Kind는 당연히 CronJob이다.
- jobTemplate이 template을 감싸고 있음을 알 수 있다. CronJob은 바로 Pod를 감쌀 수 없다는 것이다. 즉, CronJob은 Job을 감싸야하고 Job이 Pod를 감싸는 형태여야한다.
- Deployment가 ReplicasSet을 wrapping하고 ReplicaSet이 Pod를 wrapping하는 것처럼, CronJob이 Job을 wrapping하고 Job이 Pod를 wrapping하는 방식을 비슷한 원리로 볼 수 있다.
- schedule은 cron 표현식이 들어가게 된다. "/1 * * *" 는 매 1분마다 CronJob을 실행시키라는 의미이다.
- successfulJobsHistoryLimit 옵션도 주었는데, 성공한 Job 기록을 최대 5개 남기라는 의미이다.
1번째 실습을 진행해보자.
- kubectl apply -f job.yml
- job.yml을 apply 한다.
- watch kubectl get pod
- 새로운 터미널을 열고 watch 모드를 실행하여 Pod를 관찰한다.
- Running에서 바로 Completed로 바뀌었다.
- kubectl get job
- hello 라는 Job을 확인할 수 있다.
- kubectl describe job hello
- 좀 더 자세한 내역을 볼 수 있다.
- Pod Statuses에 1 Succeeded 라는 결과를 볼 수 있다.
- 무엇보다 기본적인 Selector와 Labels가 임의로 설정되었다는 것도 확인할 수 있다. 그리고 아래에 보면 Pod Template에도 Labels가 설정된 것을 확인할 수 있다.
- kubectl delete -f job.yml 하고 마무리 한다.
2번째 실습을 진행해보자.
- kubectl apply -f job-parallelism.yml
- 적용을 하면 아래와 같은 과정이 진행된다.
- 2개씩 수행할 수 있도록 설정했기에 2개씩 늘어난다.
- ... (생략)
- 최대 성공 Job 10개로 설정했기에 10개에서 멈춘다.
- kubectl logs job/hello
- Job의 로그를 확인할 수 있다.
- kubectl delete -f job-parallelism.yml 하고 마무리 한다.
3번째 실습을 진행해보자.
- kubectl apply -f job-deadline.yml
- apply를 한다.
-
- watch 모드에는 Terminating이 뜨다가 사라진다.
- kubectl get job
- COMPLETIONS가 0/1인걸 볼 수 있다.
- kubectl describe job hello
- Pod Statuses에 0 Succeeded 라는 결과를 볼 수 있다.
- 가장 하단에 Events를 보면 어떤 과정이 일어났는지 알 수 있다.
- SuccessfulCreate => SuccessfulDelete => DeadlineExceeded를 거치며 종료되는 걸 알 수 있다.
- Deadline이 3초인데 슬립5설정으로 이를 넘어서며 성공하지 못하고 종료되는 것이다.
- kubectl delete -f job-deadline.yml 하고 마무리 한다.
4번째 실습을 진행해보자.
- kubectl apply -f cronjob.yml
- cronjob 명세를 apply 한다.
- ... (생략)
- 이렇게 1분에 하나씩 추가되는 걸 알 수 있다.
- 5개가 만들어졌어도 1분이 지나면 새로 하나를 만들면서 기존의 것을 하나 제거한다.
- kubectl get cronjob
- SCHEDULE에 표현식을 볼 수 있다.
- LAST SCHEDULE을 통해 23초 전에 스케쥴링이 됐었다는 걸 확인할 수 있다.
- kubectl get job
- CronJob의 이름에 랜덤한 식별자가 추가되서 이름이 생성된 것을 볼 수 있다.
- kubectl get pod
- Pod는 거기에 또 다른 식별자가 붙어서 생성되는 걸 볼 수 있다.