HPA 개념과 API 버전
Horizontal Pod Autoscaler(HPA)는 쿠버네티스 워크로드의 파드 수를 동적으로 조절하는 리소스입니다. Deployment, StatefulSet, ReplicaSet 등의 스케일러블 리소스를 대상으로 CPU, 메모리, 사용자 정의 지표를 기반으로 자동 확장·축소를 수행합니다.
주의할 점은 스케일링이 불가능한 객체에는 적용되지 않으며, HPA는 다음 세 가지 API 버전으로 제공됩니다.
$ kubectl api-versions | grep autoscal
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
| 버전 | 지원 지표 |
|---|---|
| autoscaling/v1 | CPU만 지원 |
| autoscaling/v2beta1 | Resource Metrics, Custom Metrics |
| autoscaling/v2beta2 | Resource Metrics, Custom Metrics, External Metrics |
지표 유형별 매니페스트 구성
v2beta2 버전에서는 4가지 지표 유형을 조합하여 사용할 수 있습니다. 각 유형별 목표값 설정 방식이 상이하므로 주의가 필요합니다.
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
- type: Object
object:
metric:
name: http-latency-p99
describedObject:
apiVersion: networking.k8s.io/v1
kind: Ingress
name: api-gateway
target:
type: Value
value: 200m
- type: Pods
pods:
metric:
name: network-io-mbps
target:
type: AverageValue
averageValue: 500Mi
- type: External
external:
metric:
name: kafka-lag-count
selector:
matchLabels:
topic: order-events
target:
type: AverageValue
averageValue: 100
지표 유형별 특성
- Resource: 파드 내 컨테이너의 CPU/메모리 사용률(Utilization) 또는 평균 절대값(AverageValue)
- Object: 버네티스 내부 객체(Ingress, Service 등)의 지표. Value 또는 AverageValue 목표값 지정
- Pods: 대상 파드 집합의 평균 지표. AverageValue만 허용
- External: 클러스터 외부 시스템의 지표. Value 또는 AverageValue 목표값 지정
스케일링 알고리즘과 동작 원리
HPA 컨트롤러는 기본 15초 간격으로 각 HPA 리소스를 평가합니다. 스케일링 결정 과정은 다음과 같이 이루어집니다.
1단계: 목표 레플리카 수 산출
각 지표별로 현재값과 목표값의 비율(스케일링 계수)을 계산합니다. Resource의 Utilization 지표를 예로 들면:
desiredReplicas = ceil[currentReplicas * (currentMetricValue / desiredMetricValue)]
CPU 사용률이 264%이고 목표가 50%라면, 현재 1개 레플리카 기준 ceil[1 * (264/50)] = 6개로 확장됩니다.
2단계: 다중 지표 병합
여러 지표가 설정된 경우, 각 지표별 계산 결과 중 가장 큰 레플리카 수를 채택합니다. 이는 안정적인 서비스 운영을 위해 보수적으로 설계된 방식입니다.
3단계: 임계값 및 경계 검증
- 변화율이 10% 미만이면 스케일링 무시(기본 톨러런스)
- minReplicas, maxReplicas 경계 강제 적용
- 지표 미수집 시: 확장은 최소값으로, 축소는 최대값으로 계산하여 안정성 확보
지표 데이터 획득 경로
| API 엔드포인트 | 제공 주체 | 지표 범위 |
|---|---|---|
| metrics.k8s.io | metrics-server | CPU, 메모리 등 리소스 지표 |
| custom.metrics.k8s.io | Prometheus Adapter 등 | 클러스터 내 사용자 정의 지표 |
| external.metrics.k8s.io | Prometheus Adapter 등 | 클러스터 외부 시스템 지표 |
실습: CPU 부하 기반 자동 확장
부하 생성 애플리케이션 빌드
CPU 집약적인 PHP 애플리케이션을 컨테이너화합니다.
# Dockerfile
FROM php:7.4-apache
COPY compute.php /var/www/html/index.php
RUN chmod 755 /var/www/html/index.php
<?php
// compute.php
$factor = 0.0001;
for ($idx = 0; $idx <= 10000000; $idx++) {
$factor += log($factor + 1);
}
echo "Completed heavy computation!\n";
?>
애플리케이션 배포
apiVersion: apps/v1
kind: Deployment
metadata:
name: stress-web
spec:
replicas: 1
selector:
matchLabels:
app: stress-web
template:
metadata:
labels:
app: stress-web
spec:
containers:
- name: php-worker
image: stress-php:v1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 250m
---
apiVersion: v1
kind: Service
metadata:
name: stress-web-svc
spec:
selector:
app: stress-web
ports:
- port: 80
targetPort: 80
HPA 리소스 생성
kubectl autoscale deployment stress-web \
--cpu-percent=50 \
--min=1 \
--max=8
생성된 HPA 상태를 확인합니다.
$ kubectl get hpa stress-web
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
stress-web Deployment/stress-web 0%/50% 1 8 1
부하 테스트 및 확장 검증
busybox를 활용한 부하 생성:
kubectl run load-generator --rm -it --image=busybox:1.36 -- /bin/sh
컨테이너 내부에서 지속적 요청:
while :; do wget -qO- http://stress-web-svc.default.svc.cluster.local; done
수 초 후 HPA 상태 변화를 관찰합니다.
$ kubectl get hpa stress-web -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
stress-web Deployment/stress-web 312%/50% 1 8 1
stress-web Deployment/stress-web 312%/50% 1 8 6
stress-web Deployment/stress-web 48%/50% 1 8 6
stress-web Deployment/stress-web 52%/50% 1 8 6
파드 수 변화 확인:
$ kubectl get pods -l app=stress-web
NAME READY STATUS RESTARTS
stress-web-7d9f4a2c1-x3k9p 1/1 Running 0
stress-web-7d9f4a2c1-m7v2q 1/1 Running 0
stress-web-7d9f4a2c1-p5n8r 1/1 Running 0
stress-web-7d9f4a2c1-j4w6t 1/1 Running 0
stress-web-7d9f4a2c1-b2h1y 1/1 Running 0
stress-web-7d9f4a2c1-q9c4d 1/1 Running 0
부하 제거 후 축소 확인
부하 생성을 중단하면 CPU 사용률이 감소하며, HPA는 설정된 안정화 기간 후 파드 수를 점진적으로 축소합니다.
$ kubectl get hpa stress-web -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
stress-web Deployment/stress-web 0%/50% 1 8 6
stress-web Deployment/stress-web 0%/50% 1 8 3
stress-web Deployment/stress-web 0%/50% 1 8 1
운영 시 고려사항
- 쿨다운 기간: 기본적으로 축소는 5분, 확장은 즉시 반응. 급격한 파드 증감을 방지하려면
--horizontal-pod-autoscaler-cpu-initialization-period등 파라미터 조정 - 메트릭 서버 장애: metrics-server 비가용 시 마지막 알려진 값으로 동작하며, 장기간 장애 시 스케일링 중단
- 다중 HPA 충돌: 동일 대상에 여러 HPA를 연결하면 서로 다른 목표로 파드 수가 불안정해짐. 하나의 HPA 내에 다중 지표로 통합 관리
- 커스텀 메트릭 어댑터: Prometheus Adapter, Datadog Cluster Agent 등을 활용하면 비즈니스 지표(큐 깊이, 요청 지연시간 등) 기반 스케일링 가능