본문 바로가기

Infrastructure/Kubernetes

[워크로드 리소스] 디플로이먼트 업데이트와 롤백

디플로이먼트 업데이트와 롤백

쿠버네티스 공식문서를 확인하며 디플로이먼트의 업데이트와 롤백에 대해서 기억해야 하는 부분을 기록한다.

  • 디플로이먼트(Deployment)는 파드와 레플리카셋(ReplicaSet)에 대한 선언적 업데이트를 제공한다.
  • 디플로이먼트에서 “의도하는 상태”를 설명하고, 디플로이먼트 컨트롤러(Controller)는 현재 상태에서 의도하는 상태로 비율을 조정하며 변경한다.
  • 새 레플리카셋을 생성하는 디플로이먼트를 정의하거나 기존 디플로이먼트를 제거하고, 모든 리소스를 새 디플로이먼트에 적용할 수 있다.
  • 디플로이먼트가 소유하는 레플리카셋은 관리하지 말아야 한다.

유스케이스

  • 아래는 디플로이먼트의 일반적인 유스케이스다.
    • 레플리카셋을 롤아웃 할 디플로이먼트 생성. 레플리카셋은 백그라운드에서 파드를 생성하고 롤아웃 상태를 확인하여 성공 여부를 확인한다.
    • 디플로이먼트의 PodTemplateSpec을 업데이트해서 파드의 새로운 상태를 선언한다. 새 레플리카셋이 생성되면, 디플로이먼트는 파드를 기존 레플리카셋에서 새로운 레플리카셋으로 속도를 제어하며 이동하는 것을 관리한다. 각각의 새로운 레플리카셋은 디플로이먼트의 수정 버전에 따라 업데이트한다.
    • 디플로이먼트의 현재 상태가 안정적이지 않은 경우 디플로이먼트의 이전 버전으로 롤백한다. 각 롤백은 디플로이먼트의 수정 버전에 따라 업데이트한다.
    • 더 많은 요청을 처리하기 위해 디플로이먼트의 스케일 업한다.
    • 디플로이먼트 롤아웃 일시 중지로 PodTemplateSpec에 여러 수정 사항을 적용하고, 재개하여 새로운 롤아웃을 시작한다.
    • 롤아웃이 막혀있는지를 나타내는 디플로이먼트 상태를 이용한다.
    • 더 이상 필요없는 이전 레플리카셋을 정리한다.

[정리]

디플로이먼트는 레플리카 셋을 롤아웃 하거나 레플리카셋의 업데이트를 관리한다. 디플로이먼트의 버전이 안정적이지 않은 경우 이전 버전으로 롤백될 수 있으며 더 많은 요청을 처리하기 위해 스케일 업될 수 있다.


