쿠버네티스 비용, 노드 단가 깎아봐야 소용없다
1 views
# 쿠버네티스 비용 최적화의 실체: 노드 단가가 아니라 설계와 공수를 줄여야 한다
## 청구서가 말해주지 않는 것
전기 요금 고지서를 처음 받아 든 사람은 대개 에어컨부터 끈다. 어느 기기가 얼마를 먹는지 확인하는 쪽은 소수다. 앞의 선택은 즉시 효과가 나지만 여름을 견딜 수 없게 만들고, 뒤의 선택은 느리지만 구조를 바꾼다. 클라우드 비용 앞에서 조직이 취하는 선택도 이 둘 사이 어딘가에 놓인다.
쿠버네티스를 도입한 조직이 겪는 전형적인 경로가 있다. 애플리케이션을 컨테이너로 묶고, 클러스터에 배포하고, 트래픽이 늘면 노드를 추가한다. 여기까지는 순조롭다. 문제는 몇 분기가 지난 뒤 재무 부서에서 청구서를 들고 찾아올 때 시작된다. 쿠버네티스는 요청받은 자원을 성실히 확보하는 시스템이지, 그 요청이 타당한지 검증하는 시스템이 아니다. 개발자가 명세서에 적어 넣은 숫자는 대부분 추측이며, 그 추측은 언제나 안전한 쪽으로 부풀려진다.
이 지점에서 흔히 벌어지는 대응이 '노드 끄기'다. 유휴 자원이 많아 보이니 노드 수를 줄이고, 요청량을 일괄 삭감한다. 며칠 뒤 장애가 발생한다. 메모리 한계를 넘어선 컨테이너가 강제 종료되고(OOM), CPU 한계에 걸린 프로세스가 실행 시간을 배분받지 못해 지연이 치솟고(스로틀링), 노드를 비우는 과정에서 파드가 재배치되지 못해 배포가 멈춘다. 절감액보다 장애 비용이 커지면 조직은 최적화 자체를 포기한다.
여기서 제시하려는 명제는 단순하다. 쿠버네티스 비용의 주적은 노드 단가가 아니라 엔지니어 공수와 비대칭적 자원 설계다. 리서치가 가리키는 총소유비용(TCO)의 구조는 통념과 어긋난다. 컴퓨트가 15~30%, 컨트롤 플레인이 2~4%인 반면, 엔지니어 시간과 툴 비용이 60~70%를 차지한다. 인스턴스 단가를 몇 퍼센트 깎는 협상보다, 사람이 매주 수동으로 자원을 조정하는 관행을 없애는 편이 훨씬 큰 항목을 건드린다.

## 자원은 대칭적이지 않다
### CPU와 메모리는 다른 물질이다
가장 먼저 교정해야 할 오해는 CPU와 메모리를 같은 방식으로 다루는 습관이다. 쿠버네티스에서 requests는 스케줄러가 자리를 잡을 때 확보하는 최소 보장량이고, limits는 넘어서면 제재가 가해지는 상한이다. 문제는 두 자원의 제재 방식이 근본적으로 다르다는 데 있다.
CPU는 압축 가능한 자원이다. 상한을 넘으면 실행이 지연될 뿐 프로세스는 살아 있다. 메모리는 압축이 불가능하다. 상한을 넘는 순간 커널이 프로세스를 종료시킨다. 이 차이가 실무 공식을 만든다. CPU requests는 p95 또는 p99 관측치를 기준으로 설정하되, CPU limits는 스로틀링을 유발하므로 제거하는 편이 권장된다. 메모리는 반대다. requests와 limits를 동일하게 맞춰 Guaranteed 품질 등급을 부여하고, 한 파드의 메모리 폭주가 이웃 파드로 전파되는 경로를 차단한다.
같은 클러스터 안에서 한 자원은 상한을 풀고 다른 자원은 상한을 조여야 한다. 이 비대칭을 이해하지 못한 채 "모든 컨테이너에 limits를 설정하라"는 규칙을 일괄 적용하면, 안정성을 확보한 줄 알았던 조치가 지연의 원인이 된다.

