3편에서는, 실제 서비스 운영에서 정말 중요한 개념인
- Rolling Update (롤링업데이트 / 롤아웃)
- Rollout Undo (롤백)
를 FastAPI 앱서비스를 예제로 직접 실습하겠습니다.
💡 실습 환경
- Windows 11 + WSL2 (Ubuntu 24.04)
- Minikube v1.37.0
- Docker, kubectl 설치 완료
- 2탄에서 만든 FastAPI Deployment + NodePort Service가 있다는 가정
1. 초기 상태 정리 – v1 버전 다시 올리기
우선 2탄에서 만들었던 리소스를 한 번 정리하고,
v1 버전이 배포된 깨끗한 상태에서 시작하겠습니다.
1-1. 기존 Deployment / Service 삭제
kubectl delete svc/fastapi-k8s
kubectl delete deploy/fastapi-k8s
kubectl get deployment
kubectl get svc
# → fastapi-k8s 관련 리소스가 없어야 정상
1-2. Minikube Docker 환경 설정
eval $(minikube docker-env)
이걸 실행하면 현재 셸의 docker 명령이 Minikube 내부 Docker 데몬을 바라보게 됩니다.
1-3. Deployment / NodePort Service 재적용
kubectl apply -f deployment.yaml
kubectl apply -f service_nodeport.yaml
상태 확인
kubectl get pods -o wide
kubectl get svc fastapi-k8s
예를 들어
- Minikube IP: 192.168.49.2 (minikube ip로 확인)
- NodePort: 30080 (kubectl get svc 로 확인)
minikube ip
# 예: 192.168.49.2
curl http://192.168.49.2:30080
# → v1 메시지가 잘 나오는지 확인
이 상태를 “v1 버전 운영 중” 기준점으로 잡고 시작하겠습니다.
2. v2 코드 수정 + 이미지 빌드
이제 새 버전(v2) 을 만들어서 롤링업데이트 실습을 해볼게요.
2-1. main.py를 v2 버전으로 수정
v2에서는 버전 정보를 추가하겠습니다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {
"message":"Hello, Kubernetes v2!",
"version":"2.0"
}
@app.get("/health")
def health():
return {
"status":"ok",
"version":"2.0"
}
2-2. v2 이미지 빌드
eval $(minikube docker-env)
docker build -t fastapi-k8s:v2 .
docker images | grep fastapi-k8s
여기까지 하면
- 코드는 v2
- 이미지도 fastapi-k8s:v2까지 빌드 완료
하지만 아직 Deployment는 fastapi-k8s:v1 이미지를 사용 중이라,
실제 요청을 보내보면 여전히 v1 응답이 나옵니다.
curl http://192.168.49.2:30080
# → 여전히 v1 메시지 출력
🔍 포인트
“이미지를 새로 빌드했다고 해서 바로 서비스에 반영되는 게 아니다.”
→ Deployment 설정(image 태그)을 바꿔줘야 롤링업데이트가 시작됩니다.
3. Rolling Update / Rollout 개념 먼저 잡고 가기
그럼 이제 Rolling Update / Rollout이 정확히 뭔지부터 짚고 갈게요.
3-1. Deployment가 하는 일
Deployment는 한 줄로 요약하면
“이 스펙으로 Pod를 N개 유지해줘” 라고 쿠버네티스에 부탁하는 객체입니다.
예를 들어 deployment.yaml 안에
spec:
replicas: 2
template:
spec:
containers:
- image: fastapi-k8s:v1
이렇게 적혀 있으면, 쿠버네티스는
- “fastapi-k8s:v1 이미지를 사용하는 Pod를 2개 유지해야 한다”
라고 이해합니다.
여기서 image: fastapi-k8s:v1 → image: fastapi-k8s:v2로 변경하고 apply 를 하면
“아, 이제부터는 v2 이미지로 2개 유지해야 하는구나.”
라고 인식하고, “교체 작업” 을 시작합니다.
이 교체 작업이 바로 Rolling Update(롤링업데이트) / Rollout(롤아웃) 입니다.
3-2. RollingUpdate 전략 옵션
예제로 우리가 쓴 deployment.yaml에는 이런 부분이 있습니다.
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
이게 의미하는 것은
- maxUnavailable: 0
→ 운영 중인 Pod 수가 설정보다 줄어들지 않게 (항상 최소 replicas 개수 유지) - maxSurge: 1
→ 업데이트 중에 최대 1개까지 더 많이 띄우는 것 허용 (임시로 초과 생성 허용)
예를 들어 replicas: 2, maxSurge: 1 이라면
- 한 순간에 최대 3개(2 + 1) 까지도 떠 있을 수 있고
- 최소 2개는 계속 살아있게 유지하면서
v1 → v2로 조금씩 바꿔치기하는 구조입니다.
즉, 서비스가 끊기지 않도록
- v2 Pod 하나 띄우고
- v1 Pod 하나 내리고
- 또 v2 하나 띄우고
- 또 v1 하나 내리고
이런 식으로 조금씩 교체하는 전략이 바로 RollingUpdate입니다.

