-
KEDA: Kubernetes Event-Driven Autoscaling이코에코(Eco²)/Applied 2025. 12. 26. 17:15

GitHub: kedacore/keda
CNCF 프로젝트: Graduated (2024)
KEDA (Kubernetes Event-Driven Autoscaling)는 이벤트 기반 워크로드에 대한 세밀한 오토스케일링을 제공하는 Kubernetes 컴포넌트이다. 기존 HPA(Horizontal Pod Autoscaler)를 확장하여 외부 이벤트 소스(메시지 큐, 스트림, 데이터베이스 등)를 기반으로 스케일링할 수 있게 한다.
KEDA의 핵심 기여
┌─────────────────────────────────────────────────────────────────┐ │ KEDA의 핵심 기여 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. 이벤트 기반 스케일링 │ │ → CPU/메모리가 아닌 큐 길이, 메시지 수 등으로 스케일링 │ │ → 워크로드 특성에 맞는 정밀한 스케일링 │ │ │ │ 2. Zero-to-N 스케일링 │ │ → 이벤트가 없으면 Pod 수를 0으로 축소 (비용 절감) │ │ → 이벤트 발생 시 자동으로 Pod 생성 │ │ │ │ 3. 다양한 이벤트 소스 지원 │ │ → 60+ 스케일러: RabbitMQ, Redis, Kafka, AWS SQS 등 │ │ → 커스텀 메트릭 스케일러 지원 │ │ │ │ 4. HPA와의 원활한 통합 │ │ → 기존 HPA 인프라 활용 │ │ → External Metrics API 표준 준수 │ │ │ └─────────────────────────────────────────────────────────────────┘HPA의 한계와 KEDA의 등장 배경
┌─────────────────────────────────────────────────────────────────┐ │ HPA의 한계 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 문제 1: 제한된 메트릭 소스 │ │ ──────────────────────── │ │ • HPA는 기본적으로 CPU/Memory 메트릭만 지원 │ │ • Custom Metrics는 별도 어댑터 설치 필요 │ │ • External Metrics 연동이 복잡 │ │ │ │ 문제 2: 최소 1개 Pod 필요 │ │ ───────────────────────── │ │ • HPA는 minReplicas ≥ 1 (0으로 스케일 불가) │ │ • 유휴 시간에도 리소스 비용 발생 │ │ │ │ 문제 3: 이벤트 기반 워크로드에 부적합 │ │ ──────────────────────────────── │ │ • 큐 기반 워크로드: CPU 사용률과 처리량이 비례하지 않음 │ │ • 버스트 트래픽: CPU 메트릭 지연으로 스케일링 늦음 │ │ │ │ 해결: KEDA │ │ ──────────── │ │ • 다양한 이벤트 소스를 External Metrics로 노출 │ │ • ScaleToZero 지원으로 비용 최적화 │ │ • 이벤트 발생량에 비례한 정확한 스케일링 │ │ │ └─────────────────────────────────────────────────────────────────┘
Kubernetes HPA 기초
KEDA를 이해하기 위해 먼저 HPA의 동작 원리를 이해해야 한다.
1. HPA 동작 원리 (Control Loop)
┌─────────────────────────────────────────────────────────────────┐ │ HPA Control Loop │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ HPA Controller │ │ │ │ (kube-controller-manager 내부, 기본 15초 주기) │ │ │ └─────────────────────────┬──────────────────────────────────┘ │ │ │ │ │ ┌───────────────┼───────────────┐ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Metrics │ │ Custom │ │ External │ │ │ │ Server │ │ Metrics │ │ Metrics │ │ │ │(Resource)│ │ API │ │ API │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ │ │ └───────────────┴───────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ 메트릭 수집 완료 │ │ │ └────────┬────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ 목표 Replicas │ │ │ │ 계산 │ │ │ └────────┬────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ Deployment │ │ │ │ Scale 조정 │ │ │ └─────────────────┘ │ │ │ │ 동작 주기: --horizontal-pod-autoscaler-sync-period (기본 15s) │ │ │ └─────────────────────────────────────────────────────────────────┘2. Kubernetes 메트릭 API 계층
API 그룹 엔드포인트 제공자 용도 metrics.k8s.io /apis/metrics.k8s.io/v1beta1Metrics Server CPU, Memory (Resource) custom.metrics.k8s.io /apis/custom.metrics.k8s.io/v1beta1Prometheus Adapter 등 클러스터 내부 커스텀 메트릭 external.metrics.k8s.io /apis/external.metrics.k8s.io/v1beta1KEDA, Stackdriver 등 외부 시스템 메트릭 ┌─────────────────────────────────────────────────────────────────┐ │ Kubernetes Metrics API 계층 구조 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────┐│ │ │ API Server ││ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ │ │ metrics. │ │ custom. │ │ external. │ ││ │ │ │ k8s.io │ │ metrics. │ │ metrics. │ ││ │ │ │ │ │ k8s.io │ │ k8s.io │ ││ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ ││ │ └─────────┼───────────────┼───────────────┼───────────────────┘│ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Metrics │ │Prometheus│ │ KEDA │ │ │ │ Server │ │ Adapter │ │ Metrics │ │ │ │ │ │ │ │ Server │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ kubelet │ │Prometheus│ │ RabbitMQ │ │ │ │ (cAdvisor)│ │ │ │ Redis │ │ │ │ │ │ │ │ Kafka │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ KEDA는 external.metrics.k8s.io API를 제공하여 │ │ 외부 시스템의 메트릭을 HPA에 노출 │ │ │ └─────────────────────────────────────────────────────────────────┘3. HPA 스케일링 알고리즘
HPA는 다음 수식으로 목표 레플리카 수를 계산한다:
기본 수식:
desiredReplicas = ⌈3 × (75/50)⌉ = ⌈4.5⌉ = 5
다중 메트릭 시:
각 메트릭에 대해 desiredReplicas 계산 → 최댓값 선택예시:
현재 상태: currentReplicas = 2 currentMetricValue = 100 (큐 메시지 수) desiredMetricValue = 30 (목표: Pod당 30개) 계산: desiredReplicas = ceil(2 × 100/30) = ceil(2 × 3.33) = ceil(6.67) = 7 결과: 7개 Pod로 스케일 아웃
KEDA 아키텍처
1. 전체 구성 요소
┌─────────────────────────────────────────────────────────────────┐ │ KEDA 아키텍처 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────┐│ │ │ keda namespace ││ │ │ ││ │ │ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ ││ │ │ │ KEDA Operator │ │ KEDA Metrics │ │ Admission │ ││ │ │ │ │ │ Server │ │ Webhooks │ ││ │ │ │ ┌──────────┐ │ │ │ │ │ ││ │ │ │ │ Scaler │ │ │ External │ │ ScaledObject │ ││ │ │ │ │ Handler │ │ │ Metrics API │ │ Validation │ ││ │ │ │ └──────────┘ │ │ │ │ │ ││ │ │ └───────┬────────┘ └───────┬────────┘ └───────────────┘ ││ │ │ │ │ ││ │ └──────────┼───────────────────┼──────────────────────────────┘│ │ │ │ │ │ │ │ external.metrics.k8s.io │ │ │ │ │ │ ┌──────────┼───────────────────┼──────────────────────────────┐│ │ │ │ │ ││ │ │ ▼ ▼ ││ │ │ ┌────────────┐ ┌────────────┐ ││ │ │ │ ScaledObject│ │ HPA │ ││ │ │ │ (CR) │ │ (자동생성) │ ││ │ │ └──────┬─────┘ └──────┬─────┘ ││ │ │ │ │ ││ │ │ └───────────────────┤ ││ │ │ │ ││ │ │ ▼ ││ │ │ ┌────────────┐ ││ │ │ │ Deployment │ ││ │ │ │ / Job │ ││ │ │ └────────────┘ ││ │ │ ││ │ │ target namespace ││ │ └──────────────────────────────────────────────────────────────┘│ │ │ │ │ │ │ ▼ │ │ ┌────────────┐ │ │ │ RabbitMQ │ │ │ │ Redis │ │ │ │ Kafka │ 외부 이벤트 소스 │ │ └────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘2. KEDA Operator
역할:
- ScaledObject/ScaledJob CRD 감시
- 트리거에 해당하는 Scaler 인스턴스 생성
- HPA 객체 자동 생성/관리
- Scale-to-Zero 처리 (HPA 없이 직접 스케일링)
┌─────────────────────────────────────────────────────────────────┐ │ KEDA Operator 동작 흐름 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. ScaledObject 생성 감지 │ │ │ │ │ ▼ │ │ 2. 트리거 설정 파싱 (RabbitMQ, Redis 등) │ │ │ │ │ ▼ │ │ 3. 해당 Scaler 인스턴스 생성 │ │ │ │ │ ▼ │ │ 4. HPA 객체 생성 (minReplicas ≥ 1일 때) │ │ │ │ │ └─── HPA가 스케일링 담당 (1 ↔ maxReplicas) │ │ │ │ │ ▼ │ │ 5. Scale-to-Zero 처리 (minReplicas = 0일 때) │ │ │ │ │ └─── Operator가 직접 스케일링 (0 ↔ 1) │ │ (HPA는 0으로 스케일 불가하므로) │ │ │ └─────────────────────────────────────────────────────────────────┘3. KEDA Metrics Server
역할:
external.metrics.k8s.ioAPI 구현- HPA가 요청하는 메트릭 제공
- Scaler를 통해 외부 시스템에서 메트릭 조회
HPA ──► API Server ──► KEDA Metrics Server ──► Scaler ──► RabbitMQ │ │ GET /apis/external.metrics.k8s.io/v1beta1/ │ namespaces/*/s0-rabbitmq-queue-length ▼ 메트릭 값 반환: {value: 150}4. CRD 종류
CRD 용도 ScaledObject Deployment, StatefulSet 등 스케일링 ScaledJob Job 기반 스케일링 (완료 후 삭제) TriggerAuthentication 네임스페이스 범위 인증 정보 ClusterTriggerAuthentication 클러스터 범위 인증 정보
External Metrics API 상세
1. API 구조
# API 엔드포인트 GET /apis/external.metrics.k8s.io/v1beta1/namespaces/{namespace}/{metricName} # 예시 요청 GET /apis/external.metrics.k8s.io/v1beta1/namespaces/scan/s0-rabbitmq-queue-length # 응답 형식 { "kind": "ExternalMetricValueList", "apiVersion": "external.metrics.k8s.io/v1beta1", "metadata": {}, "items": [ { "metricName": "s0-rabbitmq-queue-length", "metricLabels": {}, "timestamp": "2025-12-26T10:00:00Z", "value": "150" } ] }2. KEDA 메트릭 이름 규칙
KEDA는 ScaledObject의 트리거를 기반으로 메트릭 이름을 생성한다:
s{trigger-index}-{scaler-type}-{metric-name} 예시: s0-rabbitmq-scan_queue # 첫 번째 트리거, RabbitMQ, queue 길이 s1-prometheus-http_requests # 두 번째 트리거, Prometheus3. KEDA가 메트릭을 제공하는 과정
┌─────────────────────────────────────────────────────────────────┐ │ KEDA External Metrics 제공 과정 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. ScaledObject 생성 │ │ └─► KEDA Operator가 Scaler 인스턴스 생성 │ │ │ │ 2. HPA가 메트릭 요청 (15초 주기) │ │ │ │ │ ├─► API Server가 KEDA Metrics Server로 라우팅 │ │ │ │ │ └─► KEDA Metrics Server가 해당 Scaler 호출 │ │ │ │ 3. Scaler가 외부 시스템 조회 │ │ │ │ │ ├─► RabbitMQ: Management API로 큐 길이 조회 │ │ ├─► Redis: XPENDING으로 Pending 메시지 수 조회 │ │ └─► Kafka: Consumer Lag 조회 │ │ │ │ 4. 메트릭 값 반환 │ │ └─► HPA가 desiredReplicas 계산 │ │ │ └─────────────────────────────────────────────────────────────────┘
ScaledObject 상세
1. 전체 구조
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: scan-worker-scaledobject namespace: scan spec: # 1. 스케일링 대상 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: scan-worker # 2. 스케일링 범위 minReplicaCount: 0 # 최소 (0 = scale-to-zero) maxReplicaCount: 10 # 최대 # 3. 동작 설정 pollingInterval: 15 # 메트릭 조회 주기 (초) cooldownPeriod: 300 # 스케일 다운 대기 시간 (초) # 4. 고급 설정 advanced: restoreToOriginalReplicaCount: false horizontalPodAutoscalerConfig: behavior: scaleDown: stabilizationWindowSeconds: 300 # 5. Fallback 설정 fallback: failureThreshold: 3 replicas: 2 # 6. 트리거 정의 triggers: - type: rabbitmq metadata: queueName: scan_queue mode: QueueLength value: "5" authenticationRef: name: rabbitmq-auth2. 주요 필드 상세
scaleTargetRef
scaleTargetRef: apiVersion: apps/v1 # 대상 API 버전 kind: Deployment # Deployment, StatefulSet 등 name: scan-worker # 대상 이름 # envSourceContainerName: worker # 환경변수 소스 컨테이너 (선택)스케일링 범위
필드 기본값 설명 minReplicaCount0 최소 레플리카 수 (0 = scale-to-zero) maxReplicaCount100 최대 레플리카 수 idleReplicaCount- 유휴 시 유지할 레플리카 수 (선택) ┌─────────────────────────────────────────────────────────────────┐ │ minReplicaCount와 idleReplicaCount 관계 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ minReplicaCount: 0, idleReplicaCount: 미설정 │ │ ──────────────────────────────────────── │ │ 이벤트 없음 → 0개 Pod │ │ 이벤트 있음 → 1~maxReplicas │ │ │ │ minReplicaCount: 0, idleReplicaCount: 2 │ │ ───────────────────────────────────────── │ │ 이벤트 없음 → 2개 Pod (대기 상태) │ │ 이벤트 있음 → 2~maxReplicas │ │ │ │ 용도: 콜드 스타트 지연 없이 빠른 응답 필요 시 │ │ │ └─────────────────────────────────────────────────────────────────┘동작 설정
필드 기본값 설명 pollingInterval30 메트릭 조회 주기 (초) cooldownPeriod300 마지막 트리거 활성화 후 스케일 다운 대기 (초) ┌─────────────────────────────────────────────────────────────────┐ │ pollingInterval과 cooldownPeriod │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 시간 ────────────────────────────────────────────────────────► │ │ │ │ 메시지 수 ████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │ │ │ │ │ │ └─ 메시지 처리 완료 (0개) │ │ │ │ │ └─ 메시지 유입 (100개) │ │ │ │ Pod 수 ┌────────────────────────────────┐ │ │ ────┘ └──── │ │ │ │ │ │ │ ◄──── cooldownPeriod ────► │ │ │ │ (300초) │ │ │ │ │ │ │ 스케일 아웃 스케일 다운 │ │ │ │ cooldownPeriod 동안 메트릭이 0이어도 스케일 다운하지 않음 │ │ → 일시적 부하 감소 시 불필요한 스케일 다운 방지 │ │ │ └─────────────────────────────────────────────────────────────────┘Fallback 설정
메트릭 조회 실패 시 안전 장치:
fallback: failureThreshold: 3 # 연속 실패 횟수 replicas: 2 # 실패 시 유지할 레플리카 수정상 ──► 메트릭 조회 실패 (1회) ──► 메트릭 조회 실패 (2회) ──► 메트릭 조회 실패 (3회) ──► Fallback 모드 (2 replicas 유지)
RabbitMQ Scaler 상세
1. 동작 원리
┌─────────────────────────────────────────────────────────────────┐ │ RabbitMQ Scaler 동작 원리 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ │ │ │ KEDA Scaler │ │ │ │ (RabbitMQ) │ │ │ └────────┬────────┘ │ │ │ │ │ │ HTTP GET /api/queues/{vhost}/{queue} │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ RabbitMQ │ │ │ │ Management API │ (포트 15672) │ │ └────────┬────────┘ │ │ │ │ │ │ 응답: │ │ │ { │ │ │ "messages": 150, ← 큐에 있는 메시지 수 │ │ │ "messages_ready": 145, ← 소비 가능한 메시지 │ │ │ "messages_unacked": 5, ← 처리 중인 메시지 │ │ │ "consumers": 2, ← 소비자 수 │ │ │ "message_stats": {...} │ │ │ } │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ 메트릭 계산 │ │ │ │ │ │ │ │ mode에 따라: │ │ │ │ • QueueLength │ → messages 사용 │ │ │ • MessageRate │ → message_stats 사용 │ │ └────────┬────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ HPA에 메트릭 │ │ │ │ 제공 │ │ │ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘2. ScaledObject 설정 예시
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: scan-worker-scaledobject namespace: scan spec: scaleTargetRef: name: scan-worker minReplicaCount: 0 maxReplicaCount: 10 pollingInterval: 15 cooldownPeriod: 300 triggers: - type: rabbitmq metadata: # 필수 설정 queueName: scan_queue # 모드 선택 mode: QueueLength # QueueLength 또는 MessageRate # 목표 값 (Pod당 처리할 메시지 수) value: "5" # RabbitMQ 연결 설정 host: amqp://guest:guest@rabbitmq.rabbitmq.svc.cluster.local:5672/ # 또는 hostFromEnv로 환경변수에서 가져오기 # hostFromEnv: RABBITMQ_URL # vhost 설정 (기본값: /) vhostName: / # 큐가 없을 때 동작 activationValue: "0" # 0이면 스케일 다운 # TLS 설정 # unsafeSsl: "true" # 인증서 검증 비활성화 authenticationRef: name: rabbitmq-auth3. TriggerAuthentication 설정
apiVersion: keda.sh/v1alpha1 kind: TriggerAuthentication metadata: name: rabbitmq-auth namespace: scan spec: # 방법 1: Secret에서 직접 참조 secretTargetRef: - parameter: host name: rabbitmq-secret key: connection-string # 방법 2: 개별 파라미터 # secretTargetRef: # - parameter: username # name: rabbitmq-secret # key: username # - parameter: password # name: rabbitmq-secret # key: password4. 스케일링 계산 예시
┌─────────────────────────────────────────────────────────────────┐ │ RabbitMQ 스케일링 계산 예시 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 설정: │ │ mode: QueueLength │ │ value: 5 (Pod당 목표 메시지 수) │ │ minReplicaCount: 0 │ │ maxReplicaCount: 10 │ │ │ │ 상황 1: 큐에 메시지 0개 │ │ ───────────────────────── │ │ desiredReplicas = ceil(0 / 5) = 0 │ │ 결과: 0개 Pod (scale-to-zero) │ │ │ │ 상황 2: 큐에 메시지 15개 │ │ ────────────────────────── │ │ desiredReplicas = ceil(15 / 5) = 3 │ │ 결과: 3개 Pod │ │ │ │ 상황 3: 큐에 메시지 100개 │ │ ─────────────────────────── │ │ desiredReplicas = ceil(100 / 5) = 20 │ │ 결과: 10개 Pod (maxReplicaCount 제한) │ │ │ │ 상황 4: 큐에 메시지 2개 │ │ ────────────────────────── │ │ desiredReplicas = ceil(2 / 5) = 1 │ │ 결과: 1개 Pod (최소 1개, 메시지 있으므로) │ │ │ └─────────────────────────────────────────────────────────────────┘5. QueueLength vs MessageRate
모드 메트릭 용도 QueueLength 큐에 쌓인 메시지 수 배치 처리, 백로그 처리 MessageRate 초당 메시지 발행/소비율 실시간 스트리밍, 일정한 처리율 유지 # QueueLength 모드 triggers: - type: rabbitmq metadata: mode: QueueLength value: "5" # Pod당 5개 메시지 처리 # MessageRate 모드 triggers: - type: rabbitmq metadata: mode: MessageRate value: "100" # Pod당 초당 100개 메시지 처리
스케일링 알고리즘 상세
1. KEDA + HPA 통합 알고리즘
┌─────────────────────────────────────────────────────────────────┐ │ KEDA 스케일링 알고리즘 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Phase 1: 메트릭 수집 (pollingInterval 주기) │ │ ───────────────────────────────────────── │ │ 각 트리거에서 메트릭 값 조회 │ │ 예: rabbitmq.GetMetrics() → 150 (큐 길이) │ │ │ │ Phase 2: IsActive 판단 │ │ ────────────────────── │ │ 메트릭 > activationValue → true (스케일링 필요) │ │ 메트릭 ≤ activationValue → false (유휴 상태) │ │ │ │ Phase 3: Scale-to-Zero 처리 (Operator) │ │ ───────────────────────────────────── │ │ if (!IsActive && currentReplicas > 0) { │ │ cooldownPeriod 대기 후 replicas = 0 │ │ } │ │ if (IsActive && currentReplicas == 0) { │ │ replicas = 1 (즉시) │ │ } │ │ │ │ Phase 4: HPA 스케일링 (1 ↔ maxReplicas) │ │ ────────────────────────────────────── │ │ HPA가 external.metrics.k8s.io에서 메트릭 조회 │ │ desiredReplicas = ceil(currentMetric / targetMetric) │ │ Deployment.replicas 조정 │ │ │ └─────────────────────────────────────────────────────────────────┘2. 수식 상세
단일 트리거:
[
\text{desiredReplicas} = \lceil \frac{\text{currentMetricValue}}{\text{targetMetricValue}} \rceil
]다중 트리거:
[
\text{desiredReplicas} = \max(\text{desiredReplicas}_1, \text{desiredReplicas}_2, ..., \text{desiredReplicas}_n)
]예시 (다중 트리거):
triggers: - type: rabbitmq metadata: queueName: scan_queue value: "5" # 목표: Pod당 5개 - type: prometheus metadata: query: http_requests_total threshold: "100" # 목표: Pod당 100 RPS큐 메시지: 30개 → desiredReplicas_rabbitmq = ceil(30/5) = 6 HTTP RPS: 250 → desiredReplicas_prometheus = ceil(250/100) = 3 최종: max(6, 3) = 6 Pods3. Stabilization Window
급격한 스케일 변동을 방지하기 위한 안정화 기간:
advanced: horizontalPodAutoscalerConfig: behavior: scaleDown: stabilizationWindowSeconds: 300 # 5분 policies: - type: Percent value: 10 periodSeconds: 60 # 분당 최대 10% 감소 scaleUp: stabilizationWindowSeconds: 0 # 즉시 스케일 업 policies: - type: Pods value: 4 periodSeconds: 60 # 분당 최대 4개 증가┌─────────────────────────────────────────────────────────────────┐ │ Stabilization Window 동작 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 시간 ────────────────────────────────────────────────────────► │ │ │ │ 계산된 replicas │ │ │ │ 10 ──────┐ │ │ │ │ │ 6 ──────┼──────┐ │ │ │ │ │ │ 3 ──────┼──────┼────────────────────────────────── │ │ │ │ │ │ │ │ │ │ │◄────►│ stabilizationWindowSeconds │ │ │ │ │ │ │ └─ 실제 스케일 다운 시점 │ │ │ │ │ └─ 스케일 다운 요청 시점 │ │ │ │ Window 기간 중 가장 높은 값으로 유지 │ │ → 스파이크 후 급격한 스케일 다운 방지 │ │ │ └─────────────────────────────────────────────────────────────────┘
운영 고려사항
1. Scale-to-Zero 동작
┌─────────────────────────────────────────────────────────────────┐ │ Scale-to-Zero 동작 상세 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────┐│ │ │ 0 Replicas ││ │ │ │ ││ │ │ 이벤트 감지 ──────────┤ ││ │ │ (pollingInterval) │ ││ │ │ ▼ ││ │ │ ┌─────────────────┐ ││ │ │ │ KEDA Operator가 │ ││ │ │ │ replicas = 1 │ ││ │ │ └────────┬────────┘ ││ │ │ │ ││ │ │ ▼ ││ │ │ ┌─────────────────┐ ││ │ │ │ Pod 생성 (콜드 │ ││ │ │ │ 스타트 지연) │ ││ │ │ └────────┬────────┘ ││ │ │ │ ││ │ │ ▼ ││ │ │ ┌─────────────────┐ ││ │ │ │ HPA 활성화 │ ││ │ │ │ (1↔maxReplicas) │ ││ │ │ └─────────────────┘ ││ │ │ ││ │ └─────────────────────────────────────────────────────────────┘│ │ │ │ 주의사항: │ │ ───────── │ │ • 콜드 스타트 지연: Pod 생성 + 컨테이너 시작 + 초기화 │ │ • 지연 허용 불가 시: idleReplicaCount 또는 minReplicaCount ≥ 1│ │ │ └─────────────────────────────────────────────────────────────────┘2. 콜드 스타트 최적화
방법 설명 idleReplicaCount유휴 시에도 지정 수 Pod 유지 이미지 프리풀 노드에 이미지 미리 캐시 Init 컨테이너 최적화 의존성 초기화 시간 단축 PodDisruptionBudget 최소 가용 Pod 보장 3. 메트릭 지연 고려
┌─────────────────────────────────────────────────────────────────┐ │ 메트릭 지연과 스케일링 타이밍 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 시간 흐름: │ │ │ │ T+0s : 메시지 100개 유입 │ │ T+15s : KEDA 메트릭 조회 (pollingInterval) │ │ T+15s : HPA 메트릭 조회 │ │ T+16s : HPA가 스케일 결정 │ │ T+20s : 새 Pod 스케줄링 │ │ T+30s : 컨테이너 시작 │ │ T+45s : Pod Ready, 메시지 처리 시작 │ │ │ │ 총 지연: ~45초 │ │ │ │ 최적화: │ │ ───────── │ │ • pollingInterval 감소 (예: 5초) │ │ • 선제적 스케일링 (예: activationValue < threshold) │ │ • idleReplicaCount로 워밍업된 Pod 유지 │ │ │ └─────────────────────────────────────────────────────────────────┘4. Prometheus 메트릭 모니터링
KEDA가 노출하는 Prometheus 메트릭:
# Operator 메트릭 keda_scaler_active{namespace, scaledObject, scaler} # 스케일러 활성 상태 keda_scaler_metrics_value{namespace, scaledObject, scaler} # 현재 메트릭 값 keda_scaled_object_errors{namespace, scaledObject} # 에러 횟수 # Metrics Server 메트릭 keda_metrics_adapter_scaler_metrics_value{...} # 어댑터가 제공하는 메트릭 # 예시 쿼리 # 스케일러별 현재 메트릭 값 keda_scaler_metrics_value{namespace="scan", scaledObject="scan-worker-scaledobject"} # 에러 발생 추이 rate(keda_scaled_object_errors[5m])5. 트러블슈팅 체크리스트
┌─────────────────────────────────────────────────────────────────┐ │ KEDA 트러블슈팅 체크리스트 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ☐ ScaledObject 상태 확인 │ │ kubectl get scaledobject -n {namespace} │ │ kubectl describe scaledobject {name} -n {namespace} │ │ │ │ ☐ HPA 자동 생성 확인 │ │ kubectl get hpa -n {namespace} │ │ │ │ ☐ KEDA Operator 로그 확인 │ │ kubectl logs -n keda deployment/keda-operator │ │ │ │ ☐ Metrics Server 로그 확인 │ │ kubectl logs -n keda deployment/keda-metrics-apiserver │ │ │ │ ☐ External Metrics API 직접 조회 │ │ kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/ │ │ namespaces/{ns}/{metric-name}" │ │ │ │ ☐ TriggerAuthentication 검증 │ │ kubectl get triggerauthentication -n {namespace} │ │ kubectl describe triggerauthentication {name} -n {namespace}│ │ │ │ ☐ RabbitMQ Management API 직접 확인 │ │ curl -u guest:guest http://rabbitmq:15672/api/queues │ │ │ └─────────────────────────────────────────────────────────────────┘
다른 스케일러 개요
KEDA는 60개 이상의 스케일러를 지원한다. 주요 스케일러:
스케일러 메트릭 용도 rabbitmq 큐 길이, 메시지율 메시지 큐 기반 워커 redis-streams Pending 메시지 수, Consumer Lag 스트림 처리 kafka Consumer Lag 이벤트 스트리밍 prometheus PromQL 쿼리 결과 커스텀 메트릭 aws-sqs ApproximateNumberOfMessages AWS 메시지 큐 azure-servicebus 메시지 수 Azure 메시지 큐 cron Cron 스케줄 시간 기반 스케일링 cpu/memory 리소스 사용률 기본 리소스 기반
References
공식 문서
Kubernetes 문서
버전 정보
- 작성일: 2025-12-26
- KEDA 버전: 2.16.0
- Kubernetes 버전: 1.28+
'이코에코(Eco²) > Applied' 카테고리의 다른 글
Dependency Injection for LLM (1) 2026.01.05 LLM Gateway & Unified Interface Pattern (0) 2026.01.05 Karpenter: Kubernetes Node Autoscaling (0) 2025.12.26 Server-Sent Events (SSE) (0) 2025.12.25 Distributed Tracing: Trace, Span으로 분산 시스템 추적하기 (0) 2025.12.25