Notes
K8s 14. Rolling Update
Kubernetes Deployment를 Pod template과 replica 수를 선언하는 workload controller로 보고, ReplicaSet, rolling update, rollout status, rollback, selector, probe, troubleshooting 흐름까지 정리한다.
- Published
- Updated
- Area
- Cloud Infrastructure
- Type
- concept
- Series
- Kubernetes Essentials
- Category
- Notes
Kubernetes에서 application을 운영할 때 가장 기본이 되는 리소스 중 하나가 Deployment다. Deployment는 Pod를 직접 하나씩 관리하는 방식이 아니라, 원하는 Pod template과 replica 수를 선언하면 Kubernetes가 그 상태를 계속 유지하도록 만드는 workload controller다.
사용자:
이 image를 사용해서
이 label을 가진 Pod를
replica 3개로 유지해줘
Kubernetes Deployment:
ReplicaSet 생성
Pod 생성
replica 수 유지
rolling update 수행
rollout history 관리
rollback 가능
Deployment는 단순히 “Pod를 띄우는 YAML”이 아니다. Stateless application을 Kubernetes에서 선언적으로 배포하고, 업데이트하고, 문제가 생겼을 때 이전 버전으로 되돌릴 수 있게 해주는 운영 단위다.
핵심 요약
Kubernetes Deployment의 핵심 구조는 다음과 같다.
Deployment
→ desired state 선언
→ ReplicaSet 생성/관리
→ Pod replica 유지
→ rolling update
→ rollout history
→ rollback
Deployment를 이해할 때는 다음 관계를 먼저 잡아야 한다.
Deployment
↓
ReplicaSet
↓
Pod
Pod
Pod
각 리소스의 역할은 다르다.
| 리소스 | 역할 |
|---|---|
| Deployment | application 배포 상태, update, rollback 관리 |
| ReplicaSet | 지정된 수의 Pod replica 유지 |
| Pod | 실제 container 실행 단위 |
한 문장으로 정리하면 다음과 같다.
Kubernetes Deployment는 Pod template과 replica 수를 선언하면 Kubernetes가 ReplicaSet을 통해 Pod를 유지하고, image update, rolling update, rollout status, rollback까지 관리해주는 stateless application 운영 리소스다.
Deployment가 필요한 이유
Kubernetes에서 가장 작은 실행 단위는 Pod다. 하지만 production에서는 보통 Pod를 직접 단독으로 만들지 않는다.
예를 들어 다음처럼 Pod 하나만 직접 띄웠다고 하자.
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-app
image: nginx:1.25
이 방식은 단순하지만 운영에는 약하다.
Pod가 죽으면 누가 다시 만들 것인가?
Pod를 3개로 늘리고 싶으면 어떻게 할 것인가?
새 image로 업데이트하려면 어떻게 할 것인가?
업데이트가 실패하면 이전 버전으로 어떻게 되돌릴 것인가?
배포 중에도 traffic을 계속 받으려면 어떻게 할 것인가?
Deployment는 이 문제를 해결한다.
Pod 직접 생성
→ 단일 실행 객체 생성
Deployment 생성
→ 원하는 Pod template과 replica 수 선언
→ ReplicaSet을 통해 Pod 수 유지
→ update/rollback 관리
즉 Deployment는 application을 “한 번 실행”하는 것이 아니라, application의 운영 상태를 선언하고 유지하는 리소스다.
Deployment의 기본 구조
가장 기본적인 Deployment는 다음처럼 생겼다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: nginx:1.25
ports:
- containerPort: 80
이 YAML에서 중요한 부분은 다음이다.
| 필드 | 의미 |
|---|---|
apiVersion | 사용할 Kubernetes API group/version |
kind | 생성할 리소스 종류, 여기서는 Deployment |
metadata.name | Deployment 이름 |
spec.replicas | 유지하고 싶은 Pod 개수 |
spec.selector | Deployment가 관리할 Pod를 찾는 label selector |
spec.template | 실제로 생성될 Pod의 template |
template.metadata.labels | Pod에 붙을 label |
template.spec.containers | Pod 안에서 실행할 container 정의 |
image | 실행할 container image |
Deployment에서 특히 중요한 것은 selector와 template.metadata.labels가 맞아야 한다는 점이다.
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
이 둘이 맞지 않으면 Deployment가 자신이 관리해야 할 Pod를 제대로 연결하지 못한다.
Deployment, ReplicaSet, Pod의 관계
Deployment를 만들면 바로 Pod만 생기는 것이 아니다. 내부적으로는 ReplicaSet이 만들어지고, ReplicaSet이 Pod replica를 유지한다.
Deployment
↓
ReplicaSet
↓
Pod
Pod
Pod
예를 들어 replicas: 3이면 다음 흐름이 된다.
Deployment desired replicas = 3
↓
ReplicaSet desired replicas = 3
↓
Pod 3개 생성
Pod 하나가 죽으면 ReplicaSet이 다시 만든다.
현재 Pod = 2
desired Pod = 3
↓
ReplicaSet이 새 Pod 1개 생성
따라서 Deployment의 핵심은 “현재 상태를 원하는 상태로 계속 맞추는 것”이다.
Declarative model: 명령이 아니라 상태를 선언한다
Kubernetes는 imperative command 중심이 아니라 declarative state 중심으로 동작한다.
Imperative 방식은 다음에 가깝다.
이 Pod 하나 실행해.
이 Pod 하나 더 실행해.
이전 Pod 지워.
새 Pod 띄워.
Declarative 방식은 다음에 가깝다.
항상 app=hello인 Pod가 3개 있어야 한다.
image는 nginx:1.25여야 한다.
Kubernetes controller는 계속 실제 상태를 관찰한다.
Desired state:
replicas = 3
Actual state:
running pods = 2
Controller action:
create 1 more pod
Deployment는 이 declarative model의 대표적인 예다.
Deployment 생성 흐름
Deployment를 적용하면 다음 명령을 사용한다.
kubectl apply -f deployment.yaml
내부 흐름은 다음과 같다.
1. kubectl이 YAML을 API Server에 전송
2. API Server가 Deployment object 저장
3. Deployment Controller가 새 Deployment 감지
4. Deployment Controller가 ReplicaSet 생성
5. ReplicaSet Controller가 필요한 Pod 수 계산
6. Pod 생성
7. Scheduler가 Pod를 Node에 배치
8. Kubelet이 해당 Node에서 container 실행
9. Pod가 Running/Ready 상태로 전환
즉 kubectl apply는 container를 직접 실행하는 명령이 아니다.
kubectl apply
→ desired state 등록
Kubernetes control plane
→ 그 desired state에 맞게 실제 리소스 생성
Deployment 상태 확인
Deployment를 만들었으면 먼저 Deployment 상태를 확인한다.
kubectl get deployments
예시 출력:
NAME READY UP-TO-DATE AVAILABLE AGE
hello-deployment 3/3 3 3 1m
각 컬럼의 의미는 다음이다.
| 컬럼 | 의미 |
|---|---|
READY | 준비된 Pod 수 / 원하는 Pod 수 |
UP-TO-DATE | 최신 template으로 생성된 Pod 수 |
AVAILABLE | 사용 가능한 Pod 수 |
AGE | 리소스 생성 후 경과 시간 |
Pod 상태도 확인한다.
kubectl get pods
ReplicaSet 상태도 볼 수 있다.
kubectl get replicasets
전체 관계를 확인하려면 다음 세 명령을 함께 보면 된다.
kubectl get deployment
kubectl get replicaset
kubectl get pods
Deployment 문제를 볼 때는 이 세 계층을 함께 봐야 한다.
Deployment 디버깅의 기본 3단계
Deployment 문제를 디버깅할 때 기본 흐름은 다음 3단계다.
1. 상태 보기
kubectl get
2. 자세한 원인 보기
kubectl describe
3. application 로그 보기
kubectl logs
상태 보기: kubectl get
먼저 전체 상태를 본다.
kubectl get deployments
kubectl get replicasets
kubectl get pods
문제 상황 예시는 다음과 같다.
Deployment READY가 0/3이다.
Pod가 Pending 상태다.
Pod가 ImagePullBackOff 상태다.
Pod가 CrashLoopBackOff 상태다.
Pod는 Running인데 Ready가 아니다.
kubectl get은 “어디가 이상한지” 빠르게 찾는 단계다.
자세히 보기: kubectl describe
이후 상세 원인을 본다.
kubectl describe deployment hello-deployment
kubectl describe pod <pod-name>
describe에서 중요한 것은 아래쪽 Events다.
Events:
Type Reason Message
---- ------ -------
Warning FailedScheduling 0/3 nodes are available: insufficient cpu
Warning Failed Failed to pull image
Warning Unhealthy Readiness probe failed
Events는 Kubernetes controller와 scheduler가 남긴 힌트다.
로그 보기: kubectl logs
Pod가 실행은 됐지만 application이 죽거나 오류를 낸다면 log를 봐야 한다.
kubectl logs <pod-name>
Deployment 단위로 볼 수도 있다.
kubectl logs deployment/hello-deployment
CrashLoopBackOff 상태에서는 이전 container log가 중요할 수 있다.
kubectl logs <pod-name> --previous
정리하면 다음이다.
kubectl get
→ 어떤 리소스가 이상한가?
kubectl describe
→ Kubernetes 관점에서 왜 이상한가?
kubectl logs
→ application 내부에서 무슨 일이 났는가?
Deployment update: image 변경
Deployment의 가장 중요한 기능 중 하나는 application version update다.
예를 들어 image를 nginx:1.25에서 nginx:1.26으로 바꾼다고 하자.
YAML을 수정한 뒤 다시 적용할 수 있다.
containers:
- name: hello
image: nginx:1.26
kubectl apply -f deployment.yaml
또는 명령으로 image를 바꿀 수 있다.
kubectl set image deployment/hello-deployment hello=nginx:1.26
이때 Deployment는 기존 Pod를 한 번에 모두 지우지 않고, 기본적으로 rolling update를 수행한다.
old ReplicaSet:
nginx:1.25
new ReplicaSet:
nginx:1.26
흐름은 다음과 같다.
1. 새 ReplicaSet 생성
2. 새 Pod 일부 생성
3. 새 Pod가 Ready 되면 기존 Pod 일부 종료
4. 이 과정을 반복
5. 모든 Pod가 새 version으로 교체
중요한 구분: application upgrade와 apiVersion
Application version을 올릴 때 Deployment의 apiVersion을 바꾸는 것이 아니다.
잘못된 이해:
application version을 올릴 때
Deployment의 apiVersion도 바꾼다.
올바른 이해:
application version을 올릴 때
container image tag나 Pod template을 바꾼다.
apiVersion은 Kubernetes API 리소스 버전을 의미한다.
예를 들어 다음은 application upgrade다.
containers:
- name: hello
image: registry.example.com/hello:1.0.0
containers:
- name: hello
image: registry.example.com/hello:1.1.0
하지만 apiVersion은 그대로일 수 있다.
apiVersion: apps/v1
kind: Deployment
apiVersion은 Kubernetes API의 version이지 application version이 아니다.
Rolling update
Deployment의 기본 update 방식은 rolling update다.
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
maxSurge는 desired Pod 수보다 초과해서 생성할 수 있는 최대 Pod 수를 의미한다. maxUnavailable은 update 중 unavailable할 수 있는 최대 Pod 수를 의미한다.
예를 들어 replica가 4개이고 다음 설정이 있다고 하자.
maxSurge: 1
maxUnavailable: 1
그러면 rolling update 중 대략 다음 조건을 지킨다.
최대 Pod 수:
desired 4 + maxSurge 1 = 5
최소 available Pod 수:
desired 4 - maxUnavailable 1 = 3
즉 Kubernetes는 update 중에도 가능한 service availability를 유지하려고 한다.
기존 Pod 4개
↓
새 Pod 1개 추가
↓
새 Pod Ready 확인
↓
기존 Pod 1개 제거
↓
반복
Rolling update는 무중단 배포에 가까운 경험을 제공하지만, application이 old/new version 동시 실행을 견딜 수 있어야 한다.
확인할 것:
old version과 new version이 동시에 떠도 되는가?
DB schema가 양쪽 version과 호환되는가?
API response가 backward-compatible한가?
cache format이 바뀌지 않는가?
event schema가 깨지지 않는가?
Rollout 상태 확인
Update 후에는 rollout 상태를 확인해야 한다.
kubectl rollout status deployment/hello-deployment
rollout 관련 주요 명령은 다음과 같다.
kubectl rollout status deployment/hello-deployment
kubectl rollout history deployment/hello-deployment
kubectl rollout undo deployment/hello-deployment
kubectl apply가 성공했다고 해서 rollout이 성공한 것은 아니다.
kubectl apply 성공
→ API Server에 desired state 등록 성공
rollout status 성공
→ 새 Pod들이 정상적으로 Ready 상태가 됨
따라서 배포 후에는 반드시 rollout 상태를 확인해야 한다.
Rollout history와 rollback
Deployment는 rollout history를 관리할 수 있다.
kubectl rollout history deployment/hello-deployment
출력 예시:
deployment.apps/hello-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
문제가 생기면 이전 revision으로 rollback할 수 있다.
kubectl rollout undo deployment/hello-deployment
특정 revision으로 되돌릴 수도 있다.
kubectl rollout undo deployment/hello-deployment --to-revision=1
이 점도 중요하다.
image 변경
env 변경
label 변경
container command 변경
→ Pod template 변경
→ 새 revision 생성
replicas 수만 변경
→ Pod template 변경 아님
→ 새 revision 생성 안 됨
즉 rollback은 application template을 되돌리는 기능이지, 모든 Deployment 설정 전체를 되돌리는 만능 undo가 아니다.
Deployment revision이 생성되는 조건
Revision은 Deployment가 rollout될 때 만들어진다. 핵심 기준은 .spec.template 변경이다.
예를 들어 다음 변경은 revision을 만든다.
spec:
template:
spec:
containers:
- name: hello
image: nginx:1.26
또는 env가 바뀌어도 revision이 생긴다.
env:
- name: FEATURE_FLAG
value: "true"
하지만 replica 수만 바꾸는 것은 revision을 만들지 않는다.
kubectl scale deployment hello-deployment --replicas=5
왜냐하면 이것은 Pod template 변경이 아니라 scaling 변경이기 때문이다.
이 구조 덕분에 Kubernetes는 autoscaling과 rollout history를 분리할 수 있다.
rollout:
Pod template 변경 관리
scaling:
replica 수 변경 관리
Deployment와 Service는 역할이 다르다
Deployment는 Pod를 만들고 유지한다. 하지만 traffic을 안정적으로 전달하려면 Service가 필요하다.
Deployment
→ Pod 생성/관리
Service
→ Pod 집합에 stable network endpoint 제공
예를 들어 Deployment가 Pod 3개를 만든다.
Pod A: 10.0.1.10
Pod B: 10.0.1.11
Pod C: 10.0.1.12
Pod IP는 언제든 바뀔 수 있다.
Pod 재시작
↓
새 Pod 생성
↓
새 IP 할당
Service는 label selector로 Pod들을 묶는다.
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
selector:
app: hello
ports:
- port: 80
targetPort: 80
구조는 다음과 같다.
Client
↓
Service
↓
Ready Pod A
Ready Pod B
Ready Pod C
Deployment만 만들고 Service를 만들지 않으면, application이 내부적으로 실행되더라도 안정적인 network endpoint가 없다.
label selector가 핵심이다
Deployment와 Service 모두 label selector에 크게 의존한다.
Deployment의 selector:
selector:
matchLabels:
app: hello
Pod template의 label:
template:
metadata:
labels:
app: hello
Service의 selector:
selector:
app: hello
이 세 가지가 맞아야 한다.
Deployment selector
↓
Pod template labels
↓
Service selector
문제가 생기는 대표 상황:
Deployment selector와 Pod label이 다름
Service selector와 Pod label이 다름
label key가 app인데 selector는 name을 봄
label value가 hello인데 selector는 hello-api를 봄
이 경우 Pod는 떠 있는데 Service endpoint가 비어 있을 수 있다.
확인:
kubectl get pods --show-labels
kubectl get endpoints hello-service
kubectl describe service hello-service
Service endpoint가 비어 있다면 selector mismatch를 가장 먼저 의심해야 한다.
readinessProbe와 Deployment rollout
Deployment rollout에서 중요한 요소는 readinessProbe다.
Pod가 Running이라고 해서 traffic을 받을 준비가 된 것은 아니다.
Running
→ container process가 시작됨
Ready
→ traffic을 받을 준비가 됨
예시:
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Deployment rolling update는 새 Pod가 Ready 상태가 되어야 안정적으로 기존 Pod를 줄일 수 있다.
새 Pod 생성
↓
새 Pod Running
↓
readinessProbe 성공
↓
새 Pod Ready
↓
기존 Pod 종료 가능
readinessProbe가 없거나 부정확하면 다음 문제가 생긴다.
Pod process만 시작됨
↓
application 초기화는 아직 안 됨
↓
Service endpoint에 포함
↓
traffic 유입
↓
5xx 발생
Deployment를 production에서 쓸 때 readinessProbe는 선택이 아니라 사실상 필수에 가깝다.
livenessProbe와 startupProbe
Deployment 운영에서는 livenessProbe도 자주 함께 사용한다.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 20
역할은 다음이다.
readinessProbe:
traffic을 받을 준비가 되었는가?
livenessProbe:
process가 살아 있고 복구 가능한 상태인가?
startupProbe:
느리게 시작하는 application의 초기 기동을 보호할 것인가?
주의할 점은 livenessProbe를 너무 공격적으로 설정하면 정상적인 지연을 장애로 오인할 수 있다는 것이다.
일시적 GC pause
일시적 DB 지연
CPU throttling
기동 중 dependency 초기화
↓
livenessProbe 실패
↓
container restart
↓
CrashLoopBackOff
Probe는 목적별로 분리해야 한다.
| Probe | 목적 | 실패 시 결과 |
|---|---|---|
startupProbe | 초기 기동 시간 보호 | startup 완료 전 liveness/readiness 판단 지연 |
readinessProbe | traffic 수신 가능 여부 판단 | Service endpoint에서 제외 |
livenessProbe | container 재시작 필요 여부 판단 | container restart |
Deployment 문제 유형
Deployment에서 자주 보는 문제는 다음과 같다.
| 증상 | 가능 원인 | 확인 명령 |
|---|---|---|
Pod가 Pending | node resource 부족, scheduling 조건 불만족 | kubectl describe pod |
Pod가 ImagePullBackOff | image 이름 오류, registry 인증 실패 | kubectl describe pod, kubectl get events |
Pod가 CrashLoopBackOff | application 시작 실패, env 누락, command 오류 | kubectl logs --previous |
Deployment READY 0/3 | Pod가 Ready 되지 않음 | kubectl describe deployment, kubectl describe pod |
| Service endpoint 없음 | label selector mismatch | kubectl get endpoints, kubectl get pods --show-labels |
| rollout 멈춤 | 새 Pod Ready 실패 | kubectl rollout status, kubectl describe pod |
| rollback 필요 | 새 version 장애 | kubectl rollout undo |
문제 해결 순서는 보통 다음과 같다.
1. Deployment 상태 확인
2. ReplicaSet 상태 확인
3. Pod 상태 확인
4. Pod describe로 Events 확인
5. Pod logs 확인
6. Service/endpoint 확인
7. rollout history 확인
8. 필요하면 rollback
ImagePullBackOff 디버깅
예를 들어 image 이름을 잘못 썼다고 하자.
image: nginx:does-not-exist
Pod 상태:
kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-deployment-abc123 0/1 ImagePullBackOff 0 1m
상세 확인:
kubectl describe pod hello-deployment-abc123
Events에 다음과 비슷한 메시지가 나온다.
Failed to pull image "nginx:does-not-exist"
Back-off pulling image
해결 방향:
image 이름 확인
tag 확인
registry 접근 가능 여부 확인
private registry라면 imagePullSecrets 확인
수정 후 다시 적용한다.
kubectl apply -f deployment.yaml
CrashLoopBackOff 디버깅
CrashLoopBackOff는 container가 실행되었다가 반복적으로 죽는 상태다.
확인:
kubectl get pods
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl logs <pod-name> --previous
가능한 원인:
application 설정 누락
필수 env 없음
DB 연결 실패
잘못된 command/args
port 충돌
config 파일 누락
permission 문제
중요한 것은 Kubernetes와 application 문제를 구분하는 것이다.
Kubernetes 문제:
scheduling 실패
image pull 실패
volume mount 실패
Application 문제:
process가 시작 후 crash
설정 오류
dependency 연결 실패
CrashLoopBackOff는 대개 application 내부 문제일 가능성이 높다. 따라서 logs --previous가 중요하다.
Rollout 실패 디버깅
새 version으로 update했는데 rollout이 끝나지 않는 경우가 있다.
kubectl rollout status deployment/hello-deployment
출력 예시:
Waiting for deployment "hello-deployment" rollout to finish:
1 out of 3 new replicas have been updated...
확인할 것:
kubectl get pods
kubectl get rs
kubectl describe deployment hello-deployment
kubectl describe pod <new-pod>
kubectl logs <new-pod>
가능한 원인:
새 image pull 실패
새 version application crash
readinessProbe 실패
resource 부족으로 Pending
잘못된 env/config
selector/label 문제
문제가 새 version 때문이라면 rollback한다.
kubectl rollout undo deployment/hello-deployment
그리고 rollback 상태를 확인한다.
kubectl rollout status deployment/hello-deployment
Deployment를 실무에서 안전하게 쓰는 기준
단순히 Deployment YAML이 적용된다고 production-ready는 아니다.
운영 기준은 다음이다.
replicas가 최소 2개 이상인가?
readinessProbe가 있는가?
livenessProbe가 과도하지 않은가?
resource requests/limits가 있는가?
rollingUpdate 전략이 적절한가?
PodDisruptionBudget이 필요한가?
Service selector가 정확한가?
container image tag가 명확한가?
latest tag를 피하고 있는가?
rollout status를 CI/CD에서 확인하는가?
rollback 전략이 있는가?
예시 production-oriented Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
labels:
app: api
spec:
replicas: 3
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/api:1.0.0
ports:
- containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
memory: "512Mi"
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 20
여기서 중요한 설정은 다음이다.
replicas: 3
→ Pod 하나 장애에도 service 유지 가능성 증가
revisionHistoryLimit: 10
→ rollback 가능한 history 유지
maxUnavailable: 0
→ rolling update 중 available Pod 감소 최소화
readinessProbe
→ 준비된 Pod만 traffic 수신
resources.requests
→ scheduler가 capacity 판단 가능
memory limit
→ memory runaway 방지
Deployment와 CI/CD
Deployment는 CI/CD pipeline과 함께 쓸 때 의미가 커진다.
일반적인 흐름:
1. code push
2. test
3. image build
4. image scan
5. registry push
6. manifest image tag update
7. kubectl apply 또는 GitOps sync
8. kubectl rollout status 확인
9. smoke test
10. 실패 시 rollback
예시:
kubectl apply -f deployment.yaml
kubectl rollout status deployment/api --timeout=300s
실패 시:
kubectl rollout undo deployment/api
중요한 점은 kubectl apply 성공이 배포 성공을 의미하지 않는다는 것이다.
kubectl apply 성공
→ API Server에 desired state 등록 성공
rollout status 성공
→ 새 Pod들이 정상적으로 Ready 상태가 됨
smoke test 성공
→ 실제 application endpoint가 정상 응답
따라서 pipeline에서는 최소한 다음을 확인해야 한다.
manifest apply 성공
rollout status 성공
Service endpoint 존재
기본 API 응답 성공
error rate 증가 없음
Deployment와 autoscaling
Deployment는 HPA와 함께 자주 사용된다.
Deployment:
Pod template과 replica desired state 관리
HPA:
metric을 보고 Deployment의 replicas 값을 조정
예시:
kubectl autoscale deployment api --min=3 --max=20 --cpu-percent=70
구조:
HPA
↓ modifies replicas
Deployment
↓ controls ReplicaSet
ReplicaSet
↓ maintains Pods
중요한 점은 Deployment rollout과 scaling이 분리된다는 것이다.
image update
→ 새 rollout revision
replica 수 변경
→ scaling
→ 새 rollout revision 아님
이 분리 덕분에 HPA가 replicas를 자주 바꿔도 rollout history가 불필요하게 늘어나지 않는다.
Recreate vs RollingUpdate
Deployment strategy에는 대표적으로 두 가지가 있다.
strategy:
type: RollingUpdate
또는 다음처럼 설정할 수 있다.
strategy:
type: Recreate
비교하면 다음과 같다.
| 전략 | 방식 | 장점 | 단점 |
|---|---|---|---|
RollingUpdate | 새 Pod와 old Pod를 점진적으로 교체 | downtime 최소화 | old/new version 동시 실행 고려 필요 |
Recreate | 기존 Pod를 모두 종료한 뒤 새 Pod 생성 | 단순함 | downtime 발생 가능 |
대부분의 web/API workload는 RollingUpdate가 적합하다.
하지만 다음 경우에는 Recreate가 더 단순할 수 있다.
old/new version 동시 실행이 절대 불가능
single-writer local state가 있음
개발/테스트 환경
짧은 downtime 허용 가능
Production에서는 RollingUpdate를 쓰더라도 application compatibility를 반드시 확인해야 한다.
Deployment와 StatefulSet의 차이
모든 workload를 Deployment로 운영하는 것은 아니다.
Deployment는 stateless application에 가장 잘 맞는다.
web server
API server
stateless worker
frontend
Stateful workload에는 StatefulSet이 더 적합할 수 있다.
database
distributed storage
stateful broker
clustered system with stable identity
차이는 다음이다.
| 구분 | Deployment | StatefulSet |
|---|---|---|
| Pod identity | 임시적 | 안정적 |
| Pod 이름 | 랜덤 suffix | 순서 있는 고정 이름 |
| storage | 필요 시 PVC 사용 가능 | Pod별 stable PVC 패턴 |
| update | stateless rollout에 적합 | ordered rollout 가능 |
| 적합한 대상 | stateless app | stateful app |
Deployment는 Pod가 언제든 교체되어도 문제가 없는 workload에 적합하다.
Pod A가 죽고 Pod B가 새로 떠도
application이 정상 동작해야 한다.
Deployment 운영에서 자주 하는 실수
latest tag 사용
image: registry.example.com/api:latest
문제:
어떤 version이 배포되었는지 추적하기 어렵다.
rollback이 불명확하다.
node마다 다른 image cache를 사용할 수 있다.
권장:
image: registry.example.com/api:1.3.7
또는 commit SHA 기반 tag를 사용한다.
image: registry.example.com/api:sha-abc1234
selector 변경
Deployment의 selector는 매우 민감하다.
selector:
matchLabels:
app: api
운영 중 selector를 잘못 바꾸면 Deployment가 기존 Pod를 더 이상 관리하지 못하거나 충돌이 생길 수 있다.
readinessProbe 없음
문제:
Pod가 process만 시작되면 traffic을 받음
초기화 중 request 실패
rolling update 중 5xx 증가
resource request 없음
문제:
scheduler가 정확한 capacity 판단 불가
Node 과밀 배치
latency 증가
OOM 위험 증가
rollout status 확인 안 함
문제:
kubectl apply만 성공
실제 Pod는 CrashLoopBackOff
pipeline은 성공으로 종료
주요 명령 요약
Deployment 운영에서 자주 사용하는 명령은 다음이다.
| 목적 | 명령 |
|---|---|
| Deployment 목록 확인 | kubectl get deployments |
| ReplicaSet 확인 | kubectl get replicasets |
| Pod 확인 | kubectl get pods |
| Deployment 상세 확인 | kubectl describe deployment <name> |
| Pod 상세 확인 | kubectl describe pod <pod-name> |
| Pod 로그 확인 | kubectl logs <pod-name> |
| 이전 container 로그 확인 | kubectl logs <pod-name> --previous |
| image 변경 | kubectl set image deployment/<name> <container>=<image> |
| rollout 상태 확인 | kubectl rollout status deployment/<name> |
| rollout history 확인 | kubectl rollout history deployment/<name> |
| rollback | kubectl rollout undo deployment/<name> |
| replica 수 변경 | kubectl scale deployment <name> --replicas=<n> |
| Service endpoint 확인 | kubectl get endpoints <service-name> |
전체 mental model
Deployment를 이해하는 흐름은 다음과 같다.
1. Pod는 Kubernetes의 실행 단위지만, production에서는 보통 Pod를 직접 운영하지 않는다.
2. Deployment는 원하는 Pod template과 replica 수를 선언하는 workload controller다.
3. Deployment는 ReplicaSet을 만들고,
ReplicaSet은 원하는 수의 Pod를 유지한다.
4. 사용자가 image나 env 등 Pod template을 바꾸면
Deployment는 새 ReplicaSet을 만들고 rolling update를 수행한다.
5. rollout 중에는 maxSurge와 maxUnavailable 설정에 따라
새 Pod와 old Pod가 점진적으로 교체된다.
6. Deployment revision은 Pod template이 바뀔 때 생성된다.
replica 수만 바꾸는 scaling은 새 revision을 만들지 않는다.
7. 문제가 생기면 kubectl get → kubectl describe → kubectl logs 순서로
상태, event, application log를 확인한다.
8. rollout 문제는 kubectl rollout status/history/undo로 확인하고 복구한다.
9. Service selector와 Pod label이 맞아야 traffic이 Deployment의 Pod로 전달된다.
10. production에서는 readinessProbe, resources, 명확한 image tag,
rollout 검증, rollback 전략이 함께 필요하다.
요약
Kubernetes Deployment는 application을 Kubernetes에서 선언적으로 배포하고 운영하기 위한 기본 리소스다.
핵심 구조는 다음이다.
Deployment
→ desired state 선언
→ ReplicaSet 생성/관리
→ Pod replica 유지
→ rolling update
→ rollout history
→ rollback
가장 중요한 운영 명령은 다음이다.
kubectl get deployments
kubectl get replicasets
kubectl get pods
kubectl describe deployment <name>
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl rollout status deployment/<name>
kubectl rollout history deployment/<name>
kubectl rollout undo deployment/<name>
Deployment를 production에서 안전하게 쓰려면 readinessProbe, 명확한 image tag, resources.requests, 적절한 rolling update 전략, rollout 검증, rollback 절차를 함께 설계해야 한다.
한 문장으로 정리하면 다음과 같다.
Kubernetes Deployment는 Pod template과 replica 수를 선언하면 Kubernetes가 ReplicaSet을 통해 Pod를 유지하고, image update, rolling update, rollout status, rollback까지 관리해주는 stateless application 운영 리소스다.