[Kubernetes] Controller

pingping·2021년 2월 13일
0

Kubernetes

목록 보기
5/10
post-thumbnail

Controller

  • 쿠버네티스 입문 책과 쿠버네티스 공식 Docs를 참고하여 정리하였습니다.

Concept

  • Controller : 파드들을 관리하는 역할을 하며 다양한 목적에 맞게 사용할 수 있다.
  • 상태가 없는 ( stateless ) 앱을 실행하는데 사용하는 컨테이너들은 Deployment로 배포할 수 있으며 이는 Deployment Controller가 관리한다. 또한 상태가 있는 (Stateful) 앱을 실행하는데 사용하는 컨테이너들은 StatefulSet로 배포할 수 있으며 StatefulSet Controller가 관리한다. 그리고 1회성 작업을 할 때 사용하는 Job, 주기적인 배치 작업을 실행할 때 사용하는 CronJob 등이 있다.

ReplicaSet

  • Replication Controller는 요즘에 잘 사용하지 않으므로 논외로 하였다.
  • 레플리카세트는 레플리케이션 컨트롤러와 같은 동작을 하지만 Set-based (집합 기반)의 셀렉터를 지원한다는 차이점을 가지고 있다.

Set-Based란?
셀렉터에서 Equality-Based는 레이블을 선택할 때 같은지 다른지 (=, ≠)만 확인하는데 반해 Set-Based (집합 기반) 셀렉터는 in, notin, exists 등과 같은 연산자(Operator)를 지원한다.

Example

  • Template
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-replicaset
  template:
    metadata:
      name: nginx-replicaset
      labels:
        app: nginx-replicaset
    spec:
      containers:
        - name: nginx-replicaset
          image: nginx
          ports:
            - containerPort: 80
  • 확인
root@instance-1:~/kubernetes-sample/controller# kubectl apply -f replicaset-nginx.yaml

root@instance-1:~/kubernetes-sample/controller# kubectl get pods
NAME                     READY   STATUS              RESTARTS   AGE
kubernetes-simple-pod    1/1     Running             0          24m
nginx-replicaset-dgbpl   0/1     ContainerCreating   0          5s
nginx-replicaset-l5vpd   0/1     ContainerCreating   0          5s
nginx-replicaset-n82xl   0/1     ContainerCreating   0          5s
root@instance-1:~/kubernetes-sample/controller# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
kubernetes-simple-pod    1/1     Running   0          24m
nginx-replicaset-dgbpl   1/1     Running   0          9s
nginx-replicaset-l5vpd   1/1     Running   0          9s
nginx-replicaset-n82xl   1/1     Running   0          9s

ReplicaSet & Pod 연관 관계

  • Pod는 Label 기준으로 관리하므로 ReplicaSet과는 느슨하게 결합되어 있다.

    • -cascade=false : 레플리카세트가 관리하는 파드에 영향을 끼치지 않고 레플리카세트만 삭제
  • 아래 나와있다 시피 rc는 삭제되었지만 pod들은 삭제되지 않았음을 확인할 수 있다.

root@instance-1:~/kubernetes-sample/controller# kubectl delete replicasets.apps nginx-replicaset --cascade=false
warning: --cascade=false is deprecated (boolean value) and can be replaced with --cascade=orphan.
replicaset.apps "nginx-replicaset" deleted

root@instance-1:~/kubernetes-sample/controller# 

root@instance-1:~/kubernetes-sample/controller# kubectl get pods,rc
NAME                         READY   STATUS    RESTARTS   AGE
pod/kubernetes-simple-pod    1/1     Running   0          31m
pod/nginx-replicaset-5n7wg   1/1     Running   0          50s
pod/nginx-replicaset-86j28   1/1     Running   0          50s
pod/nginx-replicaset-s6l8m   1/1     Running   0          50s
  • kubectl edit <<수정하려는 파드 이름>> 명령으로 에디터에 들어간 후 labels를 수정한다.
    app: hello-nginx로 수정하였음
root@instance-1:~/kubernetes-sample/controller# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
kubernetes-simple-pod    1/1     Running   0          34m
nginx-replicaset-5n7wg   1/1     Running   0          3m27s
nginx-replicaset-86j28   1/1     Running   0          3m27s
nginx-replicaset-s6l8m   1/1     Running   0          3m27s
**nginx-replicaset-wpmm5   1/1     Running   0          4s

