Kubernetes in Action : Chapter.4 레플리케이션과 그 밖의 컨트롤러

    들어가기 전

    이 글은 쿠버네티스 인 액션 책을 읽고 공부하며 작성한 글입니다. 


    4. 레플리케이션과 그 밖의 컨트롤러 : 관리되는 파드 배포

    쿠버네티스는 특정 파드들이 실패 상태에 다다르면 자동으로 복구하는 기능을 제공한다. 이런 기능은 다음 두 가지로 나누어져서 제공되는 것 같다.

    • 마스터 노드(Control Plane)의 컨트롤러들 : Replicaset, DaemonSet
    • 워커 노드의 Kubelet

    이 장에서는 어떤 메커니즘으로 실패 상태의 녀석들이 정상 상태로 회복되는지를 공부하고자 한다. 


    4.1 파드를 안정적으로 유지하기 → Kubelet이 함. 

    워커 노드에 파드가 배포된다. 파드 안에는 하나 이상의 컨테이너가 존재할 수 있다. 만약 파드 안의 컨테이너 중 하나라도 상태가 좋지 않다면 워커 노드의 kubelet이 이것을 확인하고 파드를 재시작한다. 

    컨테이너 단위로 재시작을 하면 좋겠지만, 쿠버네티스는 파드 단위로 관리하기 때문에 하나의 컨테이너라도 문제가 되면 kubelet은 파드 단위로 재시작한다. 그렇다면 파드의 컨테이너는 어떤 상황일 때 '실패 상태'로 인지해야만 할까?

    • 크래시가 발생한 상황 → Exit 1 같은 걸로 죽었을 때 (kubelet 인지 가능)
    • OOM 같은 것이 발생한 상황  (kubelet 인지 불가능)

    위 상황이다. 첫번째 상황은 kubelet이 인지하고 파드를 재시작한다. 하지만 OOM은 쿠버네티스가 자동으로 인지하지는 못한다. OOM이 발생하더라도 JVM 프로세스는 계속 실행되고 있기 때문이다. 따라서 이런 경우에 쿠버네티스가 외부에서 프로세스를 확인할 수 있도록 liveness 프로브를 직접 구현해야 한다. 


    4.1.1 Liveness Probe (컨테이너의 상태 판단 → 재기동 대상)

    파드의 스펙을 정의할 때, 각 컨테이너마다 liveness Probe를 설정할 수 있다. 쿠버네티스는 주기적으로 liveness Probe를 찔러보고 정상으로 동작하지 않는 경우 컨테이너의 문제로 판단하고 파드를 재시작한다. 쿠버네티스가 제공하는 liveness Probe는 다음 세 가지가 있다.

    • HTTP GET 프로브 : HTTP 요청에 200, 300 응답이 오면 정상. 이외의 응답은 실패로 간주.
    • TCP 소켓 프로브: 컨테이너의 지정된 포트에 TCP 연결을 함. 성공하면 프로브가 성공.  아니면 실패로 간주.
    • Exce 프로브 : 컨테이너 내의 임의의 명령을 실행하고 명령의 종료 상태 코드를 확인. 상태 코드가 0이면 성공. 아니면 실패.  → 예를 들어 특정 파일이 있는 경우, 멀쩡한 것으로 판단함. 

    4.1.2 HTTP 기반 라이브니스 프로브 생성

    먼저 도커 이미지를 하나 작성한다. 도커 이미지는 /health-check로 요청을 보낼 때, 5번에 한번씩 500 응답을 내려준다. 그리고 그 이미지를 사용하는 파드를 아래와 같이 하나 생성한다. 이 때 다음을 참고하자.

    • 컨테이너 스펙에 livenessProbe를 설정할 수 있음.
    • httpGet으로 HTTP Liveness 프로브를 사용함. 
    • 여러 설정을 통해서 Threshold를 설정할 수도 있고, 안정화 시간 이후 프로브를 시작할 수도 있음. 
    apiVersion: v1
    kind: Pod
    metadata:
      name: liveness-test-pod
    spec:
      containers:
        - image: ojt90902/ash:latest
          name: ash
          livenessProbe:
            initialDelaySeconds: 15 # 초기에는 파드가 바로 대응할 준비가 안됨.
            successThreshold: 1 # 한번만 성공해도 성공.
            failureThreshold: 5 # 다섯 번 실패해야 실패로 인정함.
            timeoutSeconds: 10 # 이 시간동안 응답오지 않으면 실패로 봄.
            periodSeconds: 1
            httpGet:
              port: 8080
              path: /health-check
          ports:
            - containerPort: 8080
              protocol: TCP

    위와 같이 Yaml 파일을 설정한 후 쿠버네티스에 배포하고 결과를 살펴보자. 아래와 같이 파드가 여러 번 재시작된 것을 볼 수 있다. 

    NAME           READY   STATUS             RESTARTS         AGE
    ash-liveness   0/1     ImagePullBackOff   15 (9m27s ago)   40m

    4.1.3 동작 중인 라이브니스 프로브 확인

    위의 예시에서 Liveness 프로브가 정상적으로 동작하고 있다면, kubelet은 컨테이너가 문제였다고 판단했을 것이다. kubelet은 파드를 재기동 시켰을텐데, 이전 파드에 발생한 문제 / 상태를 아래 명령어를 이용해서 확인할 수 있다. 

    • Describe를 이용해 마지막 상태 확인
    • --previous 옵션을 이용해 이전 파드의 로그 확인 
    // 종료된 Pod의 이전 상태를 확인.
    $ kubectl logs liveness-test-pod --previous
    
    // Event 및 이전 상태를 확인할 수 있음.
    # kubectl describe pod liveness-test-pod

    Describe 명령어를 이용하면, 컨테이너 항목의 Last State라는 항목이 추가되어있다. Last State는 현재 컨테이너 이전 컨테이너의 상태를 보여준다. 여기서 어떤 이유로 종료되었는지를 보여준다. 


    4.1.4 라이브니스 프로스 추가 속성 설정 → InitialyDelaySeconds

    일반적으로 쿠버네티스는 컨테이너가 시작되자마자 Liveness Probe를 확인하기 시작한다. 그렇지만 대부분의 경우 컨테이너가 막 시작된 순간에 어플리케이션은 헬스 체크를 받을 준비가 되어 있지 않을 것이다. 따라서 시작하자마자 kubelet은 컨테이너가 문제가 있다고 판단하고 Pod를 계속 재시작하는 악순환이 발생할 수 있다.

    이런 문제는 initialDelaySeconds를 적절히 설정하는 것으로 해결할 수 있다. initialDelaySeconds를 설정하면, kubelet은 이 시간이 지난 후부터 liveness Probe를 처음으로 체크하기 시작한다. 


    4.1.5 효과적인 라이브니스 프로브 설정

    운영 환경에서 실행 중인 파드는 반드시 Liveness Probe를 설정해야한다. 그렇지 않으면 쿠버네티스가 컨테이너에서 실행중인 어플리케이션이 정상적으로 동작하는지 알 수 있는 방법이 없기 때문이다.

     

    라이브니스 프로브가 확인해야 할 사항

    라이브니스 프로브는 어플리케이션 내부만 체크해야한다. 백엔드 서버를 예로 들면, DB가 죽었다고 해서 백엔드 서버의 Liveness Probe가 실패하면 안된다. 이 때 백엔드를 실패로 간주하고 재시작해도 문제는 해결되지 않기 때문이다.

     

    라이브니스 프로브를 가볍게 유지하기

    • 라이브니스 프로브는 너무 많은 연산 리소스를 사용하면 안됨. 
    • 빠른 시간 내에 완료되어야 함. 

    라이브니스 프로브는 파드가 살아있는한 주기적으로 호출된다. 따라서 라이브니스 프로브가 너무 많은 일을 하게 되면 컨테이너가 전체적으로 느려지게 된다. 따라서 라이브니스 프로브는 가급적 적은 연산으로 호출해야한다. 

     

    Liveness 프로브에 재시도 루프를 구현하지 마라

    Liveness 프로브에는 실패 임계값을 설정할 수 있다. 실패 임계값을 설정했을 때, 컨테이너가 강제로 종료되려면 프로브가 여러 번 '연속으로' 실패해야한다. 이런 기능을 활용하면 되기 때문에 굳이 어플리케이션에서 Liveness 프로브가 실패했을 때, 재시도하는 기능을 구현하지 않아도 된다는 것이다. 

     


    4.2 레플리케이션 컨트롤러 소개

    ReplicationController는 쿠버네티스의 컨트롤러다. 컨트롤러는 Control Plane이 관리하는 녀석이다. 이런 컨트롤러는 선언된 상태(Desired State)를 만족하지 못하는 경우, 해당 상태를 만족시키도록 동작한다. 즉, 파드가 죽으면 파드를 되살리는 역할을 한다. 여기서 짚고 넘어가야 할 부분은 다음과 같다

    • 우리가 생성한 파드는 컨트롤러의 관리를 받지 않는다. 따라서 파드가 죽어도 누가 되살려주지 않는다.
    • 컨트롤러가 만든 파드는 컨트롤러가 관리한다. 따라서 파드가 죽어도 컨트롤러가 되살린다. 

    컨트롤러가 파드를 계속 관리하는 것은 컨트롤러가 파드를 관리하는 조건을 만족하는 경우다. 뒤에서 정리하겠지만, 컨트롤러는 라벨링된 파드를 관리하는데 라벨링 조건이 바뀌게 된다면 컨트롤러는 파드를 관리하지 않는다.


    4.2.1 Replication Controller의 동작

    Replication Controller는 실행 중인 파드 목록을 지속적으로 모니터링하고, 특정 유형의 실제 파드 수가 원하는 상태(Desired State)와 맞는지를 계속 모니터링 한다. 만약 맞지 않는다면 해당 상태를 달성할 수 있도록 동작한다. 그러면 관리하는 파드의 수는 어떤 경우에 바뀔 수 있을까?

    • 누군가 같은 파드를 수동으로 생성.
    • 기존 파드의 유형을 변경. 
    • 파드를 죽임. 

     

    컨트롤러 조정 루프

    Replication Controller는 레이블 셀렉터를 이용해서 매칭되는 레이블을 가진 파드의 수를 확인하고, 적절하지 않은 상태라면 그렇게 동작하도록 조치를 취한다. 주요 로직은 다음과 같이 동작한다. 

     

     

    Replication Controller의 세 가지 요소 이해

    Replication Controller는 세 가지 필수 요소가 존재한다. 

    • 레이블 셀렉터 : Replication Contrller가 관리하는 파드를 선택함. 
      • 파드에 레이블이 3개가 있더라도, Lable Selector가 가리키는 Label로 검색되면 관리대상임. 
    • Replica Count : 파드의 Desired State를 의미함. 
    • Pod Template : 파드 Replica를 생성할 때 사용하는 붕어빵 툴. 

    여기서 ReplicationContrller는 레이블 셀렉터로 검색되는 파드의 수가 Replica Count를 만족하는지만 바라본다. Pod Template은 단지 파드를 생성할 때만 사용한다. 레이블 셀럭터에서 관리되는 파드의 실제 내용이 Pod Template과 같은지는 고려요소가 아니다. 

     

    컨트롤러의 레이블 셀렉터 또는 파드 템플릿 변경의 영향 이해 

    자세한 내용은 다음과 같이 이해해 볼 수 있다.

    • Replication Controller의 레이블 셀렉터를 변경
      • 기존 파드들은 Replication Controller의 관리 대상이 아니게 된다.
      • Replication Controller 입장에서 레이블 셀렉터에 해당되는 파드의 수는 0이다. 따라서 새롭게 파드를 생성한다. 
    • 관리되는 파드의 내용 변경
      • Label을 변경하는 경우, Replication Controller는 그 즉시 새로운 파드를 하나 만든다. 그리고 변경된 파드는 관리 대상이 아니게 된다.
      • Label 말고 다른 내용이 변경되어도 파드는 계속 Replication Controller가 관리하는 파드다. 

     

     

    Replication Controller 사용 시 이점

    Replication Controller는 다음과 같이 좋은 이점을 제공한다.

    • 기존 파드가 사라지면 새 파드를 시작해 파드가 항상 실행되도록 한다. 
    • 클러스터 노드에 장애가 발생하면 장애가 발생한 노드의 파드를 모두 정상 노드에서 다시 생성한다. 
    • 수평 확장을 손쉽게 지원한다. 

    4.2.2 Replication Controller 생성

    Replication Controller는 현대의 쿠버네티스에서 거의 사용되지 않는 옛날 컨트롤러다. 최근에는 주로 ReplicaSet Controller를 사용한다. 두 컨트롤러의 차이점은 ReplicaSet이 좀 더 정교한 레이블 셀렉터 기능을 제공한다는 것이다. 그 외에는 동일하게 동작한다. 

    Replication Controller를 선언하는 Yaml 파일의 정의는 아래와 같다.

    # 큰일나는 이유는 다음과 같다.
    # Controller는 셀렉터에 대응되는 상태를 만족하지 못하는 경우 Template에 있는 파드를 생성함.
    # 생성된 파드는 Label이 다름. 따라서 Controller가 새롭게 파드를 생성했지만, 여전히 만족하는 파드를 생성하지 못해서 계속 생성함.
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: kubia
    spec:
      replicas: 3
    #  selector: # select를 설정하지 않으면 묵시적으로 Template의 레이블을 바라봄.
    #    app: kubia # 이 실렉터가, Template을 정확하게 바라보지 않으면 큰일남.
      template:
        metadata:
          labels:
            app: kubia
        spec:
          containers:
            - name: kubia
              image: luksa/kubia
              ports:
                - containerPort: 8080
    

     

    이 녀석을 이용해서 Replication Controller를 생성할 때 주의해야 할 부분은 다음과 같다.

    • Replication Controller의 Label Selector는 반드시 Template의 Label과 일치 시켜줘야한다. 그렇지 않을 경우 무한히 파드를 생성한다. 
    • Replication Controller의 Label Selector를 설정하지 않으면, Controller는 암묵적으로 Template의 Lable과 일치하는 레이블 셀렉터를 이용한다. 

    Replication Controller 입장에서는 원하는 상태를 만족하지 못해서 Template에 있는 것을 새로 만들었는데, 만들어진 레이블과 레이블 셀렉터가 일치하지 않게 될 것이다. 따라서 컨트롤러는 자신이 필요로 하는 파드가 부족하다는 것을 알고 무한히 생성할 것이다. 따라서 Replication Controller를 선언할 때는, 레이블 셀렉터를 선언하지 않는 것이 더 좋은 케이스다. 


    4.2.3 Replication Controller의 작동 원인 및 동작 살펴보기

    Replication Controller는 레이블 셀렉터로 그룹핑 한 파드의 숫자가 변하면, 원하는 상태를 만족시키기 위해서 동작한다. 실제 동작하는 정확한 순서는 다음과 같다고 한다.

    1. Replication Controller는 삭제 / 변경되는 파드에 대해 즉시 통보한다.
    2. 이 변경사항은 Replication Controller가 동작하도록 트리거 한다.
    3. Replication Controller가 트리거 되면, 관리하는 파드의 수와 실제 수를 비교해서 조치한다. 

     

     파드 삭제

    개발자가 아래 명령어로 파드를 삭제했다. 파드가 삭제되면, 이 변경 사항이 API 서버로 전달된다. 그리고 Replication Controller가 동작하도록 트리거 되고, Replication Controller는 파드가 하나 삭제된 것을 확인한다. 원래 상태를 만족하기 위해 Replication Controller의 Template에 있는 파드를 하나 생성한다.

    $ kubectl delete pod test

     

    노드 장애

    노드에 장애가 발생하면, 마스터 노드가 워커 노드의 장애를 알아채기까지 약간의 시간이 걸린다. 이 기간동안 파드의 숫자 변화에 대한 내용이 없기 때문에 마스터 노드에는 어떠한 알람도 오지 않는다. 따라서 Replication Controller가 파드를 새로 생성하지는 않는다.

    조금 시간이 지나서 노드가 Fail되게 되면, Replication Contrller가 동작하도록 트리거 된다. 그리고 Replication Controller는 새로운 파드를 생성하도록 동작한다. 


    4.2.4 Replication Controller 범위 안팎으로 파드 이동 (Label 조절)

    Replication Controller는 Label Selector를 이용해서 파드를 그룹핑해 관리한다. Label Selector 안에 있는 것이 '범위' 안에 있는 파드라고 볼 수 있다. 이런 것들을 아래 같은 형태로 관리 범위 밖으로 뺄 수도 있다. 

    • Replication Controller의 Label Selector 변경
    • Pod의 Lable 변경 

    위 작업을 해서 Lable Selector / Lable을 각각 수정하면, Replication Controller 입장에서는 Desired State를 달성하지 못하는 상태일 것이다. 따라서 Replication Controller는 새로운 파드를 생성할 것이다.


    4.2.5 Pod Template 변경

    Replication Controller의 Template도 언제든지 변경할 수 있다. 그렇지만 앞서 이야기 했던 것처럼 Template은 다음 역할을 한다. 

    • Template은 Replication Controller가 새로운 파드를 생성해야 할 때, 사용하는 붕어빵 틀로만 사용됨. 
    • Template의 상태와 관리하는 파드의 상태가 같은지는 고려 대상이 아님. 

    이것은 다음을 의미한다

    • Pod의 내용이 바뀌어도 Replication Controller에게는 의미가 없음.
    • Replication Controller의 Template 내용이 바뀌어도 새로운 Pod가 생성되지는 않음. 

    만약 파드가 죽어서 새로운 파드를 생성한다면, 새로운 Template으로 생성되기 때문에 기존에 생성된 파드와는 다른 내용을 가질 것이다. 


    4.2.6 수평 파드 스케일링

    쿠버네티스는 파드 단위로 수평 스케일링을 제공한다. 개발자가 파드의 수를 늘리거나 줄이거나 할 수 있는데 다음 두 가지 방법을 이용할 수 있다. 

    • kubectl scale 명령어를 사용함. 
    • kubectl edit 명령어로 replicas를 수정함. 

    예를 들어서 다음 명령어를 이용해서 파드를 수평확장할 수 있다. 

    // kubia의 복제 갯수를 5개로 늘려라. 
    $ kubectl scale replicationcontroller kubia --replicas 5

    4.2.7 Replication Controller 삭제

    Replication Controller는 아래 명령어를 이용하면 삭제할 수 있다. 컨트롤러가 삭제되기 때문에 기본적으로는 관리되고 있는 파드도 삭제된다. 그렇지만 컨트롤러가 삭제되더라도 파드는 그대로 유지할 수 있는 방법도 있다. 

    // 컨트롤러 + 파드 삭제
    $ kubectl delete rc kubia 
    
    // 컨트롤러만 삭제
    $ kubectl delete rc kubia --cascade=orphan

    4.3 ReplicationController 대신 ReplicaSet 사용하기

    ReplicationController는 레거시다. 최근에 만들어지는 이런 종류의 컨트롤러는 ReplicaSet을 사용한다.  둘다 쿠버네티스가 사용하는 컨트롤러이고, Replicaset은 상위 리소스인 Deployment를 관리하는 역할을 한다. 그리고 ReplicationController와 ReplicaSet은 하나 차이가 존재한다. 

    • ReplicationController는 레이블 셀렉터만 사용 가능.
    • ReplicaSet은 레이블 셀렉터 + 다양한 Match Expression 사용 가능. 

    ReplicaSet은 더 다양한 방식의 파드 그룹핑 기능을 지원한다는 것이다. 

     


    4.3.2. ReplicatSet 정의하기 + MatchExpressions 사용하기

    ReplicaSet은 다음과 같은 방식으로 정의할 수 있다. 특별한 것은 Selector를 두 가지 사용할 수 있다는 것이다.

    • matchLabels: 하나의 라벨만 일치하는 파드 그룹을 선택해서 관리한다.
    • matchExpressions: 다양한 연산자를 이용해서 더 다채롭게 선택할 수 있다. 
      • In : 레이블의 값이 지정된 값(Values) 중 하나와 일치해야 함. 즉, Key + value가 일치해야 함.
      • NotIn : 레이블의 값이 지정된 값과 일치하지 않아야 함. 즉, Key + Value가 일치하지 않아야 함.
      • Exists : 지정된 키(key)의 값이 파드의 레이블의 Key 중 하나여야 함. 이 때 대응되는 Value 값은 중요하지 않음. 이 때 values 필드는 사용하면 안됨.
      • DoeNotExits : 지정된 키(key)의 값이 레이블에 없는 파드를 선택함. values 필드는 사용하면 안됨.
    • 여러 표현식도 지정 가능하다. 여러 표현식을 지정하는 경우, 모든 표현식이 True여야 True가 된다. 하나라도 False면 False다. 

     

    apiVersion: apps/v1
    kind: ReplicaSet
    metadata:
      name: hello
    spec:
      replicas: 1
      selector:
        matchExpressions:
          - key: app
            operator: In
            values:
              - kubia
              - hello
      template:
        metadata:
          name: kubia-hello
          labels:
            app: kubia
        spec:
          containers:
            - name: hello
              image: luksa/kubia
              ports:
                - containerPort: 80

     


    4.4 데몬셋을 사용해 각 노드에서 정확히 한 개의 파드 실행하기

    데몬셋은 각 노드에 파드가 정확히 하나씩만 배포되기를 바라는 바랄 때 사용할 수 있는 쿠버네티스 자원이자 컨트롤러다. 주로 노드의 리소스 감시(cAdvisor), 로그 수집기(fluentBit) 같은 녀석들을 데몬셋을 이용해서 배포할 수 있다. 


    4.4.1 데몬셋으로 모든 노드에 파드 실행하기

    • 데몬셋에 의해 생성되는 파드는 쿠버네티스 스케쥴러의 영향을 받지 않는다. 왜냐하면 이미 모든 노드에 파드가 생성될 것이기 때문에 스케쥴링이 필요없다. 
      • 스케쥴러에 의해서 파드가 노드에 배포되지 않도록 되는 설정은 데몬셋에는 적용되지 않는다. 왜냐하면 데몬셋은 스케쥴러를 거치지 않기 때문이다.
    • 데몬셋은 파드 셀렉터 + 노드 셀렉터에 의해 그룹핑 된 파드가 해당 노드에 1개 실행되고 있는지만 확인한다.
    • 노드가 다운되면 데몬셋 컨트롤러는 다른 노드에 파드를 생성하지 않음.
    • 노드가 추가되면 데몬셋 컨트롤러는 다른 노드에 파드를 추가함. 

    4.4.2 데몬셋을 사용해 특정 노드에서만 파드를 실행하기

    특별한 설정이 없다면 데몬셋은 모든 노드에 파드를 생성한다. 하지만 Node Selector 속성을 사용하면 데몬셋은 특정 노드에만 파드를 생성하도록 바꿀 수 있다. 

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: chapter-4-10-daemonset
    spec:
      selector:
        matchLabels:
          app: daemon
      template:
        metadata:
          name: chapter-4-10-daemonset
          labels:
            app: daemon
        spec:
          nodeSelector:
            disk: ssd
          containers:
            - name: chapter-4-10-daemonset
              image: luksa/kubia
              ports:
                - containerPort: 8080

    위 DaemonSet은 disk: sdd라는 라벨이 붙은 Node에만 파드를 반드시 하나 생성한다. 하지만, 현재 노드에는 어떠한 라벨도 없기 때문에 어떠한 파드도 생성되지 않는다. 아래 명령어를 이용해서 라벨을 추가하거나 제거해주면 노드에 데몬셋이 생겼다가 사라진다. 

    # 필요한 라벨 추가
    $ kubectl label node worker1 disk=ssd
    
    # 필요한 라벨 제거
    $ kubectl label node worker1 disk=ssd1 --overwrite

    데몬셋 역시 ReplicaSet과 동일하게 동작한다. 데몬셋 컨트롤러는 다음과 같이 동작한다. 

    • Label Selector + Node Selector를 이용해서 선택한 곳이 원하는 상태가 아닌 경우, 해당 내용은 DaemonSet 컨트롤러에게 통보된다.
    • DaemonSet 컨트롤러는 이 내용에 의해서 현재 상태 / 원하는 상태가 같은지 아닌지를 비교한다.
    • 다른 경우, Template에 있는 내용으로 새로운 파드를 생성해서 원하는 상태로 만들어준다. 

    4.5 완료 가능한 단일 태스크를 수행하는 파드 실행 (Job)

    특정 테스크만 실행하고 종료하려는 경우도 있을 것이다. 쿠버네티스에는 Job이라는 오브젝트를 통해서 'Task를 실행하고 종료된 뒤에 다시 시작되지 않는' 기능을 제공한다. 


    4.5.1 Job 리소스 소개

    쿠버네티스의 잡 리소스는 다음 기능을 제공해준다. 

    • Job은 파드를 생성해서 작업을 수행함.
    • 컨테이너 내부에서 실행 중인 프로세스가 성공적으로 완료되면, 다시 시작하지 않음. 
    • 프로세스가 실패하면 restartPolicy를 설정해 재시작 할 수 있음. 
      • Job은 무한정 재실행 하지 않으므로 OnFailure, Never를 명시해줘야 함. 
    • Job은 JobController에 의해서 관리됨. Job 실패하는 경우, 노드가 실패하는 경우 JobController에 의해서 적절히 대처된다. 
    • Job은 여러 번 반복가능하며, 병렬성을 지원해준다. (completions, parallelism)
      • Completion을 지정한 경우, 파드의 성공 횟수가 completion이 될 때 까지 반복한다. 
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: batch-job
    spec:
      completions: 5 # 5번 성공해야 Job이 완료됨.
      parallelism: 2 # 2개씩 동시에 실행함.
      template:
        metadata: # Pod Selector를 지정하지 않으면, 자동으로 Template의 라벨을 선택함.
          labels:
            app: batch-job
        spec:
          restartPolicy: OnFailure # Job은 Always 불가능.
          containers:
            - name: main
              image: luksa/batch-job
    

    4.5.5 Job 파드가 완료되는데 걸리는 시간 제한하기

    잡은 파드가 완료될 때까지 얼마나 기다려야 할까? 파드가 특정 상태에 빠져서 완료될 수 없는 경우라면 어떻게 해야할까? 이 경우, Job이 완료되는데 필요한 시간을 activeDeadlineSeconds를 이용해서 설정할 수 있다. 만약 이 시간이 지날 때까지 Pod가 완료되지 않는다면 Job은 실패된 것으로 간주된다. 

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: batch-job
    spec:
      # 이 시간까지 완료되지 않으면 실패한 Job임.
      activeDeadlineSeconds: 1 
    	...

    4.6 Job을 주기적 / 한번 실행되도록 스케쥴링 하기

    Job을 쿠버네티스 클러스터에 배포하면, 그 즉시 Job의 PodTemplate에 있는 파드가 생성되어서 동작한다. 그렇다면 주기적으로 Job을 실행하고 싶다면 어떻게 해야할까? 이를 위해서 쿠버네티스는 CronJob을 제공해준다. 크론잡은 다음과 같이 동작한다.

    • JobController는 Cron 형식을 읽어, 정해진 시간에 Job Template을 읽어 Job을 생성함. 
    • Job이 생성되면 Pod가 생성되어 실행됨 

    크론잡의 생성은 아래를 참고하면 된다. 아래 Yaml 파일이 배포되면 매 15분마다 JobTemplate에 정의된 Job을 생성한다. 매 15분마다 Job이 생성되면 Job은 Pod를 생성해서 필요한 작업을 수행한다. 

    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: c4-14-batch-job-every-fifteen-minutes
    spec:
      schedule: "0,15,30,45 * * * *"
      # Job Template
      jobTemplate:
        # Pod Template
        spec:
          template:
            metadata:
              labels:
                app: periodic-batch-job
            spec:
              containers:
                - name: main
                  image: luksa/batch-job

     

    댓글

    Designed by JB FACTORY