ResourceQuota와 LimitRange란?
Kubernetes 멀티테넌트 환경에서 특정 팀이나 서비스가 클러스터 자원을 독점하는 것을 방지하려면 ResourceQuota와 LimitRange가 필수입니다. ResourceQuota는 네임스페이스 단위의 총량 제한, LimitRange는 개별 Pod/Container 단위의 기본값과 범위 제한을 담당합니다.
이 글에서는 두 리소스의 내부 동작 원리, 실전 설정 패턴, 조합 전략, 그리고 흔한 함정과 모니터링 방법을 다룹니다.
ResourceQuota: 네임스페이스 총량 제한
기본 설정
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-alpha-quota
namespace: team-alpha
spec:
hard:
# 컴퓨트 자원
requests.cpu: "8" # 총 CPU request 합계 8코어
requests.memory: 16Gi # 총 메모리 request 합계 16Gi
limits.cpu: "16" # 총 CPU limit 합계 16코어
limits.memory: 32Gi # 총 메모리 limit 합계 32Gi
# 오브젝트 수 제한
pods: "50" # 최대 Pod 50개
services: "10"
services.loadbalancers: "2" # LB 서비스 2개까지
persistentvolumeclaims: "10"
configmaps: "20"
secrets: "20"
# 스토리지
requests.storage: 100Gi # 총 PVC 용량 100Gi
핵심 동작: ResourceQuota가 설정된 네임스페이스에서 Pod를 생성할 때, 해당 Pod의 requests/limits가 남은 쿼터 범위 안에 있는지 Admission Controller가 검증합니다. 초과하면 Pod 생성이 거부됩니다.
# 쿼터 사용 현황 확인
$ kubectl describe resourcequota team-alpha-quota -n team-alpha
Name: team-alpha-quota
Namespace: team-alpha
Resource Used Hard
-------- ---- ----
limits.cpu 4 16
limits.memory 8Gi 32Gi
pods 12 50
requests.cpu 2 8
requests.memory 4Gi 16Gi
requests.storage 20Gi 100Gi
Scoped Quota: 우선순위별 제한
노드 관리 시 PriorityClass별로 자원을 분배할 수 있습니다.
# PriorityClass 정의
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
---
# 높은 우선순위 Pod에만 적용되는 쿼터
apiVersion: v1
kind: ResourceQuota
metadata:
name: high-priority-quota
namespace: team-alpha
spec:
hard:
pods: "5"
requests.cpu: "4"
requests.memory: 8Gi
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["high-priority"]
LimitRange: 개별 리소스 기본값과 범위
apiVersion: v1
kind: LimitRange
metadata:
name: container-limits
namespace: team-alpha
spec:
limits:
# Container 레벨
- type: Container
default: # limits 기본값 (미지정 시 자동 적용)
cpu: 500m
memory: 256Mi
defaultRequest: # requests 기본값
cpu: 100m
memory: 128Mi
min: # 최소값
cpu: 50m
memory: 64Mi
max: # 최대값
cpu: "2"
memory: 2Gi
maxLimitRequestRatio: # limit/request 비율 제한
cpu: "4" # CPU limit은 request의 4배까지
# Pod 레벨 (모든 컨테이너 합산)
- type: Pod
max:
cpu: "4"
memory: 4Gi
# PVC 레벨
- type: PersistentVolumeClaim
min:
storage: 1Gi
max:
storage: 50Gi
LimitRange의 핵심 역할:
- default/defaultRequest: requests/limits를 명시하지 않은 컨테이너에 자동 주입
- min/max: 범위 벗어나면 Pod 생성 거부
- maxLimitRequestRatio: 과도한 오버커밋 방지 (limit이 request의 N배 초과 금지)
ResourceQuota + LimitRange 조합 전략
두 리소스는 반드시 함께 사용해야 합니다. 그 이유:
# ❌ ResourceQuota만 있고 LimitRange가 없는 경우
# → requests/limits 미지정 Pod는 생성 불가!
# ResourceQuota가 CPU/메모리를 추적하려면 모든 Pod에 requests가 있어야 함
Error: pods "my-pod" is forbidden: failed quota: team-alpha-quota:
must specify limits.cpu, limits.memory, requests.cpu, requests.memory
# ✅ LimitRange의 default/defaultRequest가 자동으로 채워줌
# → 개발자가 매번 명시하지 않아도 안전
실전 조합 패턴:
# 1. LimitRange: 기본값 + 범위 설정
# → 개별 Pod의 합리적인 자원 사용 보장
# 2. ResourceQuota: 네임스페이스 총량 제한
# → 팀/서비스 단위 자원 독점 방지
# 3. 관계: LimitRange min/max ⊂ ResourceQuota hard
# → LimitRange max × 최대 Pod 수 ≤ ResourceQuota hard
멀티테넌트 실전 설정 예시
# 네임스페이스 생성 + 라벨
apiVersion: v1
kind: Namespace
metadata:
name: team-alpha
labels:
team: alpha
env: production
cost-center: engineering
---
# LimitRange — 개별 제한
apiVersion: v1
kind: LimitRange
metadata:
name: standard-limits
namespace: team-alpha
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: "4"
memory: 4Gi
min:
cpu: 50m
memory: 64Mi
---
# ResourceQuota — 총량 제한
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: team-alpha
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "100"
---
# 오브젝트 수 쿼터 (별도 분리 권장)
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-quota
namespace: team-alpha
spec:
hard:
configmaps: "50"
secrets: "50"
services: "20"
services.loadbalancers: "3"
persistentvolumeclaims: "20"
모니터링 및 알림
# Prometheus 메트릭 (kube-state-metrics 제공)
kube_resourcequota{namespace, resource, type="hard"} # 할당량
kube_resourcequota{namespace, resource, type="used"} # 사용량
# 80% 이상 사용 시 알림 (Prometheus Alert Rule)
groups:
- name: quota-alerts
rules:
- alert: ResourceQuotaUsageHigh
expr: |
kube_resourcequota{type="used"}
/ kube_resourcequota{type="hard"}
> 0.8
for: 10m
labels:
severity: warning
annotations:
summary: "{{ $labels.namespace }} 쿼터 80% 초과"
description: "{{ $labels.resource }}: {{ $value | humanizePercentage }}"
Prometheus + Grafana로 대시보드를 구성하면 팀별 자원 사용 추이를 시각적으로 파악할 수 있습니다.
흔한 함정과 해결법
1. Deployment가 스케일 안 됨
# Deployment 자체는 성공하지만 ReplicaSet이 Pod를 못 만듦
$ kubectl describe rs my-app-xxxx -n team-alpha
Events:
Warning FailedCreate exceeded quota: compute-quota
# 해결: 쿼터 여유 확인 후 증설 또는 기존 Pod 정리
$ kubectl get resourcequota -n team-alpha -o wide
2. requests 없이 배포 실패
# ResourceQuota가 있는데 LimitRange가 없으면
# → requests/limits 미지정 Pod는 전부 거부됨
# 해결: LimitRange default/defaultRequest 반드시 설정
3. LimitRange max 초과
# 특정 배치 잡에 큰 리소스가 필요한 경우
# → 별도 네임스페이스에 다른 LimitRange 설정
# 또는 LimitRange에 예외를 두고 ResourceQuota로만 총량 제한
자동화: Kustomize로 표준 템플릿
# base/kustomization.yaml
resources:
- limitrange.yaml
- resourcequota-compute.yaml
- resourcequota-objects.yaml
# overlays/team-alpha/kustomization.yaml
bases:
- ../../base
namespace: team-alpha
patchesStrategicMerge:
- quota-patch.yaml # 팀별 한도 오버라이드
새 팀 온보딩 시 overlay만 추가하면 표준화된 자원 정책이 자동 적용됩니다. Helm Chart의 values.yaml로도 동일한 패턴을 구현할 수 있습니다.
마무리
ResourceQuota와 LimitRange는 Kubernetes 멀티테넌트 운영의 기본 중의 기본입니다. 핵심 정리: ResourceQuota = 네임스페이스 총량, LimitRange = 개별 Pod 기본값/범위, 둘은 반드시 함께 사용, LimitRange 없이 ResourceQuota만 쓰면 requests 미지정 Pod가 거부됨. kube-state-metrics로 사용률을 모니터링하고 80% 알림을 설정하면, 자원 부족으로 인한 배포 실패를 사전에 방지할 수 있습니다.