HPA(HorizontalPodAutoscaler) 란?
HPA는 측정된 메트릭(CPU, 메모리, 커스텀 지표)에 따라 Deployment/ReplicaSet/StatefulSet의 레플리카 수를 자동으로 늘리거나 줄이는 컨트롤러입니다. 트래픽이 몰리면 Pod를 늘려 처리량을 확보하고, 한가하면 줄여 비용을 아낍니다.
- 수평 확장(Horizontal): Pod 개수를 조절 (vs. VPA는 Pod의 리소스 한도를 조절)
- 기본 동기화 주기는 15초이며, 목표값 대비 현재값 비율로 원하는 레플리카를 계산
- 측정값을 공급하는 metrics-server(또는 커스텀 메트릭 API)가 반드시 필요
HPA가 동작하려면 Pod에 resources.requests가 설정되어 있어야 합니다. CPU 사용률은 "사용량 / requests" 비율로 계산되므로, requests가 없으면 <unknown>이 떠서 스케일링이 멈춥니다.
metrics-server 설치
HPA의 CPU/메모리 기반 스케일링은 metrics-server가 제공하는 metrics.k8s.io API에 의존합니다.
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml테스트/사설 클러스터에서 kubelet 인증서가 자체서명이라 metrics-server가 못 붙는 경우가 흔합니다. 이때만 임시로 TLS 검증을 끕니다.
kubectl patch deployment metrics-server -n kube-system --type=json \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'설치 확인:
kubectl top nodes
kubectl top pods
# 값이 나오면 metrics-server 정상스케일 대상 워크로드 준비
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
replicas: 1
selector: { matchLabels: { app: php-apache } }
template:
metadata: { labels: { app: php-apache } }
spec:
containers:
- name: php-apache
image: registry.k8s.io/hpa-example
ports: [{ containerPort: 80 }]
resources:
requests: # HPA 계산의 기준 — 필수!
cpu: 200m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
spec:
selector: { app: php-apache }
ports: [{ port: 80 }]HPA 생성 — CPU 기반
명령형 (간단)
kubectl autoscale deployment php-apache \
--cpu-percent=50 --min=1 --max=10선언형 (autoscaling/v2, 권장)
v2 API는 다중 메트릭과 스케일링 동작 튜닝을 지원합니다.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization # requests 대비 비율(%)
averageUtilization: 50
- type: Resource
resource:
name: memory
target:
type: AverageValue # 절대값 기준
averageValue: 200Mi여러 메트릭이 있으면 각각 계산해 가장 큰 레플리카 수를 채택합니다(보수적 확장).
스케일링 계산 원리
원하는 레플리카는 다음 공식으로 결정됩니다.
desiredReplicas = ceil( currentReplicas * (currentMetric / targetMetric) )예: 현재 3개 Pod, 평균 CPU 사용률 90%, 목표 50% → ceil(3 * 90/50) = ceil(5.4) = 6개로 확장.
목표값 근처(기본 ±10% tolerance)에서는 잦은 떨림을 막기 위해 스케일링하지 않습니다.
부하 테스트로 확인
# 부하 발생기
kubectl run -it --rm load --image=busybox:1.36 --restart=Never -- \
/bin/sh -c "while true; do wget -q -O- http://php-apache; done"
# 다른 터미널에서 실시간 관찰
kubectl get hpa php-apache --watch
# NAME TARGETS MINPODS MAXPODS REPLICAS
# php-apache 250%/50% 1 10 1 → 5 → ...부하 종료 후에는 기본 5분(stabilizationWindowSeconds)을 기다린 뒤 천천히 축소됩니다.
스케일링 동작 튜닝 (behavior)
급격한 트래픽에 빠르게 확장하고, 축소는 신중하게 하려면 behavior를 조정합니다.
spec:
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # 즉시 확장
policies:
- type: Percent
value: 100 # 한 번에 최대 100% 증가
periodSeconds: 30
- type: Pods
value: 4 # 또는 최대 4개씩
periodSeconds: 30
selectPolicy: Max # 둘 중 더 공격적인 정책 선택
scaleDown:
stabilizationWindowSeconds: 300 # 5분간 안정화 후 축소
policies:
- type: Percent
value: 10 # 한 번에 최대 10%만 감소
periodSeconds: 60| 파라미터 | 의미 |
|---|---|
stabilizationWindowSeconds | 결정에 사용할 과거 윈도우(떨림 방지) |
policy Percent | 비율 기반 변동 한도 |
policy Pods | 절대 개수 변동 한도 |
selectPolicy | Max(공격적)/Min(보수적)/Disabled |
커스텀·외부 메트릭 (RPS, 큐 길이)
CPU만으로 부족하면 Prometheus Adapter나 KEDA로 애플리케이션 지표 기반 확장을 합니다.
metrics:
- type: Pods # Pod당 커스텀 메트릭
pods:
metric: { name: http_requests_per_second }
target:
type: AverageValue
averageValue: "100"
- type: External # 외부 지표(예: SQS 큐 길이)
external:
metric: { name: sqs_queue_length }
target:
type: AverageValue
averageValue: "30"이벤트/메시지 기반 워크로드라면 KEDA가 0개까지 축소(scale-to-zero)와 다양한 스케일러(Kafka, RabbitMQ, Cron 등)를 제공해 순수 HPA보다 편리합니다.
트러블슈팅
kubectl describe hpa php-apache # 이벤트와 조건(Conditions) 확인| 증상 | 원인 / 해결 |
|---|---|
TARGETS가 <unknown> | metrics-server 미동작 또는 requests 누락 |
| FailedGetResourceMetric | metrics-server 인증서/네트워크 문제 |
| 확장이 안 됨 | maxReplicas 도달, tolerance 범위 내 |
| 축소가 느림 | scaleDown stabilizationWindow가 김(정상 동작) |
| 떨림(flapping) | stabilizationWindow를 늘려 완화 |
HPA와 Cluster Autoscaler는 함께 써야 완성됩니다. HPA가 Pod를 늘려도 노드 리소스가 부족하면 Pending이 되므로, 노드를 자동 추가하는 Cluster Autoscaler(또는 Karpenter)가 받쳐줘야 합니다.
정리
| 항목 | 핵심 |
|---|---|
| 전제 조건 | metrics-server + Pod의 resources.requests |
| API 버전 | autoscaling/v2 (다중 메트릭·behavior) |
| 계산식 | ceil(현재 * 현재값/목표값) |
| 메트릭 종류 | Resource(CPU/Mem) / Pods / Object / External |
| behavior | scaleUp 공격적 + scaleDown 보수적 권장 |
| 이벤트 워크로드 | KEDA(scale-to-zero) 고려 |
| 노드 부족 시 | Cluster Autoscaler/Karpenter 병행 |
HPA의 핵심은 "requests를 기준으로 한 비율 계산"입니다. requests를 현실적으로 잡고, scaleUp은 빠르게·scaleDown은 천천히 튜닝하며, 노드 오토스케일러까지 함께 구성해야 실제 트래픽 변동에 안정적으로 대응할 수 있습니다.
이 가이드는 AI 도구를 활용해 초안을 구성하고 사람이 명령어·문맥을 검토해 발행했습니다. 운영체제와 도구 버전에 따라 결과가 달라질 수 있으므로 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요.
질문 & 답변 (Q&A)
이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.