[Retry, k8s] 04. 워크로드 API - 디플로이먼트

Date:     Updated:

카테고리:

태그:

[Retry, k8s] 04. 워크로드 API - 디플로이먼트



🔔 디플로이먼트

여러 레플리카셋을 관리하여 롤링 업데이트나 롤백 등을 구현하는 리소스, 디플로이먼트가 레플리카셋을 관리하고 레플리카셋이 파드를 관리하는 관계이다.


📜 디플로이먼트 생성

cat <<EOF > sample-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.16
EOF


🔔 디플로이먼트 업데이트(레플리카셋이 생성되는) 조건

디플로이먼트에서 파드 템플릿(spec.templat)을 변경하면 새로운 레플리카셋이 생성되고 롤링 업데이트가 진행되는데 이 때, 레플리카셋은 파드 템플릿의 해시값(pod-templat-hash)을 레이블(오브젝트를 식별하고 구별하는 메타데이터)로 사용하여 파드를 식별하고 관리한다. 만약 파드 템플릿을 이전 버전으로 되돌리면 해시값도 같아지므로 새로운 레플리카셋을 생성하지 않고 기존의 것을 사용한다.

# 디플로이먼트 확인 - 해시 값은 "845c7cc945"
$ kubectl get all -o wide
NAME                                     READY   STATUS    RESTARTS   AGE   IP          NODE         NOMINATED NODE   READINESS GATES
pod/sample-deployment-845c7cc945-jnt6s   1/1     Running   0          3s    10.44.0.1   k8s-node01   <none>           <none>
pod/sample-deployment-845c7cc945-qq67w   1/1     Running   0          3s    10.36.0.2   k8s-node02   <none>           <none>
pod/sample-deployment-845c7cc945-wq7c9   1/1     Running   0          3s    10.36.0.1   k8s-node02   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   45h   <none>

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS        IMAGES       SELECTOR
deployment.apps/sample-deployment   3/3     3            3           3s    nginx-container   nginx:1.16   app=sample-app

NAME                                           DESIRED   CURRENT   READY   AGE   CONTAINERS        IMAGES       SELECTOR
replicaset.apps/sample-deployment-845c7cc945   3         3         3       3s    nginx-container   nginx:1.16   app=sample-app,pod-template-hash=845c7cc945


# 컨테이너 이미지 업데이트
$ kubectl set image deployment sample-deployment nginx-container=nginx:1.17 --record


# 다시 디플로이먼트 확인 - 해시 값이 "6c8bfc45d6" 변경된 것을 확인할 수 있다.
$ kubectl get all -o wide
NAME                                     READY   STATUS    RESTARTS   AGE   IP          NODE         NOMINATED NODE   READINESS GATES
pod/sample-deployment-6c8bfc45d6-fwnpv   1/1     Running   0          47s   10.44.0.2   k8s-node01   <none>           <none>
pod/sample-deployment-6c8bfc45d6-ngpbb   1/1     Running   0          43s   10.44.0.1   k8s-node01   <none>           <none>
pod/sample-deployment-6c8bfc45d6-p6vhn   1/1     Running   0          46s   10.36.0.3   k8s-node02   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   45h   <none>

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS        IMAGES       SELECTOR
deployment.apps/sample-deployment   3/3     3            3           118s   nginx-container   nginx:1.17   app=sample-app

NAME                                           DESIRED   CURRENT   READY   AGE    CONTAINERS        IMAGES       SELECTOR
replicaset.apps/sample-deployment-6c8bfc45d6   3         3         3       47s    nginx-container   nginx:1.17   app=sample-app,pod-template-hash=6c8bfc45d6
replicaset.apps/sample-deployment-845c7cc945   0         0         0       118s   nginx-container   nginx:1.16   app=sample-app,pod-template-hash=845c7cc945


🔔 변경 롤백

디플로이먼트에서 제공하는 롤백 기능의 실체는 현재 사용 중인 레플리카셋의 전환과 같은 것은데, 디플로이먼트가 생성한 기존 레플리카셋은 레플리카 수가 0인 상태로 남아 있기 때문에 레플리카 수를 변경시켜 다시 사용할 수 있는 상태가 된다.

# 변경 이력 확인
$ kubectl rollout history deployment sample-deployment


