20210704

Kubernetes HPA custom metrics

배경

대부분 서비스는 CPU 기반 HPA로도 충분한데, 큐 컨슈머 성격의 서비스는 CPU 여유 있어도 큐 적체가 쌓일 수 있음. Redis stream 쌓인 길이 기준으로 확장하게 하려고 custom metrics 세팅.

스택

  • Kubernetes 1.20
  • prometheus-adapter로 external metrics 노출
  • Prometheus에 redis_exporter 메트릭 이미 수집 중

prometheus-adapter config

rules:
  external:
  - seriesQuery: 'redis_stream_length{job="redis-exporter"}'
    resources:
      template: "<<.Resource>>"
    name:
      matches: "^(.*)$"
      as: "stream_length"
    metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (stream)'

HPA manifest

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: order-worker
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-worker
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: External
    external:
      metric:
        name: stream_length
        selector:
          matchLabels:
            stream: "orders"
      target:
        type: AverageValue
        averageValue: "50"

스트림에 50 이상 쌓이면 파드 하나씩 늘어감. 즉시성이 너무 강하면 flap 일어나니까 behavior.scaleDown.stabilizationWindowSeconds를 300으로 걸어둠. 2beta2부터 scaling behavior 지정 가능해서 이게 큼.

배운 점

  • 초반에 metric name 매핑이 꼬여서 HPA가 "unknown metric" 띄움. kubectl get --raw로 adapter endpoint 직접 쳐보는 게 제일 빠른 디버깅.
  • averageValue 단위 설명이 애매한데, pod 개수 나눈 평균. 즉 pod당 목표 수치.
  • 큐 기반 워커는 scale-up은 빠르게, scale-down은 천천히가 정답. 일 중간에 갑자기 절반 줄면 진행 중 작업 취소 이슈 생김.

다음 단계: VPA랑 같이 돌릴 수 있는지 실험. 메모리는 VPA, replicas는 HPA 조합이 좋을지.