4. Deployment 이미지 변경 → 롤링업데이트 실행
이제 실제로 Deployment의 이미지 버전을 바꿔보겠습니다.
4-1. deployment.yaml에서 이미지 태그 v1 → v2로 변경
deployment.yaml의 컨테이너 이미지 부분을 수정합니다.
containers:
- name: fastapi
image: fastapi-k8s:v2 # ← v2로 변경
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
터미널에서 yaml파일을 수정하고 싶다면 (WSL / GNU sed 기준)
sed -i 's/fastapi-k8s:v1/fastapi-k8s:v2/' deployment.yaml
grep "image:" deployment.yaml
4-2. 변경 사항 적용
kubectl apply -f deployment.yaml
이 명령이 실행되는 순간
- 기존 v1 ReplicaSet은 점점 줄어들고
- 새 v2 ReplicaSet이 생기면서
RollingUpdate 전략에 따라 Pod들이 교체되기 시작합니다.
spec 자체는 안 바꾸고,
“그냥 지금 상태에서 한 번 싹 재시작만 해봐” 라고 하고 싶으면
kubectl rollout restart deployment fastapi-k8s
를 쓸 수 있는데, 이번 실습에서는 image 변경 + apply 를 통해 배포 개념을 익히는 게 포인트입니다.
5. 롤아웃 진행 상황 모니터링
롤링업데이트가 어떻게 진행되는지 눈으로 직접 보는 게 가장 이해가 잘 됩니다.
5-1. Pod 목록 실시간 관찰
다른 터미널 하나를 열고
kubectl get pods -w
를 실행해두면, 이런 흐름을 볼 수 있습니다.
- v1 Pod: fastapi-k8s-xxxxx (예전 이름) → Terminating
- v2 Pod: fastapi-k8s-yyyyy (새로운 이름) → ContainerCreating → Running
조금 지나면, 모든 Pod가 v2 이미지로 교체된 상태가 되고, 더 이상 Running 상태가 유지됩니다.
5-2. rollout 상태 확인
kubectl rollout status deployment fastapi-k8s
성공적으로 끝났다면
deployment "fastapi-k8s" successfully rolled out
같은 메시지가 출력됩니다.
5-3. ReplicaSet 관찰 (선택)
롤링업데이트 과정은 내부적으로 ReplicaSet(RS) 이 바뀌면서 일어납니다.
kubectl get rs -l app=fastapi-k8s
- v1 시절의 ReplicaSet
- v2 이미지용 ReplicaSet
이 두 개가 잠깐 공존했다가, 나중에는 v2만 남아있는 것을 확인할 수 있어요.
6. 새 버전(v2) 정상 반영 확인
이제 NodePort로 다시 접속해봅니다.
minikube ip
# 예: 192.168.49.2
curl http://192.168.49.2:30080
curl http://192.168.49.2:30080/health
예상 응답
# curl http://192.168.49.2:30080
{"message": "Hello, Kubernetes!", "Version": "2.0"}
# curl http://192.168.49.2:30080/health
{"status": "ok", "version": "2.0"}
💡 참고
- Service 타입이 NodePort인 경우,
http://[minikube ip]:[NodePort] 로 바로 접근 가능해요.- minikube service fastapi-k8s --url 은 이 주소를 자동으로 찾아주고
브라우저까지 열어주는 편의 기능일 뿐입니다.
7. Rollback 실습 – 이전 버전으로 되돌리기
새 버전(v2)을 배포해봤으니, 이번엔 문제가 생겼다고 가정하고 v1으로 되돌리는 실습을 해봅니다.
7-1. 기본 Rollback (직전 리비전으로 되돌리기)
Pod 상태를 다른 터미널에서 보고 있으면서
kubectl get pods -w
메인 터미널에서 롤백 명령 실행
kubectl rollout undo deployment fastapi-k8s
kubectl rollout status deployment fastapi-k8s
그러면
- v2 Pod들이 내려가고
- 다시 v1 Pod들이 올라오면서
배포 전 상태(이전 리비전) 로 되돌아갑니다.
NodePort로 확인
curl http://192.168.49.2:30080
# → 다시 v1 메시지가 나오는지 확인
8. 특정 리비전으로 롤백 (history 기반)
Deployment는 배포 기록을 리비전(history)으로 관리합니다.
8-1. 배포 히스토리 확인
kubectl rollout history deployment fastapi-k8s
예를 들어
- revision 1 → v1
- revision 2 → v2
이런 식으로 나오게 됩니다.
8-2. 원하는 리비전으로 롤백
다시 v2로 복구하고 싶다면
kubectl rollout undo deployment fastapi-k8s --to-revision=2
kubectl rollout status deployment fastapi-k8s
그리고 다시 확인
curl http://192.168.49.2:30080
# → 다시 v2 메시지 출력 확인
이렇게 해서
- v1 → v2 Rolling Update
- v2 → v1 Rollback
- v1 → v2 재-Rollout (리비전 기반)
까지 형상에 따른 버전 이동을 해보았습니다.
9. 마무리
이번 글에서 정리할 수 있는 키워드는 다음과 같습니다.
- 이미지 빌드만으로는 배포가 바뀌지 않는다.
→ Deployment image 필드를 바꿔야 함 - Deployment = 원하는 상태(버전, replicas 등)를 선언하는 객체
- RollingUpdate 전략으로 서비스 다운타임 최소화
→ maxUnavailable, maxSurge - Rollout / Undo / History 로
- 새 버전 배포
- 문제 시 이전 버전으로 롤백
- 특정 리비전으로 재배포
'IT > [클라우드]' 카테고리의 다른 글
| [Kubernetes] Nginx·Caddy 리버스 프록시 + Metrics Server + HPA + hey 부하테스트 실습 (5) (0) | 2025.11.23 |
|---|---|
| [Kubernetes] ConfigMap & Secret으로 FastAPI 설정 분리하기 (4) (0) | 2025.11.23 |
| [Kubernetes] Minikube로 FastAPI 앱 배포하기 실습 (2) (0) | 2025.11.22 |
| [Kubernetes] AI·빅데이터 직무를 위한 쿠버네티스 개념 이해 (1) (0) | 2025.11.22 |
| [AWS EC2] EC2 인스턴스 볼륨 용량 늘리기 (0) | 2024.06.04 |