Post

Part 7/26: Namespace와 ResourceQuota

Part 7/26: Namespace와 ResourceQuota

1. Namespace 개념

1.1 Namespace란?

Namespace는 Kubernetes 클러스터 내에서 리소스를 논리적으로 분리하는 방법이다. 하나의 물리적 클러스터를 여러 개의 가상 클러스터처럼 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────────────────────┐
│                    Kubernetes Cluster                        │
│  ┌─────────────────┐  ┌─────────────────┐                   │
│  │   Namespace:    │  │   Namespace:    │                   │
│  │   development   │  │   production    │                   │
│  │  ┌───────────┐  │  │  ┌───────────┐  │                   │
│  │  │ Pod: web  │  │  │  │ Pod: web  │  │  (같은 이름 가능) │
│  │  │ Pod: api  │  │  │  │ Pod: api  │  │                   │
│  │  │ Svc: web  │  │  │  │ Svc: web  │  │                   │
│  │  └───────────┘  │  │  └───────────┘  │                   │
│  └─────────────────┘  └─────────────────┘                   │
│  ┌─────────────────┐                                        │
│  │   Namespace:    │                                        │
│  │   kube-system   │                                        │
│  │  (시스템 컴포넌트)│                                        │
│  └─────────────────┘                                        │
└─────────────────────────────────────────────────────────────┘

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 리소스

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란?

ResourceQuota는 Namespace 전체에서 사용할 수 있는 리소스의 총량을 제한한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────────────────────────────────────────────────────┐
│   Namespace: production                                      │
│   ResourceQuota:                                            │
│   - CPU 요청 합계: 최대 10 cores                            │
│   - Memory 요청 합계: 최대 20Gi                             │
│   - Pod 개수: 최대 100개                                    │
│                                                             │
│   현재 사용량:                                              │
│   - CPU 요청: 5 cores                                       │
│   - Memory 요청: 12Gi                                       │
│   - Pod 개수: 42개                                          │
│                                                             │
│   → 초과하는 리소스 생성 시 거부됨                          │
└─────────────────────────────────────────────────────────────┘

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란?

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.