infra
Platform

모듈 맵

[Kubernetes] Namespace를 활용한 여러 개발팀 간 리소스 분할 운영

0 / 29 완료

펼치기
0 / 29 완료0%

쿠버네티스 & GitOps · 10 / 29

[Kubernetes] Namespace를 활용한 여러 개발팀 간 리소스 분할 운영

Namespace로 개발·스테이징·운영을 격리하고 ResourceQuota와 LimitRange로 자원 사용을 제어합니다

🚨INCIDENT ALERT
HIGH

개발팀이 테스트 리소스를 정리하려다 운영 리소스까지 같은 클러스터에서 건드릴 뻔했습니다. 여러 팀과 환경이 한 클러스터를 공유하면 논리적 경계가 없을 때 작은 명령 하나가 큰 장애가 됩니다. Namespace는 권한, 비용, 리소스를 나누는 첫 번째 안전 울타리입니다.

Namespace — 환경 분리와 자원 제한

단일 Kubernetes 클러스터에 개발팀, 스테이징, 운영 환경을 모두 올리고 싶지만 서로 영향을 주면 안 됩니다. 개발팀이 실수로 배포한 리소스가 운영 파드와 자원을 경쟁하거나, 개발팀의 kubectl delete all이 운영 리소스를 날리는 사고가 실제로 발생합니다. 클러스터를 환경마다 따로 구축하면 비용과 관리 부담이 급증합니다. Namespace는 하나의 클러스터 안에서 논리적 구획을 만들어 이 문제를 해결합니다. RBAC으로 팀별 접근 권한을 제어하고, ResourceQuota로 Namespace별 자원 상한을 설정하면, 개발팀이 운영 Namespace에 접근하지 못하고 리소스를 독점하지도 못합니다. 대부분의 운영 조직이 이 방식으로 멀티팀 클러스터를 운영합니다.


이번 챕터에서 배울 것

Namespace로 팀과 환경을 논리적으로 분리하고, 자원 제한으로 안정적인 멀티팀 클러스터를 운영하는 방법을 실습합니다.

  • 1Namespace 개념과 기본 제공 Namespace를 설명할 수 있다
  • 2개발·스테이징·운영 환경을 Namespace로 분리할 수 있다
  • 3ResourceQuota로 Namespace 전체 자원 상한을 설정할 수 있다
  • 4LimitRange로 컨테이너별 기본값과 최댓값을 설정할 수 있다
  • 5DNS 네이밍 규칙으로 다른 Namespace 리소스에 접근할 수 있다
  • 6다른 Namespace 리소스 접근 실패를 진단할 수 있다
실습 환경 준비

kubectl 기본 사용법(kubectl-basics)을 익혔다면 바로 시작할 수 있습니다. 별도 환경 설치 없이 기존 클러스터에서 진행합니다.

클러스터 접근 확인
kubectl cluster-info
현재 Namespace 목록 확인
kubectl get namespaces
현재 컨텍스트 확인
kubectl config current-context
현재 기본 Namespace 확인
kubectl config view --minify | grep namespace
💡개념

Namespace — 클러스터 안의 클러스터

하나의 클러스터에서 여러 팀이 작업하다 보면 개발 환경의 리소스가 운영 환경 파드와 같은 네임스페이스에 뒤섞입니다. kubectl delete all을 개발 환경 정리용으로 실행했는데 운영 파드까지 삭제되는 사고가 발생합니다. Kubernetes는 기본적으로 네임스페이스를 지정하지 않으면 모든 리소스가 default에 쌓입니다. Namespace는 하나의 클러스터 안에서 논리적 구획을 만들어 팀과 환경을 분리하고, RBAC으로 각 구획의 접근 권한을 제어합니다. 이 CB에서는 Kubernetes 기본 제공 Namespace의 역할과, 사용자 정의 Namespace 생성 및 관리 방법을 다룹니다.

Namespace — 클러스터 안의 클러스터확대

