[K8s] HPA / VPA / KEDA: 자동 확장
HPA, Horizontal Pod Autoscaler, VPA, Vertical Pod Autoscaler, KEDA, Cluster Autoscaler, Karpenter
정의
Pod 를 자동으로 확장/축소하는 K8s 메커니즘. 세 가지 레벨:
| 레벨 | 도구 | 무엇을 확장 |
|---|---|---|
| Pod 수 | HPA / KEDA | 동일 spec pod 추가/삭제 |
| Pod 크기 | VPA | CPU/Memory request/limit 조절 |
| Node 수 | Cluster Autoscaler / Karpenter | node 추가/삭제 |
3가지 스케일링
flowchart TB
Q[스케일링 종류]
Q --> HPA["HPA<br/>Pod 수 증감"]
Q --> VPA["VPA<br/>Pod 리소스 증감"]
Q --> CA["Cluster Autoscaler / Karpenter<br/>Node 수 증감"]
HPA (Horizontal Pod Autoscaler)
CPU / Memory / custom metric 기반 pod 수 조정.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: { name: web }
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target: { type: Utilization, averageUtilization: 70 }
- type: Pods
pods:
metric: { name: http_requests_per_second }
target: { type: AverageValue, averageValue: "1000" }
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
HPA 알고리즘
desired = ceil(currentReplicas × (currentMetric / targetMetric))
예: 현재 4 pod, CPU 80%, 목표 50%:
- desired = ceil(4 × (80/50)) = 7 pod
HPA 제어 루프
sequenceDiagram
participant MS as metrics-server
participant HPA as HPA controller
participant D as Deployment
loop 15초마다
HPA->>MS: 현재 CPU/메모리 조회
MS-->>HPA: 평균 CPU 80%
HPA->>HPA: desired = ceil(4 * 80/50) = 7
HPA->>D: replicas: 7
D->>D: pod 3개 추가
end
- stabilizationWindowSeconds: scale down 은 기본 300초 대기 후 결정
- scaleDown.policies: 한 번에 10% 씩, 60초 간격으로 축소
Custom Metrics: Prometheus Adapter
HPA 에서 커스텀 메트릭을 사용하려면 Prometheus Adapter 로 메트릭을 K8s Custom Metrics API 에 노출:
# prometheus-adapter ConfigMap (간략)
rules:
- seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
resources:
overrides:
namespace: { resource: "namespace" }
pod: { resource: "pod" }
name:
matches: "^(.*)_total$"
as: "${1}_per_second"
metricsQuery: 'rate(<<.Series>>{<<.LabelMatchers>>}[2m])'
이후 HPA spec 에서:
metrics:
- type: Pods
pods:
metric: { name: http_requests_per_second }
target: { type: AverageValue, averageValue: "1000" }
VPA (Vertical Pod Autoscaler)
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata: { name: web }
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web
updatePolicy:
updateMode: "Auto" # Off / Initial / Recreate / Auto
resourcePolicy:
containerPolicies:
- containerName: '*'
minAllowed: { cpu: 50m, memory: 64Mi }
maxAllowed: { cpu: 2, memory: 2Gi }
CAUTION
VPA + HPA on CPU 동시 사용 금지. 둘이 같은 메트릭으로 다툼. HPA 는 custom metric, VPA 는 resource → 분리 가능.
VPA 모드 비교
| updateMode | 동작 | 재시작 |
|---|---|---|
Off | 권고값만 계산, 실제 변경 없음 | 없음 |
Initial | pod 생성 시 한 번만 적용 | 없음 |
Recreate | 변경 필요 시 pod 삭제 후 재생성 | 있음 |
Auto | 현재는 Recreate 와 동일 (인플레이스 업데이트 개발 중) | 있음 |
VPA Off 모드는 초기 resource request 추천 용도로 자주 활용.
KEDA (Kubernetes Event-Driven Autoscaling)
flowchart LR
Trigger["외부 트리거<br/>Kafka lag, SQS depth, ..."] --> KEDA
KEDA --> HPA[표준 HPA 생성]
HPA --> Deploy[Deployment scale]
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata: { name: kafka-consumer }
spec:
scaleTargetRef:
name: consumer
minReplicaCount: 0
maxReplicaCount: 30
triggers:
- type: kafka
metadata:
bootstrapServers: kafka:9092
topic: events
consumerGroup: my-group
lagThreshold: '1000'
IMPORTANT
KEDA 가 2026 시점 표준. 50+ scaler (Kafka, SQS, Prometheus, Redis, DB query, …) 지원. scale-to-zero 가능.
KEDA: Prometheus 기반 스케일링
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus:9090
metricName: http_requests_total
query: sum(rate(http_requests_total{job="web"}[2m]))
threshold: '1000'
Prometheus 가 있는 클러스터에서 임의의 PromQL 로 스케일링 가능. metrics-server + Prometheus Adapter 없이 KEDA 만으로도 커스텀 메트릭 HPA 구현 가능.
Cluster Autoscaler / Karpenter
flowchart LR
HPA --> NeedMore[새 pod 들이 Pending]
NeedMore --> CA[Cluster Autoscaler]
CA -->|"EC2 / GCE"| AddNode[새 node 추가]
AddNode --> Schedule[pending pod 스케줄]
| - | Cluster Autoscaler | Karpenter |
|---|---|---|
| 종류 | 표준 K8s 도구 | AWS 발 (이제 CNCF) |
| Node 선택 | 미리 정의된 node group | 동적 instance type 선택 |
| 속도 | 분 단위 | 수십 초 |
| 비용 최적화 | 제한적 | 우수 (spot, right-sizing) |
| 클라우드 | 다양 | AWS, Azure |
HPA vs KEDA 선택 기준
| 상황 | 추천 |
|---|---|
| CPU/Memory 기반 스케일링만 필요 | HPA 단독 |
| Kafka lag, SQS depth, Prometheus metric | KEDA |
| scale-to-zero 필요 | KEDA |
| 50+ 종류의 외부 트리거 | KEDA |
| 기존 HPA + 일부 custom metric | HPA + Prometheus Adapter |
흔한 함정
WARNING
- stabilization window 너무 짧음 = 빈번한 scale up/down → 비용 + 안정성 문제.
- HPA + VPA 동시 (같은 메트릭) = 충돌. 분리 또는 VPA off mode + 수동.
metrics-server미설치 = HPA 작동 안 함. cluster 부팅 시 자동 설치 확인.- resource request 없음 = HPA CPU 기준 무의미. requests 필수.
- minReplicas: 0 + 갑작스러운 트래픽 = cold-start latency. KEDA
minReplicaCount: 1권장.
관련 위키
- k8s-deployment
- k8s-pod
- prometheus (custom metric)
- kafka-consumer-group (lag-based scaling)
이 글의 용어 (4개)
- [Distributed] Kafka Consumer Group: rebalancing, offset, lagdistributed-systems
- 정의 Consumer Group = 같은 를 가진 consumer들이 함께 한 topic을 분담 소비. partition 단위로 분배. 핵심 특성: - 한 partition → …
- [K8s] Deployment: ReplicaSet, rolling update, rollbackkubernetes
- 정의 Deployment = stateless 워크로드를 위한 컨트롤러. 내부적으로 ReplicaSet 관리 + rolling update / rollback. 사용 시나리오 |…
- [K8s] Pod: 컨테이너의 최소 단위, sidecar, lifecyclekubernetes
- 정의 Pod = K8s 의 가장 작은 배포 단위. 1개 이상의 컨테이너 + 공유 네트워크 + 공유 스토리지. [!IMPORTANT] Pod 는 컨테이너의 wrapping 이 아니…
- [Observability] Prometheus: pull 기반 메트릭, PromQLdevops
- 정의 Prometheus = pull 기반 시계열 metric 시스템. PromQL 로 쿼리. CNCF graduated. 2026 클라우드 네이티브 메트릭 표준. 아키텍처 Pu…
💬 댓글