K8s HPA·VPA 오토스케일링

K8s 오토스케일링이란?

Kubernetes는 워크로드 부하에 따라 자동으로 리소스를 조절하는 세 가지 오토스케일링 메커니즘을 제공합니다: HPA(Horizontal Pod Autoscaler), VPA(Vertical Pod Autoscaler), Cluster Autoscaler. 이 글에서는 HPA와 VPA의 동작 원리, 설정 방법, 그리고 실전에서 마주치는 함정까지 깊이 다룹니다.

HPA: 수평 오토스케일링

HPA는 메트릭 기반으로 Pod 수를 자동 증감합니다. CPU, 메모리뿐 아니라 커스텀 메트릭도 사용할 수 있습니다.

기본 HPA: CPU 기반

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

CPU 사용률이 70%를 초과하면 Pod를 늘리고, 낮아지면 줄입니다. 반드시 Deployment에 resources.requests가 설정되어 있어야 HPA가 동작합니다:

containers:
  - name: api
    resources:
      requests:
        cpu: 200m
        memory: 256Mi
      limits:
        cpu: 500m
        memory: 512Mi

HPA 스케일링 알고리즘

HPA는 다음 공식으로 목표 Pod 수를 계산합니다:

desiredReplicas = ceil(currentReplicas × (currentMetric / desiredMetric))

예: 현재 3개 Pod, CPU 사용률 90%, 목표 70% → ceil(3 × 90/70) = ceil(3.86) = 4개로 스케일 아웃됩니다.

멀티 메트릭 HPA

CPU와 메모리를 동시에 기준으로 설정할 수 있습니다:

spec:
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

여러 메트릭이 있으면 각각 계산한 후 가장 큰 값을 채택합니다. CPU는 괜찮은데 메모리가 높으면 메모리 기준으로 스케일 아웃됩니다.

커스텀 메트릭 HPA

CPU/메모리만으로는 부족한 경우가 많습니다. 큐 길이, 요청 레이턴시 등 비즈니스 메트릭으로 스케일링하는 것이 실전에서 더 효과적입니다:

spec:
  metrics:
    # Prometheus 커스텀 메트릭
    - type: Pods
      pods:
        metric:
          name: http_requests_per_second
        target:
          type: AverageValue
          averageValue: 100
    # 외부 메트릭 (SQS 큐 길이 등)
    - type: External
      external:
        metric:
          name: sqs_queue_length
          selector:
            matchLabels:
              queue: order-processing
        target:
          type: Value
          value: 50

커스텀 메트릭을 사용하려면 Prometheus Adapter 또는 KEDA가 필요합니다. KEDA는 이벤트 기반 오토스케일링으로, 0→N 스케일링도 지원합니다.

HPA Behavior: 스케일링 속도 제어

급격한 스케일 인/아웃을 방지하는 behavior 설정은 프로덕션에서 필수입니다:

spec:
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Percent
          value: 50           # 현재 수의 50%까지만 증가
          periodSeconds: 60
        - type: Pods
          value: 4            # 또는 최대 4개까지 증가
          periodSeconds: 60
      selectPolicy: Max       # 둘 중 큰 값 채택
    scaleDown:
      stabilizationWindowSeconds: 300  # 5분 안정화
      policies:
        - type: Percent
          value: 10           # 10%씩만 감소
          periodSeconds: 120
      selectPolicy: Min       # 가장 보수적으로

스케일 다운은 보수적으로 설정하는 것이 핵심입니다. 트래픽이 잠시 줄었다가 다시 올라오는 패턴에서 급격한 스케일 다운은 서비스 장애를 유발합니다. stabilizationWindowSeconds는 해당 시간 동안의 추천값 중 가장 높은(스케일 다운) 또는 낮은(스케일 업) 값을 채택합니다.

VPA: 수직 오토스케일링

VPA는 Pod 수가 아닌 개별 Pod의 리소스(CPU/메모리) 요청량을 자동 조절합니다:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: api-server-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  updatePolicy:
    updateMode: Auto          # Off, Initial, Recreate, Auto
  resourcePolicy:
    containerPolicies:
      - containerName: api
        minAllowed:
          cpu: 100m
          memory: 128Mi
        maxAllowed:
          cpu: 2
          memory: 2Gi
        controlledResources:
          - cpu
          - memory