기본 제공 Namespace

Kubernetes
kubectl get namespaces
# NAME              STATUS   AGE
# default           Active   30d   ← namespace 미지정 시 사용되는 기본 공간
# kube-system       Active   30d   ← Kubernetes 시스템 컴포넌트 (CoreDNS, kube-proxy 등)
# kube-public       Active   30d   ← 인증 없이 읽기 가능 (클러스터 정보 공개용)
# kube-node-lease   Active   30d   ← 노드 heartbeat용 Lease 오브젝트 저장
🔍실행 후 확인할 것
  • kubectl get namespaces에서 STATUS 열 먼저 확인 — Active이면 정상, Terminating이면 삭제 중으로 finalizer가 남아 있는 것. kubectl get all -n <ns>로 남은 리소스 확인 후 강제 finalizer 제거 필요
  • kubectl get pods -n <namespace>로 각 네임스페이스의 리소스를 분리 조회 — 네임스페이스를 지정하지 않으면 현재 context의 기본 네임스페이스(default) 리소스만 나옴
  • Terminating 상태가 5분 이상 지속되면 → finalizer 때문. kubectl get namespace <ns> -o json | grep finalizers로 남은 finalizer 목록 확인 후 해당 리소스(PVC, 파드 등)를 먼저 삭제

kube-system은 절대 건드리지 않는 것이 원칙입니다. CoreDNS나 kube-proxy 같은 핵심 컴포넌트가 여기 있습니다.

Namespace 생성

Kubernetes
# 명령어로 생성
kubectl create namespace development
kubectl create namespace staging
kubectl create namespace production

# YAML로 생성 (팀 정보, 환경 정보를 label로 관리)
YAML
# namespaces.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: development
  labels:
    environment: dev
    team: backend
---
apiVersion: v1
kind: Namespace
metadata:
  name: staging
  labels:
    environment: staging
    team: backend
---
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    environment: prod
    team: backend
Kubernetes
kubectl apply -f namespaces.yaml

kubectl get namespaces --show-labels
# NAME          STATUS   LABELS
# development   Active   environment=dev,team=backend
# staging       Active   environment=staging,team=backend
# production    Active   environment=prod,team=backend

Namespace 범위 오브젝트 vs 클러스터 범위 오브젝트

Namespace 범위 (격리됨)클러스터 범위 (공유)
Pod, Deployment, ServiceNode, PersistentVolume
ConfigMap, SecretStorageClass
PersistentVolumeClaimClusterRole, ClusterRoleBinding
ServiceAccountNamespace 자체
Kubernetes
# 어떤 리소스가 Namespace 범위인지 확인
kubectl api-resources --namespaced=true | head -10
kubectl api-resources --namespaced=false | head -10

💡개념

환경 분리 실습 — 개발·스테이징·운영

같은 이름의 Deployment를 개발 환경과 운영 환경에 따로 운영해야 하는데 단일 클러스터라면 이름이 충돌합니다. 개발팀이 실수로 운영 Deployment를 롤백하거나, 스테이징 테스트가 운영 서비스에 영향을 주는 사고가 발생합니다. 환경마다 별도 클러스터를 쓰면 비용과 관리 부담이 세 배가 됩니다. Namespace를 환경별로 분리하면 같은 이름의 리소스를 독립적으로 관리하고, RBAC으로 각 환경의 접근 권한을 팀별로 제한할 수 있습니다. 이 CB에서는 development, staging, production 세 환경을 Namespace로 분리하고 같은 앱을 각각 독립적으로 배포하는 실습을 다룹니다.

동일 앱을 다른 Namespace에 각각 배포