root@instance-1:~/kubernetes-sample/controller# kubectl get pods -o=jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.metadata.labels}{'\n'}{end}"
kubernetes-simple-pod   {"app":"kubernetes-simple-pod"}
nginx-replicaset-5n7wg  {"app":"hello-nginx"}
nginx-replicaset-86j28  {"app":"nginx-replicaset"}
nginx-replicaset-s6l8m  {"app":"nginx-replicaset"}
nginx-replicaset-wpmm5  {"app":"nginx-replicaset"}**

⇒ 해당 파드는 nginx-replicaset 이라는 레플리카세트에서 분리되어 별개의 pod가 되었기 때문에 새로운 nginx-replicaset-wpmm5 라는 파드를 하나 생성하였다.

Deployment

  • Kubernetes가 stateless 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러이다.

    • 실행시켜야 할 파드 개수를 유지

    • 앱을 배포할 때

    • 롤링 업데이트 할 때

    • 앱 배포 도중 잠시 멈췄다가 배포하기

    • 앱 배포한 이후 이전 버전으로 롤백하기

      ⇒ 여러가지 기능이 있음


Example

  • replicaset이 pod를 관리하고, deployment가 replicaset을 관리한다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment
  # annotations:
    # kubernetes.io/change-cause: version 1.10.1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-deployment
  template:
    metadata:
      labels:
        app: nginx-deployment
    spec:
      containers:
      - name: nginx-deployment
        image: nginx
        ports:
        - containerPort: 80
  • Check
root@instance-1:~/kubernetes-sample/controller# kubectl get deploy,rs,rc,pods
NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           15s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-69cfdf5bc7   3         3         3       15s
replicaset.apps/nginx-replicaset              3         3         3       13m

NAME                                    READY   STATUS    RESTARTS   AGE
pod/kubernetes-simple-pod               1/1     Running   0          47m
pod/nginx-deployment-69cfdf5bc7-b7hgq   1/1     Running   0          15s
pod/nginx-deployment-69cfdf5bc7-jskvq   1/1     Running   0          15s
pod/nginx-deployment-69cfdf5bc7-xzrpt   1/1     Running   0          15s
pod/nginx-replicaset-5n7wg              1/1     Running   0          17m
pod/nginx-replicaset-86j28              1/1     Running   0          17m
pod/nginx-replicaset-s6l8m              1/1     Running   0          17m
pod/nginx-replicaset-wpmm5              1/1     Running   0          13m

Container 이미지 설정 정보 업데이트

  • 업데이트하는 방법에는 크게 3가지가 있다.
    - kubectl set
    - 직접 컨테이너 이미지를 지정

  • kubectl edit
    - 현재 파드의 설정 정보를 연 다음 컨테이너 이미지 정보 수정

  • Template에서 Container 이미지 정보 수정한 다음
    - kubectl apply 명령어

  • kubectl set image deployment <<deployment 이름>> container_name=image:version 의 방법으로 해당 컨테이너의 이미지를 수정해볼 것이다.

root@instance-1:~/kubernetes-sample/controller# kubectl set image deployment/nginx-deployment nginx-deployment=nginx:1.9.1

root@instance-1:~/kubernetes-sample/controller# kubectl get deploy,rs,pods
NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           11m

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-69cfdf5bc7   0         0         0       11m
**replicaset.apps/nginx-deployment-7b779c9596   3         3         3       43s**
replicaset.apps/nginx-replicaset              3         3         3       25m

NAME                                    READY   STATUS    RESTARTS   AGE
pod/kubernetes-simple-pod               1/1     Running   0          59m
**pod/nginx-deployment-7b779c9596-6mkdt   1/1     Running   0          33s
pod/nginx-deployment-7b779c9596-djzwq   1/1     Running   0          43s
pod/nginx-deployment-7b779c9596-r74tg   1/1     Running   0          24s**
pod/nginx-replicaset-5n7wg              1/1     Running   0          28m
pod/nginx-replicaset-86j28              1/1     Running   0          28m
pod/nginx-replicaset-s6l8m              1/1     Running   0          28m
pod/nginx-replicaset-wpmm5              1/1     Running   0          25m

