KEDA란 무엇인가?
KEDA(Kubernetes Event-Driven Autoscaling)는 이벤트 소스 기반으로 워크로드를 스케일링하는 Kubernetes 오퍼레이터입니다. 기본 HPA가 CPU/메모리 메트릭만 지원하는 반면, KEDA는 Kafka 토픽 lag, RabbitMQ 큐 길이, AWS SQS 메시지 수, Prometheus 쿼리 결과 등 60개 이상의 외부 이벤트 소스를 스케일링 트리거로 사용할 수 있습니다.
핵심 차별점은 0 → N 스케일링입니다. HPA는 최소 replicas가 1이지만, KEDA는 이벤트가 없으면 Pod를 0으로 축소하고, 이벤트 발생 시 즉시 Pod를 생성합니다. 비용 최적화에 결정적인 기능입니다.
KEDA 아키텍처 핵심 컴포넌트
KEDA는 세 가지 핵심 CRD(Custom Resource Definition)로 구성됩니다:
- ScaledObject — Deployment/StatefulSet 대상 스케일링 규칙 정의
- ScaledJob — Job 기반 워크로드 스케일링 (배치 처리에 적합)
- TriggerAuthentication — 이벤트 소스 접속 인증 정보 관리
내부적으로 KEDA는 Metrics Server 역할을 하여 외부 메트릭을 Kubernetes HPA가 이해하는 형태로 변환합니다. 즉, KEDA가 HPA를 대체하는 것이 아니라 HPA를 확장하는 구조입니다.
설치와 기본 설정
Helm을 통한 KEDA 설치는 간단합니다:
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm install keda kedacore/keda
--namespace keda
--create-namespace
--set watchNamespace=""
--set resources.operator.requests.cpu=100m
--set resources.operator.requests.memory=128Mi
설치 후 keda-operator, keda-operator-metrics-apiserver, keda-admission-webhooks 세 개의 Pod가 생성됩니다.
ScaledObject: Kafka Consumer 오토스케일링
가장 대표적인 사용 사례인 Kafka consumer lag 기반 스케일링입니다:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-consumer-scaler
namespace: production
spec:
scaleTargetRef:
name: order-consumer # 대상 Deployment 이름
pollingInterval: 15 # 메트릭 폴링 주기 (초)
cooldownPeriod: 60 # 스케일다운 대기 시간 (초)
minReplicaCount: 0 # 이벤트 없으면 0으로 축소
maxReplicaCount: 20 # 최대 Pod 수
advanced:
restoreToOriginalReplicaCount: false
horizontalPodAutoscalerConfig:
behavior:
scaleDown:
stabilizationWindowSeconds: 120
policies:
- type: Percent
value: 50
periodSeconds: 60 # 1분마다 최대 50%씩 축소
triggers:
- type: kafka
metadata:
bootstrapServers: kafka-bootstrap.kafka:9092
consumerGroup: order-consumer-group
topic: orders
lagThreshold: "10" # consumer lag 10 이상이면 스케일업
activationLagThreshold: "1" # lag 1 이상이면 0→1 활성화
offsetResetPolicy: latest
핵심 파라미터 설명:
lagThreshold— 파티션당 lag이 이 값을 초과하면 replica 추가. 값이 작을수록 민감하게 반응activationLagThreshold— 0 replica에서 1로 활성화하는 기준. lagThreshold와 별도 설정 가능cooldownPeriod— 마지막 이벤트 이후 0으로 축소하기까지 대기 시간
ScaledObject: SQS 큐 기반 스케일링
AWS SQS 메시지 수에 따른 스케일링 설정입니다:
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: aws-credentials
namespace: production
spec:
secretTargetRef:
- parameter: awsAccessKeyID
name: aws-secret
key: AWS_ACCESS_KEY_ID
- parameter: awsSecretAccessKey
name: aws-secret
key: AWS_SECRET_ACCESS_KEY
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: notification-worker-scaler
namespace: production
spec:
scaleTargetRef:
name: notification-worker
minReplicaCount: 0
maxReplicaCount: 50
triggers:
- type: aws-sqs-queue
authenticationRef:
name: aws-credentials
metadata:
queueURL: https://sqs.ap-northeast-2.amazonaws.com/123456789/notifications
queueLength: "5" # 메시지 5개당 Pod 1개
awsRegion: ap-northeast-2
activationQueueLength: "1"
queueLength: "5"는 큐에 메시지가 50개 있으면 Pod 10개를 생성한다는 의미입니다. 이 비율을 워크로드의 처리 속도에 맞춰 튜닝해야 합니다.
ScaledJob: 배치 처리 패턴
장시간 실행되는 배치 작업에는 ScaledJob이 더 적합합니다. Deployment와 달리 각 메시지를 독립 Job으로 처리합니다:
apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
name: video-encoder-job
namespace: production
spec:
jobTargetRef:
parallelism: 1
completions: 1
backoffLimit: 3
template:
spec:
containers:
- name: encoder
image: video-encoder:v2.1
resources:
requests:
cpu: "2"
memory: 4Gi
restartPolicy: Never
pollingInterval: 10
maxReplicaCount: 10
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 3
scalingStrategy:
strategy: accurate # 큐 메시지 수 = Job 수 (정확한 매핑)
triggers:
- type: rabbitmq
metadata:
host: amqp://rabbitmq.infra:5672
queueName: video-encoding
queueLength: "1" # 메시지 1개당 Job 1개
ScaledObject vs ScaledJob 선택 기준:
- ScaledObject — 상시 실행되며 메시지를 계속 소비하는 워커 (Kafka consumer, API 서버)
- ScaledJob — 메시지당 독립 실행·완료되는 배치 작업 (동영상 인코딩, 리포트 생성)
Prometheus 커스텀 메트릭 트리거
Prometheus 쿼리 결과를 스케일링 기준으로 사용하면, 어떤 메트릭이든 트리거로 활용할 수 있습니다:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: api-gateway-scaler
spec:
scaleTargetRef:
name: api-gateway
minReplicaCount: 2
maxReplicaCount: 30
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{
service="api-gateway",
status=~"2.."
}[2m]))
threshold: "100" # 초당 요청 100 이상이면 스케일업
activationThreshold: "10"
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
query: |
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket{
service="api-gateway"
}[5m])) by (le))
threshold: "0.5" # P95 응답시간 500ms 초과 시 스케일업
activationThreshold: "0.1"
여러 트리거를 동시에 설정하면, KEDA는 가장 높은 replica 수를 요구하는 트리거를 기준으로 스케일링합니다. 위 예시에서는 RPS와 응답시간 중 더 많은 Pod를 요구하는 쪽이 적용됩니다.
Cron 기반 예측적 스케일링
트래픽 패턴이 예측 가능하다면, Cron 트리거로 미리 스케일업할 수 있습니다:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: web-app-scaler
spec:
scaleTargetRef:
name: web-app
minReplicaCount: 2
maxReplicaCount: 50
triggers:
# 평일 오전 9시~오후 6시: 최소 10대
- type: cron
metadata:
timezone: Asia/Seoul
start: 0 9 * * 1-5
end: 0 18 * * 1-5
desiredReplicas: "10"
# 실시간 메트릭 기반 추가 스케일링
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
query: sum(rate(http_requests_total{app="web-app"}[2m]))
threshold: "200"
Cron 트리거와 메트릭 트리거를 조합하면, 피크 시간대 사전 준비 + 실시간 대응이라는 이상적인 스케일링 전략을 구현할 수 있습니다.
운영 시 주의사항
KEDA를 프로덕션에서 운영할 때 반드시 고려해야 할 사항들입니다:
- 0→1 콜드 스타트 — 컨테이너 이미지 pull + 앱 초기화 시간이 걸립니다. 중요 서비스는
minReplicaCount: 1이상을 권장합니다 - Graceful Shutdown — 스케일다운 시 처리 중인 메시지가 유실되지 않도록
terminationGracePeriodSeconds와 SIGTERM 핸들러를 반드시 설정하세요 - 메트릭 지연 — 외부 메트릭 소스의 업데이트 주기를 고려하여
pollingInterval을 설정하세요. 너무 짧으면 API 호출 비용이 증가합니다 - PodDisruptionBudget — 급격한 스케일다운을 방지하기 위해 PDB를 함께 설정하세요
- Fallback 설정 — 메트릭 소스 장애 시 기본 replica 수를 유지하도록
fallback옵션을 활용하세요
spec:
fallback:
failureThreshold: 3 # 3회 연속 메트릭 조회 실패 시
replicas: 5 # 5개 유지 (안전한 기본값)
관련 글: K8s ConfigMap·Secret 관리 전략에서 인증 정보 관리를, K8s StatefulSet 완벽 가이드에서 상태 유지 워크로드 운영을 함께 확인하세요.
마무리
KEDA는 Kubernetes의 스케일링 역량을 이벤트 기반으로 확장하는 핵심 도구입니다. 0→N 스케일링으로 비용을 절감하고, 60개 이상의 트리거로 유연하게 대응하며, HPA와 자연스럽게 통합됩니다. Kafka, SQS, RabbitMQ 같은 메시지 큐 기반 아키텍처를 운영하고 있다면 KEDA 도입을 적극 검토하세요.