도입배경
최근 구축중인 시스템에서 파드 오토스케일링 기능(Autoscaling)이 필수적인 상황이 되었습니다.
시스템은 Valkey(Redis) 큐를 사용해서 비동기로 뒷단의 파드에 작업을 할당하는 구조인데,
기존 쿠버네티스의 기본 HPA(Horizontal Pod Autoscaler) 동작 방식만으로는 해결하기 어려운 문제들이 있었습니다.
문제해결을 위해 최종적으로 KEDA를 도입했는데
이번 글에서 해당 기능에 대한 소개와 작업시 고민했던 부분들을 정리해볼까 합니다.
HPA란
https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/
Horizontal Pod Autoscaling
쿠버네티스에서, HorizontalPodAutoscaler 는 워크로드 리소스(예: 디플로이먼트 또는 스테이트풀셋)를 자동으로 업데이트하며, 워크로드의 크기를 수요에 맞게 자동으로 스케일링하는 것을 목표로 한
kubernetes.io
Horizontal Pod Autoscaling (HPA)는
쿠버네티스에서 워크로드 리소스(Deployment, StatefulSet 등)의 크기를 수요에 맞게 자동으로 조정하는 기능입니다.
부하가 증가하면 더 많은 자원을 할당하는 수직 스케일링(Vertical)과 달리, 파드의 개수 자체를 늘리는 수평 스케일링 방식을 취합니다.
HPA 수집방법
HPA가 파드를 스케일링하려면 현재 파드들이 자원을 얼마나 쓰고 있는지 알아야 합니다.
이 데이터는 다음과 같은 파이프라인을 거쳐 수집됩니다
kubelet과 cAdvisor
쿠버네티스의 각 워커 노드에는 API 서버와 통신하며 노드를 제어하는 kubelet 에이전트가 실행됩니다.
이 kubelet 내부에는 cAdvisor(Container Advisor)라는 리소스 모니터링 도구가 내장되어 있습니다.
cAdvisor는 컨테이너 런타임(containerd, Docker 등)을 통해
각 파드 컨테이너의 리소스(CPU, 메모리 등) 사용량을 실시간으로 수집합니다.
Metrics Server
cAdvisor가 수집한 각 노드의 파드 리소스 정보들을 중앙에서 취합하고,
이를 쿠버네티스 Metrics API 형태로 제공해 주는 서버가 바로 metrics-server입니다.
metrics-server는 쿠버네티스의 기본 컴포넌트가 아닌 애드온(AddOn)입니다.
따라서 별도로 설치해 주어야 하며 직접 배포하지 않으면 HPA가 동작하지 않습니다.

이렇게 수집된 데이터를 바탕으로,
기본 15초 주기(--horizontal-pod-autoscaler-sync-period)로 컨트롤러 매니저가 리소스 사용률을 질의합니다.

수집 메트릭 종류
- 파드 단위 리소스 (ex. CPU, 메모리)
- 사용자 정의 메트릭 (Custom)
- 오브젝트 및 외부 메트릭
HPA의 기본 동작 원리
HPA의 기본 동작은 현재 메트릭과 목표 메트릭 값의 비율을 계산합니다

- 예시: 현재 CPU가 200m이고 목표가 100m라면, 비율은 2.0이 되어 파드 수가 2배로 증가합니다
- 허용 오차(Tolerance): 계산된 비율이 1.0에 충분히 가깝다면(기본 허용 오차 10%), 불필요한 스케일링을 방지하기 위해 작업을 건너뜁니다