YAML
# dev-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: development           # 개발 환경
spec:
  replicas: 1                      # 개발: 1개 레플리카
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: app
          image: hashicorp/http-echo
          args: ["-text=Hello from DEVELOPMENT"]
          ports:
            - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
  namespace: development
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 5678
YAML
# prod-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production            # 운영 환경 — 같은 이름이지만 다른 Namespace
spec:
  replicas: 3                      # 운영: 3개 레플리카
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: app
          image: hashicorp/http-echo
          args: ["-text=Hello from PRODUCTION"]
          ports:
            - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
  namespace: production
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 5678
Kubernetes
kubectl apply -f dev-deployment.yaml
kubectl apply -f prod-deployment.yaml

# 각 Namespace에서 파드 수와 내용이 다름
kubectl get deployments -n development
# NAME     READY   UP-TO-DATE   AVAILABLE
# my-app   1/1     1            1

kubectl get deployments -n production
# NAME     READY   UP-TO-DATE   AVAILABLE
# my-app   3/3     3            3

# 전체 Namespace 조회
kubectl get pods -A | grep my-app

기본 Namespace 변경

Kubernetes
# 매번 -n 플래그 입력이 번거로울 때
kubectl config set-context --current --namespace=development

# 이후 명령어는 development Namespace가 기본
kubectl get pods              # development 파드만 표시
kubectl get pods -n production  # production 파드 확인 시 -n 명시

# 원래대로 복원
kubectl config set-context --current --namespace=default

💡개념

ResourceQuota — Namespace 전체 자원 상한

개발팀이 테스트 목적으로 수십 개의 파드를 배포하면서 클러스터 전체 CPU와 메모리를 잠식합니다. 운영 파드가 자원을 확보하지 못해 Pending 상태가 되고 배포가 지연됩니다. 팀에게 클러스터 접근 권한을 주되 전체 자원을 무제한으로 쓸 수는 없습니다. ResourceQuota는 Namespace 단위로 자원 예산을 설정하는 메커니즘입니다. Namespace 안에서 생성할 수 있는 리소스의 총합을 제한합니다. 팀별로 자원 예산을 배정하는 개념입니다.

ResourceQuota와 LimitRange — ResourceQuota는 Namespace 전체 총합 제한(requests/limits CPU·메모리, pods·services 최대 개수)이고, LimitRange는 컨테이너 단위 기본값(default·defaultRequest)·상한(max)·하한(min)을 설정. 파드 생성 시 LimitRange가 누락된 resources에 기본값을 주입한 뒤 ResourceQuota가 총량을 검사해 초과 시 403 거부확대

ResourceQuota 설정

YAML
# resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: development
spec:
  hard:
    # 컨테이너 수준 CPU/메모리 합계 제한
    requests.cpu: "4"             # 이 Namespace 전체 CPU request 합계 ≤ 4코어
    requests.memory: 8Gi          # 전체 메모리 request 합계 ≤ 8Gi
    limits.cpu: "8"               # 전체 CPU limit 합계 ≤ 8코어
    limits.memory: 16Gi           # 전체 메모리 limit 합계 ≤ 16Gi

    # 오브젝트 수 제한
    pods: "20"                    # 최대 파드 수
    services: "10"                # 최대 서비스 수
    persistentvolumeclaims: "5"   # 최대 PVC 수
    secrets: "20"                 # 최대 Secret 수
    configmaps: "20"              # 최대 ConfigMap 수
Kubernetes
kubectl apply -f resource-quota.yaml

# ResourceQuota 사용량 확인
kubectl describe resourcequota dev-quota -n development
# Name:                   dev-quota
# Namespace:              development
# Resource                Used    Hard
# --------                ----    ----
# limits.cpu              500m    8
# limits.memory           512Mi   16Gi
# pods                    2       20
# requests.cpu            250m    4
# requests.memory         256Mi   8Gi

ResourceQuota가 있으면 requests/limits 필수

ResourceQuota에 CPU/메모리 제한이 있는 Namespace에서는, 파드의 모든 컨테이너가 resources.requestsresources.limits를 명시해야 합니다. 없으면 파드 생성이 거부됩니다.