디플로이먼트 생성

  • 아래는 3개의 nginx 파드를 불러오기 위한 레플리카셋을 생성하는 디플로이먼트 예시이다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
  • .metadata.name 필드에 따라 nginx-deployment 이름으로 디플로이먼트가 생성된다.

  • .spec.replicas 필드에 따라 디플로이먼트는 3개의 레플리카 파드를 생성한다.

  • .spec.selector 필드는 디플로이먼트가 관리할 파드를 찾는 방법을 정의한다. 파드 템플릿에 정의된 레이블인 app: nginx을 선택한다. 파드 템플릿 자체의 규칙이 만족된다면 보다 정교한 선택 규칙의 적용이 가능하다.

  • .spec.selector.matchLabels 필드는 {key,value} 쌍으로 매핑되어 있다. matchLabels에 매핑된 단일 {key,value}은 matchExpressions의 요소에 해당하며, key 필드는 “key”에 그리고 operator는 “In”에 대응되며 value 배열은 “value”만 포함한다. 매칭을 위해서는 matchLabelsmatchExpressions의 모든 요건이 충족되어야 한다.

  • template 필드에는 아래의 필드가 포함되어 있다.

    • 파드는 .metadata.labels 필드를 사용해서 app: nginx라는 레이블을 붙인다.
    • 파드 템플릿의 사양 또는 .template.spec 필드는 파드가 도커 허브의 nginx 1.14.2 버전 이미지를 실행하는 nginx 컨테이너 1개를 실행하는 것을 나타낸다.
    • 컨테이너 1개를 생성하고, .spec.template.spec.containers[0].name 필드를 사용해서 nginx 이름을 붙인다.
  • 시작하기 전에, 쿠버네티스 클러스터가 실행 중인지 확인한다. 위의 yaml 파일을 사용하여 디플로이먼트를 생성하려면 아래의 단계를 따른다.

    1. 아래의 커맨드를 실행하여 디플로이먼트를 생성한다.

      kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
    2. kubectl get deployments을 실행해서 디플로이먼트가 생성되었는지 확인한다. 만약 디플로이먼트가 실행 중이라면 아래와 유사하게 출력된다.

      NAME               READY   UP-TO-DATE   AVAILABLE   AGE
      nginx-deployment   0/3     0            0           1s
    • NAME: 네임스페이스에 있는 디플로이먼트 이름 목록.
    • READY: 사용자가 사용할 수 있는 애플리케이션의 레플리카의 수를 표시한다. ready/desired 패턴을 따른다.
    • UP-TO-DATE: 의도한 상태를 얻기 위해 업데이트된 레플리카의 수를 표시한다.
    • AVAILABLE: 사용자가 사용할 수 있는 애플리케이션 레플리카의 수를 표시한다.
    • AGE: 애플리케이션의 실행된 시간을 표시한다.
    1. 디플로이먼트의 롤아웃 상태를 보려면, kubectl rollout status deployment/nginx-deployment를 실행하면 아래와 유사하게 출력되며 레플리카가 업데이트 되고 있음을 알 수 있다.

      Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
      deployment "nginx-deployment" successfully rolled out
    2. 잠시 후 다시 kubectl get deployments를 실행하여 디플로이먼트의 상태를 확인해보면 3개의 디플로이먼트가 준비(Ready)된 것을 확인할 수 있다.

      NAME               READY   UP-TO-DATE   AVAILABLE   AGE
      nginx-deployment   3/3     3            3           18s
    3. 디플로이먼트로 생성된 레플리카셋(rs)을 보려면, kubectl get rs를 실행하면 아래와 유사하게 출력된다.

      NAME                          DESIRED   CURRENT   READY   AGE
      nginx-deployment-75675f5897   3         3         3       18s
    • NAME: 네임스페이스에 있는 레플리카셋 이름의 목록이다.
    • DESIRED: 디플로이먼트 생성 시 정의된 의도된 애플리케이션 레플리카의 수를 표시하며 이것이 “의도한 상태”이다.
    • CURRENT: 현재 실행 중인 레플리카의 수를 표시한다.
    • READY: 사용자가 사용할 수 있는 애플리케이션의 레플리카의 수를 표시한다.
    • AGE: 애플리케이션이 실행된 시간을 표시한다.
    • 레플리카셋의 이름은 항상 [DEPLOYMENT-NAME]-[RANDOM-STRING] 형식이며, 문자열은 무작위로 생성되고, pod-template-hash를 시드(seed)로 사용한다.
    1. 각 파드에 자동으로 생성된 레이블을 보려면, kubectl get pods --show-labels를 실행한다.

      NAME                                READY     STATUS    RESTARTS   AGE       LABELS
      nginx-deployment-75675f5897-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
      nginx-deployment-75675f5897-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
      nginx-deployment-75675f5897-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
    • 만들어진 레플리카셋은 실행 중인 3개의 nginx파드를 보장한다.
  • 디플로이먼트에는 파드 템플릿 레이블과 적절한 셀렉터를 반드시 명시해야 한다.

  • 레이블 또는 셀렉터는 다른 컨트롤러와 겹치지 않아야 한다. 쿠버네티스는 겹치는 것을 막지 않으면, 다중 컨트롤러가 겹치는 셀렉터를 가지는 경우 해당 컨트롤러의 충돌 또는 예기치 않은 동작을 야기할 수 있다.

Pod-template-hash 레이블

  • 변경되어서는 안되는 레이블이다.
  • pod-template-hash 레이블은 디플로이먼트 컨트롤러에 의해서 디플로이먼트가 생성 또는 채택한 모든 레플리카셋에 추가된다.
  • 이 레이블은 디플로이먼트의 자식 레플리카셋이 겹치지 않도록 보장하며 레플리카셋의 PodTemplate을 해싱하고, 해시 결과를 레플리카셋 셀렉터, 파드 템플릿 레이블 및 레플리카셋이 가질 수 있는 기존의 모든 파드에 레이블 값으로 추가해서 사용하도록 생성한다.

[정리]

디플로이먼트를 생성하여 레플리카셋을 관리할 수 있다. 디플로이먼트의 파드 템플릿 레이블과 적절한 셀렉터를 반드시 명시해야 하며 다른 컨트롤러와는 겹치지 않아야 한다.