# 초기 상태의 디플로이먼트
$ kubectl rollout history deployment sample-deployment --revision 1
deployment.apps/sample-deployment with revision #1
Pod Template:
  Labels:       app=sample-app
        pod-template-hash=845c7cc945
  Containers:
   nginx-container:
    Image:      nginx:1.16
    Port:       <none>
    Host Port:  <none>
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>


# 한 번 업데이트된 후의 디플로이먼트
$ kubectl rollout history deployment sample-deployment --revision 2
deployment.apps/sample-deployment with revision #2
Pod Template:
  Labels:       app=sample-app
        pod-template-hash=6c8bfc45d6
  Containers:
   nginx-container:
    Image:      nginx:1.17
    Port:       <none>
    Host Port:  <none>
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>


# 버전 번호를 지정하여 롤백하는 경우
$ kubectl rollout undo deployment sample-deployment --to-revision 1


# 바로 이전 버전으로 롤백하는 경우 (기본값인 --to-revision 0이 지정되어 바로 이전 버전으로 롤백)
$ kubectl rollout undo deployment sample-deployment


# 롤백한 후 이전 레플리카셋에서 파드가 기동됨
$ kubectl get replicasets
NAME                           DESIRED   CURRENT   READY   AGE
sample-deployment-6c8bfc45d6   0         0         0       8m5s    # 신규 레플리카셋
sample-deployment-845c7cc945   3         3         3       8m10s   # 이전 레플리카셋


🔔 디플로이먼트 변경 일시 중지

디플로이먼트를 업데이트하면 바로 적용 되지만, 만약 안전을 위해 디플로이먼트에 대한 업데이트를 하더라도 바로 적용되지 않는 것을 원하는 경우를 위해 즉시 적용되지 않는 구조도 준비되어 있다. (먼저 kubectl rollout pause를 실행하고 다시 시작할 때는 kubectl rollout resume을 실행한다.)

# 업데이트 일시 정지
$ kubectl rollout pause deployment sample-deployment

# 업데이트 일시 정지 해제
$ kubectl rollout resume deployment sample-deployment
# 업데이트 일시 정지
$ kubectl rollout pause deployment sample-deployment

# pause 상태에서 컨테이너 이미지를 업데이트
$ kubectl set image deployment sample-deployment nginx-container=nginx:1.17

# 업데이트 대기 상태 확인
$ kubectl rollout status deployment sample-deployment
Waiting for deployment "sample-deployment" rollout to finish: 0 out of 3 new replicas have been updated...

# 업데이트 일시 정지 해제하면 업데이트가 진행된다.
$ kubectl rollout resume deployment sample-deployment


🔔 디플로이먼트 업데이트 전략

디플로이먼트를 업데이트 하면 롤링 업데이트가 실행되는데, 이것은 업데이트 전략을 지정하는 “spec.strategy.type”이라는 항목의 기본값이 RollingUpdate으로 되어 있어서 이며, 업데이트 전략은 Recreate와 RollingUpdate가 있다.

(a) Recreate

모든 파드를 한 번 삭제하고 다시 생성하기 때문에 다운타임이 발생하지만, 추가 리소스를 사용하지 않고 전환이 빠른 것이 장점이다.

cat <<EOF > sample-deployment-recreate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment-recreate
spec:
  strategy:
    type: Recreate
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.16
EOF
$ kubectl get all -o wide
NAME                                              READY   STATUS    RESTARTS   AGE   IP          NODE         NOMINATED NODE   READINESS GATES
pod/sample-deployment-recreate-845c7cc945-248kj   1/1     Running   0          19s   10.44.0.2   k8s-node01   <none>           <none>
pod/sample-deployment-recreate-845c7cc945-hmpth   1/1     Running   0          19s   10.44.0.1   k8s-node01   <none>           <none>
pod/sample-deployment-recreate-845c7cc945-z5j5b   1/1     Running   0          19s   10.36.0.1   k8s-node02   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   47h   <none>

NAME                                         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS        IMAGES       SELECTOR
deployment.apps/sample-deployment-recreate   3/3     3            3           19s   nginx-container   nginx:1.16   app=sample-app

NAME                                                    DESIRED   CURRENT   READY   AGE   CONTAINERS        IMAGES       SELECTOR
replicaset.apps/sample-deployment-recreate-845c7cc945   3         3         3       19s   nginx-container   nginx:1.16   app=sample-app,pod-template-hash=845c7cc945