Kubernetes
# ResourceQuota가 있는 Namespace에서 resources 없이 파드 생성 시
kubectl run test-pod --image=nginx -n development
# Error from server (Forbidden): pods "test-pod" is forbidden:
# failed quota: dev-quota: must specify limits.cpu for: test-pod
YAML
# resources를 명시한 올바른 파드
spec:
  containers:
    - name: app
      image: nginx
      resources:
        requests:
          cpu: "100m"       # 0.1 CPU 코어
          memory: "128Mi"
        limits:
          cpu: "500m"       # 0.5 CPU 코어
          memory: "256Mi"

💡개념

LimitRange — 컨테이너별 기본값과 최댓값 설정

ResourceQuota를 설정했는데 resources 필드 없이 파드를 배포하면 CPU와 메모리 요청이 0으로 처리되어 Quota 검사가 제대로 동작하지 않습니다. 반대로 모든 파드에 일일이 requestslimits를 작성하도록 강제하면 개발자 부담이 늘고 누락 사고가 생깁니다. LimitRange는 이 문제를 해결합니다. 개별 파드/컨테이너 수준에서 기본값과 상한·하한을 설정하여, resources를 명시하지 않은 파드에 자동으로 적절한 값을 주입합니다. 이 CB에서는 LimitRange 설정과 ResourceQuota와의 적용 순서를 다룹니다. resources 필드를 명시하지 않은 파드에 자동으로 기본값을 적용합니다.

LimitRange 설정

YAML
# limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: dev-limits
  namespace: development
spec:
  limits:
    - type: Container
      default:               # resources 미설정 시 자동 적용되는 limits 기본값
        cpu: "500m"
        memory: "256Mi"
      defaultRequest:        # requests 기본값
        cpu: "100m"
        memory: "128Mi"
      max:                   # 컨테이너 하나의 최대 한도
        cpu: "2"
        memory: "1Gi"
      min:                   # 컨테이너 하나의 최소 한도
        cpu: "50m"
        memory: "64Mi"

    - type: Pod
      max:                   # 파드 전체(컨테이너 합산) 최대 한도
        cpu: "4"
        memory: "2Gi"

    - type: PersistentVolumeClaim
      max:
        storage: "50Gi"      # PVC 최대 용량
      min:
        storage: "1Gi"       # PVC 최소 용량
Kubernetes
kubectl apply -f limit-range.yaml

# LimitRange 확인
kubectl describe limitrange dev-limits -n development
# Name:       dev-limits
# Namespace:  development
# Type        Resource  Min    Max    Default Request  Default Limit
# ----        --------  ---    ---    ---------------  -------------
# Container   cpu       50m    2      100m             500m
# Container   memory    64Mi   1Gi    128Mi            256Mi

# resources를 명시하지 않은 파드가 LimitRange 기본값을 받는지 확인
kubectl run no-limits-pod --image=nginx -n development
kubectl get pod no-limits-pod -n development -o jsonpath='{.spec.containers[0].resources}' | jq
# {
#   "limits": {"cpu": "500m", "memory": "256Mi"},     ← LimitRange 기본값 자동 적용
#   "requests": {"cpu": "100m", "memory": "128Mi"}
# }

ResourceQuota vs LimitRange 적용 순서

LimitRange와 ResourceQuota — 파드 생성 요청 시 LimitRange가 resources 없는 컨테이너에 기본값 주입→ResourceQuota가 Namespace 총 사용량+새 파드 ≤ Hard 한도 검사→YES 허용·NO 거부(403)확대


문제 상황

Kubernetes
# frontend 파드(development Namespace)에서 api-service에 접근 시도
kubectl exec -it frontend-pod -n development -- \
  curl http://api-service/users

# curl: (6) Could not resolve host: api-service
# 또는
# curl: (7) Failed to connect to api-service port 80: Connection refused

api-service는 실제로 존재하고 Running 상태인데 접근이 안 됩니다.

진단: 서비스가 어느 Namespace에 있는지 확인

