본문으로 건너뛰기
김신건의 로그

[K8s] HPA / VPA / KEDA: 자동 확장

· 수정 · 📖 약 2분 · 628자/단어 #kubernetes #autoscaling #hpa #vpa #keda #k8s
HPA, Horizontal Pod Autoscaler, VPA, Vertical Pod Autoscaler, KEDA, Cluster Autoscaler, Karpenter

정의

Pod 를 자동으로 확장/축소하는 K8s 메커니즘. 세 가지 레벨:

레벨도구무엇을 확장
Pod 수HPA / KEDA동일 spec pod 추가/삭제
Pod 크기VPACPU/Memory request/limit 조절
Node 수Cluster Autoscaler / Karpenternode 추가/삭제

3가지 스케일링

flowchart TB
    Q[스케일링 종류]
    Q --> HPA["HPA<br/>Pod 수 증감"]
    Q --> VPA["VPA<br/>Pod 리소스 증감"]
    Q --> CA["Cluster Autoscaler / Karpenter<br/>Node 수 증감"]

HPA (Horizontal Pod Autoscaler)

CPU / Memory / custom metric 기반 pod 수 조정.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: { name: web }
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 3
  maxReplicas: 50
  metrics:
    - type: Resource
      resource:
        name: cpu
        target: { type: Utilization, averageUtilization: 70 }
    - type: Pods
      pods:
        metric: { name: http_requests_per_second }
        target: { type: AverageValue, averageValue: "1000" }
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Percent
          value: 100
          periodSeconds: 15
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 10
          periodSeconds: 60

HPA 알고리즘

desired = ceil(currentReplicas × (currentMetric / targetMetric))

예: 현재 4 pod, CPU 80%, 목표 50%:

  • desired = ceil(4 × (80/50)) = 7 pod

HPA 제어 루프

sequenceDiagram
    participant MS as metrics-server
    participant HPA as HPA controller
    participant D as Deployment

    loop 15초마다
        HPA->>MS: 현재 CPU/메모리 조회
        MS-->>HPA: 평균 CPU 80%
        HPA->>HPA: desired = ceil(4 * 80/50) = 7
        HPA->>D: replicas: 7
        D->>D: pod 3개 추가
    end
  • stabilizationWindowSeconds: scale down 은 기본 300초 대기 후 결정
  • scaleDown.policies: 한 번에 10% 씩, 60초 간격으로 축소

Custom Metrics: Prometheus Adapter

HPA 에서 커스텀 메트릭을 사용하려면 Prometheus Adapter 로 메트릭을 K8s Custom Metrics API 에 노출:

# prometheus-adapter ConfigMap (간략)
rules:
  - seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
    resources:
      overrides:
        namespace: { resource: "namespace" }
        pod: { resource: "pod" }
    name:
      matches: "^(.*)_total$"
      as: "${1}_per_second"
    metricsQuery: 'rate(<<.Series>>{<<.LabelMatchers>>}[2m])'

이후 HPA spec 에서:

metrics:
  - type: Pods
    pods:
      metric: { name: http_requests_per_second }
      target: { type: AverageValue, averageValue: "1000" }

VPA (Vertical Pod Autoscaler)

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata: { name: web }
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  updatePolicy:
    updateMode: "Auto"   # Off / Initial / Recreate / Auto
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed: { cpu: 50m, memory: 64Mi }
        maxAllowed: { cpu: 2, memory: 2Gi }

CAUTION

VPA + HPA on CPU 동시 사용 금지. 둘이 같은 메트릭으로 다툼. HPA 는 custom metric, VPA 는 resource → 분리 가능.

VPA 모드 비교

updateMode동작재시작
Off권고값만 계산, 실제 변경 없음없음
Initialpod 생성 시 한 번만 적용없음
Recreate변경 필요 시 pod 삭제 후 재생성있음
Auto현재는 Recreate 와 동일 (인플레이스 업데이트 개발 중)있음

