본문 바로가기
Cloud Native/Kubernetes

5. Namespace, ResourceQuota, LimitRange

by jys275 2026. 1. 18.

클러스터를 운영한다는 건 결국 '땅을 나누고(Namespace), 울타리를 치는(ResourceQuota), 세부 규칙을 정하는(LimitRange)' 관리의 연속이다. 클라우드 네이티브 환경에서 자원 고갈은 곧 서비스 장애로 이어진다.

 

이를 위한 클러스터 자원 관리의 3대 핵심 오브젝트인 Namespace, ResourceQuota, LimitRange를 알아보자

 

 


 

 

0. 왜 자원을 제한하고 구역을 나누는가?

쿠버네티스 클러스터의 CPU와 메모리는 모든 파드가 공유하는 유한한 자원이다.

  • 즉, 클러스터라는 전체 사용할 수 있는 자원이 있다는건 알고 있다.
    • 일반적으로 Memory, CPU가 있고,
    • 여러 Namespaces가 있고, 그 안에는 여러 파드들이 있다.
    • 이 파드들이 클러스터의 자원들을 공유해서 사용하는데.
      • 안의 파드들이 클러스터 자원을 모두 사용해버리면 다른 파드 입장에선 더 이상 쓸 자원이 없어서 자원이 필요할 때 문제가 발생하게 된다.
    • 그래서 등장한 해결 방안이 Resource Quota, Litimit Range로 한계를 설정하는 것이다.
  • 자원 독점 방지: 특정 네임스페이스의 파드가 클러스터 자원을 전부 써버리면 다른 파드들이 굶어 죽게 된다.
    • 3번째 파드를 보면 5개의 자원 중 4개를 독점 중이다.
      • 리소스 쿼터(ResourceQuota)의 역할: 이걸 네임스페이스마다 달면, 네임스페이스마다 '최대 한계(2개)'라는 울타리를 친다. 즉, 자원이 부족해서 문제가 될지언정, 해당 구역의 자원이 다른 구역에 영향을 끼치지 못하게 격리되는 것이다.
        • 그렇다면 다른 문제도 있다. 최대 2개를 받은 네임스페이스가 2개의 자원을 이미 모두 사용하고 있다. 그러면 다른 파드들은 해당 네임스페이스에 못 들어오게된다.
      • 리미트 레인지(LimitRange)의 역할: 그래서 등장했다. 네임스페이스 내부로 들어오는 개별 파드의 '크기'를 제한한다. 너무 큰 파드 하나가 네임스페이스를 장악해 다른 파드들이 못 들어오는 사태를 막기 위함이다.
  • 확장성: 이 제한 기능들은 네임스페이스뿐만 아니라 클러스터 전체 자원에도 적용할 수 있다.

 


 

 

1. 네임스페이스 (Namespace)

  • 이름 중복 방지: 한 네임스페이스 내에서 같은 타입의 오브젝트(예: Pod)는 이름을 중복해서 쓸 수 없지만, 다른 네임스페이스라면 가능하다.
  • 자원 분리: 서비스와 파드의 연결(Selector-Label)은 기본적으로 네임스페이스를 넘어서지 못한다.
  • 일괄 삭제: 네임스페이스를 지우면 그 안의 모든 자원이 함께 삭제되므로 운영 시 매우 유의해야 한다.
  • 네트워크 통신: 기본적으로는 IP를 통해서는 타 네임스페이스 파드와 통신이 가능하지만, NetworkPolicy로 이를 차단할 수 있다.
    • 즉, 대부분의 자원들은 그 네임스페이스 안에서만 사용할 수가 있는 것이다.
  • 예외: 노드(Node)나 퍼시스턴트 볼륨(PV)은 특정 네임스페이스에 속하지 않는 클러스터 공용 오브젝트다.
  • YAML은 그냥 kind와 name만 지정해주는 것을 볼 수 있다.
    • 파드나 서비스를 만들 때는 속할 네임스페이스를 지정하는 것.
    • labes와 selector의 값이 같은 파드를 가르켜도 결국에는 다른 네임스페이스(nm-1 / nm-2)에 있기 때문에 무용지물이다.

 

 

2. 리소스 쿼터 (ResourceQuota)

  • 네임스페이스 총량 제한: 해당 네임스페이스에 들어갈 모든 파드의 리퀘스트(Request)와 리미트(Limit) 합계에 한계를 hard라는 속성으로 설정한다.
  • 스펙 명시 필수: 쿼터가 걸린 네임스페이스에 파드를 만들려면 반드시 자원 사용량(spec.resources.requests, limits)을 명시해야 하며, 이를 누락하거나 쿼터를 초과하면 생성이 거부된다.
  • 제한 대상: CPU, 메모리, 스토리지뿐만 아니라 파드나 서비스 같은 오브젝트의 개수도 제한할 수 있다.

 

 

 

3. 리미트 레인지 (LimitRange)

  • 파드 자원 체크: 개별 파드가 가진 리미트 값이 설정된 min(최소)보다 작거나 max(최대)보다 크면 생성이 차단된다.
  • 비율 제한: maxLimitRequestRatio를 통해 Request 대비 Limit의 비율(예: 3배 이하)을 강제할 수 있다.
    • Pod2는 limits가 requests보다 4배 이상이므로 거부된다.
  • 자동 할당: Pod3 처럼 파드에 자원 설정을 안 했을 경우에 유용한, 자동으로 옵션들이 적용되는 defaultRequest와 default(Limit) 값을 설정할 수 있다.

 

 

 

💡 꼬리 질문

Q: 네임스페이스에 ResourceQuota만 설정되어 있고 파드에 자원 명시를 깜빡했다면 생성이 거부되는데, 이때 관리자가 파드에 일일이 자원 설정을 추가하지 않고도 자동으로 배포되게 하려면 어떻게 해야 할까?

 

 

결론: 해당 네임스페이스에 LimitRange의 default 설정을 추가하면 된다.

  1. 상호 보완: ResourceQuota는 자원 명시를 강제하고 없으면 차단하지만, LimitRange는 명시되지 않은 자원을 자동으로 채워주는 역할을 한다.
  2. 동작 원리: 사용자가 자원 설정 없이 파드를 생성 요청하면, Admission Controller 단계에서 LimitRange의 default 값이 파드 스펙에 주입된다. 이후 ResourceQuota는 이 주입된 값을 바탕으로 총량 합계를 계산하여 생성을 허용하게 된다.

 

 


 

 

 

1. Namespace: 논리적 격리와 한계

인프런_대세는 쿠버네티스

apiVersion: v1
kind: Namespace
metadata:
  name: nm-1

네임스페이스는 앱 간의 논리적 구분을 위한 그룹 개념이다. 하지만 모든 것이 완벽하게 격리되는 것은 아니라는 점을 명심하자.

  • 이름 유일성: 한 네임스페이스 내에서 같은 종류의 오브젝트는 이름이 중복될 수 없다. 만약 동일한 이름의 파드를 생성하려 하면 에러가 발생한다.
apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  namespace: nm-1
  labels:
    app: pod
spec:
  containers:
  - name: container
    image: kubetm/app
    ports:
    - containerPort: 8080
apiVersion: v1
kind: Service
metadata:
  name: svc-1
  namespace: nm-1
spec:
  selector:
    app: pod
  ports:
  - port: 9000
    targetPort: 8080
  • 연결의 제한: 서비스의 셀렉터(Selector)와 파드의 라벨(Label) 연결은 오직 같은 네임스페이스 상에서만 유효하다.

격리되지 않는 자원 (주의!)

1. IP 통신: 파드의 IP나 서비스의 IP를 알면 네임스페이스가 달라도 기본적으로 통신을 막지 않는다.

  • Namespace(nm-2):Pod(pod-1)에 들어가서 타 Namespace(nm-1)에 있는 Pod(pod-2)를 호출하는 등

2. NodePort: 노드 포트는 클러스터 전역 자원이다. 특정 네임스페이스에서 30001번 포트를 선점하면 다른 네임스페이스에서는 해당 포트를 쓸 수 없다.

apiVersion: v1
kind: Service
metadata:
  name: svc-2
  namespace: nm-1
spec:
  ports:
  - port: 9000
    targetPort: 8080
    nodePort: 30001
  type: NodePort
---
apiVersion: v1
kind: Service
metadata:
  name: svc-2
  namespace: nm-2
spec:
  ports:
  - port: 9000
    targetPort: 8080
    nodePort: 30001
  type: NodePort

3. Volume (hostPath): 노드의 특정 경로를 공유하는 hostPath 볼륨은 네임스페이스가 달라도 동일한 노드 경로를 바라본다면 데이터가 그대로 공유된다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  namespace: nm-1
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-worker1
  containers:
  - name: container
    image: kubetm/init
    volumeMounts:
    - name: host-path
      mountPath: /mount1
  volumes:
  - name : host-path
    hostPath:
      path: /node-v
      type: DirectoryOrCreate
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  namespace: nm-2
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-worker1
  containers:
  - name: container
    image: kubetm/init
    volumeMounts:
    - name: host-path
      mountPath: /mount1
  volumes:
  - name : host-path
    hostPath:
      path: /node-v
      type: DirectoryOrCreate
  • 일괄 삭제: 네임스페이스를 삭제하면 그 안에 소속된 모든 오브젝트가 자동으로 삭제되니 운영 시 각별히 주의해야 한다.

 

 

 

2. ResourceQuota: 네임스페이스 총량 제한 (상세코드)

인프런_대세는 쿠버네티스

네임스페이스별 자원 사용량이나 오브젝트 개수를 제한한다.

apiVersion: v1
kind: Namespace
metadata:
  name: nm-3
apiVersion: v1
kind: ResourceQuota
metadata:
  name: rq-1
  namespace: nm-3
spec:
  hard:
    requests.memory: 1Gi
    limits.memory: 1Gi
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  namespace: nm-3
spec:
  containers:
  - name: container
    image: kubetm/app
    resources:
      requests:
        memory: 0.5Gi
      limits:
        memory: 0.5Gi
  • 자원 명시 필수: 리소스 쿼터가 설정된 네임스페이스에 파드를 만들 때는 반드시 resources.requests와 limits를 명시해야 한다. 명시하지 않으면 생성이 거부된다.
  • 초과 시 차단: 설정된 총량(예: 메모리 1Gi)을 넘어서는 자원을 요청하는 파드는 생성 단계에서 차단된다.
