이벤트 기반 워크로드에서 CPU 메트릭의 한계
Kubernetes에서 오토스케일링을 구성할 때 가장 먼저 떠올리는 지표는 CPU와 메모리다. 하지만 SQS 같은 메시지 큐를 기반으로 동작하는 이벤트 드리븐 워크로드에서는 이 전통적인 메트릭이 실제 시스템 부하를 제대로 반영하지 못하는 경우가 많다.
워커 Pod가 메시지를 기다리는 동안 CPU 사용률은 거의 0에 가깝다. 그러나 그 순간에도 SQS 큐에는 수천 건의 메시지가 쌓여 있을 수 있다. 반대로 트래픽 스파이크가 이미 지나갔음에도 Pod는 계속 살아있어 불필요한 비용을 발생시킨다. 비동기 큐 기반 시스템에서의 진짜 스케일링 신호는 인프라 사용률이 아니라 처리 대기 중인 백로그다.
KEDA와 SQS 연동 아키텍처
KEDA(Kubernetes Event-Driven Autoscaler)는 이 문제를 해결하기 위해 설계된 CNCF 프로젝트다. KEDA는 외부 이벤트 소스(여기서는 Amazon SQS)를 폴링해 메트릭을 수집하고, Kubernetes HPA(Horizontal Pod Autoscaler)의 타겟 메트릭을 동적으로 업데이트함으로써 Pod 수를 조절한다.
전체 흐름은 다음과 같다:
- 프로듀서가 SQS 큐에 메시지를 전송
- KEDA가 큐 속성을 폴링해 현재 대기 메시지 수(큐 깊이) 파악
- KEDA가 HPA의 타겟 메트릭을 업데이트
- HPA가 워커 Deployment의 레플리카 수 조정
- Kubernetes가 추가 Pod를 스케줄링해 메시지 처리
- 큐가 비워지면 레플리카 수 다시 축소
AWS 인증은 IRSA 또는 EKS Pod Identity 방식을 사용하며, KEDA가 SQS 큐 속성을 읽을 수 있는 IAM 권한이 필요하다. ScaledObject 리소스를 통해 스케일링 동작을 선언적으로 정의한다.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: sqs-worker-scaledobject
spec:
scaleTargetRef:
name: sqs-worker
minReplicaCount: 0
maxReplicaCount: 20
triggers:
- type: aws-sqs-queue
metadata:
queueURL: https://sqs.ap-northeast-2.amazonaws.com/123456789/my-queue
queueLength: "10" # Pod 1개당 처리 목표 메시지 수
activationQueueLength: "1"
awsRegion: ap-northeast-2
핵심 파라미터 튜닝 포인트
KEDA의 SQS 스케일러에서 실무적으로 중요한 파라미터는 다음과 같다:
queueLength: Pod 1개가 처리할 목표 메시지 수. 예를 들어 큐에 100개의 메시지가 있고 이 값이 10이면, 10개의 Pod가 목표 레플리카로 산정된다.activationQueueLength: 이 임계값 이하에서는 스케일링이 시작되지 않는다. 0으로 설정하면 메시지가 1개라도 있으면 즉시 반응한다.- Cooldown 설정:
scaleDown.stabilizationWindowSeconds를 통해 급격한 스케일 인/아웃 반복(플래핑)을 방지할 수 있다. minReplicaCount: 0: 큐가 완전히 비었을 때 Pod를 0으로 줄여 유휴 비용을 제거할 수 있다. 단, 첫 메시지 처리까지 콜드 스타트 지연이 발생할 수 있으므로 SLA에 따라 최솟값을 조정해야 한다.
# 스케일링 동작 확인
kubectl get scaledobject sqs-worker-scaledobject
kubectl describe hpa keda-hpa-sqs-worker-scaledobject
트러블슈팅 시에는 KEDA 오퍼레이터 로그와 HPA 이벤트를 함께 확인하는 것이 효율적이다. IAM 권한 부족이나 큐 URL 오타가 가장 흔한 원인이다.
정리
- CPU/메모리 기반 HPA는 이벤트 드리븐 워크로드의 실제 부하를 반영하지 못하며, SQS 큐 깊이가 더 정확한 스케일링 신호다.
- KEDA의
ScaledObject와queueLength파라미터를 활용하면 백로그에 비례한 정밀한 Pod 확장/축소가 가능하다. minReplicaCount: 0설정으로 유휴 비용을 제거할 수 있으나, 콜드 스타트 지연과 SLA를 고려해 값을 결정해야 한다.