2026.08.04

쓴 만큼 낼까, 예약한 만큼 낼까 - Kubernetes 비용 구조 뜯어보기

3분 읽기 26 views

청구서는 왜 줄지 않는가

회식 자리를 예약해 본 사람이라면 안다. 스무 명이 온다고 예약했는데 열두 명만 왔을 때, 식당은 스무 명분의 자리를 비워 두었으니 스무 명분의 최소 주문을 요구한다. 실제로 먹은 양과 무관하게 비워 둔 자리 자체가 비용이 된다. 예약은 사용과 별개의 회계를 만든다.

손님이 절반만 앉아 있는데도 예약석 팻말 없이 빈 의자들이 넓게 비워져 있는 식당 내부

클라우드 컴퓨팅은 쓴 만큼 낸다는 약속으로 시작했다. 서버를 미리 사서 창고에 쌓아 두던 시대의 낭비를 끝내겠다는 선언이었다. 그 위에 Kubernetes가 올라섰다. 애플리케이션을 격리된 단위로 포장한 컨테이너들을 여러 서버에 자동으로 배치하고 관리하는 오케스트레이션 시스템으로, 오늘날 상당수 기업의 서비스가 이 위에서 돌아간다. 배치가 자동화되고, 죽은 컨테이너는 알아서 되살아나고, 부하에 따라 규모가 늘고 준다. 약속대로라면 비용은 수요에 정확히 비례해야 했다.

현실의 청구서는 그렇지 않다. 트래픽이 줄어도 청구액은 줄지 않고, 서비스를 정리해도 클러스터 규모는 그대로다. 실제 자원 활용률이 확보된 용량에 크게 못 미친다는 관찰이 업계에서 반복해서 보고된다. 쓴 만큼 내겠다던 조직이 어느새 쓰지 않는 것에 대부분의 비용을 지불하고 있다. 기술의 결함이 아니라 구조의 문제다.

비용은 사용이 아니라 선언에서 발생한다

Kubernetes에서 컨테이너를 배포할 때 개발자는 두 가지 값을 선언한다. 요청(request)은 이 컨테이너가 필요로 하는 CPU와 메모리의 최소량이고, 제한(limit)은 사용할 수 있는 최대량이다. 스케줄러는 요청값을 근거로 컨테이너를 어느 서버에 배치할지 결정하고, 요청된 자원은 실제 사용 여부와 무관하게 그 컨테이너 몫으로 예약된다.

클라우드 사업자는 노드, 즉 가상 서버 단위로 과금한다. 노드 수는 스케줄러가 수용해야 할 요청값의 총합이 결정한다. 그러니 조직이 내는 돈은 컨테이너들이 실제로 소비한 자원이 아니라 개발자들이 선언한 요청값의 총합에 비례한다. Kubernetes 클러스터는 모든 팀이 혹시 몰라서 넉넉히 예약해 둔 좌석으로 가득 찬 식당인 셈이다.

개발자가 요청값을 부풀리는 데는 이유가 있다. 요청을 적게 잡았다가 트래픽이 몰리면 서비스가 느려지거나 컨테이너가 강제 종료된다. 그 장애의 책임은 즉각적이고 개인적이다. 반면 과다 예약의 비용은 월말 청구서에 뭉뚱그려져 조직 전체로 흩어진다. 위험은 나에게 오고 비용은 모두에게 분산되는 구조에서 합리적 개인은 언제나 부풀리는 쪽을 택한다. 공유지의 비극이 클러스터 안에서 그대로 재현된다.

각 팀이 실제 사용량보다 훨씬 큰 공간을 미리 차지해 창고가 가득 찬 모습의 비유적 장면

비용은 사용이 아니라 선언에서 발생하고, 선언은 검증되지 않은 채 쌓인다. 최적화란 이 선언과 실제 사이의 간극을 좁히는 작업이다.

간극을 좁히는 세 개의 층위

컨테이너 층위: 선언을 실측에 맞추다

첫 번째는 개별 컨테이너의 요청값을 바로잡는 일, 흔히 말하는 라이트사이징(rightsizing)이다. 모니터링으로 수집한 실제 사용량 분포를 근거로, 관성적으로 복사되어 온 요청값을 실측에 맞게 고친다. Kubernetes의 수직 오토스케일러(VPA)가 이를 자동화한다. 컨테이너의 과거 사용 이력을 분석해 적정 요청값을 권고하거나 직접 조정하는 장치다. 부하에 따라 컨테이너 개수를 늘리고 줄이는 수평 오토스케일러(HPA)와 달리, VPA는 컨테이너 하나의 몸집을 조정한다.

노드 층위: 예약의 총합에 맞춰 식당을 줄이다

