✔️ Job
Job
에서 하나 이상의 파드를 생성하고 지정된 수의 파드가 성공적으로 종료될 때까지 계속해서 파드의 실행을 재시도한다.- 파드가 성공적으로 완료되면, 성공적으로 완료된 잡을 추적한다.
- 지정된 수의 성공 완료에 도달하면, 작업(즉, 잡)이 완료된다.
- 잡을 삭제하면 잡이 생성한 파드가 정리된다.
- 작업을 일시 중지하면 작업이 다시 재개될 때까지 활성 파드가 삭제된다.
✔️ Job은 자동으로 레이블과 셀렉터를 설정한다.
mypi.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: mypi
spec:
template:
spec:
containers:
- image: perl
name: mypi
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: OnFailure
ttlSecondsAfterFinished: 10
vagrant@node1 ~/cont/job kubectl get job,po -o wide --show-labels
NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR LABELS
job.batch/mypi 1/1 3s 78s mypi perl controller-uid=6d7c725d-3dd0-40a5-b411-0e48d0be40c3 controller-uid=6d7c725d-3dd0-40a5-b411-0e48d0be40c3,job-name=mypi
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
pod/mypi--1-7vqkv 0/1 Completed 0 78s 10.233.96.35 node2 <none> <none> controller-uid=6d7c725d-3dd0-40a5-b411-0e48d0be40c3,job-name=mypi
Job에 selecter
와 label
을 지정하지 않았지만 이상없이 작동했다.
mypi
라고 하는 Job에 기본적으로 셀렉터가 세팅되어 있다.
그래서 셀렉터를 설정한 적 없지만 controller-uid=6d7c725d-3dd0-40a5-b411-0e48d0be40c3
레이블이 붙는다.
그리고 파드가 만들어졌으며 파드의 레이블에 Job과 같은 레이블이 붙어있다.
Job의 이름인 mypi
가 job-name=mypi
레이블로 세팅이 되어 있는 걸 볼 수가 있다.
즉, Job이 자동으로 파드의 레이블을 셀렉팅하고 있다.
셀렉팅된 대상은 controller-uid
라고 하는 key와 value가 자동으로 설정된다.
다시 한번 살펴보자
vagrant@node1 ~/cont/job kubectl explain job.spec.
selector <Object>
A label query over pods that should match the pod count. Normally, the
system sets this field for you. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
job.spec
에도 셀렉터가 있다.
셀렉터를 사용할 수 있고 사용해도 아무 문제가 없다.
그러나 문서에서 대부분의 케이스에서는 지정해서는 안된다라고 되어 있다.
결론적으로 Job에서는 가능하면 셀렉터를 지정하지 않는다.
ReplicaSet
, DaemonSet
, Deployment
, StatefulSet
은 시작되면 계속적으로 실행되는 것을 보장한다.
그러나 Job
또는 CronJob
의 경우 한번 시작하면 끝나는 것을 보장한다.
이런 동작 방식에 의해 다음과 같은 문제가 발생할 수 있다.Job
이나 CronJob
에서 셀렉터를 사용하면 이미 다른 컨트롤러에의해 관리되던 파드를 혹여 잘못해서 가리키게 될 수 있다.
그러면 해당되는 파드를 Job
이나 CronJob
컨트롤러가 죽이려고 할 수 있다.
그래서 Job
이나 CronJob
에서는 레이블과 레이블 셀렉터를 사용할 수는 있으나 사용하지 않는 것을 권장한다.
정리하자면 잘못된 매핑으로 인해 기존의 파드를 종료시키지 않기 위해 레이블과 레이블 셀렉터를 되도록 사용하지 않는다.
✔️ Job 컨트롤러와 파드는 자동으로 삭제되지 않는다.
vagrant@node1 ~/cont/job kubectl get job,po
NAME COMPLETIONS DURATION AGE
job.batch/mypi 1/1 3s 17m
NAME READY STATUS RESTARTS AGE
pod/mypi--1-7vqkv 0/1 Completed 0 78s
실제 어플리케이션(컨테이너)이 종료돼도 컨트롤러와 파드를 삭제하지 않는다.
실행이 종료된 컨트롤러와 파드가 쌓이면 DB에 악영향을 끼칠 수 있다.
물론 k8s 상에서 이런 정보들을 자동으로 지우게 만들 수는 있다.
그렇지만 해당 정보를 자동으로 지우면 문제가 발생한다.
왜, 어떤 문제가 발생할까 ?
파드를 지우면 파드의 로그는 제거된다.
어플리케이션의 성격에 따라 다르지만 앞서 실행한 컨테이너는 파이값을 소수점 2천자리까지 계산하는 이미지를 사용한다. 그리고 그 내용을 표준 출력으로 남긴다.
만약 이 컨트롤러와 파드를 지우면 컨테이너가 남긴 표준 출력을 확인할 방법이 없다.
물론 모든 애플리케이션이 표준 출력을 내는 것은 아니다.
예를 들어 DB 같은 경우 무언가 계산을 하고 DB에 계산값이 따로 저장된다면 지워져도 상관없을 수 있다.
그럼에도 불구하고 해당 컨테이너가 제대로 작동되었는지를 나중에 로그를 확인할 수 없으면 알 수 없다.
그래서 쿠버네티스에서는 컨트롤러와 파드의 삭제 선택권을 사용자에게 넘겼다.
만약 추가적인 로그 서버를 구성해놓았다면 삭제해도 상관없을 것이다. 일반적으로 ELK, EFK를 구성한다.
✔️ Job YAML 명세
✔️ activeDeadlineSeconds
job.spec.activeDeadlineSeconds
vagrant@node1 ~/cont/job kubectl explain job.spec.
FIELDS:
activeDeadlineSeconds <integer>
activeDeadlineSeconds
- 파드의 어플리케이션이 시작한 후 너무 오랫동안 실행되는 것을 방지하기 위해 특정 시간에 종료시킬 수 있다.
파이 계산을 소수점 아래 2만 자리까지 한다면 오랜 시간이 걸릴 것이다.
그래서 일정 시간이 지나면 해당 작업이 중단되게 할 수 있다.
시간이 오래걸려도 작업이 정상적으로 완료되는 것이 중요한 어플리케이션에는 사용하지 않는다.
필요하면 activeDeadlineSeconds
을 사용해 데드라인을 지정할 수 있다.
단위는 초단위이며 기본값은 없다.
✔️ backoffLimit
job.spec.backoffLimit
KIND: Job
VERSION: batch/v1
FIELD: backoffLimit <integer>
DESCRIPTION:
Specifies the number of retries before marking this job failed. Defaults to
6
backoffLimit
Job
이나 CronJob
외에는 backoffLimit
가 정해져 있지 않다.
파드의 LifeCycle에서 backoff
라는 개념이 있다.
오류가 난 경우 10초, 20초, 40초 간격으로 지수적으로 재시작 간격을 늘이고 최대는 300초 간격으로 재시작한다.
Job
에서는 6번의 재시도만 허용한다. 6번을 초과하면 실패한 작업으로 치부한다.
✔️ ttlSecondsAfterFinished
job.spec.ttlSecondsAfterFinished
KIND: Job
VERSION: batch/v1
FIELD: ttlSecondsAfterFinished <integer>
DESCRIPTION:
ttlSecondsAfterFinished limits the lifetime of a Job that has finished
execution (either Complete or Failed). If this field is set,
ttlSecondsAfterFinished after the Job finishes, it is eligible to be
automatically deleted. When the Job is being deleted, its lifecycle
guarantees (e.g. finalizers) will be honored. If this field is unset, the
Job won't be automatically deleted. If this field is set to zero, the Job
becomes eligible to be deleted immediately after it finishes. This field is
alpha-level and is only honored by servers that enable the TTLAfterFinished
feature.
말 그대로 특정 시간이 지나면은 종료, 삭제한다.
ttlSecondsAfterFinished
옵션을 사용해보자mypi.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: mypi
spec:
template:
spec:
containers:
- image: perl
name: mypi
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: OnFailure
ttlSecondsAfterFinished: 10
perl 이미지를 사용하며 pi를 소수점 2000자리 까지 계산하고 출력한다.ttlSecondsAfterFinished: 10
10초 후에 삭제한다
vagrant@node1 ~/cont/job kubectl delete -f mypi.yaml
job.batch "mypi" deleted
vagrant@node1 ~/cont/job kubectl create -f mypi.yaml
Every 1.0s: kubectl get job,po node1: Thu May 19 12:16:15 2022
NAME COMPLETIONS DURATION AGE
job.batch/mypi 1/1 3s 36s
NAME READY STATUS RESTARTS AGE
pod/mypi--1-cxq2w 0/1 Completed 0 36s
실행 → 종료 → 완료 과정을 거친다.
No resources found in default namespace
일정시간 이후 삭제가 되었다.
여기서 문제가 발생한다.
파이 연산의 계산값은 로그로 남게 될것이고 해당 로그를 다른 곳에 저장을 시켜놔야한다.
지금은 지워버렸기 때문에 그 로그를 확인할 수 있는 방법 자체가 없다.
그래서 외부의 로그 서버를 별도로 반드시 둬야한다. 이 상태로는 쓸 수 없다.
ttlSecondsAfterFinished
을 사용하면 작업이 완료된 후 자동으로 삭제되도록 만들 수 있다.
TTL이라는 단어는 Tile To Live
의 약어이다.
말 그대로 살아있을 수 있는 시간을 의미하며 설정된 값인 10초 후에 삭제한다.
✔️ completions과 parallelism
completions <integer>
Specifies the desired number of successfully finished pods the job should
be run with. Setting to nil means that the success of any pod signals the
success of all pods, and allows parallelism to have any positive value.
Setting to 1 means that parallelism is limited to 1 and the success of that
pod signals the success of the job. More info:
https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
parallelism <integer>
Specifies the maximum desired number of pods the job should run at any
given time. The actual number of pods running in steady state will be less
than this number when ((.spec.completions - .status.successful) <
.spec.parallelism), i.e. when the work left to do is less than max
parallelism. More info:
https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
parallelism
- 병렬처리, 대량의 작업을 병렬로 처리해야 할 경우 적용하는 옵션completions
- 완료, 작업을 반드시 n번 완료해야 할 경우에 적용하는 옵션
mypi-comp.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: mypi-comp
spec:
completions: 3
template:
spec:
containers:
- image: perl
name: mypi
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: OnFailure
ttlSecondsAfterFinished: 10
Every 1.0s: kubectl get job,po node1: Thu May 19 12:35:55 2022
NAME COMPLETIONS DURATION AGE
job.batch/mypi-comp 3/3 24s 5m4s
NAME READY STATUS RESTARTS AGE
pod/mypi-comp--1-6fzjw 0/1 Completed 0 4m48s
pod/mypi-comp--1-qzwxd 0/1 Completed 0 5m4s
pod/mypi-comp--1-wpnt8 0/1 Completed 0 4m56s
첫번째 파드(mypi-comp--1-qzwxd
)를 만들고 실행 → 완료 → 종료가 된다. 한 사이클이 끝난 것이다.
그리고 바로 다음 다른 파드인 mypi-comp--1-wpnt8
이 만들어지고 mypi-comp--1-wpnt8
이 실행되고 있다.
이 사이클을 총 3번 반복하게 된다. 이 사이클이 3번 완료되어야 이 작업은 끝난다라는 것이다.
mypi-comp--1-wpnt8
이 종료되면 제일 마지막인 mypi-comp--1-6fzjw
파드의 사이클이 진행된다.
그리고 mypi-comp--1-6fzjw
완료가되면 job.batch/mypi-comp
가 완전히 완료가 되는 것이다.
여기에 parallelism
옵션을 추가해보자
mypi-para.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: mypi-para
spec:
completions: 3
parallelism: 3
template:
spec:
containers:
- image: perl
name: mypi
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(1500)"]
restartPolicy: OnFailure
ttlSecondsAfterFinished: 10
vagrant@node1 ~/cont/job kubectl create -f mypi-para.yaml
job.batch/mypi-para created
Every 1.0s: kubectl get job,po node1: Thu May 19 12:39:14 2022
NAME COMPLETIONS DURATION AGE
job.batch/mypi-para 3/3 11s 11s
NAME READY STATUS RESTARTS AGE
pod/mypi-para--1-2x7tt 0/1 Completed 0 11s
pod/mypi-para--1-tdg92 0/1 Completed 0 11s
pod/mypi-para--1-zdln5 0/1 Completed 0 11s
parallelism
옵션을 사용하면 작업을 동시에 병렬로 처리한다.
결과적으로 컨트롤러 입장에서는 3개가 완료가 되어있는 것이다.
많은 퍼포먼스가 필요한 어플리케이션들은 여러개를 병렬처리해서 실행할 수 있다.
병렬 처리를 하는 주된 이유는 대량의 작업을 효율적으로 처리하기 위함이다.
예를 들어 처리해야 할 대량의 데이터가 있을 때 어플리케이션 하나로는 효율이 나지 않을 때가 있다.
그런 경우 보통 어플리케이션 3개를 띄워 나눠서 작업을 할 수 있고 각각의 어플리케이션이 할당량을 병렬적으로
처리하면 한번에 더 많은 데이터를 처리할 수 있다.
여기서 중요한 것은 해당 데이터가 병렬로 처리할 수 있어야 하며, 어플리케이션에는 병렬처리 기능이 구현돼야한다.
6번의 완료가 필요한 작업에 병렬을 3이라고 하면 처음에 3개를 먼저 병렬적으로 처리할 것이고
해당 작업이 끝나면 다시 3개를 병렬처리해서 결과적으로는 6번의 완료가 되어 전체 작업이 끝나게 된다.
당연한 이야기지만 completions
횟수 >= parallelism
횟수이다.
✔️ suspend
job.spec.suspend
FIELD: suspend <boolean>
DESCRIPTION:
Suspend specifies whether the Job controller should create Pods or not. If
a Job is created with suspend set to true, no Pods are created by the Job
controller. If a Job is suspended after creation (i.e. the flag goes from
false to true), the Job controller will delete all active Pods associated
with this Job. Users must design their workload to gracefully handle this.
Suspending a Job will reset the StartTime field of the Job, effectively
resetting the ActiveDeadlineSeconds timer too. Defaults to false.
This field is beta-level, gated by SuspendJob feature flag (enabled by
default).
suspend
옵션으로 작업을 일시 중지 시킬 수 있다.Job
, CronJob
의 특성상 일반적으로 어떤 대량의 데이터를 처리해야 되거나 시간이 오래 걸리는 작업을 다루게 된다.
suspend
옵션으로 작업을 일시 중지 할 수 있다.
suspend
는 boolean
타입으로 선언하며 default
는 false
이다.
아주 오래걸리는 작업을 하나 실행해보자
vagrant@node1 ~/cont/job kubectl create -f mypi.yaml
job.batch/mypi created
vagrant@node1 ~/cont/job kubectl edit job mypi
job.batch/mypi edited
suspend
값을 false → true로 변경하면 작업이 잠시 중단된다.
오래 걸리는 작업이기 때문에 cpu, memory를 아주 많이 쓰고 있을 수도 있다.
그래서 일시적으로 잠시동안 중단을 시키고 싶다라고 하면 suspend
를 true로 설정한다.
'DevOps > Kubernetes' 카테고리의 다른 글
[Kubernetes] Service & DNS (서비스와 DNS) (0) | 2022.05.20 |
---|---|
[Kubernetes] CronJob (크론잡) (0) | 2022.05.20 |
[Kubernetes] Kubespray로 노드 추가/삭제하기 (0) | 2022.05.20 |
[Kubernetes] DaemonSet (데몬셋) (0) | 2022.05.20 |
[Kubernetes] ReplicationController & ReplicaSets (0) | 2022.05.19 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!