# 컨테이너 이미지 업데이트
$ kubectl set image deployment sample-deployment-recreate nginx-container=nginx:1.17


# 레플리카셋 목록 표시(리소스 상태 변화가 있으면 계속 출력)
$ kubectget replicasets --watch
NAME                                    DESIRED   CURRENT   READY   AGE
sample-deployment-recreate-6c8bfc45d6   0         0         0       108s
sample-deployment-recreate-845c7cc945   3         3         3       3m13s
sample-deployment-recreate-6c8bfc45d6   0         0         0       112s
sample-deployment-recreate-845c7cc945   0         3         3       3m18s
sample-deployment-recreate-845c7cc945   0         3         3       3m18s
sample-deployment-recreate-845c7cc945   0         0         0       3m18s
sample-deployment-recreate-6c8bfc45d6   3         0         0       113s
sample-deployment-recreate-6c8bfc45d6   3         0         0       113s
sample-deployment-recreate-6c8bfc45d6   3         3         0       113s
sample-deployment-recreate-6c8bfc45d6   3         3         1       116s
sample-deployment-recreate-6c8bfc45d6   3         3         2       116s
sample-deployment-recreate-6c8bfc45d6   3         3         3       116s

(b) RollingUpdate

RollingUpdate는 업데이트 중에 동시에 정지 가능한 최대 파드 수(maxUnavailable)와 업데이트 중에 동시에 생성할 수 있는 최대 파드 수(maxSurge)를 설정이 가능하며, 이 설정을 사용하면 추가 리소스를 사용하지 않도록 하거나 많은 리소스를 소비하지 않고 빠르게 전환하는 등 업데이트를 하면서 동작을 제어할 수 있다. (maxUnavailable과 maxSurge 값을 모두 0으로 설정할 수 없다.)

cat <<EOF > sample-deployment-rollingupdate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment-rollingupdate
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.16
EOF
# 컨테이너 이미지 업데이트
$ kubectl set image deployment sample-deployment-rollingupdate nginx-container=nginx:1.17


# 레플리카셋 목록 표시(리소스 상태 변화가 있으면 계속 출력)
# maxUnavailable=0/maxSurge=1 설정의 RollingUpdate에서는 maxSurge 수만큼 추가 레플리카 수를 늘려 파드를 이동시킨다.
$ kubectl get replicasets --watch
NAME                                         DESIRED   CURRENT   READY   AGE
sample-deployment-rollingupdate-845c7cc945   3         0         0       0s
sample-deployment-rollingupdate-845c7cc945   3         0         0       0s
sample-deployment-rollingupdate-845c7cc945   3         3         0       0s
sample-deployment-rollingupdate-845c7cc945   3         3         1       1s
sample-deployment-rollingupdate-845c7cc945   3         3         2       1s
sample-deployment-rollingupdate-845c7cc945   3         3         3       2s
sample-deployment-rollingupdate-6c8bfc45d6   1         0         0       0s
sample-deployment-rollingupdate-6c8bfc45d6   1         0         0       0s
sample-deployment-rollingupdate-6c8bfc45d6   1         1         0       0s
sample-deployment-rollingupdate-6c8bfc45d6   1         1         1       2s
sample-deployment-rollingupdate-845c7cc945   2         3         3       37s
sample-deployment-rollingupdate-6c8bfc45d6   2         1         1       2s
sample-deployment-rollingupdate-845c7cc945   2         3         3       37s
sample-deployment-rollingupdate-6c8bfc45d6   2         1         1       2s
sample-deployment-rollingupdate-845c7cc945   2         2         2       37s
sample-deployment-rollingupdate-6c8bfc45d6   2         2         1       2s
sample-deployment-rollingupdate-6c8bfc45d6   2         2         2       3s
sample-deployment-rollingupdate-845c7cc945   1         2         2       38s
sample-deployment-rollingupdate-6c8bfc45d6   3         2         2       3s
sample-deployment-rollingupdate-845c7cc945   1         2         2       38s
sample-deployment-rollingupdate-6c8bfc45d6   3         2         2       3s
sample-deployment-rollingupdate-845c7cc945   1         1         1       38s
sample-deployment-rollingupdate-6c8bfc45d6   3         3         2       3s
sample-deployment-rollingupdate-6c8bfc45d6   3         3         3       5s
sample-deployment-rollingupdate-845c7cc945   0         1         1       40s
sample-deployment-rollingupdate-845c7cc945   0         1         1       40s
sample-deployment-rollingupdate-845c7cc945   0         0         0       40s


