K8s 오토스케일링이란?
Kubernetes는 워크로드 부하에 따라 자동으로 리소스를 조절하는 세 가지 오토스케일링 메커니즘을 제공합니다: HPA(Horizontal Pod Autoscaler), VPA(Vertical Pod Autoscaler), Cluster Autoscaler. 이 글에서는 HPA와 VPA의 동작 원리, 설정 방법, 그리고 실전에서 마주치는 함정까지 깊이 다룹니다.
HPA: 수평 오토스케일링
HPA는 메트릭 기반으로 Pod 수를 자동 증감합니다. CPU, 메모리뿐 아니라 커스텀 메트릭도 사용할 수 있습니다.
기본 HPA: CPU 기반
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
CPU 사용률이 70%를 초과하면 Pod를 늘리고, 낮아지면 줄입니다. 반드시 Deployment에 resources.requests가 설정되어 있어야 HPA가 동작합니다:
containers:
- name: api
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
HPA 스케일링 알고리즘
HPA는 다음 공식으로 목표 Pod 수를 계산합니다:
desiredReplicas = ceil(currentReplicas × (currentMetric / desiredMetric))
예: 현재 3개 Pod, CPU 사용률 90%, 목표 70% → ceil(3 × 90/70) = ceil(3.86) = 4개로 스케일 아웃됩니다.
멀티 메트릭 HPA
CPU와 메모리를 동시에 기준으로 설정할 수 있습니다:
spec:
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
여러 메트릭이 있으면 각각 계산한 후 가장 큰 값을 채택합니다. CPU는 괜찮은데 메모리가 높으면 메모리 기준으로 스케일 아웃됩니다.
커스텀 메트릭 HPA
CPU/메모리만으로는 부족한 경우가 많습니다. 큐 길이, 요청 레이턴시 등 비즈니스 메트릭으로 스케일링하는 것이 실전에서 더 효과적입니다:
spec:
metrics:
# Prometheus 커스텀 메트릭
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 100
# 외부 메트릭 (SQS 큐 길이 등)
- type: External
external:
metric:
name: sqs_queue_length
selector:
matchLabels:
queue: order-processing
target:
type: Value
value: 50
커스텀 메트릭을 사용하려면 Prometheus Adapter 또는 KEDA가 필요합니다. KEDA는 이벤트 기반 오토스케일링으로, 0→N 스케일링도 지원합니다.
HPA Behavior: 스케일링 속도 제어
급격한 스케일 인/아웃을 방지하는 behavior 설정은 프로덕션에서 필수입니다:
spec:
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50 # 현재 수의 50%까지만 증가
periodSeconds: 60
- type: Pods
value: 4 # 또는 최대 4개까지 증가
periodSeconds: 60
selectPolicy: Max # 둘 중 큰 값 채택
scaleDown:
stabilizationWindowSeconds: 300 # 5분 안정화
policies:
- type: Percent
value: 10 # 10%씩만 감소
periodSeconds: 120
selectPolicy: Min # 가장 보수적으로
스케일 다운은 보수적으로 설정하는 것이 핵심입니다. 트래픽이 잠시 줄었다가 다시 올라오는 패턴에서 급격한 스케일 다운은 서비스 장애를 유발합니다. stabilizationWindowSeconds는 해당 시간 동안의 추천값 중 가장 높은(스케일 다운) 또는 낮은(스케일 업) 값을 채택합니다.
VPA: 수직 오토스케일링
VPA는 Pod 수가 아닌 개별 Pod의 리소스(CPU/메모리) 요청량을 자동 조절합니다:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-server-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
updatePolicy:
updateMode: Auto # Off, Initial, Recreate, Auto
resourcePolicy:
containerPolicies:
- containerName: api
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 2
memory: 2Gi
controlledResources:
- cpu
- memory
| updateMode | 동작 | 용도 |
|---|---|---|
Off |
추천만, 적용 안 함 | 리소스 분석용 |
Initial |
Pod 생성 시에만 적용 | 안전한 적용 |
Auto |
Pod 재시작하며 적용 | 완전 자동화 |
주의: VPA Auto 모드는 리소스를 변경하기 위해 Pod를 재시작합니다. 이는 K8s PDB(PodDisruptionBudget)와 함께 설정해야 가용성을 보장할 수 있습니다.
HPA + VPA 함께 사용하기
HPA와 VPA를 동시에 사용하면 충돌이 발생할 수 있습니다. 안전한 조합 패턴:
# VPA: 메모리만 제어 (Off 모드로 추천만)
spec:
resourcePolicy:
containerPolicies:
- containerName: api
controlledResources:
- memory # CPU는 VPA에서 제외
mode: "Auto"
# HPA: CPU 기반 스케일링
spec:
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
핵심 규칙: HPA가 CPU로 스케일링하면, VPA는 CPU를 제어하지 않아야 합니다. 둘 다 CPU를 조절하면 서로 상충하는 결정을 내립니다. 가장 안전한 패턴은 VPA를 Off 모드로 두고 추천값만 참고하는 것입니다.
Cluster Autoscaler 연동
HPA가 Pod를 늘려도 노드 리소스가 부족하면 Pod가 Pending 상태에 머뭅니다. Cluster Autoscaler가 이를 감지해 노드를 추가합니다:
전체 흐름:
1. 트래픽 증가 → CPU 사용률 상승
2. HPA → Pod 수 증가 결정
3. Scheduler → 노드 리소스 부족, Pod Pending
4. Cluster Autoscaler → 새 노드 프로비저닝
5. Pod가 새 노드에 스케줄링
6. 트래픽 감소 → HPA 스케일 다운
7. 노드 사용률 저하 → Cluster Autoscaler 노드 제거
K8s ResourceQuota·LimitRange와 함께 설정하면 네임스페이스별 리소스 상한을 지정해 오토스케일링이 클러스터 전체를 잠식하는 것을 방지할 수 있습니다.
KEDA: 이벤트 기반 스케일링
KEDA(Kubernetes Event-Driven Autoscaling)는 HPA를 확장해 0→N 스케일링과 다양한 이벤트 소스를 지원합니다:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-worker
spec:
scaleTargetRef:
name: order-worker
pollingInterval: 15
cooldownPeriod: 300
minReplicaCount: 0 # 0까지 스케일 다운!
maxReplicaCount: 50
triggers:
- type: rabbitmq
metadata:
host: amqp://rabbitmq:5672
queueName: orders
queueLength: "10" # 큐 메시지 10개당 1 Pod
KEDA는 Kafka, SQS, Redis, PostgreSQL, Cron 등 60개 이상의 스케일러를 지원합니다. 워커/컨슈머 워크로드에 특히 적합합니다.
오토스케일링 트러블슈팅
자주 마주치는 문제와 해결법:
| 증상 | 원인 | 해결 |
|---|---|---|
| HPA가 unknown 표시 | metrics-server 미설치 또는 requests 미설정 | kubectl top pods 확인, requests 설정 |
| 스케일 아웃이 너무 느림 | 기본 동기화 주기 15초 | --horizontal-pod-autoscaler-sync-period 조정 |
| 플래핑(반복 스케일 인/아웃) | stabilizationWindow 미설정 | behavior.scaleDown.stabilizationWindowSeconds 증가 |
| VPA가 Pod를 계속 재시작 | 추천값과 현재값 차이 큼 | minAllowed/maxAllowed 범위 조정, Off 모드 먼저 테스트 |
# HPA 상태 확인
kubectl get hpa -w
kubectl describe hpa api-server-hpa
# VPA 추천값 확인
kubectl describe vpa api-server-vpa
# metrics-server 확인
kubectl top pods
kubectl top nodes
마무리
K8s 오토스케일링은 단순히 HPA를 설정하는 것을 넘어, behavior로 스케일링 속도를 제어하고, VPA로 리소스 최적화를 병행하며, KEDA로 이벤트 기반 스케일링까지 확장하는 것이 실전입니다. HPA와 VPA의 충돌을 피하고, Cluster Autoscaler와 연동해 노드 레벨까지 자동화하면 진정한 탄력적 인프라를 구축할 수 있습니다.