Deployment 롤백

## 변경내용 확인
## CHANGE-CAUSE에는 아무것도 기입되어 있지 않다.
## 추후 관리를 위해서는 기입해주는 것이 좋다.
root@instance-1:~/kubernetes-sample/controller# kubectl rollout history deployment nginx-deployment 
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

## revision=2 의 정보를 확인한다. **nginx:1.9.1 버전이다.**
root@instance-1:~/kubernetes-sample/controller# kubectl rollout history deployment nginx-deployment --revision=2
deployment.apps/nginx-deployment with revision #2
Pod Template:
  Labels:       app=nginx-deployment
        pod-template-hash=7b779c9596
  Containers:
   nginx-deployment:
    **Image:      nginx:1.9.1**
    Port:       80/TCP
    Host Port:  0/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

## undo 명령으로 버전 롤백
root@instance-1:~/kubernetes-sample/controller# kubectl rollout undo deployment nginx-deployment 
deployment.apps/nginx-deployment rolled back

## 확인하면 기존의 버전은 사라지고 롤백이 되고 있음을 확인할 수 있다.
root@instance-1:~/kubernetes-sample/controller# kubectl get deploy,rs,pods
NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           17m

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-69cfdf5bc7   3         3         3       17m
replicaset.apps/nginx-deployment-7b779c9596   0         0         0       6m26s
replicaset.apps/nginx-replicaset              3         3         3       31m

NAME                                    READY   STATUS        RESTARTS   AGE
pod/kubernetes-simple-pod               1/1     Running       0          65m
**pod/nginx-deployment-69cfdf5bc7-9fgj2   1/1     Running       0          7s
pod/nginx-deployment-69cfdf5bc7-j2pt7   1/1     Running       0          9s
pod/nginx-deployment-69cfdf5bc7-xrhlp   1/1     Running       0          5s
pod/nginx-deployment-7b779c9596-6mkdt   0/1     Terminating   0          6m16s
pod/nginx-deployment-7b779c9596-djzwq   0/1     Terminating   0          6m26s
pod/nginx-deployment-7b779c9596-r74tg   0/1     Terminating   0          6m7s**
pod/nginx-replicaset-5n7wg              1/1     Running       0          34m
pod/nginx-replicaset-86j28              1/1     Running       0          34m
pod/nginx-replicaset-s6l8m              1/1     Running       0          34m
pod/nginx-replicaset-wpmm5              1/1     Running       0          31m
  • CHANGE-CAUSE : 변경 사항을 알 수 있는 버전 숫자 혹은 변경 내용을 메모할 수 있음

    ⇒ yaml template의 metadata.annotations 필드에 기입할 수 있다.

  • 기입한 이후 kubectl apply 명령어로 변경사항 적용
root@instance-1:~/kubernetes-sample/controller# kubectl apply -f deployment-nginx.yaml

root@instance-1:~/kubernetes-sample/controller# kubectl rollout history 
error: required resource not specified

root@instance-1:~/kubernetes-sample/controller# kubectl rollout history deployment nginx-deployment 
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
2         <none>
**3         version 1.10.1**

파드 개수 조정하기

  • 실행 중인 Deployment의 Pod 개수를 조정하기 위해서 kubectl scale 명령을 사용한다.
root@instance-1:~/kubernetes-sample/controller# kubectl scale --replicas=5 deployment nginx-deployment 
deployment.apps/nginx-deployment scaled

root@instance-1:~/kubernetes-sample/controller# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
kubernetes-simple-pod               1/1     Running   0          79m
nginx-deployment-69cfdf5bc7-9fgj2   1/1     Running   0          14m
nginx-deployment-69cfdf5bc7-c7np8   1/1     Running   0          5s
nginx-deployment-69cfdf5bc7-j2pt7   1/1     Running   0          14m
nginx-deployment-69cfdf5bc7-qnljn   1/1     Running   0          5s
nginx-deployment-69cfdf5bc7-xrhlp   1/1     Running   0          14m

DaemonSet

  • Cluster 전체 Node에 특정 Pod를 실행할 때 사용하는 Controller이다.
    → DaemonSet는 보통 Log 수집기 혹은 Monitoring용 데몬 등 클러스터 전체에 항상 실행시켜두어야 하는 파드를 생성하고 싶을 때 사용한다.

Example

  • updateStrategy에서 rollingUpdate와 onDelete
    • rollingUpdate : 템플릿을 변경했을 때 바로 변경 사항을 반영한다.
    • onDelete : 템플릿을 변경했을 때 바로 적용되지 않으며 변경된 템플릿을 적용하기 위해서 DaemonSet로 실행한 Pod를 직접 지워야 해당 Node로 새로운 Template 버전의 pod가 실행
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  # namespace는 논리적으로 나눈 공간을 의미하며
  # kube-system에 해당 Pod를 배치하겠다는 의미이다.
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  # matchLabels : = or != 만 확인함
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  # update 전략 : RollingUpdate
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      containers:
      - name: fluentd-elasticsearch
        image: fluent/fluentd-kubernetes-daemonset:elasticsearch
        # 환경 변수 설정
        env:
        - name: testenv
          value: value
        # memory, cpu에 제한(Limit)을 걸어두었다.
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
  • Check

    확인해보니 fluentd-elasticsearch가 Master Node에는 올라오지 않았고 Worker Node에만 올라오는 것을 확인할 수 있었다.

    ⇒ kubectl get ds <<ds_name>> -o yaml 이런 식으로 default로 설정되어 있는 daemonset들과 내가 적용하려는 daemonset의 차이점이 무엇인지 확인하는 방법으로 toleration을 설정해줘야함을 확인하였다.

root@instance-1:~/kubernetes-sample/controller# kubectl get ds -n kube-system
NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
calico-node             5         5         5       5            5           <none>                   5d23h
**fluentd-elasticsearch   2         2         1       2            1           <none>                   59s**
kube-proxy              5         5         5       5            5           kubernetes.io/os=linux   5d23h
nodelocaldns            5         5         5       5            5           <none>                   5d23h

# taint가 걸려있는지 확인
root@instance-1:~/kubernetes-sample/controller# kubectl describe nodes instance-1 | grep -i taint
Taints:             node-role.kubernetes.io/master:NoSchedule
  • daemonset의 pod들에 tolerations 적용

## 정상적으로 모든 Node에 daemonset이 뜨는 것을 확인할 수 있다.
root@instance-1:~/kubernetes-sample/controller# kubectl get daemonset -n kube-system
NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
calico-node             5         5         5       5            5           <none>                   5d23h
fluentd-elasticsearch   5         5         5       5            5           <none>                   3m48s
kube-proxy              5         5         5       5            5           kubernetes.io/os=linux   5d23h
nodelocaldns            5         5         5       5            5           <none>                   5d23h

StatefulSet

  • Stateful (상태가 있는)한 App을 관리하는데 사용한다.

  • 파드들의 순서 및 고유성을 보장하는 API 오브젝트이다

    ( 각 파드의 독자성을 유지 )

    ⇒ Volume을 사용해서 특정 데이터를 저장한 후 Pod를 재시작했을 때 해당 데이터를 유지한다. 여러 개의 Pod 사이에 순서를 지정해서 실행되도록 할 수도 있다.

  • StatefulSet은 Pod를 각각 따로 관리해줘야 한다는 번거로움이 생길 수 있다. 또한 Service는 Headless Service로 생성해주어야 한다.

    ⇒ StatefulSet의 Pod Network ID를 유지하기 위해서이다.

    ⇒ Headless 서비스에는 IP가 할당되지 않지만 Domain Name을 사용하여 각 파드에 접근 가능

**When to use StatefulSet ?

1 안정적이고 고유한 네트워크 식별자가 필요한 경우
2 안정적이고 지속적인 스토리지를 사용해야 하는 경우
3 질서 정연한 포드의 배치와 확장을 원하는 경우
4 포드의 자동 롤링업데이트를 사용하기 원하는 경우**


Example

# Headless 서비스 정의
apiVersion: v1
kind: Service
metadata:
  name: nginx-statefulset-service
  labels:
    app: nginx-statefulset-service
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx-statefulset-service
---
# 스테이트풀셋 정의
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  # 셀렉터
  selector:
    matchLabels:
      app: nginx-statefulset
  # 설정할 서비스를 정의
  # 쿠버네티스 클러스터 안에서 사용하는 도메인을 생성할 수 있다.
  serviceName: "nginx-statefulset-service"
  replicas: 3 
  template:
    metadata:
      labels:
        app: nginx-statefulset
    spec:
      # 그레이스풀의 대기 시간 설정 ( 10초 )
      # 실행 중인 프로세스를 바로 종료하지 않고 하던 작업 마무리 후 종료
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx-statefulset
        image: nginx
        ports:
        - containerPort: 80
          name: web
  • Check

    파드가 실행될 때는 작은 숫자부터 순서대로 실행 (0, 1, 2)되며 삭제될 때는 반대로 (2, 1, 0) 삭제된다.

root@instance-1:~/kubernetes-sample/controller# kubectl apply -f statefulset.yaml 
service/nginx-statefulset-service created
statefulset.apps/web created

root@instance-1:~/kubernetes-sample/controller# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
kubernetes-simple-pod    1/1     Running   0          146m
nginx-replicaset-5n7wg   1/1     Running   0          115m
web-0                    1/1     Running   0          9s
web-1                    1/1     Running   0          7s
web-2                    1/1     Running   0          4s

root@instance-1:~/kubernetes-sample/controller# kubectl get statefulsets.apps
NAME   READY   AGE
web    3/3     19s

파드를 순서 없이 실행 or 종료하기

  • Parallel : 파드들이 순서 없이 병렬로 실행되거나 종료되도록 할 수 있다.
root@instance-1:~/kubernetes-sample/controller# kubectl delete -f statefulset.yaml
service "nginx-statefulset-service" deleted
statefulset.apps "web" deleted

root@instance-1:~/kubernetes-sample/controller# kubectl get pods -w
NAME                     READY   STATUS        RESTARTS   AGE
kubernetes-simple-pod    1/1     Running       0          150m
nginx-replicaset-5n7wg   1/1     Running       0          119m
web-0                    0/1     Terminating   0          36s
web-1                    0/1     Terminating   0          36s
web-0                    0/1     Terminating   0          44s
web-0                    0/1     Terminating   0          44s
web-1                    0/1     Terminating   0          44s
web-1                    0/1     Terminating   0          44s

⇒ 한꺼번에 생성되고 삭제됨을 확인할 수 있다.

Job

  • 실행된 후 종료해야 하는 성격의 작업을 실행해야 할 때 사용하는 컨트롤러

  • 잡에서 하나 이상의 파드를 생성하고 지정된 수의 파드가 성공적으로 종료되도록 한다.

    ( Job Object를 하나 생성 후 Pod를 안정적으로 실행하고 완료하는 것 )

  • Job은 여러 Pod를 병렬(Parellel)로 실행시킬 수 있다.

Example

# 배치 작업을 실행하는 v1 버전의 API
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
        - name: pi
          image: perl
          # Perl 명령어로 원주율 계산
          command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      # 파드가 항상 성공으로 끝나게 한다.
      # Never 외에 OnFailure도 가능
      # OnFailure : 컨테이너가 정상 종료되지 않을 때 컨테이너를 다시 시작하도록 한다.
      restartPolicy: Never
  # Job 실행이 실패하였을 때 최대 몇번까지 재시작할 것인지 설정
  # Default : 6
  backoffLimit: 4
  • Check
root@instance-1:~/kubernetes-sample/controller# kubectl apply -f job.yaml
job.batch/pi created

root@instance-1:~/kubernetes-sample/controller# kubectl describe job pi
Name:           pi
Namespace:      default
Selector:       controller-uid=63eeab9f-6614-476c-8421-bbb383d2c135
Labels:         controller-uid=63eeab9f-6614-476c-8421-bbb383d2c135
                job-name=pi
Annotations:    <none>
Parallelism:    1
Completions:    1
Start Time:     Sat, 13 Feb 2021 11:42:59 +0000
Pods Statuses:  1 Running / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  controller-uid=63eeab9f-6614-476c-8421-bbb383d2c135
           job-name=pi
  Containers:
   pi:
    Image:      perl
    Port:       <none>
    Host Port:  <none>
    Command:
      perl
      -Mbignum=bpi
      -wle
      print bpi(2000)
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  9s    job-controller  Created pod: pi-lk2qs