pod-template-hash 레이블은 변경되어서는 안되며 해당 디플로이먼트 컨트롤러에 의해 생성되거나 채택된 모든 레플리카셋에 추가된다.


디플로이먼트 업데이트

  • 디플로이먼트의 파드 템플릿이 변경된 경우에만 디플로이먼트의 롤아웃이 트리거된다. 대표적으로 템플릿의 레이블이나 컨테이너 이미지가 업데이트된 경우이다.
  • 디플로이먼트의 스케일링과 같은 다른 업데이트는 롤아웃을 트리거하지 말아야 한다.
  • 아래의 단계에 따라서 디플로이먼트를 업데이트한다.
  1. nginx:1.14.2 이미지 대신 nginx:1.16.1 이미지를 사용하도록 nginx 파드를 업데이트한다.
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
또는
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
  • 아래와 같이 출력된다.
deployment.apps/nginx-deployment image updated
  • 다른 대안으로 디플로이먼트를 edit해서 .spec.template.spec.containers[0].imagenginx:1.14.2에서 nginx:1.16.1로 변경한다.
kubectl edit deployment/nginx-deployment
  • 아래와 같이 출력된다.
deployment.apps/nginx-deployment edited
  1. 아래의 커멘드를 입력하여 롤아웃 상태를 확인할 수 있다.
kubectl rollout status deployment/nginx-deployment 
  • 아래와 같이 출력된다.
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
또는
deployment "nginx-deployment" successfully rolled out
  • 업데이트 된 디플로이먼트에 대한 자세한 정보를 조회할 수 있다.

    • 롤아웃이 성공한 상태에서 kubectl get deployments 커맨드를 실행하면 아래와 같이 롤아웃 상태를 확인할 수 있다.

      NAME               READY   UP-TO-DATE   AVAILABLE   AGE
      nginx-deployment   3/3     3            3           36s
    • kubectl get rs를 실행해서 디플로이먼트가 새 레플리카셋을 생성해서 파드를 업데이트 했는지 확인할 수 있고, 새 레플리카셋을 최대 3개의 레플리카로 스케일 업, 이전 레플리카셋을 0개의 레플리카로 스케일 다운한다.

      NAME                          DESIRED   CURRENT   READY   AGE
      nginx-deployment-1564180365   3         3         3       6s
      nginx-deployment-2035384211   0         0         0       36s
    • kubectl get pods를 실행하면 아래와 같이 새 파드만 표시된다.

      NAME                                READY     STATUS    RESTARTS   AGE
      nginx-deployment-1564180365-khku8   1/1       Running   0          14s
      nginx-deployment-1564180365-nacti   1/1       Running   0          14s
      nginx-deployment-1564180365-z9gth   1/1       Running   0          14s
    • 추후 파드를 업데이트 하려면 디플로이먼트의 파드 템플릿만 다시 업데이트하면 된다.

    • 디플로이먼트는 업데이트되는 동안 일정한 수의 파드만 중단되도록 보장한다. 적어도 의도한 파드 수의 75% 이상이 동작하도록 보장한다.

    • 또한, 디플로이먼트는 의도한 파드 수 보다 더 많이 생성되는 파드의 수를 제한한다. 기본적으로, 의도한 파드의 수 기준 최대 125%까지만 추가 파드가 동작할 수 있도록 제한한다.

    • 위의 디플로이먼트를 자세히 살펴보면 먼저 새로운 파드를 생성한 다음, 이전의 파드를 삭제하고 또 다른 새로운 파드를 생성하는 것을 확인할 수 있다.

    • 충분한 수의 새로운 파드가 나올 때까지 이전 파드를 죽이지 않으면, 충분한 수의 이전 파드들이 죽기 전까지 새로운 파드를 만들지 않는다.

    • 디플로이먼트의 레플리카 크기가 4인 경우, 파드 숫자는 3개에서 5개 사이이다.

  • kubectl describe deployments 커맨드를 실행하여 디플로이먼트의 세부 정보를 가져올 수 있으며 아래와 같은 출력을 확인할 수 있다.

Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Thu, 30 Nov 2017 10:56:25 +0000
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision=2
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
   Containers:
    nginx:
      Image:        nginx:1.16.1
      Port:         80/TCP
      Environment:  <none>
      Mounts:       <none>
    Volumes:        <none>
  Conditions:
    Type           Status  Reason
    ----           ------  ------
    Available      True    MinimumReplicasAvailable
    Progressing    True    NewReplicaSetAvailable
  OldReplicaSets:  <none>
  NewReplicaSet:   nginx-deployment-1564180365 (3/3 replicas created)
  Events:
    Type    Reason             Age   From                   Message
    ----    ------             ----  ----                   -------
    Normal  ScalingReplicaSet  2m    deployment-controller  Scaled up replica set nginx-deployment-2035384211 to 3
    Normal  ScalingReplicaSet  24s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 1
    Normal  ScalingReplicaSet  22s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 2
    Normal  ScalingReplicaSet  22s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 2
    Normal  ScalingReplicaSet  19s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 1
    Normal  ScalingReplicaSet  19s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 3
    Normal  ScalingReplicaSet  14s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 0
  • 처음 디플로이먼트를 생성했을 때, 디플로이먼트가 레플리카셋(nginx-deployment-2035384211)을 생성하고 3개의 레플리카로 직접 스케일 업한 것을 확인할 수 있다.
  • 디플로이먼트를 업데이트하면, 새 레플리카셋(nginx-deployment-1564180365)을 생성하고, 1개로 스케일 업한 다음 모두 실행될 때까지 대기한다.
  • 그 뒤 이전 레플리카셋을 2개로 스케일 다운하고 새 레플리카셋을 2개로 스케일 업하여 모든 시점에 대해 최소 3개 / 최대 3개의 파드가 존재하도록 하였다.
  • 이후 지속해서 같은 롤링 업데이트 정책으로 새 레플리카 셋은 스케일 다운한다.
  • 새로운 레플리카셋 3개의 사용 가능한 레플리카 구성이 되며, 이전 레플리카셋은 0개로 스케일 다운된다.
  • 쿠버네티스가 availableReplicas 수를 계산할 때 종료 중인(terminating) 파드는 포함하지 않으며, 이 수는 replicas - maxUnavailablereplicas + maxSurge 사이에 존재한다. 그 결과, 롤아웃 중에는 파드의 수가 예상보다 많을 수 있으며, 종료 중인 파드의 terminationGracePeriodSeconds가 만료될 때까지는 디플로이먼트가 소비하는 총 리소스가 replicas + maxSurge 이상일 수 있다.

