Kubernetes 비용 최적화 실전 가이드 — OpenCost·Kubecost로 네임스페이스별 비용 추적부터 HPA/VPA 튜닝까지
클라우드 비용 고지서를 받아보고 "이게 다 어디서 나온 거지?"라고 한 번쯤 멍해진 경험, 다들 있으실 것 같습니다. 저도 처음 쿠버네티스 클러스터를 운영하던 시절, AWS 청구서에 찍힌 금액을 보고 팀별로 비용을 나눠보려 했지만 노드 단위로 청구되는 구조 앞에서 속수무책이었습니다. CPU 하나, 메모리 한 줌을 여러 팀이 나눠 쓰는 환경에서 "payments 팀이 얼마 썼는지"를 측정하는 일 자체가 꽤 복잡한 문제거든요.
이 글을 읽고 나면 OpenCost를 10분 안에 설치하고, 오늘 당장 팀별 비용 리포트를 뽑아볼 수 있습니다. 저는 이 방법으로 staging 네임스페이스 비용을 한 달 만에 30% 줄였고, 업계에서 이런 식의 20~30% 절감 사례는 생각보다 정말 흔합니다. 이 글에서는 OpenCost와 Kubecost로 네임스페이스별 비용을 추적하고, HPA/VPA 오토스케일러 설정을 개선해 실질적인 비용 절감을 이끌어내는 방법을 실전 예시와 함께 살펴봅니다.
팀 단위로 클러스터를 운영하는 분들을 중심에 두고 구성했지만, 비용 규모와 무관하게 비율로 적용할 수 있는 내용들입니다. 아래 비용 예시 수치가 크게 느껴지더라도 "우리 클러스터에서의 비율"로 읽어주시면 됩니다.
핵심 개념
Kubernetes 비용 할당이 어려운 이유
클라우드 네이티브 환경의 아이러니 중 하나는, 자원을 효율적으로 공유할수록 비용 추적이 어려워진다는 점입니다. EC2 인스턴스 하나에 서비스 하나를 올리던 시절엔 비용 귀속이 간단했지만, 쿠버네티스는 수십 개의 파드가 하나의 노드를 나눠 씁니다. AWS는 노드 단위로 청구하기 때문에, 그 노드 위에 올라간 각 팀의 워크로드 비용을 분리하려면 별도의 비용 할당 레이어가 필요합니다.
여기서 두 가지 개념이 자주 등장합니다.
Showback vs Chargeback: Showback은 팀별 비용을 "보여주기만" 하는 것이고, Chargeback은 실제로 비용을 팀 예산에 청구하는 방식입니다. 대부분의 조직은 Showback부터 시작해 문화가 성숙하면 Chargeback으로 전환합니다.
OpenCost vs Kubecost — 어떤 걸 써야 할까
솔직히 말하면, 두 도구는 경쟁 관계라기보다 스펙트럼의 양 끝에 있습니다. Kubecost는 OpenCost 스펙을 기반으로 발전한 상용 제품으로, 그 위에 얼마나 많은 엔터프라이즈 기능을 얹느냐의 차이입니다. 다만 Kubecost는 자체 데이터 수집 레이어를 별도로 운용하므로, "OpenCost를 그대로 코어 엔진으로 사용한다"기보다는 공통된 스펙에서 출발해 각자의 방향으로 발전했다고 보는 것이 정확합니다.
| 항목 | OpenCost | Kubecost |
|---|---|---|
| 라이선스 | 오픈소스 (Apache 2.0) | 상용 (OpenCost 스펙 기반) |
| 가격 | 무료 | $449/월~ (비즈니스) |
| 멀티 클러스터 | 제한적 | 완전 지원 |
| RI·스팟 할인 반영 | 미지원 | AWS/GCP/Azure 빌링 연동 |
| RBAC / SSO | 미지원 | 지원 |
| 절감 추천 자동화 | 없음 | 있음 (right-sizing 포함) |
| 예산 알림 | 없음 | 있음 |
팀이 5명 이하인 스타트업이라면 OpenCost + Grafana 조합으로 충분하고, 수십 개 팀이 클러스터를 공유하며 FinOps 문화를 도입하려는 조직이라면 Kubecost의 엔터프라이즈 기능이 빛을 발합니다.
FinOps: Financial Operations의 약자. 클라우드 비용을 단순 모니터링이 아닌 팀 책임 체계와 정책으로 관리하는 문화·조직 운영 방식을 의미합니다.
HPA와 VPA — 비용 최적화의 핵심 레버
비용 추적이 "현재 얼마를 쓰는지" 측정하는 일이라면, 오토스케일러는 "얼마나 효율적으로 쓰는지"를 개선하는 도구입니다. 실무에서 자주 맞닥뜨리는 상황인데, 클러스터 전체 CPU 사용률을 보면 requests 대비 실제 사용량이 20~45% 수준에 머무는 경우가 많습니다. 즉, 예약은 많이 해놓고 실제로는 별로 안 쓴다는 뜻이죠.
- HPA (Horizontal Pod Autoscaler): CPU나 커스텀 메트릭(RPS, 큐 길이 등)에 따라 파드 레플리카 수를 늘리거나 줄입니다. 트래픽 변동에 빠르게 반응하는 것이 강점입니다.
- VPA (Vertical Pod Autoscaler): 개별 파드의 CPU/메모리 requests·limits를 실제 사용 패턴에 맞게 조정합니다. 과도하게 예약된 리소스를 줄이는 데 특화되어 있습니다.
Requests vs Limits: Requests는 파드가 스케줄링될 때 보장받는 리소스 양이고, Limits는 최대 사용 가능한 상한선입니다. 비용은 대부분의 경우 Limits보다 Requests 기준으로 산정됩니다. 단, 클라우드 공급자 및 billing 모델에 따라 다를 수 있으므로 실제 청구 방식은 각 공급자 문서에서 확인해보시는 것이 좋습니다. Requests를 실제 사용량에 맞게 줄이는 것이 비용 절감의 핵심입니다.
실전 적용
개념을 이해했으면 이제 실제로 적용해볼 차례입니다. 아래 네 가지 예시는 난이도 순으로 배치했습니다. 예시 1~3은 대부분의 팀에서 바로 적용해볼 수 있는 내용이고, 예시 4는 비용 제어를 정책 수준까지 끌어올리는 심화 패턴입니다.
예시 1: OpenCost 설치 및 네임스페이스별 비용 조회
Helm을 이용하면 설치 자체는 꽤 간단합니다. 먼저 Prometheus가 클러스터에 설치되어 있어야 OpenCost가 메트릭을 수집할 수 있습니다. Prometheus가 없다면 kube-prometheus-stack Helm 차트로 빠르게 시작해볼 수 있습니다. Prometheus까지 준비되어 있다면 OpenCost는 10분 안에 첫 비용 데이터를 볼 수 있습니다.
# OpenCost Helm 리포지토리 추가
helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update
# opencost 네임스페이스에 설치
helm install opencost opencost/opencost \
--namespace opencost --create-namespace \
--set opencost.exporter.defaultClusterId=my-cluster
# kubectl cost 플러그인 설치
# kubectl krew는 kubectl 플러그인 매니저입니다 — https://krew.sigs.k8s.io/docs/user-guide/setup/install/
kubectl krew install cost
# 최근 7일간 네임스페이스별 비용 조회
kubectl cost namespace --window 7d아래는 실제로 이 커맨드를 실행했을 때 나올 수 있는 결과 예시입니다. 수치는 대기업 클러스터 기준이지만, 비율로 보면 어떤 규모에서도 같은 패턴이 보입니다.
| 네임스페이스 | 월 환산 비용 | CPU 비용 | 메모리 비용 |
|---|---|---|---|
| analytics | $22,000 | $14,000 | $8,000 |
| payments | $18,000 | $12,000 | $6,000 |
| staging | $10,000 | $6,500 | $3,500 |
저도 처음엔 헷갈렸는데, staging 네임스페이스가 $10,000이나 나오는 걸 보고 의아했습니다. 확인해보니 야간과 주말에도 풀 스펙으로 가동 중이었던 것입니다. 이 리포트 하나가 팀 대화의 시작점이 됐습니다. CronJob으로 야간 스케일다운을 적용했더니 한 달 만에 30% 가까이 줄었습니다.
예시 2: Prometheus + Grafana 연동으로 비용 대시보드 구성
OpenCost는 기본값 기준 :9003 포트로 Prometheus 메트릭을 익스포트합니다. 아래 설정을 prometheus.yml에 추가하면 됩니다.
# prometheus.yml 스크레이프 설정
scrape_configs:
- job_name: 'opencost'
scrape_interval: 1m
static_configs:
# 서비스명.네임스페이스.svc 형식, 9003은 OpenCost 메트릭 익스포터 기본 포트
- targets: ['opencost.opencost.svc:9003']이 설정이 Prometheus로 하여금 1분 간격으로 OpenCost 메트릭을 긁어오게 합니다. 이후 Grafana에서 대시보드 ID 22208을 import하면 클러스터·네임스페이스·파드별 비용 시각화를 바로 확인해볼 수 있습니다. 별도 쿼리를 짜지 않아도 되니 이 방법이 가장 빠릅니다.
예시 3: VPA 권고 모드 + HPA 분리 적용으로 충돌 방지
HPA와 VPA를 동시에 사용하는 건 괜찮지만, 같은 메트릭(CPU 또는 메모리)을 두 오토스케일러가 동시에 건드리면 피드백 루프가 생겨 비용과 안정성 모두 나빠집니다. 팀에서 실제로 겪은 상황인데, HPA가 CPU 사용률을 줄이려 파드를 늘리면 VPA가 파드당 CPU 할당을 올리고, 그러면 다시 HPA가 반응하는 식으로 진동이 발생하더라고요.
업계에서 자리를 잡은 패턴은 역할을 명확히 분리하는 것입니다. HPA는 CPU 기반 수평 확장, VPA는 메모리 사이징 권고로 나누는 방식입니다.
# VPA: 메모리 리소스 최적화 (권고 모드 — 실제 변경은 직접 적용)
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-server-vpa
namespace: payments
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
updatePolicy:
updateMode: "Off" # 권고값만 제공, 자동 적용 안 함
resourcePolicy:
containerPolicies:
- containerName: api
mode: "Off" # 컨테이너별 자동 업데이트 비활성화
minAllowed:
cpu: "100m"
memory: "128Mi"
maxAllowed:
cpu: "2"
memory: "2Gi"mode: "Off"를 컨테이너 정책에도 명시하는 이유는, updateMode: "Off"가 전체 VPA 동작을 끄는 것과 별개로 컨테이너별 세부 제어가 가능하기 때문입니다. 처음 도입할 때 이 필드를 누락하면 나중에 특정 컨테이너만 Auto로 전환하려 할 때 혼란이 생길 수 있습니다.
# HPA: CPU 기반 레플리카 수평 확장
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server-hpa
namespace: payments
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60| 항목 | 설정값 | 이유 |
|---|---|---|
| VPA updateMode | Off |
권고만 확인 후 수동 검토해서 적용 |
| VPA containerPolicies mode | Off |
컨테이너별 자동 업데이트 비활성화 |
| HPA 메트릭 | CPU | 메모리는 반응이 느리고 파드 재시작 유발 |
| HPA minReplicas | 2 | 단일 장애 지점 방지 |
| VPA maxAllowed | cpu: 2, memory: 2Gi | 예상치 못한 과도한 리소스 할당 방지 |
예시 4: Kyverno로 네임스페이스 예산 초과 시 리소스 생성 차단 (심화)
비용 데이터를 보는 것에서 한 걸음 더 나아가, 정책으로 제어하는 것도 가능합니다. 아래는 OpenCost와 Kyverno를 연동해 특정 네임스페이스가 예산 임계값을 넘었을 때 신규 파드 생성을 차단하는 정책 예시입니다.
중요: 아래 YAML은 개념을 설명하기 위한 의사 코드(pseudo-code)입니다.
{{ opencost.namespace_cost }}는 실제 Kyverno에서 동작하는 변수 참조 형식이 아닙니다. 실제 구현에서는 Kyverno의 외부 데이터 소스(External Data) 기능과 JMESPath 표현식을 이용해 OpenCost API를 호출하는 방식으로 구성해야 합니다. 실제 동작하는 구현은 Nirmata 가이드를 참고해보시면 좋습니다.
# 개념적 예시 — 실제 동작하는 코드가 아닙니다
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: block-overspending-ns
spec:
validationFailureAction: Enforce
rules:
- name: check-namespace-cost
match:
resources:
kinds: ["Pod"]
validate:
message: "Namespace budget exceeded. Contact FinOps team."
deny:
conditions:
- key: "{{ opencost.namespace_cost }}" # 실제 구현 시 외부 데이터 소스로 대체 필요
operator: GreaterThan
value: "5000"Kyverno: 쿠버네티스 네이티브 정책 엔진. YAML로 정책을 작성하고 어드미션 컨트롤러로 동작해, 리소스 생성·수정 시 정책 위반을 실시간으로 차단하거나 감사할 수 있습니다.
장단점 분석
직접 운영해보면서 느낀 가장 뼈아픈 단점은 OpenCost의 할인 미반영 문제였습니다. Reserved Instance로 40% 할인을 받고 있는데 OpenCost 대시보드에는 온디맨드 가격으로 표시되니, 처음엔 "왜 이렇게 비싸게 나오지?"라고 당황했습니다. 이 부분은 아래 표에서 더 자세히 정리해봤습니다.
장점
| 항목 | 내용 |
|---|---|
| 즉각적인 가시성 | 네임스페이스·파드·레이블 단위 실시간 비용 확인 가능 |
| 낭비 발견 | staging 풀 가동, 과도한 requests 예약 등 숨겨진 낭비 탐지 |
| FinOps 문화 기반 | Showback → Chargeback으로 팀 책임 체계 도입 용이 |
| 오토스케일러 개선 | VPA 권고값으로 requests 최적화 시 즉시 비용 절감 효과 |
| 정책 기반 제어 | Kyverno 연동으로 예산 초과 자동 차단 가능 (심화) |
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| OpenCost 할인 미반영 | RI·스팟 할인이 비용에 반영 안 됨 → 실제보다 높게 표시 | Kubecost 또는 AWS Cost Explorer 병행 사용 |
| Prometheus 의존성 | OpenCost 기본 동작에 Prometheus 필요 | Collector Datasource(베타) 경량 옵션 검토 |
| VPA 재시작 이슈 | Auto 모드는 파드를 재시작해 requests 변경 |
updateMode: Off로 시작해 점진적 전환 |
| Kubecost 가격 | $449/월~ 부담, IBM 인수 후 가격 정책 불투명 | 소규모 팀은 OpenCost Free tier로 충분 |
| HPA 메모리 메트릭 위험 | 메모리 기반 HPA는 파드 재시작 루프 유발 가능 | CPU 또는 커스텀 메트릭(RPS, 큐 길이)으로 대체 |
Reserved Instance (RI): 클라우드 공급자에게 1년 또는 3년 약정으로 인스턴스를 예약하면 온디맨드 대비 최대 60~70% 할인을 받을 수 있습니다. OpenCost는 이 할인을 자동으로 반영하지 않기 때문에, 실제 청구 금액과 차이가 날 수 있습니다.
피해야 할 실수 TOP 3
-
HPA와 VPA를 같은 메트릭으로 동시에 활성화하는 것 — CPU를 두 오토스케일러가 동시에 건드리면 피드백 루프로 파드 수와 리소스가 예측 불가하게 진동합니다. 메트릭 역할을 반드시 분리해서 운영하는 것을 권장합니다.
-
VPA의 minAllowed / maxAllowed를 생략하는 것 — 경계값 없이 VPA를 운영하면 예상치 못한 OOM 킬이나 반대로 과도한 CPU 할당이 발생할 수 있습니다. 처음 배포할 때부터 안전한 범위를 지정해두는 것이 좋습니다.
-
비용 추적 도구를 설치만 하고 알림을 안 설정하는 것 — 대시보드가 아무리 예뻐도 아무도 안 보면 소용이 없습니다. Kubecost의 예산 알림이나 Grafana의 임계값 알림을 슬랙 채널과 연동해두면 주간 리뷰 없이도 이상 징후를 빠르게 포착할 수 있습니다.
마치며
비용 최적화는 "얼마를 쓰는지 보이게 만드는 것"에서 시작하고, HPA/VPA 튜닝으로 실질적인 절감을 만들어낼 수 있습니다. 거창한 아키텍처 변경 없이도 OpenCost 설치와 VPA 권고값 검토만으로 클러스터 비용의 20~30%를 줄인 사례는 정말 흔합니다. 저도 staging 네임스페이스에서 직접 경험한 30% 절감이 그랬습니다.
지금 바로 시작해볼 수 있는 3단계:
-
OpenCost 설치 후 첫 리포트 확인
helm install opencost opencost/opencost --namespace opencost --create-namespace한 줄로 설치한 뒤,kubectl cost namespace --window 7d로 지난 7일간 네임스페이스별 비용을 확인해보시면 됩니다. 예상보다 높은 네임스페이스가 반드시 하나는 보일 것입니다. -
비용 상위 워크로드에 VPA 권고 모드 적용 비용이 가장 높은 워크로드에 VPA를
updateMode: Off로 달아두면 권고값을 안전하게 확인할 수 있습니다. 1~2주간 데이터를 쌓은 뒤 권고된 requests 값이 현재 설정보다 훨씬 낮다면, 그것이 바로 즉시 절감할 수 있는 여지입니다. -
팀 공용 비용 현황판 구성 Grafana 대시보드 ID
22208을 import해서 팀원들이 볼 수 있는 공용 비용 현황판을 만들어보시면 좋습니다. 숫자가 눈에 보이기 시작하면 팀 문화가 바뀌기 시작합니다. FinOps의 첫걸음은 언제나 가시성에서 출발합니다.
다음 글: 이번 글에서 다룬 OpenCost 비용 데이터와 Karpenter를 함께 활용하면 — AWS EKS에서 Spot 인스턴스 활용률을 높이고 노드 수준에서 추가로 비용을 절감하는 패턴을 살펴볼 예정입니다.
참고 자료
- OpenCost 공식 사이트 | opencost.io
- OpenCost GitHub | github.com/opencost
- OpenCost 2025 연간 리뷰 | opencost.io
- OpenCost Prometheus 익스포터 설정 | opencost.io
- kubectl cost 플러그인 문서 | opencost.io
- Grafana OpenCost 대시보드 (ID: 22208) | grafana.com
- Kubecost vs OpenCost 비교 | CloudZero
- Kubecost vs OpenCost 비교 | Apptio
- Kubernetes Autoscaling HPA/VPA 가이드 | Sedai
- HPA vs VPA: 2025 선택 가이드 | ScaleOps
- Kubernetes 비용 최적화 전략 2025 | Sealos
- OpenCost + Prometheus + Grafana 실전 가이드 | hodovi.cc
- OpenCost와 Kyverno 정책 기반 비용 관리 | Nirmata
- Cloud Cost Governance: Kubecost, OpenCost, Infracost | Open Source For You
- EKS + OpenCost + AWS Managed Prometheus/Grafana 구축 사례 | Automat-it