root@instance-1:~/kubernetes-sample/controller# kubectl logs pi-lk2qs
3.1415926

Job 병렬성 관리하기

잡 병렬성 : 잡 하나가 몇 개의 파드를 동시에 실행할지를 결정하는 것
⇒ .spec.parallelism 필드에서 설정할 수 있다.
⇒ Default는 1이며 0으로 설정할 시 Job을 정지시킬 수 있다.

Job의 종류

  • 단일 잡
    • 파드 하나만 실행된다. 파드가 정상적으로 실행 종료되면 잡 실행을 완료한다.
    • .spec.completions와 .spec.parallelism 필드 설정 X (각각 default가 1이다.)
  • 병렬 잡 (완료 개수 O)
    • .spec.completions 필드 값으로 양수 설정
    • .spec.parallelism은 설정 X
  • 병렬 잡 (워크 큐 O)
    • .spec.parallelism 필드 값으로 양수 설정
    • .spec.completions는 설정 X

비정상적으로 실행 종료된 파드 관리하기

  • 파드가 비정상적으로 종료되는 이유는 여러가지가 있을 수 있다. Memory 사용량이 초과한다거나 비정상 종료 코드 표시 등이 있다.
  • 이 때 .spec.template.spec.restartPolicy 필드 값을 OnFailure로 설정할 시 Pod는 실행 중이던 Node에서 컨테이너를 재시작한다.
  • 반대로, Never로 설정하여 재시작을 막을 수도 있다. ( 파드를 실행 중이던 노드가 장애나 업그레이드 등의 이유로 정지...)

Job 종료 & 정리

  • 특정 시간을 지정해 잡 실행을 종료 : .spec.activeDeadlineSeconds

    ⇒ 지정된 시간에 해당 잡 실행을 강제로 끝내면서 모든 파드 실행도 종료한다.

    ⇒ Job의 종료 이유가 DeadlineExceeded로 표시된다.

  • kubectl delete job <<Job_Name>>

Job Pattern

  • 모든 작업을 관리하는 Job 하나를 사용하는 것이 좋다

    ⇒ Pod를 생성하는 Overhead가 크기 때문

  • 작업 개수만큼의 Pod를 생성하는 것보다 Pod 하나가 여러 개의 작업을 처리하는 것이 좋다.

    ⇒ 이 또한 Overhead 때문

  • Work Quere를 사용한다면 Kafka나 RabbitMQ 같은 Queue 서비스로 Work Querue를 구현하도록 기존 프로그램이나 컨테이너를 수정해야 한다.

    ⇒ 워크 큐를 사용하지 않으면 그냥 기본 설정 그대로 컨테이너를 사용하므로 비효율적이다.ㄹ

CronJob

  • Job을 시간 기준으로 관리하도록 생성한다.
  • 하나의 크론잡 Object는 Crontab 파일의 한 줄과 같다.
  • 백업 실행 또는 이메일 전송과 같은 정기적으로 반복적인 작업을 만드는데 유용하다. 또한 크론잡은 클러스터가 유휴 상태일 때 잡을 스케줄링하는 것과 같이 특정 시간 동안의 개별 작읍을 스케줄할 수 있다.

Example

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  # 매 1분마다 실행하도록 설정
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: hello
              image: busybox
              imagePullPolicy: IfNotPresent
              args:
                - /bin/sh
                - -c
                - date; echo Hello from the kubernetes cluster
          restartPolicy: OnFailure
  • Check

    SCHEDULE : 스케줄링한 설정

    SUSPEND : 이 크론잡이 정지되었는지 나타낸다.

root@instance-1:~/kubernetes-sample/controller# kubectl apply -f cronjob.yaml 
cronjob.batch/hello created

# 현재 실행중인 크론잡
root@instance-1:~/kubernetes-sample/controller# kubectl get cronjobs
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        <none>          15s

