본문 바로가기

IT/[클라우드]

[Kubernetes] Rolling Update & Rollback으로 FastAPI 무중단 배포하기 (3)

728x90
반응형

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로 조금씩 바꿔치기하는 구조입니다.

즉, 서비스가 끊기지 않도록

  1. v2 Pod 하나 띄우고
  2. v1 Pod 하나 내리고
  3. 또 v2 하나 띄우고
  4. 또 v1 하나 내리고

이런 식으로 조금씩 교체하는 전략이 바로 RollingUpdate입니다.

 

쿠버네티스의 배포 전략인 Rolling Update(출처. Rolling Update & Recreate Deployment Strategies in Kubernetes, Medium)


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 (새로운 이름) → ContainerCreatingRunning

조금 지나면, 모든 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. 마무리

이번 글에서 정리할 수 있는 키워드는 다음과 같습니다.

  1. 이미지 빌드만으로는 배포가 바뀌지 않는다.
    → Deployment image 필드를 바꿔야 함
  2. Deployment = 원하는 상태(버전, replicas 등)를 선언하는 객체
  3. RollingUpdate 전략으로 서비스 다운타임 최소화
    → maxUnavailable, maxSurge
  4. Rollout / Undo / History
    • 새 버전 배포
    • 문제 시 이전 버전으로 롤백
    • 특정 리비전으로 재배포
반응형