비용 최적화 — 쿠버네티스 자원 낭비 줄이기

쿠버네티스 비용 낭비가 요청(requests)·실제 사용·노드 청구 사이의 간극에서 발생하는 구조를 이해하고, 가시성 확보부터 라이트사이징(VPA)·오토스케일링(HPA·Cluster Autoscaler·Karpenter)·스팟 인스턴스·빈 패킹까지 워크로드와 인프라 양쪽에서 비용을 조이는 실전 전략을 정리합니다.

· 9 min read · PALDYN Team

지난 글에서 ResourceQuota로 한 테넌트가 자원을 독식하지 못하게 막는 이야기를 했다. 그런데 자원을 “나눠 막는 것”과 “낭비 없이 쓰는 것”은 다른 문제다. 쿠버네티스 클러스터의 청구서는 종종 실제로 일한 양보다 훨씬 크게 나온다. 그 차이가 곧 낭비다. 비용 최적화는 이 낭비가 어디서 생기는지 정확히 짚고, 워크로드와 인프라 양쪽에서 체계적으로 줄여가는 작업이다.

낭비의 정체 — 세 막대의 간극

비용 최적화를 이해하려면 서로 다른 세 가지 “양”을 구분해야 한다. 청구되는 양, 예약된 양, 실제 사용된 양이다.

낭비는 어디서 오는가 — 요청·사용·청구의 간극

청구는 노드 용량 기준이다. 노드를 켜두면 그 위에서 무엇을 하든 풀 용량만큼 돈이 나간다. 스케줄링은 requests 기준이다. 스케줄러는 Pod의 requests 합계가 노드 용량을 넘지 않는 선에서 배치하므로, requests가 예약되지 않은 빈 슬롯은 노드 비용을 내면서도 아무도 안 쓴다. 그리고 가치는 실제 사용 기준이다. requests를 잡아놨지만 실제로는 그 절반도 안 쓴다면, 그 차이(슬랙)만큼 노드를 더 켜둔 셈이다.

낭비는 이 세 막대의 간극에서 나온다. 핵심 통찰은 이것이다. 거의 모든 쿠버네티스 낭비의 근원은 과대 요청(over-request) — 실제 사용량보다 훨씬 큰 requests를 잡아두는 것이다. 그래서 최적화의 출발점은 이 간극을 측정하고 좁히는 것이다.

첫 단계는 언제나 측정

측정 없는 최적화는 추측이다. 어떤 워크로드가, 어떤 네임스페이스가, 어떤 노드가 돈을 쓰는지 보이지 않으면 손댈 곳을 알 수 없다. 다행히 앞선 글들에서 다룬 도구들이 기반이 된다 — metrics-server로 실시간 사용량을, Prometheus로 이력을, 그리고 OpenCost나 Kubecost 같은 도구로 워크로드별 비용을 환산해 볼 수 있다.

# Pod별 실제 CPU/메모리 사용량 (metrics-server 필요)
kubectl top pods -A --sort-by=memory

# requests 대비 실제 사용을 비교 — 과대 요청 찾기의 출발점
kubectl describe node <node> | grep -A12 "Allocated resources"

무엇을 볼지가 중요하다. requests 대비 실제 사용률이 낮은 워크로드(과대 요청), 오랫동안 사용률이 낮은 노드(빈 슬롯), 그리고 바인딩되지 않은 PVC나 놀고 있는 LoadBalancer 같은 “유령 자원”을 찾는다.

두 방향에서 조이기

비용을 줄이는 레버는 크게 두 방향이다. 워크로드 측에서는 요청 자체를 줄이고, 인프라 측에서는 자원의 단가를 낮춘다. 둘은 곱셈으로 작용한다.

비용 최적화 레버 — 두 방향에서 조인다

워크로드 측 — 요청을 줄인다