# 실행된 잡들
root@instance-1:~/kubernetes-sample/controller# kubectl get jobs
NAME               COMPLETIONS   DURATION   AGE
hello-1613217480   1/1           3s         2m17s
hello-1613217540   1/1           3s         77s
hello-1613217600   1/1           2s         16s
pi                 1/1           34s        17m

## 크론잡 삭제
root@instance-1:~/kubernetes-sample/controller# kubectl delete cronjobs.batch hello
cronjob.batch "hello" deleted

Cronjob 설정

  • .spec.startingDeadlineSeconds

    • 해당 필드는 지정된 시간에 크론잡이 실행되지 못했을 때 필드 값으로 설정한 시간까지 지나면 크론잡이 실행되지 않도록 해준다.
      ⇒ 설정 X 일시 시간이 좀 지나더라도 Job이 실행된다.
  • .spec.concurrencyPolicy

    • Cronjob이 실행하는 Job의 동시성을 관리한다.
    • Default는 Allow이며 Cronjob이 여러 개의 Job을 동시에 실행할 수 있도록 한다.
    • Forbid로 설정할 시 Job을 동시에 실행하지 않도록 한다.
    • Replace로 설정할 시 이전에 실행했던 Job이 실행 중인 상태에서 새로운 Job을 실행할 시간일 때 이전에 실행중이던 Job을 새로운 Job으로 대체한다.

Example

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello-concurrency
spec:
  # 매 시간 1분마다 Job 실행
  schedule: "*/1 * * * *"
  # 600초로 설정
  startingDeadlineSeconds: 600
  # Job을 동시에 실행시키지 않음
  # 처음에 실행했던 Job이 끝나야 다음 Job이 실행된다.
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster; sleep 6000
          restartPolicy: OnFailure
  • Check
  • kubectl get pods로 Pod 확인할 시 n분동안 파드가 1개만 있음 ⇒ Forbid로 설정했기 때문
root@instance-1:~/kubernetes-sample/controller# kubectl get pods
NAME                                 READY   STATUS      RESTARTS   AGE
hello-concurrency-1613219580-xcslg   1/1     Running     0          85s
kubernetes-simple-pod                1/1     Running     0          5h7m
  • Forbid → Allow로 수정
    새로운 Pod 실행
root@instance-1:~/kubernetes-sample/controller# kubectl get pods
NAME                                 READY   STATUS      RESTARTS   AGE
hello-concurrency-1613219580-xcslg   1/1     Running     0          2m4s
hello-concurrency-1613219700-8gvkl   1/1     Running     0          4s
kubernetes-simple-pod                1/1     Running     0          5h7m
  • Allow → Replace로 수정
    실행했던 Pod들의 Statue가 Terminating으로 바뀌고 종료됨을 확인할 수 있다.
NAME                                 READY   STATUS              RESTARTS   AGE
hello-concurrency-1613219580-xcslg   1/1     Terminating         0          4m2s
hello-concurrency-1613219700-8gvkl   1/1     Terminating         0          2m2s
hello-concurrency-1613219760-892jd   1/1     Terminating         0          61s
hello-concurrency-1613219820-gzgv2   0/1     ContainerCreating   0          1s
  • .spec.suspend 필드 값 false → true로 설정
    더 이상 크론잡이 실행되지 않고 멈추게 된다.
root@instance-1:~/kubernetes-sample/controller# kubectl get cronjobs.batch,pods
NAME                              SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/hello-concurrency   */1 * * * *   True      1        108s            8m55s
NAME                                     READY   STATUS      RESTARTS   AGE
profile
Cloud Infra Engineer & interested in python, IaC, k8s

1개의 댓글

comment-user-thumbnail
2021년 2월 13일

레플리카
우리 아이는 우리가 집에 있을 때 그의 곰을 카트 앞좌석에 앉힌다.
Posted on 2021년 2월 1일
우리 아이는 우리가 집에 있을 때 곰을 카트 앞좌석에 태운다. 그는 모든 사람들에게 이제 곰이 카트에 탄다고 알려준다. 우리가 쇼핑할 때 사용했던 것처럼. 그는 심지어 여러분의 집 주변을 걸어다니기도 하고, 장난감을 고르고, 카트에 넣기도 한다.
레플리카 순위

레플리카

답글 달기