Kubernetes 리소스 requests/limits 모범 사례, VPA/HPA 전략, Goldilocks, Kubecost/OpenCost, 스팟 인스턴스, 네임스페이스 쿼터, FinOps 실천법을 다룹니다.
6장에서 Karpenter를 통한 노드 수준의 비용 최적화를 살펴보았습니다. 하지만 진정한 비용 최적화는 노드 프로비저닝만으로 달성할 수 없습니다. 워크로드 수준의 리소스 관리, 오토스케일링 전략, 비용 가시성(Cost Visibility) 확보, 조직 차원의 핀옵스(FinOps) 실천이 함께 이루어져야 합니다. 이번 장에서는 Kubernetes 비용 최적화의 전체 그림을 다루겠습니다.
Kubernetes에서 리소스 설정은 스케줄링, 안정성, 비용에 직접적인 영향을 미칩니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
template:
spec:
containers:
- name: api
image: org/api:v1
resources:
requests:
cpu: 500m # 스케줄링 기준: 0.5 vCPU 보장
memory: 512Mi # 스케줄링 기준: 512 MiB 보장
limits:
cpu: 2000m # 상한: 2 vCPU까지 사용 가능
memory: 1Gi # 상한: 1 GiB 초과 시 OOM Killrequests: 컨테이너에 보장되는 최소 리소스입니다. 스케줄러는 이 값을 기준으로 Pod를 노드에 배치합니다.
limits: 컨테이너가 사용할 수 있는 최대 리소스입니다. CPU limits를 초과하면 스로틀링(Throttling)이 발생하고, 메모리 limits를 초과하면 OOM Kill이 발생합니다.
CPU limits 설정에 대해서는 커뮤니티에서 논쟁이 있습니다. CPU limits를 설정하면 불필요한 스로틀링이 발생하여 레이턴시가 증가할 수 있습니다. 많은 운영 팀이 "CPU requests만 설정하고 CPU limits는 설정하지 않는" 전략을 채택하고 있습니다. 반면 메모리 limits는 반드시 설정해야 합니다. OOM Kill 없이는 메모리 누수를 감지하기 어렵기 때문입니다.
리소스 설정에 따라 Pod의 서비스 품질(QoS) 클래스가 결정됩니다.
Guaranteed: requests == limits (모든 컨테이너)
→ 노드 압박 시 가장 마지막에 퇴거
→ 미션 크리티컬 워크로드에 적합
Burstable: requests < limits (또는 일부만 설정)
→ BestEffort 다음으로 퇴거
→ 대부분의 워크로드에 적합
BestEffort: requests/limits 모두 미설정
→ 노드 압박 시 가장 먼저 퇴거
→ 개발 환경에서만 사용
수평 파드 오토스케일러(HPA)는 메트릭 기반으로 Pod 수를 자동 조절합니다.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 3
maxReplicas: 50
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "1000"HPA의 behavior 설정은 비용 최적화에 매우 중요합니다. 스케일 다운 안정화 윈도우를 충분히 길게 설정하면(예: 5분) 트래픽 변동에 따른 불필요한 스케일 업/다운 반복을 방지할 수 있습니다. 반면 스케일 업은 빠르게 반응하도록 짧은 윈도우를 설정하십시오.
수직 파드 오토스케일러(VPA)는 컨테이너의 리소스 requests/limits를 자동으로 조정합니다.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-server
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
updatePolicy:
updateMode: "Auto" # Off, Initial, Recreate, Auto
resourcePolicy:
containerPolicies:
- containerName: api
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 4
memory: 8Gi
controlledResources: ["cpu", "memory"]
controlledValues: RequestsOnlyVPA와 HPA를 동일한 CPU/메모리 메트릭으로 동시에 사용하면 충돌이 발생합니다. 두 도구를 함께 사용할 때는 HPA는 커스텀 메트릭(예: RPS)으로, VPA는 CPU/메모리 requests 조정으로 역할을 분리하십시오. 또는 VPA를 updateMode: "Off"로 설정하여 권장값만 확인하고 수동으로 적용하는 것이 안전합니다.
Goldilocks는 VPA의 권장값을 대시보드로 시각화하여 적정 리소스를 찾는 도구입니다.
# Helm으로 설치
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm install goldilocks fairwinds-stable/goldilocks \
--namespace goldilocks \
--create-namespace
# 모니터링할 네임스페이스 레이블링
kubectl label namespace production goldilocks.fairwinds.com/enabled=trueGoldilocks는 네임스페이스 내 모든 Deployment에 대해 VPA 객체를 자동 생성하고, 권장 리소스 값을 웹 대시보드로 보여줍니다. 각 컨테이너의 현재 설정과 권장 설정을 비교하여 과다/과소 프로비저닝 상태를 한눈에 파악할 수 있습니다.
OpenCost는 CNCF 샌드박스 프로젝트로, Kubernetes 비용을 실시간으로 측정합니다. Kubecost는 OpenCost를 기반으로 한 상용 제품입니다.
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: opencost
namespace: opencost
spec:
interval: 30m
chart:
spec:
chart: opencost
version: ">=1.0.0"
sourceRef:
kind: HelmRepository
name: opencost
values:
opencost:
exporter:
defaultClusterId: production-ap
prometheus:
internal:
serviceName: prometheus-kube-prometheus-prometheus
namespaceName: monitoring
ui:
enabled: trueOpenCost가 제공하는 비용 분석 관점은 다음과 같습니다.
metadata:
labels:
# 비용 할당용 레이블
app.kubernetes.io/name: api-server
app.kubernetes.io/part-of: payment-service
cost.example.com/team: backend
cost.example.com/environment: production
cost.example.com/cost-center: CC-12346장에서 Karpenter의 스팟 인스턴스 관리를 다루었지만, 비용 관점에서 추가적인 전략을 정리합니다.
상태 비저장 상태 저장
중단 허용O 스팟 (최대 90% 절감) 스팟 + PVC 보존
중단 허용X 온디맨드 온디맨드 + RI/SP
스팟 인스턴스 사용 시 반드시 토폴로지 분산을 설정해야 합니다.
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: karpenter.sh/capacity-type
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: api-server
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: api-server멀티테넌트 환경에서 팀별 리소스 사용을 제한하는 데 리소스쿼터(ResourceQuota)와 리밋레인지(LimitRange)를 활용합니다.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-backend
namespace: backend
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "100"
services: "20"
persistentvolumeclaims: "30"
---
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: backend
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: 4
memory: 8Gi
min:
cpu: 50m
memory: 64MiLimitRange의 default와 defaultRequest를 설정하면, 개발자가 리소스를 명시하지 않은 Pod에도 자동으로 적절한 리소스가 할당됩니다. 이는 BestEffort QoS를 방지하고, ResourceQuota와 함께 사용하면 예기치 않은 리소스 폭주를 방지할 수 있습니다.
핀옵스(FinOps)는 클라우드 비용을 기술 조직, 재무 조직, 비즈니스 조직이 협력하여 관리하는 운영 문화입니다.
Crawl (기초):
- 비용 가시성 확보 (OpenCost 설치)
- 기본 레이블 전략 수립
- 월별 비용 리포트 생성
Walk (중급):
- 팀별 비용 할당과 차지백(Chargeback) 구현
- VPA/Goldilocks로 리소스 최적화
- 스팟 인스턴스 도입
- 비용 이상 탐지 알림
Run (고급):
- 실시간 비용 대시보드와 예측
- 자동화된 리소스 최적화 파이프라인
- RI/Savings Plan 최적화
- 비용 기반 배포 결정 (비용 게이트)
GitOps와 연계하여 비용 리포트를 자동화할 수 있습니다.
apiVersion: batch/v1
kind: CronJob
metadata:
name: weekly-cost-report
namespace: finops
spec:
schedule: "0 9 * * 1" # 매주 월요일 09:00
jobTemplate:
spec:
template:
spec:
containers:
- name: reporter
image: org/cost-reporter:latest
env:
- name: OPENCOST_API
value: "http://opencost.opencost:9003"
- name: SLACK_WEBHOOK
valueFrom:
secretKeyRef:
name: slack-webhook
key: url
- name: REPORT_WINDOW
value: "7d"
restartPolicy: OnFailure다음은 정기적으로 검토해야 할 비용 최적화 항목입니다.
Kubernetes 비용 최적화는 노드 프로비저닝(Karpenter), 워크로드 리소스 관리(VPA/HPA/Goldilocks), 비용 가시성(OpenCost/Kubecost), 조직 문화(FinOps)의 네 가지 축이 조화를 이루어야 합니다. 이 모든 설정은 GitOps로 관리하여 일관성을 보장하고, 변경 이력을 추적하는 것이 중요합니다.
다음 장에서는 Kubernetes를 넘어 클라우드 인프라 전체를 선언적으로 관리하는 Crossplane을 살펴보겠습니다. Crossplane을 통해 데이터베이스, 네트워크, 스토리지 같은 클라우드 리소스도 Kubernetes API로 관리하는 방법을 다룹니다.
이 글이 도움이 되셨나요?
Karpenter의 아키텍처, Cluster Autoscaler와의 비교, NodePool/EC2NodeClass CRD, 통합과 중단 관리, 스팟 인스턴스 전략, GPU 노드 프로비저닝을 다룹니다.
Crossplane의 아키텍처, Provider와 Managed Resource, XRD와 Composition을 활용한 인프라 추상화, GitOps 통합, Terraform과의 비교를 다룹니다.
Kubernetes 컨트롤러 패턴의 원리, 조정 루프, controller-runtime과 Kubebuilder를 활용한 오퍼레이터 개발, CRD 설계 모범 사례를 다룹니다.