Kubernetes
# 모든 Namespace에서 api-service 찾기
kubectl get service -A | grep api-service
# NAMESPACE    NAME          TYPE        CLUSTER-IP     PORT(S)
# production   api-service   ClusterIP   10.96.45.100   80/TCP
#              ↑ production Namespace에 있음!

원인 분석

같은 Namespace에서는 서비스 이름만으로 접근 가능합니다. 다른 Namespace의 서비스에는 Namespace가 포함된 DNS 이름을 사용해야 합니다.

클러스터 내부 DNS 해석 순서:
1. <service-name>         → <service-name>.<현재-namespace>.svc.cluster.local
2. <service-name>.<ns>   → <service-name>.<ns>.svc.cluster.local
3. FQDN                  → <service-name>.<ns>.svc.cluster.local (직접 지정)

"api-service"로 조회 → development.svc.cluster.local에서 찾음 → 없음 → 실패!

해결: Namespace 포함한 DNS 이름 사용

Kubernetes
# 방법 1: <service>.<namespace> 형식 (자주 쓰는 축약형)
kubectl exec -it frontend-pod -n development -- \
  curl http://api-service.production

# 방법 2: 전체 FQDN
kubectl exec -it frontend-pod -n development -- \
  curl http://api-service.production.svc.cluster.local

# 정상 응답 확인
# {"users": [...]}

코드/환경변수에서 수정

YAML
# 파드의 환경변수에서 서비스 URL을 FQDN으로 설정
env:
  - name: API_URL
    value: "http://api-service.production.svc.cluster.local"
    # value: "http://api-service"  ← 같은 Namespace에서만 동작

DNS 동작 확인 도구

Kubernetes
# 특정 서비스 DNS 해석 테스트
kubectl run dns-debug --image=busybox -it --rm --restart=Never \
  -n development -- nslookup api-service.production
# Server:    10.96.0.10
# Name:      api-service.production.svc.cluster.local
# Address 1: 10.96.45.100

# 현재 파드의 resolv.conf 확인 (어떤 search domain이 설정되어 있는지)
kubectl exec -it frontend-pod -n development -- cat /etc/resolv.conf
# nameserver 10.96.0.10
# search development.svc.cluster.local svc.cluster.local cluster.local
#        ↑ 현재 namespace가 첫 번째 search domain

심화 — 네임스페이스 삭제는 왜 멈추는가

💡개념

심화: Namespace 삭제의 실제 — finalizer와 네임스페이스 컨트롤러 reconcile

kubectl delete namespace는 리소스를 곧바로 지우는 명령처럼 보이지만, 실제로는 "삭제해도 좋다"는 표시만 남기는 요청입니다. 네임스페이스가 Terminating에서 오래 멈추는 사고를 이해하려면, 삭제가 어떤 컨트롤 루프를 거치는지 알아야 합니다.

  • 삭제는 두 단계다: API 서버는 네임스페이스에 deletionTimestamp를 찍고 kubernetes finalizer를 남깁니다. finalizer가 붙어 있는 한 오브젝트는 실제로 사라지지 않습니다.
  • 네임스페이스 컨트롤러가 정리한다: 컨트롤러는 이 finalizer를 붙잡고, API discovery로 "네임스페이스 범위 리소스 종류"를 전부 열거한 뒤 종류마다 남은 오브젝트를 삭제합니다. 파드·PVC·Secret이 모두 비워졌음을 확인해야 finalizer를 떼고 네임스페이스가 사라집니다.
  • discovery가 실패하면 멈춘다: 이 열거는 aggregated APIService(예: metrics.k8s.io를 제공하는 metrics-server, 커스텀 metrics 어댑터)까지 물어봅니다. 그 API가 Available=False면 컨트롤러는 아직 못 지운 종류가 남았을 수 있다고 판단해 finalizer를 떼지 않습니다. 안이 텅 비어 보여도 Terminating이 끝나지 않는 이유입니다.
  • 리소스 자체 finalizer도 흔한 원인: 특정 오브젝트에 붙은 finalizer(PVC의 pv-protection 등)가 안 떨어지면 그 리소스가 남아 네임스페이스도 못 지웁니다.

