Notes
K8s 16. High-Scale Apps
Kubernetes에서 high-scale production application을 운영할 때 Deployment, Service, HPA, node autoscaling, resource requests/limits, readinessProbe, rollout, PDB, topology spread, observability, SLO를 함께 설계하는 방법을 정리한다.
- Published
- Updated
- Area
- Cloud Infrastructure
- Type
- concept
- Series
- Kubernetes Essentials
- Category
- Notes
High-scale production application을 Kubernetes에서 운영한다는 것은 단순히 Pod replica 수를 크게 설정하는 일이 아니다. 실제 운영에서는 traffic 증가, Pod 확장, Node capacity, rollout 전략, 장애 복구, Service routing, backend dependency, observability, SLO, cost control이 모두 연결된다.
Kubernetes는 high-scale application을 유연하게 운영하기 위한 기반을 제공한다.
Deployment
→ application replica 유지
Service
→ Ready Pod 뒤의 stable endpoint 제공
HPA
→ metric 기반 Pod replica 자동 조정
Node autoscaling
→ Pod를 배치할 cluster capacity 확장
readinessProbe
→ traffic을 받을 준비가 된 Pod만 Service endpoint에 포함
rolling update
→ 배포 중 availability 유지
PodDisruptionBudget
→ node drain과 maintenance 중 최소 가용성 보호
topology spread
→ zone/node 장애에 대비한 Pod 분산
observability
→ latency, error rate, saturation, scaling 상태 확인
SLO
→ Kubernetes 상태를 사용자 경험과 연결
핵심은 다음이다.
Kubernetes에서 high-scale production app을 운영한다는 것은
단순히 Pod 수를 많이 띄우는 것이 아니다.
Deployment, Service, HPA, node autoscaling, requests/limits,
readinessProbe, rolling update, PDB, topology spread,
observability, SLO, backend capacity를 함께 설계하는 것이다.
핵심 요약
Kubernetes는 high-scale production app을 위해 Pod replica 확장, traffic routing, rolling update, self-healing, autoscaling, capacity management를 제공한다.
하지만 안정적인 운영을 위해서는 다음을 함께 설계해야 한다.
SLO
resource sizing
readiness/liveness probe
dependency capacity
rollout strategy
observability
cost control
security policy
한 문장으로 정리하면 다음과 같다.
Kubernetes는 high-scale production app을 위해 Pod replica 확장, traffic routing, rolling update, self-healing, autoscaling, capacity management를 제공하지만, 이를 안정적으로 운영하려면 SLO, resource sizing, readiness, dependency capacity, observability, rollout 전략까지 함께 설계해야 한다.
High-scale app이 의미하는 것
High-scale application은 단순히 사용자 수가 많은 application만을 뜻하지 않는다.
운영 관점에서 high scale은 다음 조건을 포함한다.
request volume이 크다.
traffic spike가 자주 발생한다.
동시 접속자가 많다.
latency SLO가 중요하다.
배포 중 downtime을 허용하기 어렵다.
특정 시간대 peak가 뚜렷하다.
일부 component만 병목이 될 수 있다.
log와 metric volume도 함께 증가한다.
장애 발생 시 영향 범위가 크다.
예를 들어 다음 workload는 모두 high-scale workload가 될 수 있다.
광고 serving
→ 짧은 시간 안에 매우 많은 request 처리
e-commerce
→ 이벤트/프로모션 시간대 traffic spike
IoT ingestion
→ 수많은 device event 수집
API platform
→ partner와 mobile client의 동시 request 처리
analytics pipeline
→ 대량 event stream 처리
gaming backend
→ 지역/시간대별 동시 접속 급증
streaming service
→ 특정 콘텐츠 공개 시 traffic 집중
High-scale 운영에서 중요한 것은 단순히 “많이 처리한다”가 아니라, traffic 변화와 장애 상황에서도 service quality를 유지하는 것이다.
높은 request volume
+
낮은 latency
+
낮은 error rate
+
배포 중 availability
+
장애 시 빠른 회복
Production에서 flexibility가 중요한 이유
High-scale production 환경은 예측대로만 움직이지 않는다.
예상보다 많은 사용자가 접속한다.
특정 API endpoint만 갑자기 느려진다.
배포 직후 일부 Pod에서 error가 증가한다.
특정 node pool에만 부하가 몰린다.
cache hit ratio가 떨어진다.
external dependency가 느려진다.
worker queue lag가 증가한다.
logging pipeline이 병목이 된다.
이때 유연성이 없으면 운영자는 둘 중 하나를 선택하게 된다.
과도하게 큰 인프라를 항상 유지한다.
→ 비용 낭비
작은 인프라로 버티다가 장애를 낸다.
→ SLO 위반
Kubernetes의 목표는 이 사이에서 균형점을 찾게 해주는 것이다.
평소에는 적정 capacity로 운영
↓
부하 증가 시 Pod scale-out
↓
Pod를 올릴 Node가 부족하면 node pool scale-out
↓
부하 감소 시 scale-in
↓
배포와 장애 상황에서도 최소 가용성 유지
즉 Kubernetes의 flexibility는 단순한 편의 기능이 아니다. Production에서 traffic 변화, 장애, 배포, 비용을 동시에 다루기 위한 운영 능력이다.
Kubernetes scaling은 한 층이 아니다
High-scale app을 Kubernetes에서 운영할 때 scaling은 여러 layer로 나뉜다.
1. Pod replica scaling
2. Node capacity scaling
3. Application-level scaling
4. Event-driven scaling
5. Traffic-level scaling
6. Data/backend scaling
가장 기본적인 것은 Pod 수를 늘리는 것이다.
kubectl scale deployment api --replicas=10
하지만 이것만으로는 충분하지 않다.
Pod를 늘렸는데 Node에 자리가 없으면 Pending이 된다.
Pod가 늘어도 DB connection limit이 낮으면 backend가 병목이 된다.
Pod가 늘어도 readinessProbe가 부정확하면 traffic이 실패한다.
Pod가 늘어도 Service endpoint가 정상 반영되지 않으면 routing이 꼬인다.
Pod가 늘어도 logging/metrics pipeline이 traffic volume을 감당하지 못할 수 있다.
따라서 high-scale 운영에서는 다음 전체 chain을 봐야 한다.
Traffic 증가
↓
Metric 증가
↓
HPA가 replica 증가
↓
Scheduler가 Pod 배치
↓
Node capacity 부족 시 node pool 확장
↓
Pod Ready
↓
Service endpoint 반영
↓
LoadBalancer / Ingress가 traffic 전달
↓
Application latency와 error rate 안정화
Scaling은 replicas 숫자 하나가 아니라 application, cluster, network, backend, observability를 관통하는 운영 흐름이다.
Horizontal Pod Autoscaler, HPA
Kubernetes에서 가장 대표적인 자동 확장 기능은 HorizontalPodAutoscaler, HPA다.
HPA는 Deployment, StatefulSet 같은 scalable workload의 replica 수를 metric에 따라 조정한다.
예시:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
의미는 다음과 같다.
api Deployment를 대상으로 한다.
최소 3개 Pod는 유지한다.
최대 50개까지 확장할 수 있다.
평균 CPU utilization이 70% 근처가 되도록 replica 수를 조정한다.
HPA의 mental model은 다음이다.
현재 metric 관찰
↓
목표 metric과 비교
↓
필요 replica 수 계산
↓
Deployment의 replicas 값 조정
↓
ReplicaSet이 Pod 생성/삭제
중요한 점은 HPA가 container를 직접 실행하지 않는다는 것이다. HPA는 Deployment.spec.replicas 같은 scale subresource를 조정하고, 실제 Pod 생성은 Deployment/ReplicaSet controller가 수행한다.
HPA에서 CPU만 보면 부족할 수 있다
입문 단계에서는 CPU 기반 HPA가 가장 쉽다. 하지만 high-scale production에서는 CPU만으로 부족할 수 있다.
예를 들어 API server가 다음 상태일 수 있다.
CPU usage는 50%
하지만 request queue가 쌓임
p95 latency가 증가
DB connection pool 대기 증가
event loop delay 증가
이 경우 CPU 기준으로는 아직 scale-out 조건이 아니지만, 사용자 경험은 이미 나빠질 수 있다.
High-scale app에서는 다음 metric을 함께 고려해야 한다.
CPU utilization
memory usage
request per second
p95 / p99 latency
error rate
queue length
Kafka consumer lag
active connection count
event loop lag
DB connection pool saturation
custom business metric
예를 들어 queue 기반 worker는 CPU보다 queue length가 더 좋은 scaling signal일 수 있다.
Queue length 증가
↓
worker Pod 증가
↓
처리량 증가
↓
Queue length 감소
Event-driven workload에서는 KEDA 같은 도구를 통해 queue length, Kafka lag, message broker metric을 기반으로 scaling할 수 있다.
Kafka topic lag 증가
↓
KEDA ScaledObject
↓
consumer Deployment replicas 증가
즉 high-scale app에서 autoscaling metric은 workload 특성에 맞게 선택해야 한다.
Pod를 늘릴 수 있어도 Node가 부족할 수 있다
HPA가 replica를 늘려도 cluster에 자리가 없으면 Pod는 Pending 상태가 된다.
HPA desired replicas = 30
현재 running replicas = 15
새 Pod 15개 생성 시도
↓
Node CPU/memory capacity 부족
↓
새 Pod Pending
확인:
kubectl get pods
kubectl describe pod <pending-pod>
대표 event:
0/5 nodes are available: insufficient cpu.
0/5 nodes are available: insufficient memory.
이때 필요한 것이 node-level autoscaling이다.
Pod scaling
→ application replica 수 조정
Node scaling
→ cluster capacity 조정
Production scaling은 두 단계로 봐야 한다.
HPA:
workload의 replica 수 증가
Cluster Autoscaler / node pool autoscaler:
부족한 Pod를 배치할 Node capacity 증가
하지만 node autoscaling에는 시간이 걸릴 수 있다.
새 node provisioning
↓
node Ready
↓
CNI/CSI 준비
↓
Pod scheduling
↓
image pull
↓
Pod Ready
따라서 sudden spike가 예상된다면 minReplicas, warm pool, scheduled scaling, pre-scaling도 함께 고려해야 한다.
Resource requests/limits가 scaling의 기준이 된다
High-scale Kubernetes 운영에서 resources.requests와 resources.limits는 매우 중요하다.
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
Scheduler는 Pod의 resource request를 보고 어느 Node에 배치할지 결정한다.
requests.cpu: "500m"
→ 이 Pod는 scheduling 관점에서 최소 0.5 CPU 필요
requests.memory: "512Mi"
→ 이 Pod는 scheduling 관점에서 최소 512Mi memory 필요
High-scale 환경에서 request가 너무 낮으면 문제가 생긴다.
scheduler가 많은 Pod를 같은 Node에 배치
↓
실제 사용량은 request보다 큼
↓
Node resource contention
↓
latency 증가 / OOM / throttling
반대로 request가 너무 높으면 cluster 활용률이 낮아진다.
Pod 하나가 실제로는 200m CPU만 쓰는데 request는 2 CPU
↓
scheduler가 Node를 빨리 가득 찬 것으로 판단
↓
Pod Pending 증가
↓
node scale-out 과도
↓
비용 증가
따라서 high-scale production에서는 request/limit을 감으로 정하면 안 된다.
실제 usage 관찰
↓
p95 또는 peak 기준 분석
↓
requests/limits 조정
↓
HPA target 조정
↓
재관찰
CPU limit은 latency-sensitive workload에서 주의해야 한다
CPU limit은 noisy neighbor를 막는 데 도움이 될 수 있지만, latency-sensitive API에서는 throttling 문제가 생길 수 있다.
API workload에서는 다음을 고민해야 한다.
CPU request는 정확히 설정한다.
CPU limit은 필요한 경우에만 신중하게 설정한다.
memory limit은 OOM 방지를 위해 설정한다.
latency-sensitive workload는 CPU throttling metric을 확인한다.
multi-tenant cluster에서는 isolation 요구사항을 고려한다.
Production에서 중요한 질문은 다음이다.
이 workload는 burst CPU를 사용해야 하는가?
CPU throttling이 p99 latency를 악화시키는가?
cluster가 trusted single-tenant인가 multi-tenant인가?
cost control이 우선인가 latency 안정성이 우선인가?
예를 들어 internal single-tenant cluster에서 latency가 매우 중요한 API라면 CPU limit을 과도하게 낮게 설정하는 것이 오히려 장애 원인이 될 수 있다. 반면 multi-tenant cluster에서는 workload 간 격리를 위해 limit이 필요할 수 있다.
High-scale production에서 Deployment 전략
High-scale app은 배포 중에도 traffic을 받아야 한다.
기본적으로 Kubernetes Deployment는 rolling update를 사용한다.
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 25%
maxUnavailable은 update 중 unavailable할 수 있는 최대 Pod 수를, maxSurge는 desired replica 수보다 초과해서 만들 수 있는 최대 Pod 수를 제어한다.
예를 들어 desired replicas가 20개이고 다음과 같이 설정했다고 하자.
maxUnavailable: 0
maxSurge: 5
가능한 흐름은 다음과 같다.
기존 Ready Pod 20개 유지
↓
새 Pod 최대 5개 추가 생성
↓
새 Pod가 Ready 되면 old Pod 일부 종료
↓
반복
High-scale production에서는 다음을 고려해야 한다.
새 version과 old version이 동시에 떠도 괜찮은가?
DB schema가 양쪽 version과 호환되는가?
cache format이 깨지지 않는가?
event payload version이 호환되는가?
readinessProbe가 정확한가?
rollout 중 error rate를 관찰하는가?
Rolling update는 무중단에 가까운 배포를 가능하게 하지만, application compatibility가 준비되지 않으면 장애가 날 수 있다.
readinessProbe는 high-scale routing의 핵심이다
Scale-out이나 rolling update에서 가장 중요한 것 중 하나가 readinessProbe다.
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Pod가 Running이라고 해서 traffic을 받아도 되는 것은 아니다.
Pod Running
→ container process가 시작됨
Pod Ready
→ Service endpoint에 들어가 traffic을 받을 수 있음
High-scale 환경에서는 readiness가 부정확하면 장애가 빠르게 확대된다.
잘못된 readiness 예:
process만 살아 있으면 ready
↓
DB connection pool 준비 안 됨
cache warm-up 안 됨
dependency health 불안정
↓
traffic 유입
↓
5xx 증가
좋은 readiness는 application이 실제로 요청을 처리할 준비가 되었는지를 반영해야 한다.
HTTP server bind 완료
필수 dependency 연결 가능
migration 완료
cache warm-up 조건 충족
consumer group join 완료
다만 readiness가 너무 엄격해도 문제가 된다.
일시적 external dependency 지연
↓
모든 Pod NotReady
↓
Service endpoint 감소
↓
traffic이 남은 Pod에 집중
↓
장애 확대
즉 readinessProbe는 “traffic을 받을 준비”에 해당하는 정확한 기준으로 설계해야 한다.
livenessProbe와 startupProbe도 신중해야 한다
High-scale production에서 livenessProbe는 application이 회복 불가능한 상태에 빠졌을 때 container를 재시작하도록 도와준다.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 20
하지만 livenessProbe가 너무 공격적이면 정상적인 지연을 장애로 오인할 수 있다.
일시적 GC pause
DB connection 지연
CPU throttling
startup 지연
↓
livenessProbe 실패
↓
container 재시작
↓
traffic 감소
↓
부하가 남은 Pod에 집중
↓
장애 확대
초기 기동이 오래 걸리는 application은 startupProbe를 고려해야 한다.
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
Probe의 역할을 구분하면 다음과 같다.
| Probe | 목적 | 실패 시 영향 |
|---|---|---|
startupProbe | 느리게 시작하는 application의 초기 기동 보호 | startup 완료 전 liveness/readiness 판단 지연 |
readinessProbe | traffic을 받을 준비가 되었는지 판단 | Service endpoint에서 제외 |
livenessProbe | application이 살아 있는지 판단 | container 재시작 |
High-scale 환경에서는 probe 하나가 전체 traffic routing과 availability에 직접 영향을 줄 수 있다.
Service와 traffic 분산
Pod가 여러 개로 늘어나면 Service가 이 Pod들을 안정적인 endpoint 뒤에 묶는다.
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api
ports:
- port: 80
targetPort: 8080
구조:
Client
↓
LoadBalancer / Ingress
↓
Service/api
↓
Ready Pods
Scale-out 후 확인해야 할 것:
kubectl get endpoints api
kubectl get endpointslice
kubectl get pods -l app=api -o wide
중요한 점은 Pod 수가 늘었다고 traffic이 항상 잘 분산되는 것은 아니라는 점이다.
확인할 것:
Service selector가 올바른가?
Pod label이 일치하는가?
Pod가 Ready 상태인가?
targetPort가 application listen port와 일치하는가?
Ingress/Gateway가 올바른 Service를 바라보는가?
client-side keep-alive 때문에 특정 Pod에 traffic이 몰리지 않는가?
High-scale app에서는 traffic 분산 상태 자체도 metric으로 봐야 한다.
Pod별 request rate
Pod별 latency
Pod별 error rate
Pod별 CPU/memory
Pod별 connection count
Multi-zone과 failure domain
Production high-scale app은 단일 Node나 단일 zone에 의존하면 안 된다.
좋은 배치:
zone-a: api Pods 일부
zone-b: api Pods 일부
zone-c: api Pods 일부
나쁜 배치:
zone-a에 모든 api Pod 집중
↓
zone-a 장애
↓
전체 API 장애
Kubernetes에서는 다음을 사용할 수 있다.
pod anti-affinity
topology spread constraints
node labels
multi-zone node pool
PodDisruptionBudget
예시:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: api
의미는 다음과 같다.
app=api Pod를 zone 간 최대한 고르게 분산한다.
High-scale app에서 zone 분산은 단순 성능 문제가 아니라 availability 문제다.
PodDisruptionBudget으로 voluntary disruption 제어
Production에서는 cluster upgrade, node drain, node replacement 같은 voluntary disruption이 발생한다.
이때 Pod가 한꺼번에 너무 많이 내려가면 장애가 날 수 있다.
PodDisruptionBudget, PDB는 replicated application에서 동시에 down될 수 있는 Pod 수를 제한한다.
예시:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-pdb
spec:
minAvailable: 80%
selector:
matchLabels:
app: api
의미는 다음과 같다.
app=api Pod 중 최소 80%는 available 상태로 유지한다.
High-scale production에서는 PDB가 중요하다.
node drain 중 전체 Pod가 과도하게 줄어드는 것을 방지
cluster upgrade 중 service availability 유지
multi-zone maintenance 중 최소 replica 보장
단, PDB는 voluntary disruption에 대한 보호 장치이지, Node가 갑자기 죽는 involuntary failure를 막지는 못한다.
High-scale 운영에서 stateful dependency가 병목이 된다
Kubernetes에서 API Pod를 늘리는 것은 상대적으로 쉽다.
kubectl scale deployment api --replicas=100
하지만 backend dependency가 scale을 감당하지 못하면 장애가 발생한다.
API Pod 10개 → 100개
↓
각 Pod가 DB connection 20개 생성
↓
DB connection 200개 → 2000개
↓
DB max connection 초과
↓
API error 증가
따라서 high-scale 운영에서는 application replica뿐 아니라 dependency capacity도 함께 봐야 한다.
database connection pool
cache capacity
message queue throughput
external API rate limit
object storage throughput
network bandwidth
DNS query volume
logging pipeline throughput
Kubernetes는 app replica를 잘 늘려주지만, DB schema, connection pool, cache architecture, event pipeline capacity까지 자동으로 해결해주지는 않는다.
Stateless하게 만들수록 scale-out이 쉬워진다
High-scale app은 가능한 한 stateless하게 만드는 것이 유리하다.
Stateless API:
Pod가 local session state를 갖지 않음
request는 어느 Pod로 가도 처리 가능
state는 external store에 저장
Pod가 죽어도 replacement가 쉬움
Stateful API:
Pod local memory에 session 저장
특정 user가 특정 Pod에 묶임
Pod restart 시 session 유실
scale-out과 rolling update가 어려움
Kubernetes Service는 기본적으로 Pod를 ephemeral endpoint로 다룬다. 따라서 Pod가 바뀌어도 app이 정상적으로 동작하려면 state를 외부화하는 것이 좋다.
session
→ Redis / external session store
file
→ object storage / shared storage
database state
→ managed DB / replicated DB
cache
→ distributed cache
High-scale Kubernetes 운영에서 가장 좋은 구조는 다음이다.
stateless app Pods
+
externalized state
+
scalable backend
+
observability
Observability 없이는 high scale을 운영할 수 없다
High-scale app에서는 kubectl get pods만으로는 부족하다.
필요한 관측 지표:
request rate
p50 / p95 / p99 latency
error rate
saturation
CPU/memory usage
Pod restart count
HPA desired/current replicas
pending pods
node utilization
ingress latency
Service endpoint count
DB connection count
queue length / consumer lag
log ingestion delay
Kubernetes 명령으로 기본 상태를 볼 수 있다.
kubectl get hpa
kubectl get pods
kubectl top pods
kubectl top nodes
kubectl describe deployment api
kubectl get events --sort-by=.metadata.creationTimestamp
하지만 production에서는 다음이 필요하다.
Prometheus
Grafana
Loki / OpenSearch
distributed tracing
alertmanager
SLO dashboard
error budget tracking
High-scale 운영에서 중요한 것은 평균값이 아니라 tail latency다.
평균 latency: 80ms
p95 latency: 300ms
p99 latency: 2s
사용자는 평균이 아니라 느린 요청을 체감한다. 따라서 autoscaling과 alerting도 p95/p99 latency, error rate, saturation을 함께 봐야 한다.
SLO 기반으로 운영해야 한다
High-scale production에서는 “Pod가 Running인지”보다 “사용자 경험이 SLO 안에 있는지”가 중요하다.
예시 SLO:
99.9% of requests should return below 300ms within 30 days.
5xx error rate should remain below 0.1%.
API availability should be 99.95%.
Kubernetes 상태와 SLO를 연결해야 한다.
Pod Ready 감소
↓
Service endpoint 감소
↓
latency 증가
↓
error rate 증가
↓
SLO burn rate 증가
SLO 기반 alert는 단순 resource alert보다 더 의미 있다.
나쁜 alert:
CPU 80% 초과
좋은 alert:
5xx error rate가 SLO error budget을 빠르게 소모 중
p99 latency가 10분 이상 SLO 초과
HPA maxReplicas 도달 + latency 증가
즉 high-scale 운영에서 Kubernetes metric은 사용자 영향도와 연결되어야 한다.
Cost와 scale의 균형
High-scale app에서 scale-out은 성능 문제이면서 비용 문제다.
replicas 증가
↓
Node 증가
↓
LoadBalancer / network / logging / storage 비용 증가
무조건 maxReplicas를 크게 잡으면 비용이 늘 수 있다.
minReplicas: 20
maxReplicas: 500
이 설정 자체가 나쁜 것은 아니지만, 다음을 확인해야 한다.
실제 peak traffic은 어느 정도인가?
Pod 하나의 처리량은 얼마인가?
Pod startup time은 얼마인가?
Node scale-out 시간은 얼마인가?
logging 비용은 traffic 증가에 따라 얼마나 늘어나는가?
scale-in 정책은 너무 느리거나 빠르지 않은가?
Cost-aware 운영에서는 다음을 함께 고려한다.
right-sizing requests
HPA target tuning
scheduled scaling
queue 기반 autoscaling
spot/preemptible node pool 활용 여부
workload별 node pool 분리
log sampling
cache hit ratio 개선
Kubernetes는 확장을 가능하게 하지만, 비용 효율성은 운영 설계에 달려 있다.
High-scale app의 rollout 위험
Traffic이 큰 app일수록 배포 한 번의 위험도 커진다.
위험한 배포:
새 version 배포
↓
전체 Pod가 빠르게 교체
↓
새 version에서 error 발생
↓
traffic 대부분 영향
안전한 배포:
새 version 일부만 배포
↓
small percentage traffic
↓
error rate / latency 확인
↓
점진적 확대
↓
문제 시 빠른 rollback
Kubernetes 기본 Deployment는 rolling update를 제공하지만, 더 정교한 전략이 필요할 수 있다.
canary deployment
blue/green deployment
traffic split
shadow traffic
feature flag
progressive delivery
예를 들어 canary 전략은 다음과 같다.
v1: 95%
v2: 5%
↓
metric 확인
↓
v2: 25%
↓
metric 확인
↓
v2: 100%
High-scale app에서는 “배포 완료”보다 “배포 후 metric 안정성”이 더 중요하다.
Production scaling checklist
High-scale Kubernetes app을 production에서 운영하려면 다음을 확인해야 한다.
Deployment replicas 최소값이 충분한가?
HPA min/maxReplicas가 현실적인가?
resource requests/limits가 실제 usage와 맞는가?
readinessProbe가 traffic 받을 준비를 정확히 반영하는가?
livenessProbe가 너무 공격적이지 않은가?
startupProbe가 필요한 workload인가?
PodDisruptionBudget이 있는가?
topology spread가 zone/node 장애를 고려하는가?
Service endpoint가 정상적으로 반영되는가?
Ingress/Gateway latency metric을 보고 있는가?
DB/cache/queue capacity가 Pod scale-out을 감당하는가?
HPA가 maxReplicas에 자주 도달하지 않는가?
Pending Pod가 생기면 node pool이 확장되는가?
rollout 중 old/new version compatibility가 보장되는가?
SLO와 error budget 기반 alert가 있는가?
scale-out 후 log/metric pipeline이 병목이 되지 않는가?
Troubleshooting: high-scale app에서 자주 보는 증상
High-scale production app에서는 단순 Pod 장애뿐 아니라 scaling chain 전체를 봐야 한다.
| 증상 | 가능 원인 | 확인 포인트 |
|---|---|---|
| HPA가 scale-out하지 않음 | metric 수집 실패, target 설정 오류 | kubectl get hpa, metrics server/custom metrics |
| Pod가 Pending | Node capacity 부족, request 과도 | kubectl describe pod, kubectl get nodes |
| scale-out했는데 latency 유지 | backend DB/cache 병목 | DB connection, cache hit ratio, queue lag |
| Pod는 Running인데 5xx 증가 | readiness 부정확, app dependency 오류 | readinessProbe, logs, error rate |
| rollout 후 error 증가 | old/new compatibility 문제 | rollout history, canary metric, logs |
| Node drain 중 availability 감소 | PDB 없음 또는 replica 부족 | kubectl get pdb, Deployment replicas |
| 특정 Pod에 traffic 집중 | connection reuse, endpoint imbalance | Pod별 request rate, ingress metric |
| HPA max 도달 | capacity 부족 또는 target 부적절 | HPA status, SLO burn rate |
| cost 급증 | over-scaling, request 과대 설정 | node utilization, HPA history, logging volume |
Kubernetes가 해주는 것과 사용자가 설계해야 하는 것
Kubernetes는 high-scale app 운영의 많은 기반을 제공한다.
Kubernetes가 해주는 것:
Pod scheduling
replica 유지
rolling update
service discovery
autoscaling hook
self-healing
declarative management
하지만 Kubernetes가 모든 문제를 자동으로 해결해주지는 않는다.
사용자가 설계해야 하는 것:
SLO
resource sizing
readiness/liveness
dependency capacity
data consistency
rollout strategy
observability
cost control
security policy
즉 Kubernetes는 high-scale app을 유연하게 운영할 수 있는 기반을 제공하지만, production architecture는 사용자가 설계해야 한다.
전체 mental model
High-scale production app을 Kubernetes에서 운영하는 흐름은 다음과 같다.
1. High-scale app은 단순히 replica 수가 많은 app이 아니라,
traffic spike, latency SLO, 장애 영향도, 배포 위험이 큰 production workload다.
2. Kubernetes는 Deployment와 Service를 통해 app replica를 안정적으로 실행하고,
traffic을 Ready Pod로 분산한다.
3. HPA는 CPU, memory, custom/external metric을 보고 workload replica 수를 조정한다.
4. Pod 수를 늘려도 Node capacity가 부족하면 Pending이 발생하므로,
node pool autoscaling과 capacity planning이 함께 필요하다.
5. resource requests/limits는 scheduling, autoscaling, cost, stability에 직접 영향을 준다.
6. readinessProbe는 scale-out과 rolling update 중 traffic을 받을 수 있는 Pod만
Service endpoint에 포함되게 하는 핵심 장치다.
7. rolling update, maxSurge, maxUnavailable, PDB, topology spread를 통해
배포와 maintenance 중 availability를 유지해야 한다.
8. High-scale 운영에서는 DB, cache, queue, external API 같은 backend dependency도
함께 확장 가능해야 한다.
9. Observability와 SLO가 없으면 high-scale app이 정상인지 판단할 수 없다.
10. Kubernetes는 high-scale production 운영의 기반을 제공하지만,
app architecture, SLO, rollout, cost, security, dependency capacity는
별도로 설계해야 한다.
요약
Kubernetes에서 high-scale production app을 운영한다는 것은 단순히 Pod 수를 많이 띄우는 것이 아니다. Deployment, Service, HPA, node autoscaling, requests/limits, readinessProbe, rolling update, PDB, topology spread, observability, SLO, backend capacity를 함께 설계하는 것이다.
핵심 흐름은 다음과 같다.
Traffic 증가
↓
Metric 증가
↓
HPA replica 증가
↓
Scheduler Pod 배치
↓
Node capacity 부족 시 node scale-out
↓
Pod Ready
↓
Service endpoint 반영
↓
Ingress/Gateway traffic 전달
↓
Latency/error rate 안정화
High-scale 운영에서는 “Pod가 Running인가?”보다 “사용자 경험이 SLO 안에 있는가?”가 더 중요하다.
한 문장으로 정리하면 다음과 같다.
Kubernetes는 high-scale production app을 위해 Pod replica 확장, traffic routing, rolling update, self-healing, autoscaling, capacity management를 제공하지만, 이를 안정적으로 운영하려면 SLO, resource sizing, readiness, dependency capacity, observability, rollout 전략까지 함께 설계해야 한다.