# maxUnavailable=1/maxSurge=0 설정을 변경하고 RollingUpdate를 시작하면 maxUnavailable 수만큼 추가 레플리카 수를 감소시킨 후 파드를 이동시킨다.
$ kubectl get replicasets --watch
NAME                                         DESIRED   CURRENT   READY   AGE
sample-deployment-rollingupdate-845c7cc945   3         0         0       0s
sample-deployment-rollingupdate-845c7cc945   3         0         0       0s
sample-deployment-rollingupdate-845c7cc945   3         3         0       0s
sample-deployment-rollingupdate-845c7cc945   3         3         1       1s
sample-deployment-rollingupdate-845c7cc945   3         3         2       2s
sample-deployment-rollingupdate-845c7cc945   3         3         3       2s
sample-deployment-rollingupdate-6c8bfc45d6   0         0         0       0s
sample-deployment-rollingupdate-6c8bfc45d6   0         0         0       0s
sample-deployment-rollingupdate-845c7cc945   2         3         3       19s
sample-deployment-rollingupdate-6c8bfc45d6   1         0         0       0s
sample-deployment-rollingupdate-845c7cc945   2         3         3       19s
sample-deployment-rollingupdate-845c7cc945   2         2         2       19s
sample-deployment-rollingupdate-6c8bfc45d6   1         0         0       0s
sample-deployment-rollingupdate-6c8bfc45d6   1         1         0       0s
sample-deployment-rollingupdate-6c8bfc45d6   1         1         1       1s
sample-deployment-rollingupdate-845c7cc945   1         2         2       20s
sample-deployment-rollingupdate-6c8bfc45d6   2         1         1       1s
sample-deployment-rollingupdate-845c7cc945   1         2         2       20s
sample-deployment-rollingupdate-845c7cc945   1         1         1       20s
sample-deployment-rollingupdate-6c8bfc45d6   2         1         1       1s
sample-deployment-rollingupdate-6c8bfc45d6   2         2         1       1s
sample-deployment-rollingupdate-6c8bfc45d6   2         2         2       2s
sample-deployment-rollingupdate-845c7cc945   0         1         1       21s
sample-deployment-rollingupdate-6c8bfc45d6   3         2         2       2s
sample-deployment-rollingupdate-845c7cc945   0         1         1       21s
sample-deployment-rollingupdate-6c8bfc45d6   3         2         2       2s
sample-deployment-rollingupdate-845c7cc945   0         0         0       21s
sample-deployment-rollingupdate-6c8bfc45d6   3         3         2       2s
sample-deployment-rollingupdate-6c8bfc45d6   3         3         3       4s


🔔 상세 업데이트 파라미터

(a) minReadySeconds(최소 대기 시간(초))

파드가 Ready 상태가 된 다음부터 디플로이먼트 리소스에서 파드 기동이 완료되었다고 파단(다음 파드의 교체가 가능하다고 판단)하기까지의 최소 시간(초)

(b) revisionHistoryLimit(수정 버전 기록 제한)

디플로이먼트가 유지할 레플리카셋 수, 롤백이 가능한 이력 수

(c) progressDeadlineSeconds(진행 기한 시간(초))

Recreate/RollingUpdate 처리 타임아웃 시간, 타임 아웃 기간이 경과하면 자동으로 롤백

cat <<EOF > sample-deployment-params.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment-params
spec:
  minReadySeconds: 0
  revisionHistoryLimit: 2
  progressDeadlineSeconds: 3600
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.16
EOF


🔔 디플로이먼트 스케일링

디플로이먼트가 관리하는 레플리카셋의 레플리카 수는 레플리카셋과 같은 방법으로 kubectl apply -f 또는 kubectl scale을 사용하여 스케일할 수 있다.

# 레플리카 수를 3에서 4로 변경한 매니페스트를 apply
$ sed -i -e 's|replicas: 3|replicas: 4|' sample-deployment.yaml

$ kubectl apply -f sample-deployment.yaml

# kubectl scale 명령어를 사용한 스케일링
$ kubectl scale deployment sample-deployment --replicas=5


KUBERNETES 카테고리 내 다른 글 보러가기

댓글 남기기