두 번째는 클러스터를 구성하는 노드의 수와 종류를 수요에 맞추는 일이다. 클러스터 오토스케일러는 배치할 곳이 없는 컨테이너가 생기면 노드를 추가하고, 비어 가는 노드는 정리한다. Karpenter처럼 워크로드의 요구에 맞는 인스턴스 유형을 그때그때 골라 프로비저닝하는 도구가 나오면서 이 층위는 한층 정교해졌다. 여기에 스팟 인스턴스를 결합하면 절감 폭이 더 커진다. 클라우드 사업자의 유휴 용량을 정가보다 크게 할인된 가격에 쓰되 언제든 회수될 수 있는 인스턴스인데, 중단을 견디도록 설계된 무상태 워크로드라면 회수 위험은 Kubernetes의 자가 복구가 흡수한다.

조직 층위: 비용을 볼 수 있게 만들다

세 번째 층위가 가장 본질적이다. 공유 클러스터의 청구서는 하나로 합산되어 도착하므로 어느 팀의 어느 서비스가 얼마를 쓰는지 보이지 않는다. 보이지 않는 비용에는 책임이 성립하지 않는다. 그래서 네임스페이스와 레이블 단위로 비용을 배분해 팀별로 보이게 만드는 작업이 필요하고, 이를 문화로 정착시키는 실천 체계가 FinOps다. Kubecost 같은 도구가 이 가시화를 맡는다. 요청값 선언에 예산의 무게가 실리는 순간, 첫 번째 층위의 교정은 캠페인이 아니라 일상이 된다.

절감은 안정성의 적인가

여유 자원은 낭비가 아니라 보험이라는 반론이 있다. 트래픽은 예측을 배반하고, 장애의 비용은 초과 예약의 비용보다 크다. 청구서 몇 푼 아끼려다 새벽의 장애 대응과 고객 이탈을 부른다면 그게 더 비싼 최적화 아닌가.

절반만 맞는 말이다. 여유가 보험인 것은 맞다. 그러나 보험은 위험을 계산하고 보험료를 산정할 때 보험이다. 지금 클러스터의 여유가 어떤 위험을 얼마나 흡수하도록 설계됐는지 답할 수 있는 조직은 드물다. 대부분의 여유는 설계된 완충이 아니라 검증되지 않은 관성의 퇴적이고, 근거 없이 다섯 배를 예약해 둔 상태는 안정성이 아니라 무지에 가깝다.

인과는 오히려 반대다. 비용 최적화의 전제인 실측과 가시화는 안정성 작업의 전제와 겹친다. 각 서비스가 실제로 얼마를 쓰는지, 부하가 몰릴 때 어떤 곡선을 그리는지 아는 조직만이 완충을 의도적으로 설계할 수 있다. 측정 위에 남긴 20%의 여유는 보험이지만, 무지 위에 쌓인 80%의 여유는 언제 무너질지 모르는 요행이다.

계기판과 그래프 곡선으로 자원 사용을 정밀하게 측정하며 완충 구간을 설계하는 관제실 분위기의 장면

다만 최적화 작업 자체에도 비용이 든다는 점은 남는다. 엔지니어의 시간은 노드보다 비싸다. 월 수십만 원을 아끼려고 수개월의 공수를 태우는 일은 최적화가 아니라 전시다. 성숙한 조직이 사람의 판단을 정책 수립에 두고 반복 판단을 오토스케일러와 자동 권고에 위임하는 이유다. 최적화는 프로젝트가 아니라 시스템의 속성이어야 한다.

선언의 정직성이라는 문제

결국 Kubernetes 비용 최적화는 인프라 기술의 문제가 아니라 선언과 실제의 간극을 관리하는 문제다. 요청값은 개발자가 시스템에 하는 약속이고 청구서는 그 약속들의 회계다. 약속이 부풀려지면 회계가 부푼다. 도구는 간극을 재고 좁히는 수단일 뿐, 간극을 만드는 것은 검증 없는 선언을 허용하는 조직이다.

같은 구조는 클라우드 바깥에도 있다. 자원을 공유하는 체계에서 각자의 요구가 검증되지 않고 비용이 전체로 분산되면 체계는 비대해진다. 이를 막는 것은 절약의 구호가 아니라 측정과 귀속의 설계다. 누가 얼마를 요구했고 실제로 얼마를 썼는지가 보이는 구조에서만 개인의 합리성과 전체의 효율이 화해한다.

좋은 클러스터 운영이란 저렴한 클러스터가 아니라 정직한 클러스터를 만드는 일이다. 비용은 시스템이 조직에게 보내는 가장 솔직한 보고서다.