[정리]

파드 템플릿이 변경된 경우에 디플로이먼트의 롤아웃이 트리거되며 대표적으로 레이블이나 컨테이너 이미지가 변경된 경우가 있다. 스케일링과 같은 다른 업데이트에는 롤아웃을 트리거하지 말아야 한다. 디플로이먼트는 업데이트되는 동안 일정 수의 파드만 중단되도록 보장하며 일정 수는 의도한 파드 수의 75%이상이 기본 값이다. 또한 의도한 파드 수 보다 더 많이 생성되는 파드의 수를 제한하며 일정 수는 의도한 파드 수의 125%이다.


롤오버(인-플라이트 다중 업데이트)

  • 디플로이먼트 컨트롤러는 각 시간마다 새로운 디플로이먼트에서 레플리카셋이 의도한 파드를 생성하고 띄우는 것을 주시한다.
  • 만약 디플로이먼트가 업데이트되면, 기존 레플리카셋에서 .spec.selector 레이블과 일치하는 파드를 컨트롤 하지만, 템플릿과 .spec.template이 불일치하면 스케일 다운이 된다. 결국 레플리카셋은 .spec.replicas로 스케일되고, 기존의 모든 레플리카셋은 0개로 스케일된다.
  • 기존 롤아웃이 진행되는 중에 디플로이먼트를 업데이트하는 경우 디플로이먼트가 업데이트에 따라 새 레플리카셋을 생성하고, 스케일 업하기 시작한다. 그리고 이전에 스케일 업 하던 레플리카셋에 롤오버 한다. 이것은 기본 레플리카셋 목록에 추가하고 스케일 다운하게 된다.
  • 디플로이먼트로 nginx:1.14.2 레플리카를 5개 생성한다. nginx:1.14.2 레플리카 3개가 생성되었을 때 디플로이먼트를 업데이트해서 nginx:1.16.1 레플리카 5개를 생성하도록 업데이트를 한다고 가정한다. 디플로이먼트는 즉시 생성된 3개의 nginx:1.14.2 파드 3개를 죽이기 시작하고 nginx:1.16.1 파드를 생성하기 시작한다. 이러한 과정은 nginx:1.14.2 레플리카 5개가 생성되는 것을 기다리지 않는다.

