같은 클러스터를 여러 팀이 나눠 쓰는데 한 팀이 Pod를 마구 띄워 노드 메모리를 다 잡아먹으면, 다른 네임스페이스의 Pod까지 Pending이나 Evicted로 밀려납니다. 네임스페이스마다 "여기까지만 써라"라는 상한을 거는 것이 ResourceQuota이고, 개별 컨테이너에 기본값·상한을 강제하는 것이 LimitRange입니다. 둘은 역할이 달라 보통 함께 씁니다.
둘의 차이부터
| 오브젝트 | 적용 단위 | 막는 것 |
|---|---|---|
ResourceQuota | 네임스페이스 전체 합계 | CPU·메모리 총량, 오브젝트 개수 |
LimitRange | 컨테이너/Pod 1개 | requests·limits 기본값과 최소·최대 |
ResourceQuota만 걸면, requests를 안 적은 Pod가 들어와 합계 계산이 깨지거나 배포가 거부됩니다. 그래서 LimitRange로 "안 적으면 이 기본값"을 채워주는 짝이 필요합니다.
1단계 — ResourceQuota로 총량 제한
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
이 네임스페이스의 모든 Pod requests 합이 CPU 4코어, 메모리 8Gi를 넘으면 새 Pod 생성이 거부됩니다.
2단계 — LimitRange로 컨테이너 기본값
apiVersion: v1
kind: LimitRange
metadata:
name: team-a-limits
namespace: team-a
spec:
limits:
- type: Container
default: # limits 미지정 시 기본
cpu: 500m
memory: 512Mi
defaultRequest: # requests 미지정 시 기본
cpu: 200m
memory: 256Mi
max:
cpu: "2"
memory: 2Gi
이제 requests를 빼먹은 매니페스트도 자동으로 기본값이 채워져 Quota 계산이 깔끔하게 맞아떨어집니다.
3단계 — 적용과 확인
kubectl apply -f quota.yaml -f limitrange.yaml
kubectl describe resourcequota team-a-quota -n team-a
kubectl describe limitrange team-a-limits -n team-a
describe의 Used / Hard 컬럼이 현재 사용량과 상한을 한눈에 보여줍니다.
자주 만나는 거부 에러
requests·limits를 안 적은 채로 배포하면 이런 거부가 뜹니다.
Error from server (Forbidden): error when creating "deploy.yaml":
pods "web" is forbidden: failed quota: team-a-quota:
must specify limits.cpu,requests.cpu
LimitRange의 default/defaultRequest가 없으면 이렇게 막히니, 위 2단계를 먼저 적용했는지 확인하세요. 또 limit이 LimitRange의 max를 넘으면 maximum cpu usage per Container is 2 같은 메시지로 거부됩니다.
적용 체크리스트
kubectl get resourcequota -A # 네임스페이스별 쿼터 존재 여부
kubectl describe resourcequota -n team-a # Used/Hard 비교
kubectl get pods -n team-a --field-selector=status.phase=Pending # 쿼터에 막힌 Pod
이 3개로 "누가 한도를 다 썼는지"와 "왜 새 배포가 안 뜨는지"가 바로 좁혀집니다.
ResourceQuota를 직접 걸어 보고 일부러 한도를 넘겨 거부 메시지를 받아보는 실습은 쿠버네티스 트랙에서 해볼 수 있습니다 — 회원가입 없이 무료로.