KEDA는 Kubernetes에서 이벤트 기반 오토스케일링을 지원하는 프레임워크입니다. 기존 HPA (Horizontal Pod Autoscaler)가 CPU 및 메모리와 같은 리소스 메트릭을 기반으로 스케일링을 수행하는 반면, KEDA는 특정 이벤트를 감지하여 Pod의 개수를 조정할 수 있습니다.
| 비교 항목 | HPA (Horizontal Pod Autoscaler) | KEDA (Kubernetes Event Driven Autoscaler) |
|---|---|---|
| 기반 메트릭 | CPU, Memory 등의 리소스 사용률 | 이벤트(Queue, DB, Cron 등) |
| Pod 스케일링 | 특정 리소스 활용률 초과 시 확장 | 특정 이벤트 발생 시 확장 |
| Scale to Zero 지원 | ❌ 지원하지 않음 | ✅ 지원 (이벤트 없을 때 0으로 축소) |
| Metrics Server | Kubernetes 기본 Metrics Server 사용 | KEDA Metrics Server 사용 |
| 설정 방식 | kubectl autoscale 또는 HPA 설정 | ScaledObject 리소스 활용 |
KEDA를 사용하면 특정 Queue의 메시지 수, Kafka 메시지 대기열 길이, Cron 스케줄 등의 이벤트를 기준으로 Pod의 개수를 자동으로 조정할 수 있습니다.
KEDA는 Helm을 이용하여 간편하게 설치할 수 있습니다.
# 설치 전 기존 metrics-server 제공 Metris API 확인
kubectl get --raw "/apis/metrics.k8s.io" -v=6 | jq
kubectl get --raw "/apis/metrics.k8s.io" | jq
{
"kind": "APIGroup",
"apiVersion": "v1",
"name": "metrics.k8s.io",
...
# KEDA 설치 : serviceMonitor 만으로도 충분할듯
# KEDA 설정값 작성 (keda-values.yaml)
cat <<EOT > keda-values.yaml
metricsServer:
useHostNetwork: true
prometheus:
metricServer:
enabled: true
port: 9022
portName: metrics
path: /metrics
serviceMonitor:
# Enables ServiceMonitor creation for the Prometheus Operator
enabled: true
podMonitor:
# Enables PodMonitor creation for the Prometheus Operator
enabled: true
operator:
enabled: true
port: 8080
serviceMonitor:
# Enables ServiceMonitor creation for the Prometheus Operator
enabled: true
podMonitor:
# Enables PodMonitor creation for the Prometheus Operator
enabled: true
webhooks:
enabled: true
port: 8020
serviceMonitor:
# Enables ServiceMonitor creation for the Prometheus webhooks
enabled: true
EOT
# Helm 저장소 추가 및 업데이트
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
# KEDA 설치
helm install keda kedacore/keda --version 2.16.0 --namespace keda --create-namespace -f keda-values.yaml
# KEDA 설치 확인
kubectl get crd | grep keda
kubectl get all -n keda
kubectl get validatingwebhookconfigurations keda-admission -o yaml
kubectl get podmonitor,servicemonitors -n keda
kubectl get apiservice v1beta1.external.metrics.k8s.io -o yaml
# CPU/Mem은 기존 metrics-server 의존하여, KEDA metrics-server는 외부 이벤트 소스(Scaler) 메트릭을 노출
## https://keda.sh/docs/2.16/operate/metrics-server/
kubectl get pod -n keda -l app=keda-operator-metrics-apiserver
# Querying metrics exposed by KEDA Metrics Server
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "external.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "externalmetrics",
"singularName": "",
"namespaced": true,
"kind": "ExternalMetricValueList",
"verbs": [
"get"
]
}
]
}






KEDA는 Kubernetes 클러스터 내에서 아래와 같은 주요 컴포넌트로 구성됩니다.

https://keda.sh/docs/2.10/concepts/
KEDA Operator (Agent)
KEDA Metrics Server
Admission Webhooks

KEDA는 다양한 Scalers를 지원하며, 그중 하나인 Kafka 트리거를 예제로 살펴보겠습니다.
아래 YAML 파일을 사용하여 Kafka 메시지 대기열 길이를 기반으로 자동 확장할 수 있습니다.
triggers:
- type: kafka
metadata:
bootstrapServers: kafka.svc:9092
consumerGroup: my-group
topic: test-topic
lagThreshold: '5' # 스케일링을 트리거하는 평균 타겟 값(Default: 5, Optional)
activationLagThreshold: '3' # 스케일러 활성화 기준
offsetResetPolicy: latest
allowIdleConsumers: false
scaleToZeroOnInvalidOffset: false
excludePersistentLag: false
limitToPartitionsWithLag: false
version: 1.0.0
partitionLimitation: '1,2,10-20,31'
sasl: plaintext
tls: enable
unsafeSsl: 'false'
위 설정을 적용하면, Kafka 대기열 길이가 5개 이상일 경우 Pod가 자동 확장됩니다.
다음은 특정 시간대에만 Pod를 활성화하는 Cron ScaledObject 설정 예제입니다.
# keda 네임스페이스에 디플로이먼트 생성
kubectl apply -f php-apache.yaml -n keda
kubectl get pod -n keda
# Cron 기반 ScaledObject 설정
# 매 정각(00,15,30,45분)에 Pod가 활성화되며, 5분 후에는 다시 0으로 축소됨
cat <<EOT > keda-cron.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: php-apache-cron-scaled
spec:
minReplicaCount: 0
maxReplicaCount: 2 # Specifies the maximum number of replicas to scale up to (defaults to 100).
pollingInterval: 30 # Specifies how often KEDA should check for scaling events
cooldownPeriod: 300 # Specifies the cool-down period in seconds after a scaling event
scaleTargetRef: # Identifies the Kubernetes deployment or other resource that should be scaled.
apiVersion: apps/v1
kind: Deployment
name: php-apache
triggers: # Defines the specific configuration for your chosen scaler, including any required parameters or settings
- type: cron
metadata:
timezone: Asia/Seoul
start: 00,15,30,45 * * * *
end: 05,20,35,50 * * * *
desiredReplicas: "1"
EOT
# ScaledObject 배포
kubectl apply -f keda-cron.yaml -n keda
# 그라파나 대시보드 추가 : 대시보드 상단에 namespace : keda 로 변경하기!
# KEDA 대시보드 Import : https://github.com/kedacore/keda/blob/main/config/grafana/keda-dashboard.json
# 모니터링
watch -d 'kubectl get ScaledObject,hpa,pod -n keda'
kubectl get ScaledObject -w
# ScaledObject 상태 확인
kubectl get ScaledObject,hpa,pod -n keda
kubectl get hpa -o jsonpath="{.items[0].spec}" -n keda | jq
...
"metrics": [
{
"external": {
"metric": {
"name": "s0-cron-Asia-Seoul-00,15,30,45xxxx-05,20,35,50xxxx",
"selector": {
"matchLabels": {
"scaledobject.keda.sh/name": "php-apache-cron-scaled"
}
}
},
"target": {
"averageValue": "1",
"type": "AverageValue"
}
},
"type": "External"
}
정각 전



정각(Pod 활성화)



5분 후(다시 0으로 축소)


# KEDA 및 deployment 등 삭제
kubectl delete ScaledObject -n keda php-apache-cron-scaled && kubectl delete deploy php-apache -n keda && helm uninstall keda -n keda
kubectl delete namespace keda