가장 효과가 큰 것은 라이트사이징(rightsizing)이다. 과대 요청을 실제 사용에 맞게 낮추면, 같은 노드에 더 많은 Pod가 들어가고 노드 수가 줄어든다. 앞서 다룬 VPA(Vertical Pod Autoscaler)가 메트릭을 바탕으로 적정 requests를 추천해 주므로, 이를 권고 모드로 돌려 데이터를 모은 뒤 적용한다.

# VPA를 '권고만' 모드로 — 추천값을 보고 사람이 판단
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: api-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  updatePolicy:
    updateMode: "Off"          # 추천만, 자동 변경 없음

다음은 HPA다. 부하에 따라 복제본을 늘리고 줄이면, 한가한 시간대에 자원을 반납해 비용을 아낀다. 마지막으로 유휴 정리 — 개발/스테이징 환경을 야간이나 주말에 0으로 축소하고, 쓰지 않는 PVC와 LoadBalancer를 회수한다. 24/7로 켜둘 이유가 없는 환경은 의외로 큰 비용이다.

인프라 측 — 단가를 낮춘다

워크로드가 요청을 줄였다면, 이제 그 요청을 더 싸게 충족한다. Cluster Autoscaler나 Karpenter는 빈 노드를 자동으로 끄고, 수요가 늘면 노드를 공급한다 — 특히 Karpenter는 워크로드의 요구에 딱 맞는 인스턴스 타입을 골라 빈 슬롯을 줄인다. 스팟(Spot) 인스턴스는 같은 자원을 큰 폭으로 할인된 가격에 제공한다. 중단될 수 있다는 단점이 있으므로, 중단에 견디는(stateless, 재시작 가능한) 워크로드를 스팟에 배치하는 것이 정석이다.

여기에 빈 패킹(bin-packing)으로 노드 밀도를 높이고, 안정적인 기저 부하(baseline)에 대해서는 클라우드의 예약/약정 할인을 적용하면 단가가 더 내려간다. 변동 부하는 스팟·온디맨드로, 기저 부하는 약정으로 — 이 조합이 비용 곡선을 크게 낮춘다.

순서가 중요하다

레버가 많다고 아무거나 당기면 안 된다. 순서가 있다. 먼저 가시성을 확보해 낭비의 위치를 파악하고, 라이트사이징으로 과대 요청을 잡고, 오토스케일링으로 수요에 맞춰 자원을 신축적으로 만든 다음, 마지막으로 단가 인하(스팟·약정)를 적용한다. 순서를 거꾸로 하면 — 예를 들어 과대 요청을 그대로 둔 채 노드만 스팟으로 바꾸면 — 낭비를 싼값에 사는 셈이 된다.

그리고 비용 최적화는 한 번의 프로젝트가 아니라 지속적인 운영(FinOps)이다. 워크로드는 계속 바뀌므로, 측정 → 조정 → 검증의 루프를 정기적으로 돌려야 절감 효과가 유지된다.

정리 — 그리고 다음

쿠버네티스 비용 낭비는 요청·사용·청구의 세 막대 간극에서 오며, 그 근원은 대부분 과대 요청이다. 측정으로 낭비를 드러내고, 워크로드 측에서는 라이트사이징·HPA·유휴 정리로 요청을 줄이고, 인프라 측에서는 오토스케일러·스팟·빈 패킹·약정으로 단가를 낮춘다. 가시성 → 라이트사이징 → 오토스케일링 → 단가 인하의 순서를 지키고, 이를 지속적 루프로 운영한다.

여기까지 클러스터를 안정적이고 효율적으로 운영하는 법을 다뤘다. 하지만 아무리 잘 운영해도 재해는 온다 — 리전 장애, 인적 실수, 데이터 손상. 다음 글에서는 최악의 상황에 대비하는 재해 복구(DR) 전략으로 이어진다.


지난 글: 멀티 테넌시 — 하나의 클러스터를 안전하게 나눠 쓰기

다음 글: 재해 복구 — 최악의 상황에 대비하는 DR 전략


읽어주셔서 감사합니다. 😊