본문 바로가기
1. K8s Core & Architecture/1.3. 파드(Pod)와 워크로드 아키텍처

Deployment 리소스의 내부 동작: ReplicaSet을 어떻게 관리하는가?

by K8s Architect 2026. 4. 9.

Deployment 리소스의 내부 동작: ReplicaSet을 어떻게 관리하는가?

쿠버네티스 환경에서 무상태(Stateless) 애플리케이션을 배포할 때 가장 기본적이고 필수적으로 사용하는 API 리소스는 단연 Deployment(디플로이먼트)입니다. 우리는 습관적으로 Deployment의 YAML 명세서에 파드의 개수(replicas)와 컨테이너 이미지를 적어 넣고 클러스터에 배포합니다.

하지만 많은 인프라 엔지니어가 간과하는 사실이 있습니다. Deployment는 파드(Pod)를 직접 생성하거나 관리하지 않는다는 점입니다. 파드의 개수를 유지하고 장애가 발생한 파드를 다시 살려내는 실제 작업은 하위 컨트롤러인 ReplicaSet(레플리카셋)이 전담합니다.

본 가이드에서는 쿠버네티스 아키텍처의 우아한 추상화 계층을 보여주는 Deployment와 ReplicaSet의 관계를 파헤치고, 무중단 배포와 롤백이 내부적으로 어떻게 구현되는지 그 심연의 동작 원리를 완벽하게 해부합니다.


1. 아키텍처 계층 구조: 관심사의 완벽한 분리

쿠버네티스 컨트롤 플레인은 복잡성을 제어하기 위해 철저한 '관심사의 분리(Separation of Concerns)' 패턴을 따릅니다.

  • Pod: 컨테이너를 실행하는 가장 작은 논리적 단위입니다.
  • ReplicaSet: 사용자가 지정한 '원하는 파드의 개수(Desired State)'가 항상 클러스터 내에 유지되도록 보장하는 파수꾼입니다. 파드가 죽으면 새로 생성하고, 너무 많으면 삭제합니다.
  • Deployment: 이 ReplicaSet의 '버전(Version)'을 관리하는 최상위 오케스트레이터입니다. 애플리케이션의 이미지가 변경되거나 설정이 바뀌면, 새로운 ReplicaSet을 생성하고 기존 ReplicaSet의 파드를 점진적으로 줄이는 '배포 전략'을 총괄합니다.

이러한 계층 구조 덕분에 쿠버네티스는 파드의 가용성 유지(ReplicaSet의 역할)와 애플리케이션의 버전 업데이트(Deployment의 역할)라는 두 가지 복잡한 과제를 독립적이고 안정적으로 수행할 수 있습니다.


2. 라벨(Label)과 해시(Hash)의 마법: pod-template-hash

Deployment가 여러 개의 ReplicaSet을 헷갈리지 않고 정확하게 통제할 수 있는 핵심 비결은 바로 라벨 셀렉터(Label Selector)와 자동 생성되는 해시값에 있습니다.

새로운 Deployment를 배포하면 쿠버네티스 내부에서는 다음과 같은 연쇄 작용이 일어납니다.

  1. 해시값 생성: Deployment 컨트롤러는 명세서 내의 podTemplate(컨테이너 이미지, 포트, 환경변수 등) 영역을 읽어 들여 고유한 해시(Hash) 문자열을 수학적으로 계산합니다. (예: 7b5467984)
  2. ReplicaSet 생성: Deployment는 계산된 해시값을 이름 뒤에 붙여 새로운 ReplicaSet을 생성합니다. (예: my-app-7b5467984)
  3. 라벨 주입: 가장 중요한 단계입니다. Deployment는 생성한 ReplicaSet과 그 하위의 모든 파드들에게 pod-template-hash=7b5467984라는 특수한 라벨을 강제로 주입합니다.

pod-template-hash 라벨은 클러스터 내에서 해당 파드들이 정확히 '어떤 버전의 ReplicaSet'에 속해 있는지를 증명하는 절대적인 주민등록번호 역할을 합니다. 만약 이 라벨이 없다면, 과거 버전의 ReplicaSet과 새로운 버전의 ReplicaSet이 서로 상대방의 파드를 자신의 것이라 착각하여 파드를 무한정 생성하고 삭제하는 충돌(Collision) 대참사가 발생하게 됩니다.


3. 무중단 배포의 핵심: 롤링 업데이트(Rolling Update) 알고리즘