VPA Off 모드는 초기 resource request 추천 용도로 자주 활용.

KEDA (Kubernetes Event-Driven Autoscaling)

flowchart LR
    Trigger["외부 트리거<br/>Kafka lag, SQS depth, ..."] --> KEDA
    KEDA --> HPA[표준 HPA 생성]
    HPA --> Deploy[Deployment scale]
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata: { name: kafka-consumer }
spec:
  scaleTargetRef:
    name: consumer
  minReplicaCount: 0
  maxReplicaCount: 30
  triggers:
    - type: kafka
      metadata:
        bootstrapServers: kafka:9092
        topic: events
        consumerGroup: my-group
        lagThreshold: '1000'

IMPORTANT

KEDA 가 2026 시점 표준. 50+ scaler (Kafka, SQS, Prometheus, Redis, DB query, …) 지원. scale-to-zero 가능.

KEDA: Prometheus 기반 스케일링

triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      metricName: http_requests_total
      query: sum(rate(http_requests_total{job="web"}[2m]))
      threshold: '1000'

Prometheus 가 있는 클러스터에서 임의의 PromQL 로 스케일링 가능. metrics-server + Prometheus Adapter 없이 KEDA 만으로도 커스텀 메트릭 HPA 구현 가능.

Cluster Autoscaler / Karpenter

flowchart LR
    HPA --> NeedMore[새 pod 들이 Pending]
    NeedMore --> CA[Cluster Autoscaler]
    CA -->|"EC2 / GCE"| AddNode[새 node 추가]
    AddNode --> Schedule[pending pod 스케줄]
-Cluster AutoscalerKarpenter
종류표준 K8s 도구AWS 발 (이제 CNCF)
Node 선택미리 정의된 node group동적 instance type 선택
속도분 단위수십 초
비용 최적화제한적우수 (spot, right-sizing)
클라우드다양AWS, Azure

HPA vs KEDA 선택 기준

상황추천
CPU/Memory 기반 스케일링만 필요HPA 단독
Kafka lag, SQS depth, Prometheus metricKEDA
scale-to-zero 필요KEDA
50+ 종류의 외부 트리거KEDA
기존 HPA + 일부 custom metricHPA + Prometheus Adapter

흔한 함정

WARNING

  1. stabilization window 너무 짧음 = 빈번한 scale up/down → 비용 + 안정성 문제.
  2. HPA + VPA 동시 (같은 메트릭) = 충돌. 분리 또는 VPA off mode + 수동.
  3. metrics-server 미설치 = HPA 작동 안 함. cluster 부팅 시 자동 설치 확인.
  4. resource request 없음 = HPA CPU 기준 무의미. requests 필수.
  5. minReplicas: 0 + 갑작스러운 트래픽 = cold-start latency. KEDA minReplicaCount: 1 권장.

관련 위키

이 글의 용어 (4개)
[Distributed] Kafka Consumer Group: rebalancing, offset, lagdistributed-systems
정의 Consumer Group = 같은 를 가진 consumer들이 함께 한 topic을 분담 소비. partition 단위로 분배. 핵심 특성: - 한 partition → …
[K8s] Deployment: ReplicaSet, rolling update, rollbackkubernetes
정의 Deployment = stateless 워크로드를 위한 컨트롤러. 내부적으로 ReplicaSet 관리 + rolling update / rollback. 사용 시나리오 |…
[K8s] Pod: 컨테이너의 최소 단위, sidecar, lifecyclekubernetes
정의 Pod = K8s 의 가장 작은 배포 단위. 1개 이상의 컨테이너 + 공유 네트워크 + 공유 스토리지. [!IMPORTANT] Pod 는 컨테이너의 wrapping 이 아니…
[Observability] Prometheus: pull 기반 메트릭, PromQLdevops
정의 Prometheus = pull 기반 시계열 metric 시스템. PromQL 로 쿼리. CNCF graduated. 2026 클라우드 네이티브 메트릭 표준. 아키텍처 Pu…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기