Kubernetes Deployment Update 전략별 다운타임 비교
이 포스트에서는 Kubernetes Deployment Update 전략인 Recreate/RollingUpdate 방식으로 Deployment 2개를 배포하고, 각 Deployment를 업데이트할 때 Pod의 다운타임 차이를 비교해 보겠습니다.
각 Deployment의 Pod로 연결되는 Service로 지속적으로 요청을 전송하고, Deployment 업데이트를 통해 Pod 내부 NGINX 컨테이너의 이미지를 교체할 경우, Pod가 재생성 되는 시간 동안의 응답 코드를 통해 다운타임을 측정하겠습니다.
목차
1. Kubernetes Deployment Update 전략이란?
2. Kubernetes Deployment Update 전략 비교를 위한 구성
3. 전략별 다운타임 비교
3-1. Recreate
3-2. RollingUpdate
4. 결론
1. Kubernetes Deployment Update 전략이란?
Kubernetes Deployment Update 전략은 Recreate와 RollingUpdate가 있습니다. 해당 옵션은 yaml 파일의 .spec.strategy 항목에서 설정할 수 있으며, 오래된 Pod를 새로운 Pod로 교체할 때 사용할 전략을 지정합니다.
기본값은 RollingUpdate입니다.
Recreate

Recreate 전략의 경우 오래된 Pod를 모두 종료하고, 새로운 Pod를 생성합니다. 새로운 Pod는 이전 Pod의 성공적인 제거가 확인된 후에 생성됩니다.
사용자가 수동으로 Pod를 삭제할 경우, 새로운 Pod가 즉시 생성됩니다. 이 경우, 이전 Pod가 여전히 “Terminating” 상태에 있을 수 있습니다.
RollingUpdate

