글 목록으로 돌아가기

CloudNative

Kubernetes ReplicaSet과 Deployment

ReplicaSet의 Pod 수 조정과 삭제 전파, Deployment의 배포 전략·진행 조건·Rollback 및 Node 유지보수 정리

Dohyeon Kim
Dohyeon Kim 2026년 8월 27일 · 10분 읽기 · 수정 2026년 9월 7일
CloudNative AutoEverSW Kubernetes

ReplicaSet은 Label Selector와 일치하는 Pod를 지정한 수만큼 유지한다. Deployment는 ReplicaSet을 한 단계 위에서 관리하여 Pod 수 유지뿐 아니라 Application의 Rolling Update와 Rollback까지 수행한다.

1 ) ReplicaSet


ReplicaSet

Label Selector와 일치하는 Pod가 spec.replicas에 지정한 수만큼 실행되도록 지속적으로 조정하는 Controller Resource이다.

Pod만 직접 생성하면 Container Process가 실패했을 때 kubelet이 Container를 재시작할 수는 있지만, Pod가 삭제되거나 Node 장애로 사라진 Pod를 대신할 새 Pod를 생성하는 상위 Controller는 없다. ReplicaSet은 현재 Pod 수가 원하는 수보다 적으면 새 Pod를 만들고, 많으면 일치하는 Pod를 줄인다.

ReplicationController도 Pod 복제 수를 관리하지만 Legacy Resource이다. 신규 구성에서는 ReplicaSet을 사용하며, 일반적인 Application은 ReplicaSet을 직접 배포하기보다 Deployment를 통해 관리한다.

Control Plane과 Worker의 조정 흐름

ReplicaSet의 상태 조정은 다음과 같이 이루어진다.

Control Plane
ReplicaSet Controller
  │ Label Selector와 일치하는 Pod 수 계산
  ├── 부족함 ──▶ Pod 생성 요청
  └── 초과함 ──▶ Pod 삭제 요청
                    │
                    ▼
               Scheduler
                    │ Worker 선택
                    ▼
Worker의 kubelet ──▶ Container Runtime ──▶ Container 실행

Worker나 Pod에 장애가 생기면 Control Plane은 API Server에 기록된 상태를 기준으로 부족한 Replica를 감지한다. Scheduler가 새 Pod를 실행할 Worker를 선택하고 해당 Worker의 kubelet이 Container를 실행한다.

ReplicaSet은 Application 자체의 Data 복제나 Session 복구를 수행하지 않는다. 여러 Pod가 대체 가능하도록 Application을 구성하고 필요한 Data는 외부 저장소에서 관리해야 한다.

2 ) ReplicaSet 생성


다음 내용을 sample-rs.yaml로 저장한다.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: sample-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx
Field 역할
spec.replicas 유지할 Pod 수
spec.selector.matchLabels ReplicaSet이 관리 대상으로 계산할 Pod Label
spec.template Pod 수가 부족할 때 새로 생성할 Pod Template
template.metadata.labels 생성되는 Pod에 부여할 Label

Master 또는 kubeconfig가 설정된 관리 Client에서 Manifest를 적용한다.

kubectl apply -f sample-rs.yaml

ReplicaSet과 생성된 Pod를 확인한다.

kubectl get replicasets
kubectl get pods -l app=sample-app -o wide

ReplicaSet이 생성한 Pod의 이름은 sample-rs-<임의 문자열> 형태이다. 각 Pod의 이름은 다르지만 같은 Pod Template과 Label을 사용한다.

상세 상태와 최근 Event를 확인한다.

kubectl describe replicaset sample-rs

describe는 장기간 증감 이력을 제공하는 명령이 아니다. 현재 Replica 수, Selector, Pod Template, Condition과 최근 Event를 확인하는 데 사용한다.

3 ) Label Selector와 Pod 수 조정


ReplicaSet의 selectortemplate에 지정한 Label을 포함해야 한다. 두 값이 일치하지 않으면 API Server가 Resource 생성을 거부한다.

다음 잘못된 Manifest를 sample-rs-fail.yaml로 저장한다.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: sample-rs-fail
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app-fail
    spec:
      containers:
        - name: nginx-container
          image: nginx

적용하면 Selector가 Pod Template Label과 일치하지 않는다는 오류가 발생한다.

kubectl apply -f sample-rs-fail.yaml
The ReplicaSet "sample-rs-fail" is invalid:
spec.template.metadata.labels: Invalid value:
selector does not match template labels

