쿠버네티스 오토스케일링 계층 — HPA · KEDA · Karpenter
트래픽이 몰릴 때마다 사람이 kubectl scale 을 치고 있을 수는 없으니 부하에 맞춰 알아서 늘고
한가해지면 줄어야 합니다. 그런데 쿠버네티스에서 이걸 붙이려고 찾아보면 HPA 와 KEDA, Karpenter 가
같이 나옵니다.
셋 다 뭔가를 자동으로 늘려 준다고 소개돼 있어서 문서만 봐서는 HPA 를 쓸지 KEDA 를 쓸지 안 갈립니다. Karpenter 는 그 둘의 대안인지 같이 쓰는 건지도 모르겠고, 셋을 한꺼번에 켜 두면 서로 반대로 움직여서 파드가 늘었다 줄었다 하지 않을지도 걸렸습니다.
셋은 경쟁 관계가 아니라 층이 다릅니다. HPA 와 KEDA 가 파드 개수를 조절하고 Karpenter 는 그 파드가 올라갈 노드를 늘리니, 하나가 파드를 늘리면 다음이 노드를 띄우는 식으로 이어집니다.
Pod를 늘리는 층 — HPA와 KEDA
HPA 는 CPU 나 메모리 사용률을 보고 Pod replicas 를 조절합니다. 그 사용률을 읽어 오려면 metrics-server 가 클러스터에 깔려 있어야 합니다. KEDA 도 같은 일을 하지만 볼 수 있는 대상이 훨씬 넓습니다. SQS 큐 깊이, Kafka lag, Prometheus 쿼리 결과처럼 CPU·메모리가 아닌 값을 기준으로 Pod 를 늘립니다.
설정을 나란히 놓으면 차이가 한눈에 들어옵니다.
# HPA — CPU 사용률을 보고 늘린다
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
scaleTargetRef: { kind: Deployment, name: <앱> }
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target: { type: Utilization, averageUtilization: 70 }
# KEDA — 큐에 쌓인 개수를 보고 늘린다
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
spec:
scaleTargetRef: { name: <앱> }
minReplicaCount: 0 # 큐가 비면 0 까지 내린다
maxReplicaCount: 10
triggers:
- type: aws-sqs-queue
metadata:
queueURL: <큐 URL>
queueLength: "5" # 메시지 5개당 파드 1개
갈리는 지점은 metrics 와 triggers, 무엇을 보고 늘리느냐 하나입니다. 큐가 쌓이면 워커를
늘리고 다 처리하면 0 으로 줄이는 배치성 워크로드라면 CPU 사용률로는 큐가 쌓였다는 걸 표현할
방법이 없으니, 이런 자리에 KEDA 와 큐 조합이 맞습니다. HPA 는 기본 설정으로는 minReplicas 를 0
으로 못 내리는 것도 차이입니다.
노드를 늘리는 층 — Karpenter
Pod 를 늘려 봐야 노드에 자리가 없으면 그대로 Pending 이고, 자리를 만드는 건 Karpenter 의 몫입니다.
KEDA 가 하는 건 “Pod 를 더 만들어라” 까지고 그 Pod 가 뜰 자리(노드)는 Karpenter 가 만드는 것이라, Pod 층과 노드 층 사이에서는 둘이 부딪힐 일이 없습니다.
부딪히는 건 같은 Pod 층에 둘을 같이 올렸을 때고, KEDA 는 ScaledObject 마다 HPA 를 자기가 만들어
관리하기 때문에 이미 HPA 가 붙은 Deployment 에 ScaledObject 를 만들면 already managed by the hpa 로 거부합니다. 그래도 넘기려면 소유권을 넘기는 어노테이션을 따로 붙여야 하니, 같은 층에서는
둘 중 하나만 쓰는 게 맞습니다.
Pod 층에서는 KEDA 나 HPA 중 하나만 쓰고, 노드 층은 Karpenter 가 받습니다.
scale-to-zero의 cold start
KEDA 는 Pod 를 0 까지 줄일 수 있습니다(scale-to-zero). 비용은 좋지만 큐가 비었다가 첫 요청이 올 때 Pod 가 없어서 지연(cold start)이 생깁니다.
완화하는 방법은 몇 가지고, minReplicaCount: 1 로 최소 하나는 항상 띄워 두거나 cooldownPeriod
를 조정해 너무 빨리 0 으로 안 내려가게 하거나, ScaledJob 으로 요청이 있을 때만 Pod 를 Job 형태로
만들게 할 수 있습니다.
0 까지 줄여 비용을 아끼는 것과 첫 요청 지연은 맞바꾸는 관계라 요청이 얼마나 자주 오는지와 그 지연을 얼마나 견딜 수 있는지를 보고 값을 정합니다.
층이 나뉘어 있으면 볼 곳도 나뉨
스케일이 안 되는 것 같을 때는 파드가 안 늘어나는 건지 노드가 안 늘어나는 건지부터 가릅니다. replicas 가 그대로면 HPA 나 KEDA 쪽이고 replicas 는 늘었는데 새 파드가 Pending 에 쌓여 있으면 노드 층이라 Karpenter 를 봅니다. 셋이 이름만 보면 다 스케일링 같아서 어디를 손댈지 헷갈리지만 이 한 줄로 갈립니다.
댓글 0