세밀한 제어 : behavior
파드가 급격히 늘어나거나 줄어드는 플래핑(Flapping) 현상을 막기 위해 behavior 필드를 활용할 수 있습니다.
autoscaling/v2 API부터는 behavior 필드를 통해 스케일업/다운 동작을 세밀하게 제어할 수 있습니다.
안정화 윈도우 (Stabilization Window)
과거 특정 시간 동안 계산된 목표 상태 중 가장 높은 값을 사용하여 파드 수가 급격히 줄어드는 것을 방지합니다.
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 5분 동안 관찰 후 스케일 다운
스케일링 정책 (Scaling Policies)
파드가 늘어나거나 줄어드는 속도를 제어합니다. 개수(Pods)나 비율(Percent) 단위로 설정이 가능합니다.
behavior:
scaleDown:
policies:
- type: Percent
value: 10
periodSeconds: 60 # 1분 동안 최대 10%만 스케일 다운 허용
- type: Pods
value: 5
periodSeconds: 60 # 1분 동안 최대 5개 스케일 다운 허용
selectPolicy: Min # 두 정책 중 '더 적은 파드'에 영향을 주는 정책 선택
AI 에이전트 워크로드에서 HPA의 명확한 한계
일반적인 웹서버는 트래픽이 몰리면 CPU나 메모리 사용량이 비례해서 상승합니다.
하지만 AI 에이전트 워크로드인 기존 프로젝트 파이프라인은 다른 기준이 필요했습니다.
1. I/O 대기 : 에이전트가 LLM API를 호출하는 동안 실제 동작하는 파드의 CPU 사용량은 낮아질 수 있습니다.
2. 메모리 착시 : 여러 AI 모델을 로드하고 처리하는 과정에서 실제 유효한 트래픽이 없어도 메모리 사용률이 높게 유지되어 불필요한 스케일 아웃이 발생할 수 있습니다.
결국 CPU/메모리 지표만 바라보는 HPA 특성상
파드가 정말 바빠서 부하가 걸린 상태인지 API 응답을 대기하며 노는 상태인지 정확히 판별할 수가 없었습니다.
해결책 : KEDA 도입

KEDA
Application autoscaling made simple
keda.sh
KEDA(Kubernetes Event-Driven Autoscaling)는 HPA의 확장판입니다.
Redis 큐, Kafka, AWS SQS 등 100가지 이상의 외부 이벤트 소스를 기준으로 Pod를 스케일할 수 있습니다.
KEDA는 CNCF Graduated 프로젝트로, 이미 프로덕션 레벨에서 안정성이 검증된 도구입니다.
Graduated and Incubating Projects
Graduated and incubating projects are considered stable and are used successfully in production environments. View metrics of CNCF projects moving through the project maturity levels.
www.cncf.io
중요한 점은 KEDA가 기존 HPA를 직접 없애고 대체하는 방식이 아니라는 것입니다.
KEDA는 외부 이벤트 메트릭을 쿠버네티스가 이해할 수 있도록 번역하고
스케일 제로(Scale-to-Zero)를 관리할 뿐,
파드의 숫자를 늘리고 줄이는 실제 작업은 내부적으로 자동 생성한 HPA에게 일임합니다.
KEDA ScaledObject 배포
│
▼ (자동 생성)
HPA (keda-hpa-vega-worker-scaledobject)
│
▼
Deployment 스케일

