파드와 클러스터 노드의 오토스케일링
- 15.1 Horizontal Pod Autoscaler — 파드 수 자동 조절
- 15.2 Vertical Pod Autoscaling — 파드 자체 키우기
- 15.3 Cluster Autoscaler — 노드 자체를 늘리기
- 15.4 PodDisruptionBudget — 스케일다운 안전망
14장에서 requests/limits를 잡는 법을 배웠다면, 15장은 그 위에서 자동으로 파드와 노드를 늘리고 줄이는 이야기야. 트래픽 패턴이 예측 불가한 서비스, 야간 배치, 학습·추론 워크로드 모두에 필수야.
먼저 HPA(Horizontal Pod Autoscaler). HPA는 Deployment/ReplicaSet/StatefulSet의 replicas 필드를 메트릭에 따라 자동 조정해. 동작은 3단계야 — 대상 리소스에 속한 파드들의 메트릭 수집, 목표 값에 맞추기 위한 필요 replica 수 계산, Scale 서브리소스를 통해 replicas 업데이트. 메트릭 수집 경로는 Pod → cAdvisor(Kubelet 내장) → Heapster → HPA controller야. 책 시점은 Heapster 기반인데, 현재는 metrics-server(CPU/메모리)와 custom.metrics.k8s.io API(커스텀 메트릭, Prometheus Adapter 등)가 표준이야. 흐름은 같아 — Aggregated API Server를 거쳐 HPA가 메트릭을 가져와.
계산 공식의 핵심은 단순해 — desiredReplicas = ceil(currentReplicas × (currentMetric / targetMetric)). 예를 들어 현재 replica 1개, CPU 사용률 108%, 목표 30%면 1 × (108/30) = 3.6 → 올림 4가 돼. 실제로 4개로 늘리면 평균이 약 27%로 떨어져서 목표 근처가 돼. 여러 메트릭이 있으면 각각 계산해서 가장 큰 값을 채택해. CPU 기준 4개, QPS 기준 3개 필요면 4개로 가는 거야. HPA 만들기는 kubectl autoscale deployment kubia --cpu-percent=30 --min=1 --max=5 같은 한 줄 명령으로 가능하고, YAML로도 metrics에 type: Resource와 targetAverageUtilization을 적어서 만들 수 있어.
CPU 사용률의 기준이 헷갈리지 말아야 할 게, HPA의 CPU%는 실제 사용량 ÷ requests야. limits가 아니야. 그래서 requests가 없는 파드는 HPA가 작동하지 않아. 14장에서 배운 그 requests 말이야. 운영 팁으로 목표 사용률은 절대 90% 넘기지 마. 80% 이하 권장. 트래픽 급증을 흡수할 여유가 필요해. 그리고 항상 Deployment 레벨에 HPA를 걸어. ReplicaSet에 걸면 Deployment가 새 버전 배포할 때마다 새 ReplicaSet을 만드니까 갱신될 때 사라져. 수동 스케일도 마찬가지야.
스케일링 속도엔 제한이 있어. scale-up은 한 번에 최대 2배(단 1~2 replica일 땐 4까지), 직전 스케일 후 3분 이내엔 안 해. scale-down은 5분 이내엔 안 해. 급격한 출렁임(thrashing)을 방지하기 위한 거야. 모니터링 보면서 "왜 안 늘어나지?" 싶을 때 이 cooldown을 의심해. 현재 버전에선 HPA behavior 필드로 scale-up/down 정책(stabilizationWindowSeconds, policies)을 세밀히 조정할 수 있어.
메모리 기반 HPA는 위험해. CPU와 달리 메모리는 압축 불가능하거든. 스케일 아웃해도 기존 파드가 메모리를 안 놔. 시스템이 강제로 release할 방법이 없어. 결국 무한히 max까지 늘어나기만 해. 메모리는 HPA 대상으로 잘 안 쓰는 게 좋아. 메트릭 타입은 세 종류야 — Resource(CPU/메모리 같은 컨테이너 리소스), Pods(파드 자체에 대한 커스텀 메트릭, 예를 들면 pod당 QPS나 큐 깊이, 파드들의 평균을 본다), Object(다른 리소스의 메트릭, 예를 들면 Ingress의 latency, 파드 평균이 아니라 그 객체의 단일 값). 메트릭이 자동스케일링에 적합한지 판단할 때 핵심은 replica를 늘렸을 때 메트릭 값이 비례해서 떨어져야 한다는 거야. QPS는 OK — 파드 2배면 파드당 QPS 절반이거든. 메모리는 NO. 내가 만든 메트릭으로 스케일링 전에 이 선형성부터 확인해. 그리고 현재 minReplicas=0은 불가능해. idle/un-idle(트래픽 오면 파드 깨우기)은 K8s 자체 기능엔 없고 Knative 같은 서버리스 레이어가 해결해.
Vertical Pod Autoscaling은 수평이 아니라 파드 한 개의 requests/limits를 늘리는 거야. 책 시점엔 미완성이고 InitialResources admission plugin이 새 파드의 requests를 과거 사용 데이터 기반으로 자동 설정하는 정도야. 현재는 VPA(Vertical Pod Autoscaler) 컴포넌트가 별도로 존재하고 recommendation/auto/initial 모드가 있어. 중요한 한계 — VPA가 requests를 바꾸려면 파드를 재생성해야 해 (in-place 업데이트는 1.27+에서 alpha). 그래서 HPA + VPA를 같은 메트릭으로 동시에 거는 건 금지야. 서로 충돌하거든. CPU는 HPA, 메모리는 VPA로 나눠 쓰는 패턴이 흔해.
**Cluster Autoscaler(CA)**는 HPA가 아무리 늘려달라 해도 노드에 자리가 없으면 파드는 Pending이니까, 클라우드 API를 호출해서 노드 자체를 추가·제거하는 거야. 스케일 업은 Pending 파드 발견(스케줄 불가 사유: insufficient resources) → 노드 그룹들 중 어느 타입이 이 파드를 수용할 수 있는지 시뮬레이션 → 수용 가능한 그룹이 있으면 그 그룹 크기 증가 → 클라우드가 새 노드 프로비저닝 → Kubelet이 새 노드에서 API 서버에 등록 → 스케줄 가능, 이런 흐름이야. 스케일 다운은 노드의 모든 파드 requests 합이 50% 미만이면 후보가 돼. 단 시스템 파드(DaemonSet 외)가 그 노드에서만 돌고 있거나, 관리되지 않는(unmanaged) 파드가 있거나, 로컬 스토리지를 쓰는 파드가 있으면(옮기면 데이터 손실) 안 내려. 내릴 때는 cordon → drain → 클라우드에서 노드 제거 순서야. CA가 보는 건 requests 기준이지 실제 사용량이 아니야. 그래서 14장의 requests 설정이 비용에 직결돼 — 과대 잡으면 노드가 안 줄어드니까. 수동 cordon/drain은 kubectl cordon <node>(새 파드 안 받게만), kubectl drain <node>(cordon + 기존 파드 evict), kubectl uncordon <node>로 해. 노드 점검 시 표준 절차고 CA의 자동 동작과 동일한 로직이야.
마지막으로 PodDisruptionBudget(PDB). CA의 drain이나 사람의 drain 때 "동시에 너무 많이 죽으면 서비스 멈춤"을 방지하는 거야. PDB는 항상 살아있어야 할 최소 파드 수(또는 죽어도 되는 최대 수)를 정의해. kubectl create pdb kubia-pdb --selector=app=kubia --min-available=3 한 줄로 만들 수 있고, YAML로는 minAvailable: 3(또는 60% 같은 비율)과 selector를 적으면 돼. maxUnavailable로도 표현 가능해. PDB가 있으면 drain은 한 번에 하나씩 evict하면서 ReplicaSet이 새 파드를 띄울 때까지 기다려. 한 가지 — PDB는 자발적 disruption(drain, CA 스케일 다운, 노드 업그레이드)에만 적용돼. 노드 장애 같은 비자발적 disruption은 못 막아. quorum 기반 시스템(etcd, Kafka 같은 거)을 운영할 때 필수야.
정리
15장 읽고 기억할 거 세 가지:
- HPA는 requests 대비 사용률로 동작한다. requests가 없으면 HPA가 안 돈다. 14장과 한 묶음. 메트릭은 Resource/Pods/Object 세 종류이고, 커스텀 메트릭으로 스케일링하려면 replica 증가 시 메트릭이 선형으로 감소하는지 먼저 확인. 메모리 기반 HPA는 거의 항상 잘못된 선택.
- HPA + Cluster Autoscaler는 한 세트. HPA가 파드를 늘려도 노드에 자리가 없으면 Pending. CA가 노드를 추가하는 건 클라우드 API를 통해서고, 노드 그룹 단위라 미리 적절한 그룹을 잘 정의해둬야 한다. 스케일 다운은 requests 기준 50% 미만 + 옮길 수 있는 파드들로만. 비싸게 굴면 14장의 requests를 다시 봐라.
- drain 전에 PDB부터 깔아라. CA의 자동 스케일 다운, 노드 업그레이드, 수동 drain — 모두 자발적 disruption이고 PDB가 막을 수 있다. 비자발적 장애는 못 막는다는 점도 명심. quorum 시스템이라면 PDB 없이 운영하면 안 된다. VPA는 HPA와 같은 메트릭에 동시에 쓰지 마라(충돌).