Kubernetes Deployment rollback 옵션 활용 가이드
이 포스트는 Kubernetes 클러스터의 Deployment 리소스의 효과적인 업데이트 및 rollback 을 위한 옵션에 관해 설명합니다. Deployment 리소스에 progressDeadlineSeconds 옵션을 사용하여 rolling-update 진행 중 지정된 시간을 초과하면 업데이트를 실패로 간주하도록 하고, revision history를 통해 이전 버전으로 롤백할 수 있는 revison의 최댓값을 RevisionHistoryLimit을 통해 설정 후 동작을 확인하겠습니다.
목차
1. Deployment rollback을 위한 yaml 구성
2. progressDeadlineSeconds를 통한 Deployment 업데이트 실패 확인
3. RevisionHistoryLimit을 통한 Deployment 업데이트 내역 관리 및 rollback
4. 결론
1. Deployment rollback 을 위한 yaml 구성
Deployment rollback 예제 구성을 위해 다음 yaml 파일을 사용했습니다.
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
progressDeadlineSeconds: 30
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
- progressDeadlineSeconds 값을 30으로 설정하여, 30초 동안 Deployment 업데이트가 성공하지 않을 때 업데이트를 실패로 간주하도록 설정했습니다. (기본값 600)
- revisionHistoryLimit 값을 3으로 설정하여, Deployment의 rollback을 위해 이전 replicasets를 3개로 유지하도록 설정했습니다. (기본값 10)
- replicas는 3으로 설정하여 Pod를 3개로 구성하고, maxSurge 값으로 1로 설정하여 업데이트 중 4개의 Pod가 존재할 수 있도록 구성했습니다. 또한 maxUnavailable 값을 1로 설정하여 업데이트 시 기존 Pod가 1개가 비활성화될 수 있습니다.
yaml 파일을 사용해 Deployment를 배포합니다.
$ kubectl apply -f deployment.yaml -n rollback
deployment.apps/nginx created
$ kubectl get deploy,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 3/3 3 3 8s
NAME READY STATUS RESTARTS AGE
pod/nginx-6cfb64b7c5-8hbjv 1/1 Running 0 8s
pod/nginx-6cfb64b7c5-grcvd 1/1 Running 0 8s
pod/nginx-6cfb64b7c5-zplj8 1/1 Running 0 8s
2. progressDeadlineSeconds를 통한 Deployment 업데이트 실패 확인
1. 배포한 Deployment의 nginx 이미지를 존재하지 않는 태그로 설정하여, 의도적으로 실패하는 업데이트를 수행합니다.
$ kubectl set image deployment/nginx nginx=nginx:nonexistent
deployment.apps/nginx image updated
2. 명령어를 사용하여 Deployment의 업데이트 상태를 확인합니다.
$ kubectl rollout status deployment/nginx
Waiting for deployment "nginx" rollout to finish: 2 out of 3 new replicas have been updated...
# 30초 경과 후
error: deployment "nginx" exceeded its progress deadline
Deployment의 Rolling Update의 종료를 기다리다가, progressDeadlineSeconds 값인 30초를 넘기자 에러 메시지를 출력합니다.
3. 명령어를 사용해 Deployment와 Pod의 상태를 확인합니다.
$ kubectl get deploy,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 2/3 2 2 6m53s
NAME READY STATUS RESTARTS AGE
pod/nginx-57775b8976-cb2tl 0/1 ImagePullBackOff 0 4m47s
pod/nginx-57775b8976-gw7lk 0/1 ImagePullBackOff 0 4m47s
pod/nginx-6cfb64b7c5-8hbjv 1/1 Running 0 6m53s
pod/nginx-6cfb64b7c5-zplj8 1/1 Running 0 6m53s
기존 3개의 Pod에서 maxSurge 값으로 인해 1개의 Pod가 추가로 구성되어 총 4개의 Pod가 존재하고, maxUnavailable 값으로 인해 기존 Pod중 1개의 Pod가 비활성화된 것을 확인할 수 있습니다.
$ kubectl describe deployments nginx
Name: nginx
Namespace: rollback
CreationTimestamp: Mon, 25 Nov 2024 15:54:40 +0900
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 2
Selector: app=nginx
Replicas: 3 desired | 2 updated | 4 total | 2 available | 2 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:nonexistent
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
OldReplicaSets: nginx-6cfb64b7c5 (2/2 replicas created)
NewReplicaSet: nginx-57775b8976 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 5m34s deployment-controller Scaled up replica set nginx-6cfb64b7c5 to 3
Normal ScalingReplicaSet 3m28s deployment-controller Scaled up replica set nginx-57775b8976 to 1
Normal ScalingReplicaSet 3m28s deployment-controller Scaled down replica set nginx-6cfb64b7c5 to 2 from 3
Normal ScalingReplicaSet 3m28s deployment-controller Scaled up replica set nginx-57775b8976 to 2 from 1
Conditions 항목에서 Progressing의 False 상태와, ProgressDeadlineExceeded Reason을 확인할 수 있습니다. 또한 하단에 업데이트로 인해 생성된 Replicasets 정보와, Pod의 스케일링 이벤트를 확인할 수 있습니다.
3. RevisionHistoryLimit을 통한 Deployment 업데이트 내역 관리 및 rollback
Deployment 업데이트 시 Kubernetes는 기존 ReplicaSet을 유지하면서, 업데이트된 설정으로 새로운 ReplicaSet을 생성합니다. Kubernetes는 각 ReplicaSet의 스케일링을 통해 Pod의 개수를 조절하며 롤링 업데이트를 진행합니다.
이 과정에서, revisionHistoryLimit 설정을 통해 이전 ReplicaSet을 몇 개까지 유지할지 지정할 수 있습니다. 이를 통해 필요할 경우 이전 Deployment 설정으로 롤백할 수 있습니다.
1. 명령어를 사용하여 revision 히스토리를 확인합니다.
$ kubectl rollout history deployment/nginx
deployment.apps/nginx
REVISION CHANGE-CAUSE
1 <none>
2 <none>
특정 revision의 정보도 확인할 수 있습니다.
$ kubectl rollout history deployment/nginx --revision=1
deployment.apps/nginx with revision #1
Pod Template:
Labels: app=nginx
pod-template-hash=6cfb64b7c5
Containers:
nginx:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
$ kubectl rollout history deployment/nginx --revision=2
deployment.apps/nginx with revision #2
Pod Template:
Labels: app=nginx
pod-template-hash=57775b8976
Containers:
nginx:
Image: nginx:nonexistent
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
기존 1번 revision에서 이미지가 변경되어 2번 revision으로 기록된 것을 확인할 수 있습니다.
2. 명령어를 사용하여 이전 버전으로 Deployment를 rollback 합니다.
$ kubectl rollout undo deployment/nginx
deployment.apps/nginx rolled back
명령어에 옵션을 추가하여 특정 revision으로 rollback도 가능합니다.
# revision 1으로 rollback
$ kubectl rollout undo deployment/nginx --to-revision=1
3. 명령어를 사용하여 rollback 상태를 확인합니다.
$ kubectl rollout status deployment/nginx
deployment "nginx" successfully rolled out
4. Deployment와 Pod의 상태를 확인합니다.
$ kubectl get deploy,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 3/3 3 3 13m
NAME READY STATUS RESTARTS AGE
pod/nginx-6cfb64b7c5-8hbjv 1/1 Running 0 13m
pod/nginx-6cfb64b7c5-lrgjt 1/1 Running 0 3m21s
pod/nginx-6cfb64b7c5-zplj8 1/1 Running 0 13m
업데이트 중 비활성화되었다가, rollback 이후 새로 생성된 revision 1의 Pod를 확인할 수 있습니다.
4. 결론
이번 포스트에서는 Kubernetes 클러스터의 Deployment 업데이트 및 rollback 시 유용하게 사용할 수 있는 옵션들에 대해 알아봤습니다. progressDeadlineSeconds 옵션을 사용하여 지정된 시간을 초과한 업데이트는 실패로 간주하도록 하고, revisionHistoryLimit 옵션을 통해 Deployment의 업데이트 내역의 최대 개수를 설정했습니다.
progressDeadlineSeconds 옵션을 환경에 맞게 설정하면 비정상적인 업데이트 및 실패를 감지하고 클러스터의 안정성을 높일 수 있습니다. revisionHistoryLimit 옵션의 경우 Deployment가 이전 버전으로 rollback이 필요한 상황에도 손쉽고 빠르게 적용할 수 있어 유용합니다.
하지만 두 옵션 모두 환경에 맞는 적절한 설정이 필요합니다. progressDeadlineSeconds 옵션이 너무 짧게 설정될 경우 정상적인 업데이트로 실패로 간주될 수 있고, 너무 길 경우 문제 감지가 늦어지게 됩니다. revisionHistoryLimit 옵션은 너무 적게 설정 시 이전 버전으로 복구가 제한되고, 너무 많이 설정하면 etcd에 저장되는 데이터가 증가하여 불필요한 리소스 소비가 발생할 수 있습니다.
Kubernetes 클러스터에서 높은 점유율을 자랑하는 NGINX Ingress Controller의 상업용 엔터프라이즈 버전인 NGINX Plus Ingress Controller를 사용해 보고 싶으시다면, NGINX STORE를 통해 문의해 무료로 NGINX Plus trial을 체험해 보세요.