Kubernetes HPA 실무 가이드

커버 이미지
직접 생성. 무단 사용 금지

HPA(Horizontal Pod Autoscaler)란 무엇인가

Kubernetes HPA는 워크로드의 메트릭(CPU, 메모리, 사용자 정의 메트릭)을 기반으로 Pod 수를 자동 조절하는 컨트롤러입니다. Deployment, ReplicaSet, StatefulSet에 연결할 수 있으며, 기본적으로 metrics-server가 클러스터에 설치되어 있어야 합니다.

HPA v2 API(autoscaling/v2)를 사용하면 CPU와 메모리뿐 아니라 사용자 정의 메트릭(Custom Metrics)과 외부 메트릭(External Metrics)까지 스케일 기준으로 활용할 수 있습니다. 공식 문서에서는 autoscaling/v2를 권장합니다.

기본 HPA 설정: CPU 기반

가장 흔한 설정은 CPU 사용률 기준 스케일링입니다.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60

주의: averageUtilization은 Pod의 requests.cpu 대비 실제 사용량 비율입니다. requests가 설정되지 않으면 HPA는 동작하지 않습니다.

CPU 기준 스케일링의 함정

CPU 사용률만으로 스케일링하면 다음 문제가 발생합니다.

  • I/O 바운드 워크로드: DB 쿼리 대기, 외부 API 호출 등으로 응답 시간이 늘어나도 CPU는 낮게 유지됩니다.
  • JVM 워크로드: JIT, GC로 CPU 패턴이 불규칙합니다.
  • 큐 컨슈머: CPU를 거의 안 쓰지만 큐가 쌓이면 처리 지연이 발생합니다.
  • requests 오설정: 너무 낮으면 과도한 스케일 아웃, 너무 높으면 반응 지연.

메모리 기준 스케일링의 한계

메모리는 한번 잡으면 잘 안 내려갑니다. JVM 힙, Go 런타임 등 GC가 OS에 메모리를 반환하지 않는 경우가 많아, 스케일 인이 거의 되지 않고 항상 maxReplicas로 수렴합니다.

Custom Metrics 기반 HPA

실무에서 효과적인 스케일링을 하려면 Custom Metrics를 사용합니다. Prometheus Adapter 또는 KEDA를 통해 애플리케이션 메트릭을 HPA에 연결합니다.

# KEDA ScaledObject 예시
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: my-app-scaledobject
spec:
  scaleTargetRef:
    name: my-app
  minReplicaCount: 2
  maxReplicaCount: 30
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus.monitoring:9090
      metricName: http_request_duration_p99
      query: |
        histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
      threshold: "0.5"

HPA behavior 튜닝

  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 120

scaleDown은 보수적으로(300~600초), scaleUp은 빠르게(30~60초) 설정하는 것이 일반적입니다.

실전 운영 체크리스트

  1. requests 값을 kubectl top pod으로 검증했는가?
  2. metrics-server가 정상 동작하는가?
  3. minReplicas가 2 이상인가?
  4. maxReplicas에 클러스터 용량이 충분한가?
  5. PodDisruptionBudget을 함께 설정했는가?
  6. 부하 테스트로 HPA 동작을 검증했는가?
  7. maxReplicas 도달 시 알림이 설정되어 있는가?

HPA 디버깅

kubectl get hpa my-app-hpa -o wide
kubectl describe hpa my-app-hpa
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods"

흔한 에러: FailedGetResourceMetric(metrics-server 문제), FailedComputeMetricsReplicas(requests 미설정), InvalidMetricSourceType(API 버전 불일치).

마무리

HPA는 한 번 배포하고 끝이 아닙니다. 트래픽 패턴 변화에 따라 임계값을 재검토하고, 정기적으로 이벤트 로그를 리뷰하세요. CPU만으로는 부족하고, 비즈니스에 의미 있는 메트릭(요청 수, 레이턴시, 큐 깊이)을 스케일 기준으로 삼아야 합니다.

7) HPA 설정 실전 YAML과 커스텀 메트릭

CPU/메모리 기반 HPA는 기본이고, 실전에서는 RPS(초당 요청 수)나 큐 길이 같은 커스텀 메트릭 기반 스케일링이 더 효과적입니다.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-server-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  minReplicas: 2
  maxReplicas: 20
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60    # 스케일업은 빠르게
      policies:
        - type: Percent
          value: 50                      # 최대 50%씩 증가
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300   # 스케일다운은 5분 관찰 후
      policies:
        - type: Percent
          value: 25                      # 최대 25%씩 감소
          periodSeconds: 120
  metrics:
    # 1) CPU 기반 (기본)
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

    # 2) 메모리 기반
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

    # 3) 커스텀 메트릭: RPS (Prometheus Adapter 필요)
    - type: Pods
      pods:
        metric:
          name: http_requests_per_second
        target:
          type: AverageValue
          averageValue: "100"

8) HPA 디버깅과 흔한 문제

# HPA 상태 확인
kubectl get hpa api-server-hpa -o wide
# NAME             REFERENCE              TARGETS   MINPODS   MAXPODS   REPLICAS
# api-server-hpa   Deployment/api-server   65%/70%   2         20        5

# 상세 이벤트 확인
kubectl describe hpa api-server-hpa

# ⚠️ TARGETS에 "<unknown>/70%" 표시되면:
# → metrics-server가 설치되지 않았거나
# → Pod에 resources.requests가 설정되지 않음 (필수!)

# metrics-server 확인
kubectl top pods -n default
kubectl get apiservice v1beta1.metrics.k8s.io
  • requests 미설정: HPA는 requests 대비 사용률을 계산. requests 없으면 <unknown> 표시.
  • 플래핑(Flapping): 스케일업/다운이 반복되면 stabilizationWindowSeconds를 늘리세요.
  • 스케일다운 너무 빠름: 트래픽이 간헐적이면 scaleDown 정책을 보수적으로 설정.

9) 관련 글

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux