포스팅은 CloudNet@팀 서종호(Gasida)님이 진행하시는 AWS EKS Workshop Study 내용을 참고하여 작성합니다.
안녕하세요!
이번 포스팅은 파드 오토스케일링 기술인
HPA, VPA에 대해서 알아보도록 하겠습니다.
01. HPA (Horizontal Pod Autoscaling)
HPA는 언제, 어떻게 스케일 판단을 내리나? 가 핵심입니다.
단순히 "CPU가 높으면 늘린다"가 아닙니다.
메트릭 수집 → 목표값과 비교 → 수식으로 replica 수 계산 → 실제 반영 (4단계로 나뉘며, 반복합니다)
📌 메트릭은 어디서 가져올까요?
HPA Controller
│
├─ metrics.k8s.io ← CPU/Memory (metrics-server)
├─ custom.metrics.k8s.io ← Prometheus Adapter 등
└─ external.metrics.k8s.io ← 외부 시스템 (SQS 큐 길이 등)
오늘 실습 내용은 metrics.k8s.io 경로 즉, metrics-server가 수집한 CPU 사용률을 씁니다.
부하 발생 → 파드 CPU 250% (request 200m의 250% = 500m, limit 찍음)
→ HPA: 목표 50% 초과 감지
→ replica 1 → 4 → (곧 5) 스케일 아웃
부하를 발생 시켜볼까요? (위 내용 중 반복 호출 실행)
목표 50%를 초과하여 파드가 10개까지 올라간 상태입니다.
파드 10개가 2개 노드에 분산됐는데 노드 2가 좀 더 부하를 받고 있네요. (CPU 확인)
sleep 0.01 (100 RPS) → 파드 10개로도 CPU 69% → 목표 50% 초과 유지 중
→ max 10개라서 더 이상 못 늘림
이제 반복 호출을 취소하면 어떻게 scaleDown 될까요?
호출이 없으니 CPU가 점차 낮아지고, HPA가 파드를 스케일 다운하는 것을 확인 가능합니다.
02. VPA (Vertical Pod Autoscaler)
파드를 배포할 때 resources.requests를 개발자가 설정할거에요.
resources:
requests:
cpu: 200m
memory: 256Mi
근데 이 값을 처음부터 정확하게 잡기가 어렵습니다.
너무 크게 잡으면 → 노드 자원 낭비, 스케줄링 안됨. 너무 작게 잡으면 → OOMKill, CPU 스로틀링 발생함.
📌 VPA가 하는 일은?
실제 사용량을 장기간 관찰해서 "이 파드한테 이 정도 request가 적당해" 를 자동으로 계산하고 적용해줍니다.
최적값 계산 방식은 아래와 같습니다.
Recommender가 metrics-server로 파드 사용량 수집 (히스토리 누적)
↓
백분위수 기반으로 기준값 결정
ex) CPU 사용량 상위 90% 값 → 기준값
↓
안전 마진 추가 (버퍼)
기준값 × 1.15 (15% 여유)
↓
이 값을 request로 추천/적용
그래서 실제 적용 흐름도는 아래와 같습니다.
파드 running
↓ (수분~수시간 관찰)
VPA Recommender → recommendation 계산
↓
updateMode에 따라:
Off → kubectl describe vpa 로 추천값만 확인
Recreate → 기존 파드 삭제 → 새 파드를 추천 request로 생성
📌VPA 3가지 컴포넌트
Recommender → 메트릭 수집, 최적값 계산 및 추천
Updater → 추천값과 현재값 비교, 재시작 필요 파드 판단
Admission Controller → 새 파드 생성 시 추천값으로 request 자동 주입
📌 VPA 4가지 모드 (updateMode)
모드
동작
Off
추천값만 계산, 적용 안함 (추천값 확인용)
Initial
파드 최초 생성 시에만 적용
Recreate
추천값 벗어나면 파드 재시작해서 적용
Auto
현재는 Recreate와 동일
VPA의 가장 큰 특징은 HPA와 같이 사용을 하지 못합니다. Why?
HPA: CPU 사용률 기준으로 replica 수 조정
VPA: CPU request 값 자체를 변경
→ request가 바뀌면 HPA 스케일 기준이 흔들림
→ 서로 충돌
원래 설정 값은 cpu request: 100m 입니다. 하지만 VPA 추천 값은 아래와 같습니다.
Lower Bound: 268m ← 최소한 이 정도는 있어야 함 Target: 587m ← 이걸로 설정해라 (실제 적용값) Upper Bound: 1000m ← 이 이상은 필요 없음
그래서 실제 동작 (Event)을 보면,
vpa-updater가 파드 3번 evict함
→ 재시작하면서 request를 100m → 587m 으로 적용
kube-ops-view에서 본 동작:
파드가 삭제되네요. VPA가 request 값을 바꾸려면 실행 중인 파드를 수정할 수 없습니다.
Kubernetes에서 실행 중인 파드의 resources.requests는 변경 불가입니다. 그래서 아래와 같이 동작합니다.
기존 파드 (cpu request: 100m) 실행 중
↓
VPA Updater: "587m으로 바꿔야 해, 근데 수정 불가"
↓
기존 파드 강제 evict (삭제)
↓
Deployment가 새 파드 생성 시도
↓
VPA Admission Controller가 가로채서
새 파드 spec에 cpu request: 587m 주입
↓
새 파드가 587m으로 뜸
실제로 아래와 같이 VPA에 의해 기존 파드 삭제되고 신규 파드가 생성되는 것도 확인이 가능합니다.
In-Place Pod Resource Resize (CPU) 적용
간단하게 말씀드리자면, 기존 VPA 방식과 In-Place의 다른 점은 아래와 같습니다.
기존: request 변경 → 파드 삭제 → 재시작
In-Place: request 변경 → 파드 살아있는 채로 즉시 적용
즉, 서비스 중단 없이 리소스 조정이 가능하단 얘기네요.
여기서 주의할 점은 In-Place Resize는 K8s 1.27 + alpha, 1.33 stable 이상에 지원합니다.