오류를 해결하려면 spec.selector.matchLabelsspec.template.metadata.labelsapp 값을 같게 설정한다.

같은 Label의 독립 Pod 생성

다음 내용을 sample-rs-pod.yaml로 저장한다. 이 Pod는 ReplicaSet과 같은 app: sample-app Label을 사용하지만 ownerReferences는 없는 독립 Pod로 요청된다.

apiVersion: v1
kind: Pod
metadata:
  name: sample-rs-pod
  labels:
    app: sample-app
spec:
  containers:
    - name: nginx-container
      image: nginx

Pod를 생성하고 즉시 상태 변화를 관찰한다.

kubectl apply -f sample-rs-pod.yaml
kubectl get pods -l app=sample-app --watch

API Server는 Pod 생성 요청을 정상적으로 처리한다. 그 결과 일치하는 Pod가 replicas: 3보다 많아지면 ReplicaSet Controller가 Selector와 일치하는 Pod 중 하나를 삭제하여 총수를 다시 3개로 맞춘다. 반드시 새로 생성한 sample-rs-pod가 삭제된다고 보장되지는 않는다.

최종 Pod 수를 확인한다.

kubectl get pods -l app=sample-app

4 ) ReplicaSet Scaling


Replica 수는 Manifest의 spec.replicas를 수정한 뒤 다시 적용하거나 kubectl scale로 변경한다.

kubectl scale replicaset sample-rs --replicas=5

변경된 원하는 수와 현재 실행 수를 확인한다.

kubectl get replicaset sample-rs
kubectl get pods -l app=sample-app

kubectl scale은 Cluster의 Live Object를 직접 변경한다. Manifest를 기준으로 지속적으로 관리한다면 File의 spec.replicas도 같은 값으로 수정하여 다음 apply에서 원래 값으로 되돌아가지 않게 한다.

ReplicaSet 삭제와 Garbage Collection

Kubernetes Resource는 metadata.ownerReferences로 소유 관계를 기록한다. ReplicaSet이 생성한 Pod에는 ReplicaSet을 가리키는 소유자 정보가 있으며, ReplicaSet 삭제 시 Garbage Collector가 이 관계를 기준으로 종속 Pod를 처리한다.

전파 방식 동작
background 소유자를 먼저 삭제한 뒤 Garbage Collector가 종속 Resource를 비동기로 삭제한다. kubectl delete의 기본 방식이다.
foreground 종속 Resource가 삭제될 때까지 소유자를 삭제 중 상태로 유지한다.
orphan 소유자만 삭제하고 종속 Resource는 남긴다. 남은 Pod는 더 이상 해당 ReplicaSet이 관리하지 않는다.

먼저 ReplicaSet과 Pod의 소유 관계를 확인한다.

kubectl get pod -l app=sample-app \
  -o custom-columns='NAME:.metadata.name,OWNER_KIND:.metadata.ownerReferences[0].kind,OWNER_NAME:.metadata.ownerReferences[0].name'

삭제 전파 방식은 --cascade Option으로 선택한다.

kubectl delete replicaset sample-rs --cascade=foreground

orphan을 확인하려면 ReplicaSet을 다시 생성한 뒤 다음과 같이 삭제한다.

kubectl apply -f sample-rs.yaml
kubectl delete replicaset sample-rs --cascade=orphan
kubectl get pods -l app=sample-app

남은 Pod에는 ReplicaSet의 자동 복구와 Scaling이 적용되지 않는다. 다음 실습을 위해 Manifest를 다시 적용할 때 같은 Label의 고아 Pod가 Replica 수 계산에 포함될 수 있으므로 먼저 정리한다.

kubectl delete pods -l app=sample-app
kubectl apply -f sample-rs.yaml

5 ) Deployment


Deployment

ReplicaSet을 생성하고 전환하여 Stateless Application의 배포, Scaling, Rolling Update와 Rollback을 관리하는 Controller Resource이다.

Deployment의 제어 관계는 다음과 같다.

Deployment Controller
        │ ReplicaSet 생성·전환
        ▼
    ReplicaSet
        │ Pod 수 유지
        ▼
       Pods

직접 생성한 단독 Pod는 삭제된 뒤 자동으로 대체되지 않는다. ReplicaSet은 Pod 수를 유지하지만 Pod Template 변경에 대한 Rollout과 Rollback을 관리하지 않는다. 일반적인 Stateless Application은 Deployment로 배포한다.

6 ) Deployment 생성


다음 내용을 sample-deployment.yaml로 저장한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  minReadySeconds: 10
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: sample-deployment
  template:
    metadata:
      labels:
        app: sample-deployment
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.26

