ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쿠버네티스 컨트롤러 : 잡(Job)
    Kubernetes 2018. 6. 25. 09:00
    잡 컨트롤러는 계속해서 실행되어야하는 성격이 아니라 실행되고나서 종료되어야하는 성격의 작업을 실행시킬때 사용하는 컨트롤러 입니다. 잡은 특정 개수 만큼의 포드가 성공적으로 완료되는걸 보장해 줍니다. 가장 간단한 경우로는 잡이 포드 하나를 실행하고 포드가 정상적으로 종료됐는지 확인하는 것입니다. 실행한 포드가 실패하거나 하드웨어 장애가 발생하거나 노드가 재부팅 되는등 문제가 발생하면 다시 포드를 실행합니다. 잡 하나가 포드를 여러개 실행하는 것도 가능합니다.

    다음 예제 yaml을 job.yaml파일로 만들고 kubectl apply -f job.yaml로 실행해 봅니다.
    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

    kubectl describe job pi로 잡 상태를 확인해 볼수 있습니다. 실행 결과는 로그를 보면 알수 있는데 아래처럼 하면 됩니다. pods에 포드 id를 할당 받아서 kubectl logs명령어로 해당 포드의 로그를 볼 수 있습니다.
    pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath={.items..metadata.name})
    kubectl logs $pods

    잡의 종류
    잡의 종류는 3가지가 있습니다. 
    • 단일 잡
      • 포드 하나만 실행됩니다. 포드가 성공으로 종료되면 잡이 완료됩니다. 
      • .spec.completions와 .spec.parallelism를 설정하지 않습니다. 두 설정의 기본값은 1입니다.
    • 완료 개수가 있는 병렬(parallel) 잡
      • .spec.completions 에 양수를 설정합니다. 여기에 값이 1로 설정되면 성공한 포드가 1개만 생기면 잡이 완료됩니다. 
      • .spec.parallelism은 설정하지 않거나 기본값인 1로 설정해야 합니다.
    • 워크 큐를 가진 병렬(parallel) 잡
      • .spec.completions값을 설정하지 않으면 기본값이 .spec.parallelism과 동일하게 설정됩니다. 
      • 각 포드들은 종료됐는지를 모두 독립적으로 결정할수 있고, 모든 잡이 실행됩니다.
      • 포드 하나라도 성공으로 종료되면, 새로운 포드가 실행되지는 않습니다.
      • 최소한 1개의 포드가 성공으로 종료되고나서 모든 포드가 종료되면, 잡이 성공으로 종료됩니다.
      • 일단 포드 1개가 성공으로 종료되면 다른 포드들은 더이상 작동하거나 결과를 내지 않도록 됩니다. 다른 포드들은 모두 종료 과정으로 들어가게 됩니다.
      • .spec.completions은 설정하지 않고, .spec.parallelism은 양수로 설정합니다.

    잡 병렬성 관리
    하나의 잡이 몇개의 포드를 몇개나 동시에 실행할지 병렬성은 .spec.parallelism 옵션으로 지정할 수 있습니다. 기본값은 1이고 0으로 설정하면 잡을 정지할 수 있습니다. 병렬성 옵션으로 지정했다고 하더라고 다음 같은 이유로 지정된 값보다 병렬잡이 적게 실행될 수 있습니다.
    • 완료되는 잡의 개수를 고정하기 위해서 실제로 실행되는 포드들은 남아 있는 완료잡의 개수를 초과해서 실행되지 않습니다. 남아 있는 완료잡이 1이라면 병렬성을 3으로 설정했다고 하더라도 실제 포드는 1개만 실행됩니다.
    • 워크 큐 잡에서는 포드 하나가 성공으로 완료되고 나면 새로운 포드가 실행되지 않습니다. 현재 실행중이던 잡은 마저 실행될 수 있습니다. 
    • 컨트롤러가 반응하지 못하는 경우도 있습니다.
    • 컨트롤러가 쿼터 부족이나 권한 부족같은 이유로 포드를 실행하지 못하는 경우도 있습니다. 
    • 잡의 이전 포드들이 너무 많이 실패했으면 컨트롤러가 새로운 포드 생성을 제한할수 있습니다. 
    • 포드가 그레이스풀하게 종료된 경우.

    포드 실패 관리하기
    포드내의 컨테이너가 실패로 끝났을때의 처리를 위해서 .spec.template.spec.restartPolicy 옵션을 지정할 수 있습니다. 컨테이너는 비정상 종료되는 경우에는 메모리 제한, 비정상 종료코드등 다양한 이유가 있을 수 있습니다. 이때 .spec.template.spec.restartPolicy = "OnFailure"이렇게 컨테이너 재시작 정책이 OnFailure로 설정되어 있다면 포드는 원래 실행중이던 노드에서 컨테이너를 재시작합니다. 그래서 컨테이너로 띄운 앱에서 이렇게 컨테이너가 재시작되는 경우를 감안해서 만들어져 있어야 합니다. 그렇게 되어 있지 않다면 재시작 옵션을 "Never"로 줘서 재시작되는걸 막아야 합니다. 
    포드가 실패하는 경우도 있을 수 있습니다. 포드가 실행중이던 노드가 장애나 업그레이드등의 이유로 정지 된다거나 .spec.template.spec.restartPolicy = "Never"옵션을 줘서 컨테이너가 실패하면 포드가 실패할수 있습니다. 이때 잡은 새로운 포드를 실행합니다. 이렇게 포드가 재실행됐을때의 경우도 앱에서 처리해 줘야 합니다. 이전 포드에서 처리중이던 상태를 인식해서 거기서부터 재시작하거나 아니면 초기화하고 처음부터 다시 시작할 수 있어야 합니다. .spec.parallelism = 1 , .spec.completions = 1 , .spec.template.spec.restartPolicy = "Never" 이렇게 설정해도 같은 프로그램이 2번 실행될 수 있습니다. .spec.parallelism, .spec.completions을 둘다 1보다 크게 설정하면 한번에 여러개의 포드가 실행될 수 있습니다. 앱이 이런경우를 감안해서 처리할 수 있게 설계되어 있어야 합니다.

    포드 백오프(backoff) 실패 정책
    잡이 실패하고 계속해서 재시작을 시도할때 몇번까지 재시도하게 할지를 .spec.backoffLimit 에 설정해둘 수 있습니다. 기본값은 6입니다. 잡 컨트롤러가 재시작할때마다 시간 간격을 늘립니다. 처음 실패 후 10초를 기다린후 재시작하고 그 다음은 20초, 그 다음은 40초 이런식으로 계속 재시작 대기 시간을 늘려가면서 시도 합니다. 이렇게 재시작을 하다가 포드가 성공하게 되면 재시도 횟수는 0으로 초기화 됩니다.

    잡 종료와 정리
    잡이 완료되면 포드가 새로 생성되지도 않지만 포드가 삭제되지도 않습니다. 포드가 삭제되지 않고 남아 있으면 로그를 확인해서 에러나 경고를 확인해서 필요한 분석을 할 수 있습니다. 포드 뿐만 아니라 잡도 남아 있습니다. 그래서 잡의 상태를 계속해서 확인할 수 있습니다. 잡을 삭제하는건 사용자가 직접하도록 되어 있습니다. 잡을 삭제하면 관련된 포드들도 같이 삭제 됩니다. 
    잡을 종료하려면 .spec.activeDeadlineSeconds 옵션에 시간을 지정해 주면 됩니다. 지정된 시간이 되면 해당잡이 종료되고 실행중이던 모든 포드가 종료됩니다. 잡의 상태를 보면 종료 이유는 reason: DeadlineExceeded 로 표시됩니다. 

    잡 패턴
    잡에서 포드를 병렬로 실행하기는 하지만 각 포드들이 서로 통신하면서 작동하는 형태는 아닙니다. 각 포드들이 독립적으로 작동하는걸 전제하고 작동합니다. 메일을 발송하거나 파일을 변환하는 등의 분산 가능한 작업을 한꺼번에 실행하는 경우입니다. 일반적인 사용 패턴은 다음 같은 경우가 있고 그에 따른 장단점은 다음과 같습니다.
    • 각 작업마다 잡을 한개씩 생성하는 것과 모든 작업에 대해서 하나의 잡을 사용 하는 경우. 잡을 생성하는 오버헤드가 크기 때문에 작업이 많아질수록 잡 하나로 처리하는게 좋습니다.
    • 작업 개수 만큼의 포드를 생성하는 것과 포드 하나가 여러개의 작업을 처리하게 하는 것. 포드하나가 여러개의 작업을 처리하는게 포드를 생성하는 오버헤드가 줄어들기 때문에 작업이 많은경우에 유리합니다.
    • 워크 큐를 사용하는 경우. 큐 서비스를 사용하고 워크 큐를 사용하게 기존 프로그램이나 컨테이너를 수정해야 합니다. 워크 큐를 사용하지 않으면 기존 컨테이너에 별다른 수정을 하지 않고도 사용할 수 있습니다. 















    댓글

Designed by Tistory.