그래서 Terminating이 안 끝날 때 spec.finalizers를 강제로 비우는 것은 마지막 수단입니다 — 남은 리소스를 고아로 만들고, 진짜 원인(깨진 확장 API)을 덮어버립니다.

상황: team-a 네임스페이스를 지웠는데 STATUS가 계속 Terminating입니다. kubectl get all -n team-a, kubectl get pvc,secret -n team-a 모두 비어 있고, 다른 네임스페이스 삭제는 정상입니다.

원인: 네임스페이스 컨트롤러가 삭제를 끝내려면 "이 네임스페이스에 어떤 종류의 리소스가 있는지"를 API discovery로 다 물어봐야 합니다. 그런데 클러스터에 등록된 aggregated APIService 하나(예: v1beta1.metrics.k8s.io)가 Available=False였습니다. metrics-server가 죽어 그 API 응답이 끊기자 discovery가 실패했고, 컨트롤러는 리소스 종류 열거를 끝내지 못해 kubernetes finalizer를 떼지 못한 것입니다.

진단: 죽은 확장 API와 네임스페이스 조건을 확인합니다.

Kubernetes
kubectl get apiservice | grep -v True
# v1beta1.metrics.k8s.io   ...   False (MissingEndpoints)

kubectl get namespace team-a -o json | jq '.status.conditions'
# NamespaceDeletionDiscoveryFailure ... "Discovery failed for some groups"

status.conditions에 NamespaceDeletionDiscoveryFailure가 뜨면 discovery 문제로 확정입니다.

해결: 근본 원인인 확장 API를 고칩니다 — metrics-server를 되살리거나, 더 이상 안 쓰는 APIService면 kubectl delete apiservice v1beta1.metrics.k8s.io로 제거합니다. discovery가 다시 성공하면 컨트롤러가 스스로 삭제를 완료합니다. spec.finalizers를 직접 비우는 우회는 남은 리소스를 고아로 만들고 원인을 가리므로 마지막 수단으로만 씁니다.


💼
실무 맥락
현업 패턴

실무에서 Namespace를 어떻게 구분하는가

팀마다 다르지만 가장 많이 쓰이는 두 가지 패턴입니다.

패턴 1: 환경별 분리

production    ← 운영 환경 (인프라 팀 관리)
staging       ← 스테이징 (QA 팀 접근)
development   ← 개발 환경 (개발 팀 자유롭게 사용)

패턴 2: 팀별 분리

team-backend    ← 백엔드 팀
team-frontend   ← 프론트엔드 팀
team-data       ← 데이터 팀
infra           ← 공유 인프라 (Ingress Controller, 모니터링)

규모가 커지면 두 패턴을 조합합니다: backend-prod, backend-dev, frontend-prod 등.

RBAC으로 Namespace 접근 제어

YAML
# 개발팀에게 development Namespace만 접근 권한 부여
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-team-binding
  namespace: development         # 이 Namespace에서만 유효
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: edit                     # edit = 조회, 생성, 수정 가능 (삭제 불가)
subjects:
  - kind: Group
    name: dev-team               # OIDC 그룹 또는 ServiceAccount
    apiGroup: rbac.authorization.k8s.io

Namespace 삭제 시 주의

위험 명령어Namespace 안의 Pod, Service, PVC 등 모든 리소스가 함께 삭제될 수 있습니다.

Namespace 삭제

안전한 실행 조건: 학습용 Namespace이거나 소유 리소스를 모두 확인한 뒤 정리할 때만 실행하세요.

