1. 개요

앱을 새 버전으로 바꿀 때 서비스를 멈추고 싶지 않다. Deployment 는 그 일을 맡는 컨트롤러다. 이 글에서는 Deployment 가 내부적으로 무엇을 만드는지, 롤링 업데이트가 어떤 규칙으로 옛 Pod 를 새 Pod 로 바꾸는지, 그리고 그 과정에서 잠깐 자원이 더 필요하다는 점을 본다.


2. 핵심 내용

2-1. Deployment → ReplicaSet → Pod

Deployment 는 Pod 를 직접 만들지 않는다. Deployment 가 ReplicaSet 을 만들고, ReplicaSet 이 “이 템플릿의 Pod 를 N 개 유지한다” 를 맡는다. 1편의 조정 루프가 두 층으로 돌고 있는 셈이다.

이미지 태그 같은 Pod 템플릿을 바꾸면 Deployment 는 새 ReplicaSet 을 만들고, 새 쪽의 replicas 를 늘리면서 옛 쪽을 줄인다. 옛 ReplicaSet 은 replicas 0 인 채로 남는다. 롤백에 쓰려는 것이다.

kubectl get rs -l app=web
# web-7d9f6c8b5   3  3  3   (새 버전)
# web-5b4c9d7f6   0  0  0   (이전 버전, 남겨 둠)

2-2. RollingUpdate 의 두 숫자

기본 전략이 RollingUpdate 이고 규칙은 두 값으로 정해진다.

  • maxSurge: 원하는 개수보다 몇 개까지 더 띄워도 되나. 기본 25%, 소수는 올림한다.
  • maxUnavailable: 몇 개까지 동시에 못 쓰는 상태여도 되나. 기본 25%, 소수는 내림한다.

replicas 가 4 면 새 Pod 를 최대 1개 먼저 띄우고, 1개까지는 못 써도 된다. replicas 가 1 이면 maxSurge 는 올림으로 1, maxUnavailable 은 내림으로 0 이 된다. 새 Pod 가 Ready 가 된 뒤에야 옛 Pod 를 내린다는 뜻이다. 여기서 2편의 readiness 프로브가 일을 한다. readiness 가 없으면 프로세스만 뜨면 준비된 것으로 취급돼서, 아직 워밍업 중인 새 Pod 로 트래픽이 가고 옛 Pod 는 사라진다.

spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

2-3. 롤아웃 중에는 자원이 더 든다

maxSurge 가 있다는 건 옛 Pod 와 새 Pod 가 잠깐 겹친다는 뜻이다. 메모리를 크게 쓰는 앱이면 겹치는 동안 필요한 메모리가 늘어난다. 여유가 빠듯한 노드에서는 새 Pod 가 Pending 에 걸려 롤아웃이 멈추거나, 노드가 메모리 압력을 받는다. 여러 서비스를 연달아 배포하면 이 겹침이 서로 쌓인다. 실제로 겪은 압력 이야기는 DoEatFit k3s 운영기 5 - CI 빌드 폭주가 운영 DB를 굳힌 날에 있다.

작은 클러스터에서는 maxSurge: 0, maxUnavailable: 1 로 바꿔서 “하나 내리고 하나 올리는” 방식으로 자원을 아끼기도 한다. 대신 그동안 처리 용량이 줄어든다. 어느 쪽을 아낄지는 선택이다.

2-4. 롤백과 이력

kubectl rollout status deployment/web    # 진행 상황 지켜보기
kubectl rollout history deployment/web   # 리비전 목록
kubectl rollout undo deployment/web      # 직전 리비전으로
kubectl rollout undo deployment/web --to-revision=2

undo 는 남겨 둔 옛 ReplicaSet 의 replicas 를 다시 올리는 것이다. 이력은 revisionHistoryLimit(기본 10)개까지 보관한다. 이 값을 0 으로 두면 롤백할 대상이 없어진다. 줄이더라도 최소 한두 개는 남긴다.

2-5. 어디서 실수하나

  • latest 같은 고정 안 된 태그를 쓰면 템플릿이 안 바뀌어서 롤아웃이 일어나지 않는다. 버전 태그를 쓴다.
  • 롤아웃이 멈춘 것을 “배포 성공” 으로 착각한다. rollout status 로 끝났는지 확인한다.
  • git 에 있는 YAML 을 되돌리는 것과 rollout undo 는 별개다. GitOps 를 쓴다면 undo 로 클러스터만 바꿔도 git 이 다시 덮어쓴다.

3. 마무리

요약

  • Deployment 는 ReplicaSet 을 만들고, ReplicaSet 이 Pod 개수를 유지한다.
  • RollingUpdate 는 maxSurge(기본 25%, 올림)와 maxUnavailable(기본 25%, 내림)로 교체 속도를 정한다.
  • 롤아웃 중에는 옛 Pod 와 새 Pod 가 겹쳐 자원이 잠깐 더 필요하다.
  • rollout undo 는 남겨 둔 옛 ReplicaSet 을 되살리며, 보관 개수는 revisionHistoryLimit(기본 10)이다.

다음은 Kubernetes 기초 4 - Service 와 DNS이다.