RollingUpdate 전략의 경우 새로운 Pod를 먼저 생성한 후 해당 Pod의 상태가 Ready로 전환되어 정상적으로 작동하는 것이 확인되면 오래된 Pod를 제거합니다. RollingUpdate 전략을 통해 조정되는 새로운 Pod와 오래된 Pod의 개수는 maxUnavailable 값과 maxSurge 값으로 관리됩니다.
2. Kubernetes Deployment Update 전략 비교를 위한 구성
두 전략을 비교하기 위해, NGINX 이미지를 사용하는 Pod를 2개의 relpicas로 관리하는 Deployment를 배포했습니다. spec.strategy.type 값을 각 전략에 맞게 설정했으며, 레이블을 update: recreate/rollout 으로 구성했습니다.
예제에 사용된 yaml 파일은 모두 NGINX Store GitHub 리포지토리에서 확인하실 수 있습니다.
recreate-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-recreate
labels:
app: nginx
update: recreate
spec:
replicas: 2
strategy:
type: Recreate
selector:
matchLabels:
app: nginx
update: recreate
template:
metadata:
labels:
app: nginx
update: recreate
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
rollout-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-rollout
labels:
app: nginx
update: rollout
spec:
replicas: 2
strategy:
type: RollingUpdate
selector:
matchLabels:
app: nginx
update: rollout
template:
metadata:
labels:
app: nginx
update: rollout
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Pod로 요청을 전송하여 다운타임을 비교하기 위해 Service도 각각 배포했습니다. 테스트를 위해 NodePort 타입의 Service를 배포했습니다.
recreate-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service-recreate
spec:
type: NodePort
selector:
app: nginx
update: recreate
ports:
- protocol: http
port: 80
targetPort: 80
rollout-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service-rollout
spec:
type: NodePort
selector:
app: nginx
update: rollout
ports:
- protocol: http
port: 80
targetPort: 80
테스트 환경에 다음과 같이 배포되었습니다.
$ kubectl get deploy,service
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment-recreate 2/2 2 2 4h30m
deployment.apps/nginx-deployment-rollout 2/2 2 2 4h29m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-service-recreate NodePort 10.108.60.61 <none> 80:32029/TCP 4h27m
service/nginx-service-rollout NodePort 10.109.250.101 <none> 80:31327/TCP 4h26m
3. 전략별 다운타임 비교 테스트
테스트는 Python을 활용하여 지속적으로 NodePort로 노출된 Service로 요청을 전송하고, 응답의 상태 코드를 통해 다운타임을 측정했습니다.
다운타임 비교에 사용한 코드인 downtime.py 코드는 NGINX STORE GitHub 리포지토리에서 확인하실 수 있습니다. 해당 코드를 통해 요청을 전송할 URL, 전송 간격, 지속적으로 전송할 시간을 설정하고 결과를 파일로 저장할 수 있습니다.
다음과 같이 실행하여 다운타임을 측정할 수 있습니다.
$ python downtime.py --url <서비스 url> --duration <요청을 전송할 시간> --interval <요청 전송 간격> --output <결과 파일 이름 지정>
Deployment의 업데이트는 다음과 같이 NGINX 컨테이너의 이미지 버전을 변경하여 테스트했습니다.
$ kubectl set image deploy/<Deployment 이름> <컨테이너 이름>=<변경할 이미지>
3-1. Recreate
1. 명령어를 통해 Pod의 상태를 모니터링합니다.
$ kubectl get po -w
NAME READY STATUS RESTARTS AGE
nginx-deployment-recreate-784dbb8b55-5vvq4 1/1 Running 0 144m
nginx-deployment-recreate-784dbb8b55-sfnh7 1/1 Running 0 144m
2. downtime.py 코드를 실행하여 다운타임 측정을 시작합니다.
$ python downtime.py --url http://192.168.200.91:32029 --duration 80 --interval 1 --output recreate_result
80초 동안 1초 간격으로 요청을 전송합니다. URL의 Node IP와 NodePort로 설정된 Port는 실제 환경에 맞게 변경합니다.
3. 새로운 터미널을 열고 명령어를 통해 Deployment의 Pod image를 변경합니다.
$ kubectl set image deploy/nginx-deployment-recreate nginx=nginx:1.23.1
deployment.apps/nginx-deployment-recreate image updated
기존 nginx 이름을 가진 컨테이너의 이미지가 nginx:1.23.1로 변경됩니다.
4. Pod의 상태와 결과로 출력된 파일을 확인합니다.
NAME READY STATUS RESTARTS AGE
nginx-deployment-recreate-784dbb8b55-5vvq4 1/1 Running 0 144m
nginx-deployment-recreate-784dbb8b55-sfnh7 1/1 Running 0 144m
# Pod 제거 시작
nginx-deployment-recreate-784dbb8b55-5vvq4 1/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-sfnh7 1/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-sfnh7 0/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-5vvq4 0/1 Terminating 0 144m
# Pod 생성 시작
nginx-deployment-recreate-79c958f4bd-mtmkg 0/1 Pending 0 0s
nginx-deployment-recreate-79c958f4bd-j9cnp 0/1 Pending 0 0s
nginx-deployment-recreate-79c958f4bd-mtmkg 0/1 Pending 0 1s
nginx-deployment-recreate-79c958f4bd-j9cnp 0/1 Pending 0 0s
nginx-deployment-recreate-79c958f4bd-mtmkg 0/1 ContainerCreating 0 1s
nginx-deployment-recreate-79c958f4bd-j9cnp 0/1 ContainerCreating 0 0s
nginx-deployment-recreate-784dbb8b55-sfnh7 0/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-5vvq4 0/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-sfnh7 0/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-sfnh7 0/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-5vvq4 0/1 Terminating 0 144m
nginx-deployment-recreate-784dbb8b55-5vvq4 0/1 Terminating 0 144m
nginx-deployment-recreate-79c958f4bd-j9cnp 1/1 Running 0 22s
nginx-deployment-recreate-79c958f4bd-mtmkg 1/1 Running 0 25s
기존의 Pod가 모두 Terminating 상태로 전환되어 먼저 제거되고, 이후 새로운 Pod가 Pending 상태로 생성되기 시작하는 것을 확인할 수 있습니다.
recreate_result_analysis.txt
Test Results for http://192.168.200.91:32029
Duration: 80 seconds
Request Interval: 1.0 seconds
Total Requests: 68
Failed Requests: 12
Success Rate: 82.35%
Downtime Periods:
- 11.00 seconds
Total Downtime: 11.00 seconds
기존의 Pod를 제거하고, 새로운 Pod를 생성하고 요청을 수신하기까지 대략 11초의 다운타임이 발생한 것을 확인할 수 있습니다.
3-2. RollingUpdate
Recreate 전략과 동일한 방식으로 다운타임을 확인합니다.
1. 명령어를 통해 Pod의 상태를 모니터링합니다.
$ kubectl get po -w
NAME READY STATUS RESTARTS AGE
nginx-deployment-rollout-889449b9-n8c22 1/1 Running 0 24m
nginx-deployment-rollout-889449b9-vbtz5 1/1 Running 0 25m
2. downtime.py 코드를 실행하여 다운타임 측정을 시작합니다.
$ python downtime.py --url http://192.168.200.91:31327 --duration 80 --interval 1 --output rollout_result
80초 동안 1초 간격으로 요청을 전송합니다. URL의 Node IP와 NodePort로 설정된 Port는 실제 환경에 맞게 변경합니다.
3. 새로운 터미널을 열고 명령어를 통해 Deployment의 Pod image를 변경합니다.
$ kubectl set image deploy/nginx-deployment-rollout nginx=nginx:1.23.1
deployment.apps/nginx-deployment-rollout image updated
기존 nginx 이름을 가진 컨테이너의 이미지가 nginx:1.23.1로 변경됩니다.
4. Pod의 상태와 결과로 출력된 파일을 확인합니다.
NAME READY STATUS RESTARTS AGE
nginx-deployment-recreate-79c958f4bd-j9cnp 1/1 Running 0 9m54s
nginx-deployment-recreate-79c958f4bd-mtmkg 1/1 Running 0 9m55s
# Pod 생성 시작
nginx-deployment-rollout-7fd968f458-gl9n7 0/1 Pending 0 0s
nginx-deployment-rollout-7fd968f458-gl9n7 0/1 Pending 0 1s
nginx-deployment-rollout-7fd968f458-gl9n7 0/1 ContainerCreating 0 1s
nginx-deployment-rollout-7fd968f458-gl9n7 1/1 Running 0 6s
# Pod 제거 시작
nginx-deployment-rollout-889449b9-vbtz5 1/1 Terminating 0 25m
# Pod 생성 시작
nginx-deployment-rollout-7fd968f458-5fzf5 0/1 Pending 0 0s
nginx-deployment-rollout-7fd968f458-5fzf5 0/1 Pending 0 0s
nginx-deployment-rollout-7fd968f458-5fzf5 0/1 ContainerCreating 0 0s
nginx-deployment-rollout-889449b9-vbtz5 0/1 Terminating 0 25m
nginx-deployment-rollout-889449b9-vbtz5 0/1 Terminating 0 25m
nginx-deployment-rollout-889449b9-vbtz5 0/1 Terminating 0 25m
nginx-deployment-rollout-889449b9-vbtz5 0/1 Terminating 0 25m
nginx-deployment-rollout-7fd968f458-5fzf5 1/1 Running 0 4s
# Pod 제거 시작
nginx-deployment-rollout-889449b9-n8c22 1/1 Terminating 0 25m
nginx-deployment-rollout-889449b9-n8c22 0/1 Terminating 0 25m
nginx-deployment-rollout-889449b9-n8c22 0/1 Terminating 0 25m
nginx-deployment-rollout-889449b9-n8c22 0/1 Terminating 0 25m
nginx-deployment-rollout-889449b9-n8c22 0/1 Terminating 0 25m
새로운 Pod 1개가 먼저 Pending 상태로 생성되기 시작하고, Running 상태로 전환된 이후 이전의 Pod가 Terminating 상태로 제거되는 것을 확인할 수 있습니다.
rollout_result_analysis.txt
Test Results for http://192.168.200.91:31327
Duration: 80 seconds
Request Interval: 1.0 seconds
Total Requests: 79
Failed Requests: 0
Success Rate: 100.00%
Downtime Periods:
Total Downtime: 0.00 seconds
RolloutUpdate 전략의 경우 이전의 Recreate 전략과 다르게, 새로운 Pod가 생성되고 난 이후 기존 Pod를 제거하는 과정을 반복하여, 다운타임이 발생하지 않고 모든 요청에 정상적으로 응답함을 확인할 수 있습니다.
4. 결론
이번 포스트에서는 2개의 Deployment를 각각 Recreate/RollingUpdate 설정으로 배포하고, Deployment의 구성이 변경되어 Pod를 재생성할 때, 각 전략별 다운타임을 비교해 봤습니다.
Recreate의 경우 동작 중인 Pod를 모두 제거한 후, 새로운 Pod를 생성하기 때문에 Pod가 생성되는 동안 다운타임이 발생하였고, RollingUpdate의 경우 새로운 Pod의 생성과 기존 Pod의 제거를 순차적으로 진행하여 다운타임이 발생하지 않는 것을 확인할 수 있었습니다.
Recreate는 모든 기존 Pod를 삭제하고 새 버전을 배포하여 충돌을 방지하며, 데이터 일관성이 중요한 서비스에 적합합니다. 반면, RollingUpdate는 순차적으로 새 버전을 배포하여 무중단 서비스를 지원하며, 고가용성이 요구되는 애플리케이션에 적합합니다. Deployment를 통해 배포할 Pod의 특징에 맞춰 업데이트 전략을 선택함으로써, 서비스의 가용성과 성능을 극대화할 수 있습니다.
Kubernetes 클러스터에도 배포할 수 있는 NGINX Plus, 혹은 높은 점유율을 자랑하는 NGINX Ingress Controller에 추가 기능이 포함된 Plus 버전을 사용해 보고 싶으시다면, NGINX STORE를 통해 문의해 무료로 NGINX Plus trial을 체험해 보세요.
댓글을 달려면 로그인해야 합니다.