전공영역 공부 기록

쿠버네티스 잡(job)

악분 2021. 8. 21. 15:38
반응형

안녕하세요. 이 글은 쿠버네티스 job에 대해 설명합니다. 예제 코드는 github(https://github.com/choisungwook/kubernetes-job)에서 확인할 수 있습니다.

글 수정 이력
● 2021.8.22 backofflimit 설명 수정
● 2021.8.22 job오류와 pod오류 처리 설명 수정

 

1. job이해

1.1 job이란?

job은 쿠버네티스 ①pod를 이용해서 ②일회성 또는 정기적인 작업을 실행할 때 사용합니다. pod와 다른점은 종료되는 것을 기대하고 작업 실행결과를 알려줍니다.

 

일반적으로 pod는 시작되면 항상 실행되는 것을 기대합니다. 예를 들어서 웹 애플리케이션처럼요. 이와 다르게 job은 실행되면 몇 분 또는 몇 시간, 몇일 뒤에 종료되는 것(또는 주기적으로 실행되는 작업)을 실행합니다. 그리고 실행이 잘되었다는 결과를 사용자가 확인할 수 있습니다. [그림 1]은 job으로 실행시킨 작업 1개가 끝나다는 것을 COMPLETIONS칼럼에 보여줍니다.

그림1 kubectl get job예

 

 

1.2 job관리는 누가 할까?

쿠버네티스 controller 중 하나인 job controller가 관리합니다. kubectl describe job으로 상세내용을 확인하면 job-controller이 관리하는 것을 알 수 있습니다.

그림2 kubectl describe job 예제

 

1.3 job 실행횟수 - COMPLETIONS

job은 설정한 성공횟수(COMPLETIONS)에 도달할때까지 실행됩니다. 디폴트로 1로 설정되어 있습니다. 작업이 성공적으로 끝나면 COMPLETIONS이 증가합니다. 작업이 실패로 끝나면 설정에 따라 실패한 작업을 재실행합니다. 

참고자료: https://kubernetes.io/ko/docs/concepts/workloads/controllers/job/#parallel-jobs

 

아래 [그림 3]예제는 COMPLETIONS이 1로 설정된 job실행결과입니다. COMPLETIONS 칼럼에 1/1로 표시가 되어있습니다. 이 의미는 (성공적으로 작업이 끝난 횟수)/(설정한 COMPLETIONS 값)입니다.  1/1로 설정되어 있으니 [그림 3]에서 실행한 JOB은 성공적으로 실행되었다는 것을 알 수 있습니다.

그림3 job실행 COMPELTIONS확인

 

1.4 에러처리 방법 설정(restartPolicy)

job오류가 발생하면 restartPolicy정책에 따라서 에러처리가 달라집니다. restartPolicy Never로 되면 새로운 pod를 실행해서 다시 job을 실행합니다. restartPolicy가 Never이 아니면 pod를 재실행합니다.

 

[그림 4]를 보시면 바로 이해가실 건데요! 왼쪽 job은 restartPolicy가 Never로되어 있어서 pod를 재실행해서 job을 다시 실행합니다. 오른쪽 job은 restartPolicy가 Onfailure로 설정되어있으므로 pod가 재실행되면서 job을 다시 실행합니다.

그림4 job오류와 pod오류

 

2. 실습 준비

2.1 쿠버네티스 클러스터

당연히 쿠버네티스가 설치되어 있어야 합니다. 저는 미니큐브(minikube)를 사용했습니다.

미니큐브 설치방법은 https://malwareanalysis.tistory.com/150을 참고해주세요.

 

2.2 vscode

vscode(visualstudio code)로 job에 관련된 yaml파일을 작성합니다. 그리고 kubernetes extension설치도 필요합니다.

 

2.3 vscode extension

kubernetes extension을 사용해서 yaml파일 작성을 단축시킵니다.

그림5 kubernetes extension

 

3. helloworld job 실행

챕터3에서는 job을 디폴트 설정으로 실행하는 예제를 다룹니다.

 

3.1 job template 생성

job이라고 입력하면 kubernetes extension템플릿을 선택할 수 있습니다. Kubernetes Job 템플릿을 선택하겠습니다.

그림6 쿠버네티스 템플릿 선택화면

 

기본 job템플릿을 선택하면 [그림3]와 같이 job yaml파일이 자동으로 만들어집니다.

그림7 쿠버네티스 job템플릿

 

기본 job템플릿에서 몇가지를 수정해서 helloworld를 출력하는 예제로 변경해보겠습니다.

소스코드: https://github.com/choisungwook/kubernetes-job/blob/main/success-helloworld.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: hello-world
spec:
  template:
    spec:
      containers:
      - name: helloworld
        image: busybox
        command: ["echo", "helloworld"]
      restartPolicy: Never

 

3.2 job 실행

job yaml파일을 저장하고 실행해봅시다.

kubectl create -f <yaml경로>

그림8 job실행

 

3.3 job 실행기록 확인

kubectl get job으로 job목록을 확인할 수 있습니다. job은 설정한 COMPLETIONS을 별도로 설정하지 않아서 1로 설정되어 있습니다. 현재 1/1로 표시되었으므로 JOB이 성공적으로 1번 실행되었다는 것입니다.

그림9 job목록 확인

 

job은 pod로 실행되기 때문에 pod목록에서도 확인가능합니다. 성공적으로 job실행이 끝난 pod는 Completed상태로 기록됩니다. 반면 오류가 발생하면 pod 오류코드(Failed, ImagePullError 등)가 보입니다.

그림10 Pod목록 확인

 

job은 pod로 실행되기 때문에 stdout, stderr로 출력하는 로그를 볼수있습니다.

그림11 job 로그 확인

 

3.4 job 삭제

kubectl delete명령어로 job을 삭제할 수 있습니다. job을 삭제하면 기존 pod기록도 삭제됩니다.

kubectl delete job <job이름>

 

4. 오류시나리오

챕터 3에서는 정상적으로 실행되는 job을 실행했었습니다. 이번 챕터에서는 강제로 job 오류를 발생시켜보겠습니다.

 

4.1 restartPolicy: Never설정 시나리오

오류가 발생하는 리눅스 명령어를 실행하는 job 템플릿을 만들었습니다. restartpolicy를 제외한 나머지 설정은 디폴트를 사용했습니다. 예제에서 오류가 발생하는 이유는 리눅스 명령어를 실행해서 에러가 발생하기 때문입니다. ls명령어는 유효하지 않는 경로에 작업을 시도하면 에러가 발생합니다.

소스코드: https://github.com/choisungwook/kubernetes-job/blob/main/error-default.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: errorjob-unvalidcommand
spec:
  template:
    spec:
      containers:
      - name: errorjob-unvalidcommand
        image: busybox
        command: ["ls", "unvalid path"]
      restartPolicy: Never

 

kubectl create명령어로 job을 실행합니다.

kubectl create -f <yaml경로>

 

job 상태를 확인하면 [그림 4]와 다르게 0/1로 표시됩니다. 컨테이너 1개를 실행했고 작업이 실패했다는 의미입니다.

kubectl get job

그림12 실패job 확인

 

pod상태가 Error인게 여러개 보입니다. job 에러가 발생했기 때문에 새로운 pod를 실행함으로써 작업을 다시 실행한 흔적입니다. 새로운pod를 생성해서 실행하는 이유는 restartPolicy가 Never로 되어 있기 때문입니다.

그림13 job 에러 확인

 

 

pod 로그를 확인하면 리눅스 명령어 오류를 확인할 수 있습니다. 예상한 대로, 없는 경로에 ls명령어를 사용했으므로 오류가 발생한 것입니다.

그림14 job에러

 

4.2 에러발생 시 job, pod 재실행 제한 - backoffLimit

디폴트 설정으로 오류가 발생하면 job을 6번 재실행합니다. 처음 실행했던 pod를 합치면 총 7번 job이 재실행됩니다. 상황에 따라서 오류 발생시 job실행횟수를 제한하고 싶다면 backoffLimit을 설정하시면 됩니다.

참고자료: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy

 

job에러가 발생하면 더 이상 실행하지 않도록 하려면 어떻게 해야할까요? backoffLimit을 0으로 설정하면 됩니다.

소스코드: https://github.com/choisungwook/kubernetes-job/blob/main/error-backofflimit.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: errorjob-unvalidcommand-backofflimit
spec:
  template:
    spec:
      containers:
      - name: errorjob-unvalidcommand
        image: busybox
        command: ["ls", "unvalid path"]
      restartPolicy: Never
  # job에러가 발생해도 pod는 1개만 실행
  backoffLimit: 0

 

kubectl create명령어로 job을 실행하고 pod목록을 확인해봅시다. [그림13]과 다르게 pod는 1개만 생성됩니다. backoffLimit이 1개로 설정되어 있기 때문입니다.

그림15 backoffLimit 설정 후 pod목록 확인

 

4.3 restartPolicy: Onfailure설정 시나리오

4.1챕터와 다르게 restartPolicy를 Onfailure로 설정해보겠습니다.

 

컨테이너가 종료할 때 종료코드가 0이 아니면 쿠버네티스는 pod가 정상종료되지 않았다고 생각합니다. 그리고 다시 pod를 다시 재실행합니다. 이 때 restartPolicy를 Onfailure설정해주셔야 합니다.

소스코드: https://github.com/choisungwook/kubernetes-job/blob/main/error-poderror-restart.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: errorjob-restartpod
spec:
  template:
    spec:
      containers:
      - name: unexited-code
        image: busybox
        command: ["exit 1"]
      restartPolicy: OnFailure

 

RESTARTS를 보면 pod가 총 3번 재실행되었습니다. restartPolicy를 Onfailure로 설정했기 때문에 [그림 13]과 다르게 pod가 재실행되고 job을 다시 실행합니다.

그림16 pod재실행

 

5. job 실행시간 제한 - activedeadlineseconds

job 실행시간을 제한시켜야할 때 activeDeadlineSeconds옵션을 사용하면 됩니다. 디폴트는 null?로 설정되어 있어 끝날때까지 실행하는 것 같습니다.

 

아래 예제에서는 무한루프를 도는 job을 실행합니다. 하지만, activeDeadLineSeconds가 10(초)로 설정되어 있어서 10초후에 job은 강제종료됩니다.

소스코드: https://github.com/choisungwook/kubernetes-job/blob/main/success-infinity-print-activedeadlineseconds.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: infinity-print-activedeadlineseconds
spec:
  activeDeadlineSeconds: 10
  template:
    spec:
      containers:
      - name: infinity-print-activedeadlineseconds
        image: busybox
        command: ["/bin/sh"]
        args: ["-c", "while true; do echo hello; sleep 3; done"]
      restartPolicy: Never

 

6. 참고자료

https://www.magalix.com/blog/kubernetes-jobs-101

반응형