updateMode 동작 용도
Off 추천만, 적용 안 함 리소스 분석용
Initial Pod 생성 시에만 적용 안전한 적용
Auto Pod 재시작하며 적용 완전 자동화

주의: VPA Auto 모드는 리소스를 변경하기 위해 Pod를 재시작합니다. 이는 K8s PDB(PodDisruptionBudget)와 함께 설정해야 가용성을 보장할 수 있습니다.

HPA + VPA 함께 사용하기

HPA와 VPA를 동시에 사용하면 충돌이 발생할 수 있습니다. 안전한 조합 패턴:

# VPA: 메모리만 제어 (Off 모드로 추천만)
spec:
  resourcePolicy:
    containerPolicies:
      - containerName: api
        controlledResources:
          - memory          # CPU는 VPA에서 제외
        mode: "Auto"

# HPA: CPU 기반 스케일링
spec:
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

핵심 규칙: HPA가 CPU로 스케일링하면, VPA는 CPU를 제어하지 않아야 합니다. 둘 다 CPU를 조절하면 서로 상충하는 결정을 내립니다. 가장 안전한 패턴은 VPA를 Off 모드로 두고 추천값만 참고하는 것입니다.

Cluster Autoscaler 연동

HPA가 Pod를 늘려도 노드 리소스가 부족하면 Pod가 Pending 상태에 머뭅니다. Cluster Autoscaler가 이를 감지해 노드를 추가합니다:

전체 흐름:
1. 트래픽 증가 → CPU 사용률 상승
2. HPA → Pod 수 증가 결정
3. Scheduler → 노드 리소스 부족, Pod Pending
4. Cluster Autoscaler → 새 노드 프로비저닝
5. Pod가 새 노드에 스케줄링
6. 트래픽 감소 → HPA 스케일 다운
7. 노드 사용률 저하 → Cluster Autoscaler 노드 제거

K8s ResourceQuota·LimitRange와 함께 설정하면 네임스페이스별 리소스 상한을 지정해 오토스케일링이 클러스터 전체를 잠식하는 것을 방지할 수 있습니다.

KEDA: 이벤트 기반 스케일링

KEDA(Kubernetes Event-Driven Autoscaling)는 HPA를 확장해 0→N 스케일링과 다양한 이벤트 소스를 지원합니다:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: order-worker
spec:
  scaleTargetRef:
    name: order-worker
  pollingInterval: 15
  cooldownPeriod: 300
  minReplicaCount: 0          # 0까지 스케일 다운!
  maxReplicaCount: 50
  triggers:
    - type: rabbitmq
      metadata:
        host: amqp://rabbitmq:5672
        queueName: orders
        queueLength: "10"     # 큐 메시지 10개당 1 Pod

KEDA는 Kafka, SQS, Redis, PostgreSQL, Cron 등 60개 이상의 스케일러를 지원합니다. 워커/컨슈머 워크로드에 특히 적합합니다.

오토스케일링 트러블슈팅

자주 마주치는 문제와 해결법:

증상 원인 해결
HPA가 unknown 표시 metrics-server 미설치 또는 requests 미설정 kubectl top pods 확인, requests 설정
스케일 아웃이 너무 느림 기본 동기화 주기 15초 --horizontal-pod-autoscaler-sync-period 조정
플래핑(반복 스케일 인/아웃) stabilizationWindow 미설정 behavior.scaleDown.stabilizationWindowSeconds 증가
VPA가 Pod를 계속 재시작 추천값과 현재값 차이 큼 minAllowed/maxAllowed 범위 조정, Off 모드 먼저 테스트
# HPA 상태 확인
kubectl get hpa -w
kubectl describe hpa api-server-hpa

# VPA 추천값 확인
kubectl describe vpa api-server-vpa

# metrics-server 확인
kubectl top pods
kubectl top nodes

마무리

K8s 오토스케일링은 단순히 HPA를 설정하는 것을 넘어, behavior로 스케일링 속도를 제어하고, VPA로 리소스 최적화를 병행하며, KEDA로 이벤트 기반 스케일링까지 확장하는 것이 실전입니다. HPA와 VPA의 충돌을 피하고, Cluster Autoscaler와 연동해 노드 레벨까지 자동화하면 진정한 탄력적 인프라를 구축할 수 있습니다.

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