[정리]

디플로이먼트 컨트롤러는 각 시간마다 새로운 디플로이먼트가 업데이트되면, 기존 레플리카셋에서 .spec.slector 레이블과 일치하는 파드를 컨트롤 하지만 .spec.template이 불일치하면 스케일 다운되어 기존의 모든 레플리카셋은 0개로 스케일된다.

롤오버 과정이 진행되고 있는 중에 디플로이먼트가 업데이트된다면 기존의 업데이트의 완료가 보장되지 않는다. 여기서 보장되지 않는다는 의미는 .spec.replicas에 정의한 수의 레플리카셋이 생성될 때까지 기다렸다가 다음 업데이트가 진행되지 않는다는 의미이다.


레이블 셀렉터 업데이트

  • 일반적으로 레이블 셀렉터를 업데이트 하는 것을 권장하지 않으며 셀렉터를 미리 계획하는 것을 권장한다.
  • 어떤 경우든 레이블 셀렉터의 업데이트를 해야 하는 경우 매우 주의하고, 모든 영향을 파악했는지 확인해야 한다.
  • API 버전 apps/v1 에서 디플로이먼트의 레이블 셀렉터는 생성 이후에는 변경할 수 없다.
  • 셀렉터 추가 시 디플로이먼트의 사양에 있는 파드 템플릿 레이블도 새 레이블로 업데이트해야 하며 그렇지 않은 경우 유효성 검사 오류가 반환된다. 이러한 변경은 겹치지 않는 변경으로 새 셀렉터가 이전 셀렉터로 만든 레플리카셋과 파드를 선택하지 않게 되고, 그 결과로 모든 기존 레플리카셋은 고아가 되며, 새로운 레플리카셋을 생성하게 된다.
  • 셀렉터 업데이트는 기존 셀렉터 키 값을 변경하며, 결과적으로 추가와 동일한 동작을 한다.
  • 셀렉터 삭제는 디플로이먼트 셀렉터의 기존 키를 삭제하며 파드 템플릿 레이블의 변경을 필요로 하지 않는다. 기존 레플리카셋은 고아가 아니며, 새 레플리카셋은 생성되지 않는다. 제거된 레이블은 기존 파드와 레플리카셋에 역시 존재한다는 점을 기억해야 한다.

[정리]

레이블 셀렉터를 업데이트하는 것은 권장되지 않기 때문에 처음에 셀렉터를 설계할 때 주의하여 설계해야 한다. 특정 API 버전에서는 레이블 셀렉터를 변경할 수 없다. 셀렉터를 추가하는 경우 파드 템플릿의 레이블도 새로운 레이블로 업데이트 되어야 하며 그렇지 않으면 기존의 레플리카셋은 고아가 되고, 새로운 레플리카셋이 생성된다.


