/엔지니어/Docker / 컨테이너/Kubernetes HPA 오토스케일링 — 리소스
Docker / 컨테이너고급linuxkuberneteshpaautoscaling

Kubernetes HPA 오토스케일링 — 리소스 기반 Pod 자동 확장

metrics-server 설치부터 CPU/메모리·커스텀 메트릭 기반 HorizontalPodAutoscaler 구성, 스케일링 동작(behavior) 튜닝, 트러블슈팅까지 실전으로 다룹니다.

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에 의존합니다.

Bash
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

테스트/사설 클러스터에서 kubelet 인증서가 자체서명이라 metrics-server가 못 붙는 경우가 흔합니다. 이때만 임시로 TLS 검증을 끕니다.

Bash
kubectl patch deployment metrics-server -n kube-system --type=json \
  -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'

설치 확인:

Bash
kubectl top nodes
kubectl top pods
# 값이 나오면 metrics-server 정상

스케일 대상 워크로드 준비

YAML
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 기반

명령형 (간단)

Bash
kubectl autoscale deployment php-apache \
  --cpu-percent=50 --min=1 --max=10

선언형 (autoscaling/v2, 권장)

v2 API는 다중 메트릭과 스케일링 동작 튜닝을 지원합니다.

YAML
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

여러 메트릭이 있으면 각각 계산해 가장 큰 레플리카 수를 채택합니다(보수적 확장).


스케일링 계산 원리

원하는 레플리카는 다음 공식으로 결정됩니다.

CODE
desiredReplicas = ceil( currentReplicas * (currentMetric / targetMetric) )

예: 현재 3개 Pod, 평균 CPU 사용률 90%, 목표 50% → ceil(3 * 90/50) = ceil(5.4) = 6개로 확장.

목표값 근처(기본 ±10% tolerance)에서는 잦은 떨림을 막기 위해 스케일링하지 않습니다.


부하 테스트로 확인

Bash
# 부하 발생기
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를 조정합니다.

YAML
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절대 개수 변동 한도
selectPolicyMax(공격적)/Min(보수적)/Disabled

커스텀·외부 메트릭 (RPS, 큐 길이)

CPU만으로 부족하면 Prometheus Adapter나 KEDA로 애플리케이션 지표 기반 확장을 합니다.

YAML
  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보다 편리합니다.


트러블슈팅

Bash
kubectl describe hpa php-apache       # 이벤트와 조건(Conditions) 확인
증상원인 / 해결
TARGETS가 <unknown>metrics-server 미동작 또는 requests 누락
FailedGetResourceMetricmetrics-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
behaviorscaleUp 공격적 + scaleDown 보수적 권장
이벤트 워크로드KEDA(scale-to-zero) 고려
노드 부족 시Cluster Autoscaler/Karpenter 병행

HPA의 핵심은 "requests를 기준으로 한 비율 계산"입니다. requests를 현실적으로 잡고, scaleUp은 빠르게·scaleDown은 천천히 튜닝하며, 노드 오토스케일러까지 함께 구성해야 실제 트래픽 변동에 안정적으로 대응할 수 있습니다.

#kubernetes#hpa#autoscaling#metrics-server#scaling
편집 안내 · Editorial Note

이 가이드는 AI 도구를 활용해 초안을 구성하고 사람이 명령어·문맥을 검토해 발행했습니다. 운영체제와 도구 버전에 따라 결과가 달라질 수 있으므로 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요.

질문 & 답변 (Q&A)

이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.