### 자동 조정 도구의 함정
VPA(Vertical Pod Autoscaler)는 관측된 사용량에 맞춰 자원 명세를 자동 갱신하는 도구다. 이론적으로는 사람이 손댈 일이 사라진다. 그러나 프로덕션에서 VPA의 갱신 모드는 파드 재시작을 동반한다. 비용을 줄이려다 무계획적 재시작을 도입하는 셈이다.
현장에서 정착한 구조는 VPA를 추천 전용(Off) 모드로 돌리고, Goldilocks 같은 시각화 도구로 권장치를 노출한 뒤, GitOps 워크플로우를 통해 명세 변경을 코드로 반영하는 방식이다. 자동화의 대상은 '판단'이 아니라 '관측과 제안'이다. 반영 시점은 사람이 통제하되, 관측과 계산의 부담은 기계가 진다.
수평 확장과의 충돌도 검토 대상이다. HPA(Horizontal Pod Autoscaler)와 VPA가 같은 메트릭을 바라보면 서로의 결정을 무효화한다. 메트릭을 분리하거나, VPA를 Off 모드로 두고 HPA만 실제 조정을 담당하게 하는 구성이 안전하다.
### 노드 프로비저닝의 세대교체
파드 단위 조정 위에는 노드 단위 조정이 있다. 오랫동안 표준이었던 Cluster Autoscaler는 미리 정의된 노드 그룹을 늘리고 줄이는 방식이다. Karpenter는 대기 중인 파드의 요구 사항을 직접 읽어 그에 맞는 인스턴스를 즉석에서 선택한다. 프로비저닝 소요 시간은 3~4분에서 45~60초 수준으로 단축되며, WhenEmptyOrUnderutilized 정책에 따른 동적 빈 패킹으로 컴퓨트 노드를 30~60% 줄인 사례가 보고된다.
여기에 이벤트 기반 확장을 담당하는 KEDA를 더하면 큐 길이나 외부 지표에 반응하는 확장과 트래픽 없는 워크로드의 완전 축소(scale-to-zero)가 가능해진다. 다만 KEDA의 cron 스케일러는 축소 시점에 즉시 0으로 떨어지는 미해결 이슈(Issue #3609)가 보고되어 있어, 반응형 스케일러와 결합해 하한을 확보하는 구성이 필요하다.
## 절감은 구매 구조와 배선에서 완성된다
### 기초와 변동을 분리한다
인스턴스 구매 전략의 핵심은 트래픽을 두 층으로 나누는 데 있다. 하루 중 어느 시점에도 사라지지 않는 기초 부하는 Compute Savings Plan이나 예약 인스턴스로 덮는다. 그 위에서 출렁이는 변동 부하는 스팟 인스턴스로 처리한다. 스팟은 가격이 대폭 저렴한 대신 클라우드 사업자가 언제든 회수할 수 있는 잉여 용량이므로, 중단을 견디는 워크로드에만 얹어야 한다.
Karpenter의 price-capacity-optimized 할당 전략은 가격뿐 아니라 회수 가능성까지 함께 고려해 인스턴스를 선택한다. 여기에 PriorityClass로 중단 허용 워크로드와 비허용 워크로드를 명시적으로 구분하면, 회수가 발생해도 기초 서비스는 영향권 밖에 남는다.
### 스토리지와 네트워크의 누수
컴퓨트에 집중하는 동안 조용히 새는 항목이 둘 있다. 스토리지에서는 gp2 볼륨을 gp3로 전환하는 것만으로 20~40% 절감이 보고된다. 여기에 볼륨 생성을 실제 파드 배치 시점까지 미루는 WaitForFirstConsumer 설정, 삭제된 클레임에 딸린 볼륨을 회수하는 PV Reclaim Policy 관리, 접근 빈도가 낮은 데이터를 객체 스토리지 아카이브 계층으로 옮기는 티어링이 더해진다. 남겨진 리소스를 주기적으로 정리하는 kubectl-gc 같은 도구도 함께 쓰인다.
네트워크는 더 은밀하다. NAT 게이트웨이는 GB당 0.135달러 이상의 처리량 요금을 부과한다. 클러스터 내부 서비스가 객체 스토리지나 관리형 데이터베이스를 호출할 때마다 이 요금이 누적된다. VPC 엔드포인트를 도입하면 이 경로를 우회할 수 있다. S3와 DynamoDB용 게이트웨이 엔드포인트는 무료이며, 인터페이스 엔드포인트는 77% 절감이 보고된다. 여기에 Topology-Aware Routing을 적용해 가용 영역을 넘나드는 트래픽을 차단하면, 청구서에서 원인을 짚기 가장 어려웠던 항목이 사라진다.

## 자동화는 규율 없이 지속되지 않는다
### 비용을 보이게 만드는 일
절감 조치는 통제 장치 없이는 원상 복구된다. 새로 배포되는 워크로드가 다시 과잉 요청을 적어 넣기 때문이다. 그래서 거버넌스 계층이 필요하다.
출발점은 라벨링이다. 네임스페이스와 라벨로 비용의 귀속처를 확정하되, AWS 비용 및 사용 보고서(CUR)의 라벨 50개 제한 같은 실무적 제약을 설계 단계에서 반영해야 한다. 그 위에 ResourceQuota와 LimitRange를 계층적으로 걸어 상한을 강제하고, OPA나 Kyverno 같은 정책 엔진으로 명세 규칙을 배포 시점에 검증한다. 이것이 가드레일이다. 사람이 매번 리뷰하는 대신, 위반 자체가 성립하지 않게 만든다.
비용 배분은 단계적으로 진행한다. 각 팀에 비용을 보여주기만 하는 쇼백(Showback)에서 시작해, 실제 예산에서 차감하는 차지백(Chargeback)으로 이행한다. 배분 산식은 requests 70%와 실사용량 30%를 조합하는 방식이 쓰인다. 확보한 자원에 대한 책임과 실제 소비에 대한 책임을 함께 묻는 구조다.
### 스케줄러의 기본값은 절약을 지향하지 않는다
기본 스케줄러는 파드를 여러 노드에 고르게 분산하는 LeastAllocated 방식을 취한다. 가용성에는 유리하나 노드 활용률은 떨어진다. MostAllocated 빈 패킹으로 전환하면 파드를 이미 사용 중인 노드에 몰아 담아 유휴 노드를 비우고 회수할 수 있다. 여기에 Scheduling Gates를 적용해 선행 조건이 충족되지 않은 파드가 대기 상태로 머물게 하면, 실행 불가능한 파드를 위해 노드를 새로 띄우는 낭비를 막는다.
### 도구는 역할이 다르다
시장의 도구들은 두 갈래로 나뉜다. OpenCost와 Kubecost는 비용을 계측하고 귀속시키는 가시성 도구다. Cast AI, ScaleOps, Spot Ocean 같은 플랫폼은 노드와 파드를 실제로 조정하는 자동화 도구다. 이 구분을 흐리면 대시보드만 늘고 청구서는 그대로인 상태에 도달한다. 가시성 도구는 무엇을 바꿀지 알려주고, 자동화 도구는 바꾸는 일을 대신한다. 순서를 뒤집을 수 없다.
기대치도 환경별로 나누어 세워야 한다. 개발과 스테이징 같은 비프로덕션 환경은 야간 축소와 공격적 스팟 활용이 가능해 60~80% 절감이 보고된다. 프로덕션은 가용성 제약 때문에 30~50%가 현실적 범위다. 이 둘을 하나의 목표로 묶으면 프로덕션에서 무리한 조치가 나오거나, 비프로덕션에서 남은 여지를 놓친다. Wio Bank, NielsenIQ, Vorwerk 등의 사례가 인용되는 맥락도 각 환경의 제약을 전제한 수치다.
## 순서가 결과를 결정한다
실행은 네 단계로 정리된다. 1~4주 차에는 가시성을 확보한다. 계측 도구를 붙이고, 30일 기준선을 수집하고, 라벨 체계를 강제한다. 이때 비용 지표만 모으면 부족하다. PodDisruptionBudget 위반, OOM 발생 건수, P99 지연을 함께 기록해야 절감이 안정성을 훼손하지 않았음을 증명할 수 있다. 재무 승인은 절감액이 아니라 이 증명 위에서 나온다.
4~12주 차에는 비대칭 원칙에 따라 자원 명세를 재조정하고, Karpenter를 도입하고, gp3로 전환한다. 3~6개월 차에는 VPC 엔드포인트와 Topology-Aware Routing으로 네트워크 경로를 정리하고, 기초와 변동을 나눈 2계층 구매 구조를 확립한다. 이후로는 OPA 가드레일, 70/30 차지백, 정기적 유휴 리소스 정리가 상시 운영으로 남는다.
이 순서를 지키는 이유는 명확하다. 계측 없는 절감은 근거가 없고, 자동화 없는 절감은 사람의 시간을 태우며, 거버넌스 없는 절감은 다음 분기에 원상 복구된다. 세 요소는 선후 관계로 묶인 계층이다.
절감의 크기는 얼마나 많은 노드를 껐는지가 아니라, 잘못된 자원 요청이 애초에 클러스터에 들어올 수 없도록 얼마나 촘촘한 규율을 세웠는지로 결정된다.