디플로이먼트 롤백

  • 디플로이먼트가 지속적인 충돌로 안정적이지 않은 경우 디플로이먼트의 롤백을 원할 수 있다.

  • 기본적으로 모든 디플로이먼트의 롤아웃 기록은 시스템에 남아있기 때문에 원할 때 롤백이 가능하다.

  • 디플로이먼트의 수정 버전은 디플로이먼트 롤아웃시 생성되고 이는 디플로이먼트 파드 템플릿(.spec.template)이 변경되는 경우에만 새로운 수정 버전이 생성된다는 것을 의미한다.

  • 디플로이먼트의 스케일링과 같은 다른 업데이트시 디플로이먼트 수정 버전은 생성되지 않으며 수동-스케일링 또는 자동-스케일링을 동시에 수행할 수 있다. 이는 이전 수정버전으로 롤백을 하는 경우에 디플로이먼트 파드 템플릿 부분만 롤백된다는 것을 의미한다.

  • 디플로이먼트를 업데이트하는 동안 이미지 이름을 nginx:1.16.1이 아닌 nginx:1.161로 오타를 입력했다고 가정해본다.

      kubectl set image deployment/nginx-deployment nginx=nginx:1.161
    • 정상적으로 업데이트 되었다는 결과가 출력된다.

      deployment.apps/nginx-deployment image updated
    • 오타로 인해 롤아웃은 고착될 것이고 kubectl rollout status deployment/nginx-deployment커맨드를 입력하여 롤아웃 상태를 확인할 수 있다.

      Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
    • kubectl get rs를 입력하여 레플리카셋의 상태를 확인해보면 nginx-deployment-1564180365nginx-deployment-2035384211은 이전 레플리카 2개이며 nginx-deployment-3066724191은 새로 생성된 레플리카 임을 알 수 있다.

      NAME                          DESIRED   CURRENT   READY   AGE
      nginx-deployment-1564180365   3         3         3       25s
      nginx-deployment-2035384211   0         0         0       36s
      nginx-deployment-3066724191   1         1         0       6s
    • kubectl get pods 커맨드를 실행하여 파드의 상태를 확인해보면 새로운 레플리카셋에 생성된 1개의 파드가 이미지 풀 루프(pull loop)에 고착된 것을 확인할 수 있다.

      NAME                                READY     STATUS             RESTARTS   AGE
      nginx-deployment-1564180365-70iae   1/1       Running            0          25s
      nginx-deployment-1564180365-jbqqo   1/1       Running            0          25s
      nginx-deployment-1564180365-hysrc   1/1       Running            0          25s
      nginx-deployment-3066724191-08mng   0/1       ImagePullBackOff   0          6s
    • 디플로이먼트 컨트롤러가 잘못된 롤아웃을 자동으로 중지하고, 새로운 레플리카셋의 스케일 업을 중지한 상태다. 이는 지정한 롤링 업데이트 파라미터인 maxUnavailable에 따라서 달라지며 기본적으로 25%값으로 설정된다.

    • kubectl describe deployment를 입력하여 디플로이먼트의 상세 정보를 확인할 수 있다.

      Name:           nginx-deployment
      Namespace:      default
      CreationTimestamp:  Tue, 15 Mar 2016 14:48:04 -0700
      Labels:         app=nginx
      Selector:       app=nginx
      Replicas:       3 desired | 1 updated | 4 total | 3 available | 1 unavailable
      StrategyType:       RollingUpdate
      MinReadySeconds:    0
      RollingUpdateStrategy:  25% max unavailable, 25% max surge
      Pod Template:
      Labels:  app=nginx
      Containers:
       nginx:
        Image:        nginx:1.161
        Port:         80/TCP
        Host Port:    0/TCP
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
      Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    ReplicaSetUpdated
      OldReplicaSets:     nginx-deployment-1564180365 (3/3 replicas created)
      NewReplicaSet:      nginx-deployment-3066724191 (1/1 replicas created)
      Events:
      FirstSeen LastSeen    Count   From                    SubObjectPath   Type        Reason              Message
      --------- --------    -----   ----                    -------------   --------    ------              -------
      1m        1m          1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 2
      21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 1
      21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
    • 이러한 문제를 해결하려면 디플로이먼트를 안정적인 이전 수정 버전으로 롤백해야 한다.

디플로이먼트의 롤아웃 기록 확인

  • 아래의 커맨드를 실행하여 디플로이먼트의 수정 사항을 확인한다.
kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION    CHANGE-CAUSE
1           kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml
2           kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.161
  • CHANGE-CAUSE는 수정 생성시 디플로이먼트 주석인 kubernetes.io/change-cause 에서 복사하고 CHANGE-CAUSE 메시지를 지정할 수 있다.
    • 디플로이먼트에 kubectl annotate deployment/nginx-deployment [kubernetes.io/change-cause="image](http://kubernetes.io/change-cause="image) updated to 1.16.1"로 주석을 단다.
    • 수동으로 리소스 매니페스트 편집.
  • 아래의 커맨드를 실행하여 각 수정 버전의 세부 정보를 확인할 수 있다.
kubectl rollout history deployment/nginx-deployment --revision=2
deployments "nginx-deployment" revision 2
  Labels:       app=nginx
          pod-template-hash=1159050644
  Annotations:  kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
  Containers:
   nginx:
    Image:      nginx:1.16.1
    Port:       80/TCP
     QoS Tier:
        cpu:      BestEffort
        memory:   BestEffort
    Environment Variables:      <none>
  No volumes.

이전 수정 버전으로 롤백

  • 아래의 커맨드를 입력하여 현재 롤아웃을 실행 취소하고 이전 수정 버전으로 롤백한다. 만약 원하는 특정 revision이 있다면 --to-revision 태그를 사용하여 지정할 수 있다.

      kubectl rollout undo deployment/nginx-deployment // 직전으로 롤백
      kubectl rollout undo deployment/nginx-deployment --to-revision=2 // 특정 버전으로 롤백
    • 정상적으로 롤백되었다면 아래와 같이 출력된다.

      deployment.apps/nginx-deployment rolled back

참고 자료