Manifest를 적용하고 Deployment가 사용 가능한 상태가 될 때까지 기다린다.

kubectl apply -f sample-deployment.yaml
kubectl rollout status deployment/sample-deployment

Deployment, ReplicaSet과 Pod의 관계를 Label과 함께 확인한다.

kubectl get deployments
kubectl get replicasets
kubectl get pods -l app=sample-deployment --show-labels

Manifest 없이 간단한 Deployment를 생성할 수도 있다.

kubectl create deployment sample-deployment-by-cli --image=nginx

명령형 생성은 빠른 확인에는 편리하지만 설정을 반복하고 변경 이력을 관리하려면 Manifest를 저장하여 kubectl apply로 관리하는 편이 적합하다.

7 ) Image Update와 ReplicaSet 전환


Deployment의 Pod Template에 있는 Image를 변경한다.

kubectl set image deployment/sample-deployment \
  nginx-container=nginx:1.27

Rollout 진행 상태를 확인한다.

kubectl rollout status deployment/sample-deployment
kubectl get replicasets
kubectl get pods -l app=sample-deployment

Pod Template이 변경되면 Deployment는 새 ReplicaSet을 만들거나 동일한 Template의 기존 ReplicaSet을 재사용하여 전환한다. 기본 Rolling Update에서는 새 Pod를 늘리고 이전 Pod를 줄이며, 준비 상태를 확인하면서 전환한다.

Rolling Update 중 유지할 Pod 수는 다음 Field로 조정할 수 있다.

Field 역할
spec.strategy.rollingUpdate.maxSurge 원하는 Replica 수보다 추가로 만들 수 있는 최대 Pod 수
spec.strategy.rollingUpdate.maxUnavailable Update 중 사용할 수 없어도 되는 최대 Pod 수

maxSurgemaxUnavailable은 정수 또는 비율로 지정한다. Replica가 3개이고 두 값을 모두 1로 설정하면 Update 중 최대 4개까지 생성할 수 있으며, 사용 가능한 Pod는 최소 2개를 유지한다.

Recreate 전략

Recreate는 Pod Template이 변경되면 이전 ReplicaSet의 Pod를 모두 종료한 뒤 새 ReplicaSet의 Pod를 생성한다. 두 Version이 동시에 실행되면 안 되는 Workload에는 사용할 수 있지만 전환 중 Application이 중단된다.

다음 내용을 sample-deployment-recreate.yaml로 저장한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment-recreate
spec:
  replicas: 3
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: sample-deployment-recreate
  template:
    metadata:
      labels:
        app: sample-deployment-recreate
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.26

적용 후 Image를 변경하면서 Pod 종료와 생성을 관찰한다.

kubectl apply -f sample-deployment-recreate.yaml
kubectl get pods -l app=sample-deployment-recreate --watch

다른 Terminal에서 다음 명령을 실행한다.

kubectl set image deployment/sample-deployment-recreate \
  nginx-container=nginx:1.27

RollingUpdate 전략과 배포 진행 조건

RollingUpdate는 이전 Pod를 줄이는 과정과 새 Pod를 늘리는 과정을 겹쳐 가용성을 유지한다. Control Plane의 Deployment Controller가 두 ReplicaSet의 Replica 수를 조정하고, Scheduler가 새 Pod를 배치하면 선택된 Worker의 kubelet이 Container를 실행하고 Probe 결과를 보고한다.

Field 역할
spec.minReadySeconds 새 Pod가 Ready가 된 뒤 Available로 인정되기까지 안정적으로 유지해야 하는 최소 시간
spec.revisionHistoryLimit Rollback에 사용할 이전 ReplicaSet을 보존하는 개수
spec.progressDeadlineSeconds 배포 진행이 멈췄다고 판단하기까지 기다리는 시간

progressDeadlineSeconds를 초과하면 Deployment Condition에 ProgressDeadlineExceeded가 기록된다. 이 Field 자체가 자동 Rollback을 수행하지는 않으므로 상태를 감시하는 운영 절차나 별도 자동화가 필요하다.

kubectl get deployment sample-deployment \
  -o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\n"}{end}'

spec.replicas만 변경하는 Scaling은 Pod Template 변경이 아니므로 새로운 ReplicaSet을 만들지 않는다.

과거 kubectl set image--record Option은 실행 Command를 변경 원인으로 기록하는 데 사용되었지만 Deprecated되어 현재 명령에서는 사용하지 않는다. 변경 목적은 배포 절차나 Annotation 등 별도의 관리 방식으로 기록한다.

