K8s ResourceQuota·LimitRange

ResourceQuota와 LimitRange란?

Kubernetes 멀티테넌트 환경에서 특정 팀이나 서비스가 클러스터 자원을 독점하는 것을 방지하려면 ResourceQuotaLimitRange가 필수입니다. 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% 알림을 설정하면, 자원 부족으로 인한 배포 실패를 사전에 방지할 수 있습니다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux