Post

Part 7/26: Namespace와 ResourceQuota

Part 7/26: Namespace와 ResourceQuota

1. Namespace 개념

1.1 Namespace란?

원문 (kubernetes.io - Namespaces): Namespaces provide a mechanism for isolating groups of resources within a single cluster. Names of resources need to be unique within a namespace, but not across namespaces.

번역: Namespace는 단일 클러스터 내에서 리소스 그룹을 격리하는 메커니즘을 제공한다. 리소스 이름은 namespace 내에서 고유해야 하지만 namespace 간에는 고유할 필요가 없다.

즉, 하나의 물리적 클러스터를 여러 개의 가상 클러스터처럼 사용할 수 있다.

flowchart TB
    subgraph cluster["Kubernetes Cluster"]
        subgraph dev["Namespace: development"]
            dev_web["Pod: web"]
            dev_api["Pod: api"]
            dev_svc["Svc: web"]
        end
        subgraph prod["Namespace: production"]
            prod_web["Pod: web"]
            prod_api["Pod: api"]
            prod_svc["Svc: web"]
        end
        subgraph sys["Namespace: kube-system"]
            sys_comp["시스템 컴포넌트"]
        end
    end

    note["같은 이름의 리소스가<br/>다른 Namespace에 존재 가능"]

Namespace의 역할:

  • 리소스 이름 충돌 방지 (같은 이름을 다른 Namespace에서 사용 가능)
  • 팀/프로젝트별 리소스 격리
  • RBAC을 통한 접근 제어
  • ResourceQuota를 통한 리소스 할당

1.2 기본 Namespace

클러스터 생성 시 자동으로 생성되는 Namespace:

Namespace용도
default별도 지정 없이 생성한 리소스가 들어가는 기본 Namespace
kube-systemKubernetes 시스템 컴포넌트 (API Server, Scheduler, CoreDNS 등)
kube-public모든 사용자가 읽을 수 있는 리소스 (인증 없이도 접근 가능)
kube-node-lease노드 하트비트를 위한 Lease 객체 저장
1
2
3
4
5
6
7
# Namespace 목록 확인
kubectl get namespaces
kubectl get ns

# 특정 Namespace의 리소스 조회
kubectl get pods -n kube-system
kubectl get all -n kube-system

1.3 Namespaced vs Cluster-scoped 리소스

원문 (kubernetes.io - Namespaces): Not all objects are in a namespace. Namespace-scoped resources, like Pods and Services, are in a namespace. Cluster-scoped resources, like nodes and persistentVolumes, are not in a namespace.

번역: 모든 객체가 namespace에 있는 것은 아니다. Pod 및 Service와 같은 namespace 범위 리소스는 namespace에 있다. 노드 및 persistentVolume과 같은 클러스터 범위 리소스는 namespace에 없다.

역할/설명:

Namespaced 리소스 (Namespace에 속함):

  • Pod, Service, Deployment, ReplicaSet
  • ConfigMap, Secret
  • PersistentVolumeClaim
  • Role, RoleBinding

Cluster-scoped 리소스 (Namespace와 무관):

  • Node
  • PersistentVolume
  • Namespace 자체
  • ClusterRole, ClusterRoleBinding
  • StorageClass
1
2
3
4
5
# Namespaced 리소스 목록
kubectl api-resources --namespaced=true

# Cluster-scoped 리소스 목록
kubectl api-resources --namespaced=false

2. Namespace 관리

2.1 Namespace 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
# 명령형
kubectl create namespace production

# YAML로 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    env: production
    team: platform
EOF

2.2 기본 Namespace 변경

1
2
3
4
5
6
7
8
# 현재 컨텍스트의 기본 Namespace 변경
kubectl config set-context --current --namespace=production

# 확인
kubectl config view --minify | grep namespace

# 이후 명령에서 -n 옵션 불필요
kubectl get pods  # production 네임스페이스의 Pod 조회

2.3 Namespace 삭제

1
2
3
4
# Namespace 삭제 (내부 모든 리소스도 삭제됨)
kubectl delete namespace production

# 주의: kube-system, kube-public 등 시스템 Namespace는 삭제하지 않는다

주의사항:

  • Namespace 삭제 시 내부 모든 리소스가 함께 삭제된다
  • 삭제 중인 Namespace는 Terminating 상태가 된다
  • Finalizer가 있는 리소스가 있으면 삭제가 지연될 수 있다

3. ResourceQuota

3.1 ResourceQuota란?

원문 (kubernetes.io - Resource Quotas): A resource quota provides constraints that limit aggregate resource consumption per namespace. It can limit the quantity of objects that can be created in a namespace by type, as well as the total amount of compute resources.

번역: Resource quota는 namespace별 총 리소스 소비를 제한하는 제약 조건을 제공한다. namespace에서 유형별로 생성할 수 있는 객체 수와 총 컴퓨팅 리소스 양을 제한할 수 있다.

flowchart TB
    subgraph ns["Namespace: production"]
        subgraph quota["ResourceQuota (제한)"]
            q1["CPU 요청 합계: 최대 10 cores"]
            q2["Memory 요청 합계: 최대 20Gi"]
            q3["Pod 개수: 최대 100개"]
        end
        subgraph usage["현재 사용량"]
            u1["CPU 요청: 5 cores"]
            u2["Memory 요청: 12Gi"]
            u3["Pod 개수: 42개"]
        end
        note["⚠️ 초과하는 리소스 생성 시 거부됨"]
    end

3.2 ResourceQuota 종류

컴퓨팅 리소스:

항목설명
requests.cpuCPU 요청 합계
requests.memoryMemory 요청 합계
limits.cpuCPU 제한 합계
limits.memoryMemory 제한 합계

스토리지 리소스:

항목설명
requests.storagePVC 스토리지 요청 합계
persistentvolumeclaimsPVC 개수
<storageclass>.storageclass.storage.k8s.io/requests.storage특정 StorageClass의 스토리지 합계

오브젝트 수:

항목설명
podsPod 개수
configmapsConfigMap 개수
secretsSecret 개수
servicesService 개수
services.loadbalancersLoadBalancer 타입 Service 개수
services.nodeportsNodePort 타입 Service 개수

3.3 ResourceQuota 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: production
spec:
  hard:
    # 컴퓨팅 리소스
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi

    # 오브젝트 수
    pods: "100"
    services: "10"
    services.loadbalancers: "2"
    services.nodeports: "5"
    configmaps: "20"
    secrets: "20"
    persistentvolumeclaims: "10"

    # 스토리지
    requests.storage: 100Gi

3.4 ResourceQuota 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Quota 확인
kubectl get resourcequota -n production
kubectl describe resourcequota compute-quota -n production

# 출력 예시:
# Name:                   compute-quota
# Namespace:              production
# Resource                Used   Hard
# --------                ----   ----
# limits.cpu              4      20
# limits.memory           8Gi    40Gi
# pods                    42     100
# requests.cpu            2      10
# requests.memory         4Gi    20Gi

3.5 Quota가 있을 때 주의사항

ResourceQuota가 있으면 Pod에 반드시 requests/limits 설정 필요:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ResourceQuota가 있는 Namespace에서는 이 Pod이 거부됨
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    # resources 미설정 → 거부됨

---
# 올바른 설정
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 200m
        memory: 256Mi

이를 자동화하려면 LimitRange를 사용한다.


4. LimitRange

4.1 LimitRange란?

원문 (kubernetes.io - Limit Ranges): A LimitRange is a policy to constrain resource allocations (to Pods or Containers) in a namespace. A LimitRange provides constraints that can: Enforce minimum and maximum compute resources usage per Pod or Container in a namespace; Enforce minimum and maximum storage request per PersistentVolumeClaim; Enforce a ratio between request and limit for a resource; Set default request/limit for compute resources and automatically inject them to Containers at runtime.

번역: LimitRange는 namespace에서 리소스 할당(Pod 또는 Container에)을 제한하는 정책이다. LimitRange는 다음과 같은 제약 조건을 제공할 수 있다: namespace의 Pod 또는 Container별 최소 및 최대 컴퓨팅 리소스 사용량 강제; PersistentVolumeClaim별 최소 및 최대 스토리지 요청 강제; 리소스에 대한 요청과 제한 간의 비율 강제; 컴퓨팅 리소스에 대한 기본 요청/제한을 설정하고 런타임에 Container에 자동으로 주입.

역할/설명:

LimitRange는 개별 Pod/Container의 리소스 제한을 설정한다.

구분ResourceQuotaLimitRange
대상Namespace 전체개별 Pod/Container
역할총량 제한기본값/최소/최대 설정
1
2
3
4
5
6
7
8
9
10
┌─────────────────────────────────────────────────────────────┐
│   LimitRange:                                                │
│   - Container 최대 CPU: 2 cores                             │
│   - Container 최소 Memory: 64Mi                             │
│   - Container 기본 CPU: 200m (설정 안 하면 자동 적용)        │
│                                                             │
│   Pod 생성 시:                                              │
│   - 최소/최대 검증                                           │
│   - 기본값 자동 주입                                         │
└─────────────────────────────────────────────────────────────┘

4.2 LimitRange 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
apiVersion: v1
kind: LimitRange
metadata:
  name: resource-limits
  namespace: production
spec:
  limits:
  # Container 레벨 제한
  - type: Container
    default:          # 기본 limits (설정 안 하면 적용)
      cpu: 500m
      memory: 512Mi
    defaultRequest:   # 기본 requests (설정 안 하면 적용)
      cpu: 100m
      memory: 128Mi
    max:              # 최대값
      cpu: 2
      memory: 2Gi
    min:              # 최소값
      cpu: 50m
      memory: 64Mi

  # Pod 레벨 제한
  - type: Pod
    max:
      cpu: 4
      memory: 4Gi

  # PVC 레벨 제한
  - type: PersistentVolumeClaim
    max:
      storage: 10Gi
    min:
      storage: 1Gi

4.3 LimitRange 동작

1. 기본값 자동 주입:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# LimitRange가 있을 때, resources 미설정 시:
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: nginx
    image: nginx
    # resources 미설정

# → 자동으로 defaultRequest와 default가 적용됨:
#   resources:
#     requests:
#       cpu: 100m
#       memory: 128Mi
#     limits:
#       cpu: 500m
#       memory: 512Mi

2. 범위 검증:

1
2
3
4
5
6
7
8
9
10
11
# max를 초과하면 생성 거부:
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      limits:
        cpu: 5          # max(2)를 초과 → 거부됨
        memory: 2Gi

4.4 LimitRange 확인

1
2
kubectl get limitrange -n production
kubectl describe limitrange resource-limits -n production

5. Namespace 활용 패턴

5.1 환경별 분리

1
2
3
4
5
6
7
8
# 환경별 Namespace 생성
kubectl create namespace development
kubectl create namespace staging
kubectl create namespace production

# 환경별로 다른 ResourceQuota 적용
kubectl apply -f quota-dev.yaml -n development
kubectl apply -f quota-prod.yaml -n production

5.2 팀별 분리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 팀별 Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: team-platform
  labels:
    team: platform
---
apiVersion: v1
kind: Namespace
metadata:
  name: team-frontend
  labels:
    team: frontend

5.3 RBAC과 함께 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Namespace에 대한 Role 정의
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: development
rules:
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "create", "delete"]

---
# 사용자에게 Role 바인딩
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding
  namespace: development
subjects:
- kind: User
  name: john
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

6. Namespace 간 통신

6.1 Service DNS

같은 Namespace 내에서는 Service 이름만으로 접근 가능:

1
http://my-service

다른 Namespace의 Service에 접근:

1
2
3
http://my-service.other-namespace
http://my-service.other-namespace.svc
http://my-service.other-namespace.svc.cluster.local
1
2
3
4
5
6
7
8
9
10
11
┌─────────────────────────────────────────────────────────────┐
│  DNS 형식:                                                  │
│  <service>.<namespace>.svc.cluster.local                   │
│                                                             │
│  예시:                                                      │
│  - nginx-svc.production.svc.cluster.local                  │
│  - api-svc.staging.svc.cluster.local                       │
│                                                             │
│  같은 Namespace 내에서는 생략 가능:                          │
│  - nginx-svc                                                │
└─────────────────────────────────────────────────────────────┘

6.2 NetworkPolicy로 격리

기본적으로 Namespace 간 통신이 허용된다. NetworkPolicy로 제한할 수 있다:

1
2
3
4
5
6
7
8
9
10
11
12
13
# production Namespace에서 development로부터의 접근 차단
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-from-other-namespaces
  namespace: production
spec:
  podSelector: {}     # 모든 Pod에 적용
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {} # 같은 Namespace만 허용

7. 면접 빈출 질문

Q1. ResourceQuota와 LimitRange의 차이는?

ResourceQuota:

  • Namespace 전체의 리소스 총량 제한
  • Pod 합계, 서비스 개수 등 제한
  • 예: “이 Namespace에서 CPU 요청 합계는 10 cores까지”

LimitRange:

  • 개별 Pod/Container의 리소스 제한
  • 기본값 설정, 최소/최대 범위 설정
  • 예: “각 Container는 최대 2 cores까지”

둘은 보완적으로 사용된다. LimitRange로 개별 Pod을 제한하고, ResourceQuota로 전체 사용량을 제한한다.

Q2. Namespace를 삭제하면 어떻게 되는가?

  1. Namespace 상태가 Terminating으로 변경
  2. Namespace 내 모든 리소스가 삭제됨 (Pod, Service, ConfigMap, Secret 등)
  3. Finalizer가 있는 리소스가 있으면 삭제가 지연됨
  4. 모든 리소스 삭제 후 Namespace 완전 삭제

복구 불가능하므로 주의해야 한다.

Q3. 다른 Namespace의 Service에 어떻게 접근하는가?

FQDN(Fully Qualified Domain Name)을 사용한다:

1
<service-name>.<namespace>.svc.cluster.local

예: nginx-svc.production.svc.cluster.local

.svc.cluster.local은 생략 가능하여 nginx-svc.production으로도 접근 가능하다.

Q4. ResourceQuota가 있는 Namespace에서 Pod 생성이 실패하는 이유는?

ResourceQuota가 컴퓨팅 리소스(CPU, Memory)를 제한하고 있으면, 모든 Pod에 requests/limits 설정이 필수다.

해결 방법:

  1. Pod에 직접 resources.requestsresources.limits 설정
  2. LimitRange를 만들어 기본값 자동 적용

8. CKA 실습

8.1 Namespace 생성 및 컨텍스트 설정

1
2
3
4
5
6
7
8
# Namespace 생성
kubectl create namespace production

# 기본 Namespace 설정
kubectl config set-context --current --namespace=production

# 확인
kubectl config view --minify | grep namespace

8.2 ResourceQuota 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
# quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: production
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 4Gi
    limits.cpu: "8"
    limits.memory: 8Gi
    pods: "10"
1
2
3
4
kubectl apply -f quota.yaml

# 확인
kubectl describe resourcequota compute-quota -n production

8.3 LimitRange 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: production
spec:
  limits:
  - type: Container
    default:
      cpu: 500m
      memory: 256Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    max:
      cpu: 2
      memory: 2Gi
    min:
      cpu: 50m
      memory: 64Mi
1
2
3
4
kubectl apply -f limitrange.yaml

# 확인
kubectl describe limitrange default-limits -n production

8.4 테스트

1
2
3
4
5
# resources 없이 Pod 생성 시도
kubectl run nginx --image=nginx -n production

# Pod의 자동 설정된 resources 확인
kubectl get pod nginx -n production -o yaml | grep -A 10 resources

정리

주요 개념 체크리스트

  • Namespace의 역할과 기본 Namespace
  • Namespaced vs Cluster-scoped 리소스
  • ResourceQuota로 Namespace 리소스 총량 제한
  • LimitRange로 개별 Pod/Container 제한 및 기본값 설정
  • Namespace 간 Service 통신 (DNS)
  • RBAC과 NetworkPolicy를 통한 격리

다음 포스트

Part 8: ReplicaSet과 Deployment에서는 무중단 배포 전략을 다룬다.


참고 자료

This post is licensed under CC BY 4.0 by the author.