8 ) Rollout History와 Rollback


Deployment의 Revision 목록을 확인한다.

kubectl rollout history deployment/sample-deployment

특정 Revision의 Pod Template을 확인한다.

kubectl rollout history deployment/sample-deployment --revision=2

특정 Revision으로 되돌린다.

kubectl rollout undo deployment/sample-deployment --to-revision=2
kubectl rollout status deployment/sample-deployment

바로 이전 Revision으로 되돌릴 때는 Revision 번호를 생략한다.

kubectl rollout undo deployment/sample-deployment
kubectl rollout status deployment/sample-deployment

Rollback은 과거 Pod를 그대로 다시 실행하는 방식이 아니다. Deployment가 이전 Pod Template을 원하는 상태로 선택하고 ReplicaSet의 Replica 수를 조정하여 Pod를 다시 전환한다.

9 ) Rollout Pause와 Resume


여러 Pod Template 변경을 하나의 Rollout으로 묶어 적용하려면 진행을 일시 중지할 수 있다.

kubectl rollout pause deployment/sample-deployment

Image를 변경한다.

kubectl set image deployment/sample-deployment \
  nginx-container=nginx:1.28

Pause 상태에서도 Deployment의 Pod Template 변경은 저장되지만 새 ReplicaSet으로 전환하는 Rollout은 진행되지 않는다. kubectl rollout status는 Rollback 명령이 아니며 배포 완료 여부를 기다리는 명령이므로, Pause 상태에서는 완료를 기다리며 종료되지 않을 수 있다.

현재 Image와 Pause Condition을 확인한다.

kubectl get deployment sample-deployment \
  -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'

kubectl describe deployment sample-deployment

변경을 적용하려면 Rollout을 재개하고 상태를 확인한다.

kubectl rollout resume deployment/sample-deployment
kubectl rollout status deployment/sample-deployment

10 ) Deployment Scaling


Manifest의 spec.replicas를 수정해서 적용하거나 kubectl scale로 Replica 수를 변경할 수 있다.

kubectl scale deployment/sample-deployment --replicas=5

Deployment가 원하는 Replica 수와 사용 가능한 Replica 수를 확인한다.

kubectl get deployment sample-deployment
kubectl get pods -l app=sample-deployment

kubectl scale 역시 Live Object를 변경하므로 Manifest를 지속적인 기준으로 사용한다면 File의 replicas 값도 함께 맞춘다.

11 ) cordon으로 신규 Pod 배치 차단


cordon

Node를 SchedulingDisabled 상태로 변경하여 Scheduler가 일반적인 신규 Pod를 해당 Node에 배치하지 않도록 설정하는 작업이다.

Hardware 이상 징후를 확인했거나 점검을 준비하는 Worker에는 새로운 Pod가 배치되지 않도록 먼저 Cordon을 설정할 수 있다. 모든 명령은 Master 또는 kubeconfig가 설정된 관리 Client에서 실행한다.

실습 전 Worker 이름과 현재 Pod 배치를 확인한다.

kubectl get nodes
kubectl scale deployment/sample-deployment --replicas=2
kubectl get pods -l app=sample-deployment -o wide

Scheduler는 Resource 여유, Scheduling 조건과 점수에 따라 Worker를 선택한다. Worker가 두 대라고 해서 Pod가 항상 정확히 절반씩 배치되는 것은 아니다.

worker1에 Cordon을 설정한다.

kubectl cordon worker1
kubectl get nodes

worker1의 상태에 SchedulingDisabled가 표시되는지 확인한다. Cordon은 이미 실행 중인 Pod를 이동하거나 종료하지 않는다.

Deployment를 4개로 확장하고 새 Pod의 배치 위치를 확인한다.

kubectl scale deployment/sample-deployment --replicas=4
kubectl get pods -l app=sample-deployment -o wide

기존 worker1 Pod는 그대로 실행되지만 새 Pod는 Scheduling 가능한 다른 Worker에 배치된다. Cluster에 사용할 수 있는 다른 Worker가 없거나 Resource가 부족하면 신규 Pod는 Pending 상태에 머물 수 있다.

Control Plane과 Worker 관점의 동작은 다음과 같다.

Master·관리 Client의 kubectl cordon
                │
                ▼
            API Server
                │ Node를 SchedulingDisabled로 변경
                ▼
             Scheduler
                │ 신규 Pod 배치 대상에서 worker1 제외
                ▼
다른 Worker의 kubelet ──▶ Container Runtime ──▶ 신규 Container 실행