apiVersion: v1
kind: ResourceQuota
metadata:
  name: rq-2
  namespace: nm-3
spec:
  hard:
    cpu: 4                   # 1-1. 컴퓨팅 리소스 제한 (얼마나 무거운가)
    memory: 4Gi     # 1-2. 컴퓨팅 리소스 제한
    pods: 2                # 2. 객체 수 제한 (몇 개나 되는가)
    secrets: 5           # (심지어 시크릿 개수도 제한 가능)
  • 개수 제한: 메모리뿐만 아니라 생성 가능한 파드의 개수 자체도 제한할 수 있다.
1. Pod 생성 → 2. ResourceQuota 생성 → 3. Pod 생성
  • 실무 팁 (예외 상황): 리소스 쿼터를 만들기 전에 이미 존재하는 파드들은 쿼터 규칙의 적용을 받지 않고 그대로 살아남는다.
    1. Resource가 명시되어 있지 않는 Pod가 있는 상태이다
    2. ResourceQuota를 만든다.
    3. 기존 Pod는 ResourceQuota 규칙과 상관이 없다. 벗어난다.
      • 이 경우 쿼터에 명시된 한계보다 더 많은 자원을 쓰는 상태가 발생할 수 있으므로, 쿼터 설정 전에는 네임스페이스를 비워두는 것이 정석이다.

 

 

 

 

3. LimitRange: 개별 파드의 제약 조건

네임스페이스에 들어올 수 있는 개별 파드의 자원 크기를 체크하고 제어한다.

apiVersion: v1
kind: LimitRange
metadata:
  name: lr-1
  namespace: nm-5
spec:
  limits:
  - type: Container
    min:
      memory: 0.1Gi
    max:
      memory: 0.4Gi
    maxLimitRequestRatio:
      memory: 3
    defaultRequest:
      memory: 0.1Gi
    default:
      memory: 0.2Gi
  • 최소/최대(min/max) 제한: 컨테이너가 가질 수 있는 자원의 최소값과 최대값을 강제한다. 최대값(max)을 초과하거나 비율(maxLimitRequestRatio)을 어긴 파드는 생성이 금지된다.
  • 기본값(Default) 할당: 파드 정의서에 리소스 설정을 누락했을 때 자동으로 적용될 defaultRequest와 default(Limit) 값을 지정할 수 있다.
apiVersion: v1
kind: Namespace
metadata:
  name: nm-6
-----
apiVersion: v1
kind: LimitRange
metadata:
  name: lr-5
  namespace: nm-6
spec:
  limits:
  - type: Container
    min:
      memory: 0.1Gi
    max:
      memory: 0.5Gi
    maxLimitRequestRatio:
      memory: 1
    defaultRequest:
      memory: 0.5Gi
    default:
      memory: 0.5Gi
----
apiVersion: v1
kind: LimitRange
metadata:
  name: lr-3
  namespace: nm-6
spec:
  limits:
  - type: Container
    min:
      memory: 0.1Gi
    max:
      memory: 0.3Gi
    maxLimitRequestRatio:
      memory: 1
    defaultRequest:
      memory: 0.3Gi
    default:
      memory: 0.3Gi
  • 중복 설정의 위험 (주의): 위와 같이 한 네임스페이스(nm-6)에 여러 개의 리미트 레인지(lr-5, lr-3)를 적용할 수 있다. 이 경우 쿠버네티스는 가장 엄격한 기준(더 작은 max 값 등)을 적용한다. 이는 예상치 못한 생성 에러를 유발할 수 있으므로 관리가 매우 까다롭다.
    • 예를 들면, 위의 상황에서 0.5Gi를 적용하려고 할때, 0.5Gi가 설정된 lr-5가 있어도 lr-3에 있는 0.3Gi가 더 엄격하기 때문에 lr-3이 적용된 것이다.

 

 

 

💡 꼬리 질문

Q: 리소스 쿼터가 적용된 네임스페이스에 파드를 배포할 때, 왜 리미트 레인지를 함께 설정하는 것이 운영상 더 효율적일까?

 

결론: 사용자 경험을 개선하고 배포 실패율을 낮추기 위해서다.

  • 리소스 쿼터만 단독으로 있으면 모든 사용자가 일일이 자원 스펙을 기입해야 하고, 누락 시 배포가 실패한다.
  • 하지만 리미트 레인지의 default 설정을 함께 두면, 자원 정보를 깜빡하고 넣지 않은 파드에도 자동으로 적절한 자원량이 주입된다.
  • 결과적으로 리소스 쿼터의 '자원 명시 필수' 제약을 자동으로 통과하게 만들어주므로, 운영 자동화 측면에서 훨씬 유리하다.

 

위 학습용 정리 내용 및 사진 자료는 "인프런_대세는 쿠버네티스(https://inf.run/Lv5RV)" 강의를 소스로 작성하였습니다.