실행 전 반드시 확인

  • 현재 컨텍스트와 Namespace가 의도한 대상인지 확인했는가
  • 운영 트래픽이나 상태 저장 데이터에 미치는 영향을 확인했는가
  • 되돌릴 매니페스트, 백업, 또는 복구 절차가 준비되어 있는가
kubectl delete namespace development

위 항목을 모두 확인한 후 복사할 수 있습니다

Kubernetes
# Namespace 삭제는 그 안의 모든 리소스를 삭제함
kubectl delete namespace development

# 삭제 전 반드시 내부 리소스 확인
kubectl get all -n development
kubectl get pvc -n development     # PVC는 데이터 포함

# Namespace가 Terminating 상태에 멈추는 경우 (finalizer 문제)
kubectl get namespace development -o json | jq '.spec.finalizers'
# 비어 있어야 정상 삭제됨

공유 서비스를 위한 Namespace 패턴

monitoring     ← Prometheus, Grafana (전체 팀이 읽기 접근)
ingress-nginx  ← Ingress Controller (인프라 팀 관리)
cert-manager   ← 인증서 자동화
logging        ← Loki, ELK (전체 로그 집중)

이런 공유 Namespace는 ClusterRole로 특정 팀에 읽기 권한만 부여하고, 수정은 인프라 팀만 가능하게 제한합니다.


정리

위험 명령어Namespace 안의 Pod, Service, PVC 등 모든 리소스가 함께 삭제될 수 있습니다.

Namespace 삭제

안전한 실행 조건: 학습용 Namespace이거나 소유 리소스를 모두 확인한 뒤 정리할 때만 실행하세요.

실행 전 반드시 확인

  • 현재 컨텍스트와 Namespace가 의도한 대상인지 확인했는가
  • 운영 트래픽이나 상태 저장 데이터에 미치는 영향을 확인했는가
  • 되돌릴 매니페스트, 백업, 또는 복구 절차가 준비되어 있는가
kubectl delete namespace <name> # 안의 모든 리소스도 삭제됨!

위 항목을 모두 확인한 후 복사할 수 있습니다

Kubernetes
# Namespace 관련 주요 명령어

# Namespace 목록
kubectl get namespaces
kubectl get ns               # 축약형

# Namespace 생성/삭제
kubectl create namespace <name>
kubectl delete namespace <name>   # 안의 모든 리소스도 삭제됨!

# 특정 Namespace에서 명령어 실행
kubectl get pods -n <namespace>
kubectl get all -n <namespace>

# 모든 Namespace에서 조회
kubectl get pods -A
kubectl get pods --all-namespaces

# 기본 Namespace 변경 (매번 -n 생략하려면)
kubectl config set-context --current --namespace=<namespace>

# ResourceQuota 확인
kubectl describe resourcequota -n <namespace>

# LimitRange 확인
kubectl describe limitrange -n <namespace>

# 다른 Namespace 서비스 접근 (DNS)
# http://<service-name>.<namespace>.svc.cluster.local
실습 단계
1

네임스페이스 생성 및 확인

kubectl create namespace development kubectl create namespace staging kubectl create namespace production kubectl get namespaces | grep -E 'development|staging|production'

예상 출력

development   Active   5s
production    Active   5s
staging       Active   5s
2

ResourceQuota 적용

kubectl apply -f - <<'EOF' apiVersion: v1 kind: ResourceQuota metadata: name: dev-quota namespace: development spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi pods: "5" EOF

예상 출력

resourcequota/dev-quota created
3

쿼터 현황 확인

kubectl describe resourcequota dev-quota -n development

예상 출력

Name:            dev-quota
Namespace:       development
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     2
limits.memory    0     2Gi
pods             0     5
requests.cpu     0     1
requests.memory  0     1Gi
4

다른 네임스페이스 서비스 DNS 이름 확인

kubectl run dns-test --image=busybox:1.36 -it --rm --restart=Never -n development -- nslookup kubernetes.default.svc.cluster.local

예상 출력

Server:    10.96.0.10
Name:      kubernetes.default.svc.cluster.local
Address 1: 10.96.0.1
5