12 ) drain과 uncordon


drain

Node 유지보수를 위해 Scheduling을 차단하고 Eviction 가능한 일반 Workload Pod를 안전하게 비우는 작업이다.

worker1의 일반 Workload Pod를 다른 Worker로 이동할 수 있도록 Drain을 실행한다.

kubectl drain worker1 --ignore-daemonsets
Option 역할
--ignore-daemonsets Drain이 직접 제거하지 않는 DaemonSet 관리 Pod를 무시하고 작업 계속
--delete-emptydir-data emptyDir Data가 삭제됨을 허용하며 명시적으로 사용해야 하는 Option
--force Controller가 관리하지 않는 Pod가 있을 때 삭제를 허용하는 Option

--delete-emptydir-data--force는 Data 손실이나 독립 Pod 삭제 가능성이 있으므로 오류를 확인하지 않고 바로 추가하지 않는다. PodDisruptionBudget이 허용 중단 수를 제한하면 Drain은 Application 가용성을 지키기 위해 대기하거나 실패할 수 있다.

Drain 요청이 처리되는 흐름은 다음과 같다.

Master·관리 Client의 kubectl drain
                │
                ▼
          API Server의 Eviction
                │
                ▼
Deployment·ReplicaSet Controller가 부족한 Pod 감지
                │
                ▼
Scheduler가 다른 Worker 선택
                │
                ▼
다른 Worker의 kubelet이 대체 Pod 실행

DaemonSet Pod는 각 Node에서 수행할 역할이 있으므로 --ignore-daemonsets를 사용해도 Drain이 직접 삭제하지 않는다. Static Pod와 nodeName을 직접 지정하여 Scheduler를 우회한 Pod도 별도로 확인해야 한다.

Pod가 다른 Worker에서 Ready 상태인지 확인한다.

kubectl get pods -l app=sample-deployment -o wide
kubectl get node worker1

Node 점검이 끝나면 Scheduling을 다시 허용한다.

kubectl uncordon worker1
kubectl get nodes

Uncordon은 이후 생성되는 Pod의 배치 대상으로 Node를 되돌린다. 다른 Worker로 이동한 기존 Pod를 자동으로 worker1에 재분배하지는 않는다.

13 ) 실습 Resource 정리


Master 또는 관리 Client에서 생성한 Resource를 정리한다.

kubectl delete -f sample-rs-pod.yaml --ignore-not-found
kubectl delete -f sample-rs.yaml --ignore-not-found
kubectl delete -f sample-deployment.yaml --ignore-not-found
kubectl delete -f sample-deployment-recreate.yaml --ignore-not-found
kubectl delete deployment sample-deployment-by-cli --ignore-not-found

삭제 결과를 확인한다.

kubectl get replicasets,deployments,pods

전체 정리


최종 정리

  • ReplicaSet은 Label Selector와 일치하는 Pod를 spec.replicas 수만큼 유지한다.

  • Selector와 Pod Template Label은 일치해야 하며 같은 Label의 독립 Pod도 Replica 수 계산에 포함된다.

  • ReplicaSet 삭제 시 Garbage Collector는 소유 관계와 삭제 전파 방식에 따라 종속 Pod를 삭제하거나 남긴다.

  • Deployment는 ReplicaSet을 관리하여 Stateless Application의 Rolling Update와 Rollback을 제공한다.

  • Recreate는 이전 Pod를 모두 종료한 뒤 새 Pod를 생성하고, RollingUpdate는 두 ReplicaSet의 Pod를 점진적으로 전환한다.

  • minReadySeconds, revisionHistoryLimit, progressDeadlineSeconds로 가용 판정, Revision 보존, 진행 제한 시간을 조정한다.

  • Pod Template 변경은 ReplicaSet 전환을 일으키지만 Replica 수만 변경하는 Scaling은 새 ReplicaSet을 만들지 않는다.

  • rollout history는 Revision을 확인하고 rollout undo는 이전 Pod Template으로 전환하며 rollout status는 진행 상태를 기다린다.

  • cordon은 신규 Scheduling을 차단하고 drain은 Eviction 가능한 Workload Pod를 비우며 uncordon은 Scheduling을 다시 허용한다.

  • Scheduler는 여러 Worker에 Pod를 배치하지만 항상 정확히 같은 수로 균등 분배한다고 보장하지 않는다.

  • Control Plane의 Controller가 원하는 상태를 조정하고 Worker의 kubelet과 Container Runtime이 실제 Pod를 실행한다.

댓글