ScaledObject를 배포해 HPA가 자동 생성되면, KEDA는 구간별로 역할을 분담합니다
HPA가 지원하지 않는 0 ↔ 1 (Scale-to-Zero) 전환은 KEDA Operator가 직접 처리하고
파드가 1개 이상일 때의 1 ↔ N 동적 스케일링은 자동 생성된 HPA가 전담합니다.
KEDA 구성요소
| 구성 요소 | 핵심 역할 |
| keda-operator | ScaledObject를 지속적으로 감시하며, 그에 맞는 HPA를 자동 생성하고 관리합니다. (파드를 0에서 1로, 1에서 0으로 스케일하는 주체) |
| keda-operator-metrics-apiserver | 외부 메트릭(예: Redis 큐 길이)을 가져와 쿠버네티스 Metrics API가 읽을 수 있는 형태로 노출해 줍니다. |
| keda-admission-webhooks | 사용자가 작성한 ScaledObject 등 KEDA 관련 YAML 매니페스트의 문법과 유효성을 검사합니다. |
| ScaledObject (CRD) | "어떤 Deployment를, 어떤 기준(트리거)으로, 몇 개까지 스케일할 것인지" 규칙을 정의하는 명세서입니다. |
| TriggerAuthentication (CRD) | Redis 비밀번호, AWS 인증 키 등 메트릭 소스에 접근하기 위한 민감한 인증 정보를 워크로드와 분리하여 안전하게 관리합니다. |
프로젝트 적용 아키텍처: Redis Queue + KEDA
만들고 있는 시스템은 클라이언트의 동시 다발적인 요청을 FastAPI가 받아
Redis(Valkey) 큐에 비동기 작업(apply_async)으로 밀어 넣는 구조입니다.
사용자 요청 (N개 동시)
│
▼
FastAPI (Backend)
│ apply_async()
▼
Valkey (Redis)
celery LIST
┌─────────────────────┐
│ task1 │ ◄──── [1] KEDA가 주기적으로 LLEN (큐 길이) 체크
│ task2 │
│ task3 │
│ task4 │
└─────────────────────┘
│
▼
KEDA Operator
(ScaledObject: worker-scaledobject)
│ [2] 큐 길이에 맞춰 목표 Replica 수 계산
▼
HPA (자동생성 됨)
(keda-hpa-worker-scaledobject)
│ [3] Deployment 레플리카 조정
▼
Worker Deployment (Celery)
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Pod-1 │ │ Pod-2 │ │ Pod-3 │
│ [t1][t2] │ │ [t3][t4] │ │ [t5] │
└──────────┘ └──────────┘ └──────────┘
이 구조를 통해 Redis 큐에 미처리된 작업 개수를 모니터링하여,
적체된 작업량에 비례해 워커 파드를 정확하게 늘릴 수 있게 되었습니다.
더불어, 별도의 어댑터 설치 없이 KEDA만으로 Prometheus 메트릭을 통한 스케일링까지 통합가능했습니다.
코드 예시
TriggerAuthentication (인증 정보 매핑)
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: redis-auth-trigger
namespace: default
spec:
secretTargetRef:
- parameter: password # KEDA Redis 스케일러가 참조할 파라미터명
name: redis-secret # 실제 자격 증명이 있는 K8s Secret 이름
key: redis-password # Secret 데이터 안의 Key
ScaledObject (스케일링 룰 정의)
대기열(List)에 작업이 5개 쌓일 때마다 워커 파드를 스케일 아웃하며, 작업이 없으면 0개로 스케일 다운(Scale-to-Zero) 하도록 설정한 명세서입니다.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: worker-scaler
namespace: default
spec:
scaleTargetRef:
name: worker # 스케일링할 타겟 Deployment 이름
minReplicaCount: 0 # 큐가 비면 워커를 0개로 축소 (비용 최적화)
maxReplicaCount: 8 # 큐가 폭증할 때 늘어날 최대 파드 수
triggers:
- type: valkey # 또는 redis
metadata:
address: valkey-master.default.svc.cluster.local:6379 # Valkey(Redis) 주소
listName: celery # 모니터링할 큐(List) 이름
listLength: "5" # 작업이 5개 쌓일 때마다 워커 1개씩 추가
authenticationRef:
name: redis-auth-trigger # 위에서 만든 TriggerAuthentication 연결
마치며
KEDA를 통해 애플리케이션의 실제 워크로드(이벤트)를 기반으로 유연한 스케일링 환경을 구축할 수 있었습니다.
다만 KEDA 역시 HPA를 통한 제어이므로 HPA에 대한 작동원리가 정확하게 필요합니다.
또한, 파드가 무분별하게 확장될 때 노드 리소스가 고갈되지 않도록
각 파드의 request, limit 설정을 꼼꼼히 하여 일관된 QoS(Quality of Service)를 보장하는 작업도 필요합니다.
참고자료
https://techblog.gccompany.co.kr/keda-16204b60a388
KEDA
안녕하세요. 여기어때컴퍼니 인프라개발팀에서 EKS(Elastic Kubernetes Service, AWS의 관리형 Kubernetes 서비스)를 담당하고 있는 젠슨입니다.
techblog.gccompany.co.kr
https://velog.io/@jihwankim94/Kubernetes-Keda-%EB%9E%80
[Kubernetes] Keda 란?
TL:DR; redis queue 길이에 따른 autoscaling이 필요했는데 keda를 사용 ScaledObjects represent the desired mapping between an event source (e.g. Rabbit MQ) and the K
velog.io
5W - HPA, KEDA를 활용한 파드 오토스케일링
5W - HPA, KEDA를 활용한 파드 오토스케일링 개요 이번 주차에서는 운영의 탄력성을 부여하는 오토스케일링에 대해 알아본다. 이 문서는 그 중 워크로드 자체에 대한 스케일링 툴들을 중점적으로
zerotay-blog.vercel.app
'devops > k8s' 카테고리의 다른 글
| 쿠버네티스 인증서 (0) | 2026.02.22 |
|---|---|
| [k8s deploy] Bootstrap Kubernetes the hard way #1 (0) | 2026.01.11 |
| [쿠버네티스 어나더 클래스] 쿠버네티스 패턴 (0) | 2025.12.31 |
| cgroup v1/v2, request/limit (1) | 2025.12.27 |
| [쿠버네티스 인 액션] 쿠버네티스 API 서버 보안 (2) | 2025.07.26 |