실습 리소스 정리

kubectl delete namespace development staging production

예상 출력

namespace "development" deleted
namespace "staging" deleted
namespace "production" deleted

명령어·단축키 빠른 참조

이 모듈에서 다룬 네임스페이스 조회·자원 제한·크로스 네임스페이스 DNS·삭제 진단 명령을 실전 옵션과 함께 모았습니다.

명령어/단축키용도자주 쓰는 예
kubectl get ns네임스페이스 목록·STATUS 확인kubectl get ns --show-labels(env/team 레이블)
kubectl create/delete namespace네임스페이스 생성·삭제kubectl delete namespace dev(안의 모든 리소스도 삭제)
kubectl get ... -n / -A특정/전체 네임스페이스 리소스 조회kubectl get pods -A(= --all-namespaces)
kubectl config set-context기본 네임스페이스 변경(매번 -n 생략)kubectl config set-context --current --namespace=development
kubectl config view --minify현재 컨텍스트의 기본 네임스페이스 확인kubectl config view --minify | grep namespace
kubectl describe resourcequota네임스페이스 총량 Used/Hard 확인kubectl describe resourcequota dev-quota -n development
kubectl describe limitrange컨테이너 기본값·min/max 확인kubectl describe limitrange dev-limits -n development
kubectl api-resources네임스페이스 범위 vs 클러스터 범위 구분kubectl api-resources --namespaced=true
크로스 네임스페이스 DNS다른 네임스페이스 서비스 접근curl http://api-service.production.svc.cluster.local
kubectl run ... -- nslookup서비스 DNS 해석 테스트kubectl run dns-test --image=busybox -it --rm -- nslookup api-service.production
kubectl get ns -o json | jqTerminating 멈춤 시 finalizer·조건 확인kubectl get ns team-a -o json | jq '.status.conditions'
kubectl get apiservice삭제 교착 유발하는 죽은 확장 API 탐지kubectl get apiservice | grep -v True

관련 모듈로 더 깊이:

다음 모듈 rbac에서는 네임스페이스와 연계한 접근 제어를 다룹니다. Role과 RoleBinding으로 특정 네임스페이스에만 권한을 부여하고, ServiceAccount에 최소 권한을 적용해 멀티팀 클러스터 보안 경계를 구성하는 방법을 실습합니다.

지식 확인

퀴즈 — 8문제

Q1

개발팀이 실수로 kubectl delete deployment --all을 실행했는데 운영 Deployment까지 삭제됐다. 이 사고를 예방하는 가장 직접적인 방법은?

Q2

다른 Namespace의 Service에 접근하는 올바른 DNS 형식은?

Q3

ResourceQuota와 LimitRange의 차이는?

Q4

kubectl 명령어에서 특정 Namespace를 지정하지 않으면 어떤 Namespace가 사용되는가?

Q5

kube-system 네임스페이스를 함부로 건드리면 안 되는 이유는?

Q6

한 팀이 클러스터 자원을 독식하지 못하게 네임스페이스 단위로 'CPU·메모리 총량·오브젝트 개수'를 제한하려면?

Q7

[심화] kubectl delete namespace를 실행하면 네임스페이스가 곧바로 사라지지 않고 잠시 Terminating 상태를 거친다. 이 사이에 실제로 무슨 일이 일어나는가?

Q8

[심화] kubectl delete namespace team-a가 30분째 Terminating이고 kubectl get all -n team-a는 비어 있다. 가장 먼저 확인할 것은?

0 / 8 답변

🧪 실습으로 확인하기

K8s 기초 — Pod/Deployment/Service 생성

초급

kubectl로 nginx Pod를 생성하고 Deployment와 Service를 차례로 만들어 클러스터 외부에서 접근 가능한 상태까지 구성한다. K8s 3대 리소스의 역할과 관계를 직접 손으로 익힌다.

55📋 5단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요