Kubernetes Deployment — 무중단 배포의 표준 워크로드
Deployment가 ReplicaSet을 만들고, ReplicaSet이 Pod를 만든다. 이 한 단계를 더 둠으로써 RollingUpdate, Rollback, History가 가능해지는 구조를 분석한다.
Kubernetes Deployment — 무중단 배포의 표준 워크로드
Deployment가 하는 일
Deployment는 Stateless 애플리케이션을 선언적으로 배포/업데이트/롤백하기 위한 워크로드다.
핵심은 직접 Pod를 만들지 않는다는 점이다.
Deployment ──생성──▶ ReplicaSet ──생성──▶ Pod이 한 단계를 거침으로써:
- 이미지를 바꾸면 새 ReplicaSet을 만들고, 옛 ReplicaSet을 점진적으로 줄인다 → RollingUpdate
- 옛 ReplicaSet이 한동안 남아있어서 → Rollback 가능
- 변경 이력이 보존되어 → revision history
기본 YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web # selector와 일치해야 함
spec:
containers:
- name: app
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests: { cpu: "100m", memory: "128Mi" }
limits: { cpu: "500m", memory: "256Mi" }spec.template은 결국 Pod 정의다. Deployment는 이 템플릿대로 Pod를 N개 유지한다.
Rolling Update 전략
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 추가로 띄울 수 있는 Pod 비율
maxUnavailable: 25% # 동시에 죽일 수 있는 Pod 비율이 두 값이 무중단 배포의 핵심이다.
maxSurge0,maxUnavailable1 → 기존 Pod를 먼저 죽이고 새 Pod를 띄움 (자원 절약, 일시적 capacity 감소)maxSurge1,maxUnavailable0 → 새 Pod를 먼저 띄우고 기존 Pod를 죽임 (안전, 자원 일시 증가)
type: Recreate로 바꾸면 옛 Pod 전부 죽인 뒤 새 Pod를 띄운다. 다운타임이 발생하지만, 두 버전이 동시에 떠 있으면 안 되는 경우(예: DB 마이그레이션)에 쓴다.
배포와 롤백
# 이미지 변경 (RollingUpdate 트리거)
kubectl set image deployment/web app=nginx:1.28
# 진행 상황 확인
kubectl rollout status deployment/web
# 변경 이력
kubectl rollout history deployment/web
# 직전 버전으로 롤백
kubectl rollout undo deployment/web
# 특정 revision으로 롤백
kubectl rollout undo deployment/web --to-revision=2이력이 유지되는 이유는 옛 ReplicaSet들이 replicas: 0 상태로 남아있기 때문이다.
kubectl get rs
# web-7d4f5 3 3 3 (current)
# web-6c2e8 0 0 0 (이전 버전)
# web-5a1d3 0 0 0 (그 이전)spec.revisionHistoryLimit (기본 10)으로 보존 개수를 조절한다.
진행 / 정체 / 실패의 판정
Deployment는 다음 조건들로 상태를 판단한다.
progressDeadlineSeconds(기본 600초) 안에 진행이 없으면 FailedminReadySeconds— 새 Pod가 Ready 된 후 이 시간만큼 안정적이어야 다음 Pod로 진행
spec:
progressDeadlineSeconds: 300
minReadySeconds: 10자주 하는 실수
selector를 나중에 바꿀 수 없다
selector:
matchLabels:
app: web이 selector는 immutable이다. 바꾸려면 Deployment를 삭제 후 재생성해야 한다.
이미지 태그로 latest 사용
nginx:latest를 쓰면 같은 태그가 다른 이미지를 가리킬 수 있어 RollingUpdate가 트리거되지 않거나, 노드별로 다른 이미지가 떠 있을 수 있다. 항상 명시적 버전 태그를 쓰자.
정리
Deployment의 진짜 역할은 "Pod를 만드는 것"이 아니라 두 ReplicaSet 사이에서 점진적으로 트래픽을 옮기는 일이다. 다음 글에서는 그 ReplicaSet 자체를 더 자세히 본다.
Related Posts
같이 읽으면 좋은 글
Kubernetes CronJob — 정해진 시간마다 Job을 만드는 스케줄러
CronJob은 Job을 직접 실행하지 않는다. 스케줄에 따라 Job 객체를 만들 뿐이다. concurrencyPolicy와 startingDeadlineSeconds를 잘못 쓰면 같은 작업이 중복 실행되는 사고가 난다.
Kubernetes Job — 한 번 실행되고 끝나는 워크로드
DB 마이그레이션, 배치 처리처럼 '성공할 때까지 한 번만' 실행해야 하는 일에 Job을 쓴다. completions, parallelism, backoffLimit 세 필드의 조합이 핵심이다.
Kubernetes DaemonSet — 모든 노드에 정확히 하나씩 떠야 하는 워크로드
로그 수집, 모니터링 에이전트, CNI 플러그인은 왜 Deployment가 아니라 DaemonSet으로 떠야 하는가. 노드 추가/제거 시 자동 대응 메커니즘과 스케줄링 차이를 정리한다.