애플리케이션의 새로운 버전(예: 이미지 태그 v1 -> v2)을 배포하기 위해 Deployment 명세서를 수정하고 적용(Apply)하면, Deployment 컨트롤러는 기존의 v1 ReplicaSet을 즉시 삭제하지 않고 정교한 롤링 업데이트 상태 머신을 가동합니다.

Deployment는 관리자가 설정한 두 가지 파라미터를 기반으로 업데이트 속도와 가용성을 수학적으로 통제합니다.

  • MaxSurge (최대 초과 파드 수): 업데이트 과정에서 원래 지정된 파드 개수(Replicas)보다 얼마나 더 많은 파드를 임시로 생성할 수 있는지 결정합니다. (예: 25% 또는 1개)
  • MaxUnavailable (최대 불가 파드 수): 업데이트 과정에서 동시에 서비스가 불가능해져도 허용되는 파드의 최대 개수입니다. (예: 25% 또는 1개)

롤링 업데이트 진행 시퀀스:

  1. Deployment는 변경된 podTemplate을 기반으로 새로운 해시값을 계산하여 새로운 ReplicaSet(v2)을 빈 껍데기로 생성합니다.
  2. MaxSurge 설정값에 따라, 새로운 ReplicaSet(v2)의 파드 개수(Replicas)를 점진적으로 1개씩(혹은 설정된 비율만큼) 늘리도록 API 서버에 명령합니다.
  3. 새로운 v2 파드가 정상적으로 구동되고 Ready 상태가 되면, Deployment는 MaxUnavailable 규칙을 위반하지 않는 선에서 기존 ReplicaSet(v1)의 파드 개수를 1개씩 줄입니다(Scale down).
  4. 이 교차 스케일링(Cross-scaling) 작업은 새로운 ReplicaSet이 목표한 파드 개수를 100% 달성하고, 구형 ReplicaSet의 파드 개수가 0이 될 때까지 물 흐르듯 반복됩니다.

이 완벽한 시퀀스 덕분에 외부 사용자들은 단 1초의 서비스 단절(Downtime)도 느끼지 못한 채 완전히 새로운 버전의 애플리케이션으로 이동하게 됩니다.


4. 과거로의 회귀: 리비전(Revision)과 롤백(Rollback)

새로 배포한 v2 애플리케이션에 치명적인 버그가 발견되어 황급히 이전 버전으로 되돌려야 하는 상황(Rollback)이 발생할 수 있습니다. Deployment 리소스는 이 과정을 놀랍도록 단순하게 만들어줍니다.

롤링 업데이트가 완료되어 파드가 0개가 된 구형 ReplicaSet(v1)은 클러스터에서 완전히 삭제될까요? 그렇지 않습니다.
Deployment 컨트롤러는 만약의 사태를 대비하여 파드가 하나도 없는 빈 껍데기 상태의 구형 ReplicaSet 객체들을 일정 개수만큼 고스란히 보존합니다. 이를 리비전(Revision)이라고 부릅니다.

  • revisionHistoryLimit: Deployment 명세서에서 이 값을 설정(기본값 10)하여 과거의 ReplicaSet을 몇 개까지 보존할지 결정할 수 있습니다.

관리자가 kubectl rollout undo deployment/my-app 명령어를 입력하면, Deployment 컨트롤러는 즉시 현재 진행 중이거나 구동 중인 신규 ReplicaSet의 파드를 축소(Scale down)하고, 고이 간직해 두었던 바로 이전 리비전의 구형 ReplicaSet의 파드 개수를 다시 원래 목표치로 늘립니다(Scale up).

과거의 ReplicaSet은 당시의 컨테이너 이미지 버전, 환경 변수, 설정값들을 완벽하게 기억하고 있는 타임캡슐과 같습니다. 따라서 롤백 명령이 떨어지는 즉시, 별도의 설정 파일 수정 없이도 인프라 상태를 완벽하게 과거 시점으로 되감을 수 있습니다.


결론적으로 쿠버네티스의 Deployment는 단순히 컨테이너를 실행하는 도구가 아닙니다. 하위의 ReplicaSet을 장기말처럼 부리며, 해시 알고리즘으로 버전을 통제하고, 무중단 배포와 롤백이라는 고도의 인프라 엔지니어링을 자동화한 강력한 오케스트레이션 엔진입니다. Deployment와 ReplicaSet의 이 우아한 계층적 협력 구조를 명확히 이해하는 것이 클라우드 네이티브 아키텍처를 마스터하는 진정한 시작점입니다.