← 모든 글

네임스페이스를 통한 리소스 격리와 다중 테넌시 - 팀별, 환경별 격리

여러 팀과 환경이 하나의 클러스터를 사용하는 상황을 가정해 네임스페이스, 리소스 할당량과 네트워크 격리 구성을 정리합니다

CKA 준비 · 7 / 8편

이 글의 목차

학습 예시 안내: 본문의 상황과 출력은 개념 설명을 위한 예시로 정리했습니다. 당시 실행 여부는 확인되지 않았으며, 현재 환경에서의 클러스터 실습도 별도 검증이 필요합니다.

🎯 학습 목표

2026-09-29 점검: 이 글의 환경별 예제는 각각 독립적인 구성 예시입니다. 모든 파일을 같은 클러스터에 순서대로 적용하는 완성된 실습 묶음은 아닙니다. 애플리케이션 이미지·ServiceAccount/RBAC·자동화 스크립트의 실제 동작은 별도 검증이 필요합니다.

이 글을 통해 다음을 학습할 수 있습니다:

  • 네임스페이스의 개념과 격리 메커니즘 이해
  • 팀별, 환경별 네임스페이스 설계 패턴
  • ResourceQuota와 LimitRange를 통한 리소스 제어
  • NetworkPolicy를 활용한 네트워크 격리
  • 다중 테넌시 환경에서의 보안과 관리 전략
  • CKA 준비 과정에서 연습할 네임스페이스 관련 문제 해결

📝 앞선 개념과 이번 예제

지난 글에서는 Pod의 헬스체크를 다뤘습니다. 이번에는 여러 팀이 하나의 클러스터를 함께 사용하는 학습용 상황을 가정합니다.

예제에서 가정한 환경

# 기존 리소스들 확인
kubectl get all
kubectl get pods --all-namespaces

# 현재 네임스페이스 확인
kubectl get namespaces
kubectl config current-context
kubectl config view --minify --output 'jsonpath={..namespace}'

가정한 문제 상황

팀이 늘어나고 개발·스테이징·운영 환경을 구분해야 하는 가상의 조직을 예로 들어 보겠습니다:

# 현재 모든 리소스가 default 네임스페이스에 혼재
kubectl get pods -o wide
kubectl get services
kubectl get configmaps

# 이름 충돌 문제 시뮬레이션
kubectl run web-app --image=nginx  # 개발팀이 생성
kubectl run web-app --image=httpd  # 운영팀이 생성 (에러 발생!)
# Error: pods "web-app" already exists

가정한 상황의 문제점:

  1. 리소스 이름 충돌: 여러 팀이 같은 이름의 리소스를 생성하려 시도
  2. 리소스 사용량 제어 불가: 한 팀이 클러스터 자원을 모두 점유
  3. 환경 구분 없음: 개발, 스테이징, 운영이 모두 섞여있음
  4. 보안 문제: 모든 팀이 서로의 리소스에 접근 가능
  5. 관리의 어려움: 어떤 리소스가 어느 팀 소유인지 파악 어려움
# 문제 상황 재현
# 개발팀 작업
kubectl create deployment frontend-dev --image=nginx:1.20
kubectl create configmap app-config --from-literal=env=development

# 운영팀 작업 (같은 네임스페이스에서)
kubectl create deployment frontend-prod --image=nginx:1.21
kubectl create configmap app-config --from-literal=env=production
# Error: configmaps "app-config" already exists

# 서로 다른 팀의 리소스가 보이는 문제
kubectl get all  # 모든 팀의 리소스가 한번에 보임

이런 문제를 다루기 위해 네임스페이스를 통한 리소스 격리와 다중 테넌시 구성 방법을 살펴보겠습니다.

💡 네임스페이스 기본 개념과 격리 메커니즘

네임스페이스란?

쿠버네티스 네임스페이스는 논리적 클러스터 분할을 제공하는 메커니즘입니다:

단일 물리 클러스터
├── dev 네임스페이스 (개발팀)
├── staging 네임스페이스 (스테이징)
├── prod 네임스페이스 (운영팀)
├── monitoring 네임스페이스 (모니터링팀)
└── kube-system 네임스페이스 (시스템)

격리되는 것들:

  • 리소스 이름 (Pod, Service, ConfigMap 등)
  • 네트워크 정책 (NetworkPolicy 적용 시)
  • 리소스 할당량 (ResourceQuota 적용 시)

격리되지 않는 것들:

  • 노드 레벨 리소스 (Node, PersistentVolume)
  • 클러스터 레벨 리소스 (ClusterRole, StorageClass)
  • 네트워크 (기본적으로는 통신 가능)

첫 번째 네임스페이스 생성

# 기본 네임스페이스 확인
kubectl get namespaces
# NAME              STATUS   AGE
# default           Active   30d
# kube-node-lease   Active   30d
# kube-public       Active   30d
# kube-system       Active   30d

# 개발팀용 네임스페이스 생성
kubectl create namespace development
kubectl create namespace staging
kubectl create namespace production

# YAML로 네임스페이스 생성
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: frontend-team
  labels:
    team: frontend
    environment: multi
    managed-by: platform-team
  annotations:
    description: "Frontend team namespace for all environments"
    contact: "frontend-team@company.com"
EOF

네임스페이스별 리소스 관리

# 특정 네임스페이스에 리소스 생성
kubectl run dev-app --image=nginx --namespace=development
kubectl run staging-app --image=nginx --namespace=staging
kubectl run prod-app --image=nginx --namespace=production

# 같은 이름의 리소스가 각 네임스페이스에 생성됨
kubectl get pods --all-namespaces | grep app
# development   dev-app       1/1     Running
# staging       staging-app   1/1     Running
# production    prod-app      1/1     Running

# 네임스페이스별로 확인
kubectl get pods -n development
kubectl get pods -n production

🏢 기업 환경 네임스페이스 설계 패턴

1. 환경별 분리 패턴 (Environment-based)

가장 일반적인 패턴으로, 개발 생명주기에 따른 환경 분리입니다:

# 환경별 네임스페이스 생성
kubectl create namespace dev
kubectl create namespace test
kubectl create namespace staging
kubectl create namespace prod

# 각 환경에 라벨과 어노테이션 추가
kubectl label namespace dev environment=development
kubectl label namespace test environment=testing
kubectl label namespace staging environment=staging
kubectl label namespace prod environment=production

kubectl annotate namespace dev description="Development environment for all teams"
kubectl annotate namespace prod description="Production environment - restricted access"

환경별 애플리케이션 배포:

# dev-environment.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: dev
  labels:
    environment: development
    cost-center: engineering
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: dev
spec:
  replicas: 1  # 개발환경은 최소 리소스
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
        environment: dev
    spec:
      containers:
      - name: web
        image: nginx:1.20
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: dev
data:
  database_url: "dev-db.internal:5432"
  debug_mode: "true"
  log_level: "debug"
# prod-environment.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: prod
  labels:
    environment: production
    cost-center: engineering
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: prod
spec:
  replicas: 3  # 운영환경은 고가용성
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
        environment: prod
    spec:
      containers:
      - name: web
        image: nginx:1.21  # 기존 학습 기록의 버전 (현재 지원 여부 별도 확인)
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: prod
data:
  database_url: "prod-db.internal:5432"
  debug_mode: "false"
  log_level: "info"
# 환경별 배포
kubectl apply -f dev-environment.yaml
kubectl apply -f prod-environment.yaml

# 같은 이름의 리소스가 각 환경에 존재
kubectl get deployments -n dev
kubectl get deployments -n prod
kubectl get configmaps -n dev
kubectl get configmaps -n prod

2. 팀별 분리 패턴 (Team-based)

팀 조직 구조에 따른 네임스페이스 분리입니다:

# 팀별 네임스페이스 생성
kubectl create namespace frontend-team
kubectl create namespace backend-team
kubectl create namespace data-team
kubectl create namespace platform-team

# 팀 정보 라벨링
kubectl label namespace frontend-team team=frontend
kubectl label namespace backend-team team=backend
kubectl label namespace data-team team=data
# 이메일에는 라벨 값에 허용되지 않는 @가 있으므로 annotation 사용
kubectl annotate namespace frontend-team owner=john.doe@example.com
kubectl annotate namespace backend-team owner=jane.smith@example.com
kubectl annotate namespace data-team owner=alice.wilson@example.com

팀별 리소스 구성:

# frontend-team-resources.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: frontend-team
  labels:
    team: frontend
    department: engineering
  annotations:
    contact: "frontend-team@company.com"
    budget-code: "ENG-FE-2024"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: react-app
  namespace: frontend-team
spec:
  replicas: 2
  selector:
    matchLabels:
      app: react-app
      team: frontend
  template:
    metadata:
      labels:
        app: react-app
        team: frontend
    spec:
      containers:
      - name: react
        image: node:16-alpine
        command: ["npm", "start"]
---
apiVersion: v1
kind: Service
metadata:
  name: react-service
  namespace: frontend-team
spec:
  selector:
    app: react-app
  ports:
  - port: 3000
    targetPort: 3000

3. 하이브리드 패턴 (Team + Environment)

대규모 조직에서 사용하는 팀과 환경을 결합한 패턴입니다:

# 하이브리드 네임스페이스 명명 규칙: {team}-{environment}
kubectl create namespace frontend-dev
kubectl create namespace frontend-staging
kubectl create namespace frontend-prod
kubectl create namespace backend-dev
kubectl create namespace backend-staging
kubectl create namespace backend-prod

# 복합 라벨링
kubectl label namespace frontend-dev team=frontend environment=development
kubectl label namespace frontend-prod team=frontend environment=production
kubectl label namespace backend-dev team=backend environment=development
kubectl label namespace backend-prod team=backend environment=production
# 라벨 기반 리소스 조회
kubectl get namespaces -l team=frontend
kubectl get namespaces -l environment=production
kubectl get namespaces -l team=frontend,environment=production

🛡️ ResourceQuota로 리소스 사용량 제어

기본 ResourceQuota 설정

각 네임스페이스의 리소스 사용량을 제한하여 공정한 자원 분배를 보장합니다:

# dev-resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev
spec:
  hard:
    # 컴퓨트 리소스 제한
    requests.cpu: "2"      # 총 CPU 요청량 2코어
    requests.memory: 4Gi   # 총 메모리 요청량 4GB
    limits.cpu: "4"        # 총 CPU 제한량 4코어
    limits.memory: 8Gi     # 총 메모리 제한량 8GB
    
    # 오브젝트 수 제한
    pods: "10"             # 최대 Pod 10개
    services: "5"          # 최대 Service 5개
    secrets: "10"          # 최대 Secret 10개
    configmaps: "10"       # 최대 ConfigMap 10개
    persistentvolumeclaims: "5"  # 최대 PVC 5개
    
    # 스토리지 제한
    requests.storage: "50Gi"  # 총 스토리지 요청량 50GB
# prod-resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: prod-quota
  namespace: prod
spec:
  hard:
    # 운영환경은 더 많은 리소스 할당
    requests.cpu: "8"
    requests.memory: 16Gi
    limits.cpu: "16"
    limits.memory: 32Gi
    
    pods: "50"
    services: "20"
    secrets: "20"
    configmaps: "20"
    persistentvolumeclaims: "20"
    
    requests.storage: "200Gi"
# ResourceQuota 적용
kubectl apply -f dev-resource-quota.yaml
kubectl apply -f prod-resource-quota.yaml

# 할당량 확인
kubectl describe resourcequota -n dev
kubectl describe resourcequota -n prod

# 사용량 모니터링
kubectl top pods -n dev
kubectl top pods -n prod

고급 ResourceQuota 패턴

# team-based-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: frontend-team-quota
  namespace: frontend-team
spec:
  hard:
    # 스코프별 제한
    count/deployments.apps: "10"
    count/services: "10"
    count/jobs.batch: "5"
    count/cronjobs.batch: "3"
    
    # 스토리지 클래스별 제한
    requests.storage: "100Gi"
    gold.storageclass.storage.k8s.io/requests.storage: "20Gi"
    silver.storageclass.storage.k8s.io/requests.storage: "50Gi"
    
---
# 특정 우선순위 클래스에 해당하는 Pod의 자원만 따로 집계
apiVersion: v1
kind: ResourceQuota
metadata:
  name: frontend-priority-quota
  namespace: frontend-team
spec:
  hard:
    pods: "10"
    requests.cpu: "4"
    requests.memory: "8Gi"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["high-priority", "medium-priority"]

할당량 초과 테스트:

다음은 dev의 CPU requests 할당량이 2이고, 다른 Pod가 요청량을 사용하지 않는 경우입니다. 기존 워크로드가 있으면 더 일찍 거부될 수 있습니다. 위 우선순위별 quota는 해당 Pod만 집계하며, 다른 PriorityClass의 사용 자체를 금지하는 정책은 아닙니다.

# 개발 네임스페이스에서 리소스 할당량 테스트
for index in 1 2 3; do
  kubectl run "test-pod-$index" --image=nginx -n dev --dry-run=client -o yaml |
    kubectl set resources --local -f - --requests=cpu=1,memory=1Gi --limits=cpu=1,memory=1Gi -o yaml |
    kubectl apply -f -
done
# 세 번째 Pod는 할당량 초과로 생성 실패

# apply의 거부 메시지와 quota 사용량 확인
kubectl describe resourcequota dev-quota -n dev

🔒 LimitRange로 개별 리소스 제어

ResourceQuota가 네임스페이스 전체 제한이라면, LimitRange는 개별 오브젝트 제한입니다:

# dev-limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: dev-limits
  namespace: dev
spec:
  limits:
  # Pod 제한
  - type: Pod
    max:
      cpu: "2"          # Pod당 최대 CPU
      memory: "2Gi"     # Pod당 최대 메모리
    min:
      cpu: "50m"        # Pod당 최소 CPU
      memory: "64Mi"    # Pod당 최소 메모리
      
  # Container 제한
  - type: Container
    max:
      cpu: "1"
      memory: "1Gi"
    min:
      cpu: "10m"
      memory: "32Mi"
    default:
      cpu: "100m"
      memory: "128Mi"
    defaultRequest:
      cpu: "50m"
      memory: "64Mi"
      
  # PVC 제한
  - type: PersistentVolumeClaim
    max:
      storage: "10Gi"   # PVC당 최대 스토리지
    min:
      storage: "1Gi"    # PVC당 최소 스토리지
# prod-limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: prod-limits
  namespace: prod
spec:
  limits:
  - type: Pod
    max:
      cpu: "4"
      memory: "4Gi"
    min:
      cpu: "100m"
      memory: "128Mi"
  # 기본값 주입은 Container 항목에서 설정
  - type: Container
    default:
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:
      cpu: "250m"
      memory: "256Mi"
# LimitRange 적용
kubectl apply -f dev-limit-range.yaml
kubectl apply -f prod-limit-range.yaml

# 제한 확인
kubectl describe limitrange -n dev
kubectl describe limitrange -n prod

# 자동으로 리소스가 설정되는지 테스트
kubectl run auto-limit-test --image=nginx -n dev
kubectl describe pod auto-limit-test -n dev
# resources 섹션에 자동으로 설정된 값들 확인

🌐 NetworkPolicy를 통한 네트워크 격리

기본적으로 네임스페이스 간 네트워크 통신은 허용됩니다. 보안을 위해 NetworkPolicy로 격리할 수 있습니다:

NetworkPolicy를 지원하는 네트워크 플러그인이 필요합니다. 정책은 허용 규칙을 합산하므로, 다른 정책에서 이미 허용한 통신을 뒤의 규칙으로 취소할 수 없습니다. 아래 환경 간 예제는 각각 독립적으로 검토합니다. NetworkPolicy 공식 문서

기본 네트워크 격리

# deny-all-network-policy.yaml
# 이 정책을 적용해 수신 트래픽을 기본 차단
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
  namespace: prod
spec:
  podSelector: {}  # 네임스페이스 내 모든 Pod 적용
  policyTypes:
  - Ingress
  # ingress 규칙이 없으므로 모든 수신 트래픽 차단
---
# 모든 송신 트래픽 차단
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: prod
spec:
  podSelector: {}
  policyTypes:
  - Egress
  # egress 규칙이 없으므로 모든 송신 트래픽 차단

선택적 네트워크 허용

# selective-network-policy.yaml
# 운영 환경에서 필요한 통신만 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: prod-network-policy
  namespace: prod
spec:
  podSelector:
    matchLabels:
      app: web-app
  policyTypes:
  - Ingress
  - Egress
  
  ingress:
  # 1. 같은 네임스페이스 내 Pod 간 통신 허용
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: prod
    ports:
    - protocol: TCP
      port: 80
      
  # 2. 스테이징 환경에서의 접근 허용 (테스트 목적)
  - from:
    - namespaceSelector:
        matchLabels:
          environment: staging
    ports:
    - protocol: TCP
      port: 80
      
  # 3. 모니터링 네임스페이스에서의 접근 허용
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: monitoring
    ports:
    - protocol: TCP
      port: 8080  # 메트릭 엔드포인트
      
  egress:
  # 1. DNS 해석 허용
  - to: []
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
      
  # 2. 데이터베이스 접근 허용
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: database
    ports:
    - protocol: TCP
      port: 5432
      
  # 3. 외부 API 호출 허용 (특정 IP 대역)
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8  # 내부 네트워크
  - to:
    - ipBlock:
        cidr: 192.168.0.0/16

개발/운영 환경 간 네트워크 분리

# cross-environment-policy.yaml
# 개발 환경에서 운영 환경 접근 차단
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: block-dev-to-prod
  namespace: prod
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  # 환경 라벨이 있고 개발 환경이 아닌 네임스페이스만 허용
  - from:
    - namespaceSelector:
        matchExpressions:
        - key: environment
          operator: Exists
        - key: environment
          operator: NotIn
          values: ["development", "dev"]
---
# 반대로 개발 환경에서는 더 자유로운 정책
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-dev
  namespace: dev
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - {}  # 모든 수신 트래픽 허용
  egress:
  - {}  # 모든 송신 트래픽 허용
# NetworkPolicy 적용 및 테스트
kubectl apply -f deny-all-network-policy.yaml
kubectl apply -f selective-network-policy.yaml

# 네트워크 정책 확인
kubectl get networkpolicies -n prod
kubectl describe networkpolicy prod-network-policy -n prod

# 네트워크 연결 테스트
kubectl run test-client --image=busybox --rm -it -n dev -- sh
# 컨테이너 내에서: wget -qO- --timeout=3 http://web-app.prod.svc.cluster.local
# 정책에 따라 연결 성공/실패 확인

🔍 실전 시나리오: 멀티 테넌트 환경 구축

스타트업에서 중견기업으로 성장하는 시나리오

조직 규모가 커지는 상황을 가정한 단계별 구성 예시입니다. 특정 회사의 실제 도입 이력을 기록한 것은 아닙니다.

1단계: 기본 환경 분리

# 초기 환경 구성
kubectl create namespace development
kubectl create namespace production

# 기본 라벨링
kubectl label namespace development environment=dev tier=non-prod
kubectl label namespace production environment=prod tier=prod

2단계: 팀 증가에 따른 네임스페이스 확장

# team-namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: frontend-dev
  labels:
    team: frontend
    environment: development
    cost-center: "CC-001"
  annotations:
    contact: "frontend@company.com"
    description: "Frontend team development environment"
---
apiVersion: v1
kind: Namespace
metadata:
  name: frontend-prod
  labels:
    team: frontend
    environment: production
    cost-center: "CC-001"
---
apiVersion: v1
kind: Namespace
metadata:
  name: backend-dev
  labels:
    team: backend
    environment: development
    cost-center: "CC-002"
---
apiVersion: v1
kind: Namespace
metadata:
  name: backend-prod
  labels:
    team: backend
    environment: production
    cost-center: "CC-002"
---
apiVersion: v1
kind: Namespace
metadata:
  name: shared-services
  labels:
    team: platform
    environment: shared
    cost-center: "CC-000"
  annotations:
    description: "Shared services like monitoring, logging"

3단계: 환경별 리소스 할당 정책

# resource-allocation-policy.yaml
# 개발 환경 (제한적 리소스)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: frontend-dev
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "20"
    services: "10"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: dev-limits
  namespace: frontend-dev
spec:
  limits:
  - type: Container
    default:
      cpu: "200m"
      memory: "256Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    max:
      cpu: "1"
      memory: "1Gi"
---
# 운영 환경 (충분한 리소스)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: prod-quota
  namespace: frontend-prod
spec:
  hard:
    requests.cpu: "8"
    requests.memory: 16Gi
    limits.cpu: "16"
    limits.memory: 32Gi
    pods: "50"
    services: "20"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: prod-limits
  namespace: frontend-prod
spec:
  limits:
  - type: Container
    default:
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:
      cpu: "250m"
      memory: "256Mi"
    max:
      cpu: "2"
      memory: "2Gi"

4단계: 네트워크 보안 정책

# security-network-policies.yaml
# 운영 환경 보안 강화
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: production-security
  namespace: frontend-prod
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  
  ingress:
  # 로드밸런서와 인그레스에서만 접근 허용
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: ingress-system
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 443
      
  # 모니터링 시스템 접근 허용
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: shared-services
    ports:
    - protocol: TCP
      port: 8080
      
  egress:
  # DNS 해석 허용
  - to: []
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
      
  # 백엔드 서비스 호출 허용
  - to:
    - namespaceSelector:
        matchLabels:
          team: backend
          environment: production
    ports:
    - protocol: TCP
      port: 8080
---
# 개발 환경에서는 비운영 네임스페이스와 DNS로만 송신 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: development-open
  namespace: frontend-dev
spec:
  podSelector: {}
  policyTypes:
  - Egress
  
  egress:
  # 환경 라벨이 있고 운영 환경이 아닌 네임스페이스만 허용
  - to:
    - namespaceSelector:
        matchExpressions:
        - key: environment
          operator: Exists
        - key: environment
          operator: NotIn
          values: ["production", "prod"]
  # DNS 조회 허용 (실제 DNS 구성에 맞춰 목적지도 제한 가능)
  - ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
# 멀티 테넌트 환경 구축
kubectl apply -f team-namespaces.yaml
kubectl apply -f resource-allocation-policy.yaml
kubectl apply -f security-network-policies.yaml

# 구축 결과 확인
kubectl get namespaces --show-labels
kubectl get resourcequotas --all-namespaces
kubectl get networkpolicies --all-namespaces

🎯 고급 네임스페이스 관리 패턴

1. 동적 네임스페이스 생성과 관리

실제 기업 환경에서는 네임스페이스를 동적으로 생성하고 관리해야 합니다:

# namespace-template.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ${TEAM_NAME}-${ENVIRONMENT}
  labels:
    team: "${TEAM_NAME}"
    environment: "${ENVIRONMENT}"
    created-by: platform-team
    managed: "true"
  annotations:
    contact: "${TEAM_EMAIL}"
    cost-center: "${COST_CENTER}"
    description: "${DESCRIPTION}"
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: ${TEAM_NAME}-${ENVIRONMENT}-quota
  namespace: ${TEAM_NAME}-${ENVIRONMENT}
spec:
  hard:
    requests.cpu: "${CPU_REQUESTS}"
    requests.memory: "${MEMORY_REQUESTS}"
    limits.cpu: "${CPU_LIMITS}"
    limits.memory: "${MEMORY_LIMITS}"
    pods: "${MAX_PODS}"
    services: "${MAX_SERVICES}"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: ${TEAM_NAME}-${ENVIRONMENT}-limits
  namespace: ${TEAM_NAME}-${ENVIRONMENT}
spec:
  limits:
  - type: Container
    default:
      cpu: "${DEFAULT_CPU}"
      memory: "${DEFAULT_MEMORY}"
    defaultRequest:
      cpu: "${DEFAULT_CPU_REQUEST}"
      memory: "${DEFAULT_MEMORY_REQUEST}"
    max:
      cpu: "${MAX_CPU}"
      memory: "${MAX_MEMORY}"

네임스페이스 생성 스크립트:

#!/bin/bash
# create-team-namespace.sh

set -euo pipefail

TEAM_NAME=${1:?팀 이름 필요}
ENVIRONMENT=${2:?dev 또는 prod 필요}
TEAM_EMAIL=${3:?연락 이메일 필요}
COST_CENTER=${4:?비용 코드 필요}
DESCRIPTION="${TEAM_NAME} ${ENVIRONMENT} environment"

# 환경별 리소스 할당량 설정
case $ENVIRONMENT in
  "dev")
    CPU_REQUESTS="2"
    MEMORY_REQUESTS="4Gi"
    CPU_LIMITS="4"
    MEMORY_LIMITS="8Gi"
    MAX_PODS="20"
    MAX_SERVICES="10"
    DEFAULT_CPU="200m"
    DEFAULT_MEMORY="256Mi"
    DEFAULT_CPU_REQUEST="100m"
    DEFAULT_MEMORY_REQUEST="128Mi"
    MAX_CPU="1"
    MAX_MEMORY="1Gi"
    ;;
  "prod")
    CPU_REQUESTS="8"
    MEMORY_REQUESTS="16Gi"
    CPU_LIMITS="16"
    MEMORY_LIMITS="32Gi"
    MAX_PODS="50"
    MAX_SERVICES="20"
    DEFAULT_CPU="500m"
    DEFAULT_MEMORY="512Mi"
    DEFAULT_CPU_REQUEST="250m"
    DEFAULT_MEMORY_REQUEST="256Mi"
    MAX_CPU="2"
    MAX_MEMORY="2Gi"
    ;;
  *)
    echo "환경은 dev 또는 prod로 지정하세요." >&2
    exit 1
    ;;
esac

# envsubst가 읽을 수 있도록 템플릿의 모든 변수를 내보냄
export TEAM_NAME ENVIRONMENT TEAM_EMAIL COST_CENTER DESCRIPTION
export CPU_REQUESTS MEMORY_REQUESTS CPU_LIMITS MEMORY_LIMITS MAX_PODS MAX_SERVICES
export DEFAULT_CPU DEFAULT_MEMORY DEFAULT_CPU_REQUEST DEFAULT_MEMORY_REQUEST MAX_CPU MAX_MEMORY

# 템플릿에서 네임스페이스 생성
envsubst < namespace-template.yaml | kubectl apply -f -

echo "Created namespace: ${TEAM_NAME}-${ENVIRONMENT}"
echo "Contact: ${TEAM_EMAIL}"
echo "Cost Center: ${COST_CENTER}"
# 스크립트 사용 예제
chmod +x create-team-namespace.sh
./create-team-namespace.sh mobile dev mobile-team@company.com CC-003
./create-team-namespace.sh mobile prod mobile-team@company.com CC-003

2. 네임스페이스 생명주기 관리

아래 CronJob은 검증 전 초안입니다. 삭제 대상 검토, 전용 ServiceAccount와 최소 RBAC 권한, 컨테이너의 date -d 지원을 준비해야 합니다. Pod가 없다고 PVC 등 다른 리소스까지 없는 것은 아니므로 빈 Pod 목록만으로 네임스페이스를 삭제하면 안 됩니다.

# namespace-cleanup-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: namespace-cleanup
  namespace: kube-system
spec:
  schedule: "0 2 * * 0"  # 매주 일요일 새벽 2시
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cleanup
            image: bitnami/kubectl:latest
            command:
            - /bin/sh
            - -c
            - |
              # 만료된 임시 네임스페이스 삭제
              kubectl get namespaces -l temporary=true -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | \
              while IFS= read -r ns; do
                created=$(kubectl get namespace $ns -o jsonpath='{.metadata.creationTimestamp}')
                # 7일 이상 된 임시 네임스페이스 삭제
                if [ $(date -d "$created" +%s) -lt $(date -d '7 days ago' +%s) ]; then
                  echo "Deleting expired namespace: $ns"
                  kubectl delete namespace $ns
                fi
              done
              
              # 사용하지 않는 네임스페이스 식별
              kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | \
              while IFS= read -r ns; do
                pod_count=$(kubectl get pods -n $ns --no-headers 2>/dev/null | wc -l)
                if [ $pod_count -eq 0 ]; then
                  echo "Empty namespace detected: $ns"
                  kubectl label namespace $ns empty=true
                fi
              done
          restartPolicy: OnFailure

3. 네임스페이스 모니터링과 알림

아래는 자동화 구조를 설명하는 미완성 예제입니다. kubectl top의 CPU m·메모리 Mi와 quota의 Gi 등을 같은 단위로 환산해야 하며, 현재 단순 awk 합계로는 임계치 판정이 정확하지 않습니다. ServiceAccount/RBAC, jq·bc 제공 여부와 실패 처리도 보완한 뒤 실행해야 합니다.

# namespace-monitoring.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: namespace-monitoring-script
  namespace: monitoring
data:
  monitor.sh: |
    #!/bin/bash
    
    # 리소스 사용량 임계치 체크
    kubectl get namespaces -o json | jq -r '.items[] | select(.metadata.labels.managed=="true") | .metadata.name' | \
    while read ns; do
      # CPU 사용량 체크 (80% 이상)
      cpu_usage=$(kubectl top pods -n $ns --no-headers 2>/dev/null | awk '{sum+=$2} END {print sum}' || echo 0)
      cpu_limit=$(kubectl get resourcequota -n $ns -o jsonpath='{.items[0].spec.hard.limits\.cpu}' 2>/dev/null || echo "0")
      
      if [ $(echo "$cpu_usage > $cpu_limit * 0.8" | bc -l) -eq 1 ]; then
        echo "ALERT: Namespace $ns CPU usage is over 80%"
        # Slack 또는 이메일 알림 전송
      fi
      
      # 메모리 사용량 체크
      memory_usage=$(kubectl top pods -n $ns --no-headers 2>/dev/null | awk '{sum+=$3} END {print sum}' || echo 0)
      memory_limit=$(kubectl get resourcequota -n $ns -o jsonpath='{.items[0].spec.hard.limits\.memory}' 2>/dev/null || echo "0")
      
      # Pod 수 체크
      pod_count=$(kubectl get pods -n $ns --no-headers 2>/dev/null | wc -l)
      pod_limit=$(kubectl get resourcequota -n $ns -o jsonpath='{.items[0].spec.hard.pods}' 2>/dev/null || echo 999)
      
      if [ $pod_count -gt $(($pod_limit * 8 / 10)) ]; then
        echo "ALERT: Namespace $ns Pod count is over 80% of limit"
      fi
    done
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: namespace-monitor
  namespace: monitoring
spec:
  schedule: "*/15 * * * *"  # 15분마다 실행
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: monitor
            image: bitnami/kubectl:latest
            command: ["/bin/sh", "/scripts/monitor.sh"]
            volumeMounts:
            - name: monitoring-script
              mountPath: /scripts
          volumes:
          - name: monitoring-script
            configMap:
              name: namespace-monitoring-script
              defaultMode: 0755
          restartPolicy: OnFailure

🚨 네임스페이스 트러블슈팅

일반적인 문제 시나리오

1. 리소스 할당량 초과 문제

# 문제 상황: Pod 생성 실패
kubectl run test-app --image=nginx -n dev
# Error: pods "test-app" is forbidden: exceeded quota

# 원인 분석
kubectl describe resourcequota -n dev
# Used vs Hard 비교

kubectl get events -n dev --field-selector reason=FailedCreate
# 상세한 에러 메시지 확인

# 해결 방법 1: 할당량 증가
kubectl patch resourcequota dev-quota -n dev -p '{"spec":{"hard":{"pods":"15"}}}'

# 해결 방법 2: 기존 리소스 정리
kubectl get pods -n dev --sort-by=.metadata.creationTimestamp
kubectl delete pod old-pod-1 old-pod-2 -n dev

2. 네트워크 정책으로 인한 연결 실패

# 문제 상황: 서비스 간 통신 불가
kubectl run debug-pod --image=busybox --rm -it -n frontend-dev -- sh
# 컨테이너 내에서: wget -qO- --timeout=3 http://api-service.backend-dev:8080
# 연결 타임아웃 발생

# 원인 분석
kubectl get networkpolicies -n backend-dev
kubectl describe networkpolicy backend-security -n backend-dev

# 허용된 트래픽 확인
kubectl get networkpolicy backend-security -n backend-dev -o yaml

# 해결: 네트워크 정책 수정
kubectl patch networkpolicy backend-security -n backend-dev -p '
{
  "spec": {
    "ingress": [
      {
        "from": [
          {
            "namespaceSelector": {
              "matchLabels": {
                "team": "frontend"
              }
            }
          }
        ],
        "ports": [
          {
            "protocol": "TCP",
            "port": 8080
          }
        ]
      }
    ]
  }
}'

3. 네임스페이스 삭제가 안되는 문제

# 문제 상황: 네임스페이스가 Terminating 상태에서 멈춤
kubectl delete namespace stuck-namespace
kubectl get namespace stuck-namespace
# STATUS: Terminating (계속 유지)

# 원인 분석
kubectl get all -n stuck-namespace
# 남아있는 리소스 확인

kubectl api-resources --verbs=list --namespaced -o name | \
  xargs -n 1 kubectl get --show-kind --ignore-not-found -n stuck-namespace

# Finalizer 문제 확인
kubectl get namespace stuck-namespace -o yaml | grep finalizers

# 강제 삭제 (주의: 데이터 손실 가능)
kubectl get namespace stuck-namespace -o json > stuck-namespace.json
# finalizers 배열을 비우고 다시 적용
jq '.spec.finalizers = []' stuck-namespace.json | kubectl replace --raw "/api/v1/namespaces/stuck-namespace/finalize" -f -

4. RBAC 권한 문제

# 문제 상황: 특정 네임스페이스 접근 불가
kubectl get pods -n production
# Error: User cannot list pods in namespace "production"

# 현재 사용자 권한 확인
kubectl auth can-i get pods -n production
kubectl auth can-i create deployments -n production

# 사용자 권한 상세 확인
kubectl auth can-i --list -n production

# 관리자가 권한 확인 및 부여
kubectl get rolebindings -n production
kubectl describe rolebinding production-access -n production

# 권한 부여 (관리자가 실행)
kubectl create rolebinding developer-access \
  --clusterrole=edit \
  --user=developer@company.com \
  --namespace=production

🎯 CKA 대비 연습 패턴

연습할 문제 유형

1. 네임스페이스 생성과 리소스 배포

# 문제: 새로운 네임스페이스를 생성하고 애플리케이션 배포
kubectl create namespace exam-ns
kubectl run web-app --image=nginx --port=80 -n exam-ns
kubectl expose pod web-app --port=80 --target-port=80 -n exam-ns

# 또는 YAML로 한번에
kubectl create namespace exam-ns --dry-run=client -o yaml > ns.yaml
printf '\n---\n' >> ns.yaml
kubectl run web-app --image=nginx --port=80 -n exam-ns --dry-run=client -o yaml >> ns.yaml
kubectl apply -f ns.yaml

2. ResourceQuota 설정

# 문제: 네임스페이스에 리소스 할당량 설정
kubectl create quota my-quota \
  --hard=requests.cpu=2,requests.memory=4Gi,limits.cpu=4,limits.memory=8Gi,pods=10 \
  -n exam-ns

# 또는 파일로 생성
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
  name: my-quota
  namespace: exam-ns
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "10"
EOF

3. 네임스페이스별 리소스 조회

# 문제: 특정 조건의 네임스페이스나 리소스 찾기
kubectl get namespaces --show-labels
kubectl get pods --all-namespaces -l environment=production
kubectl get services -A --field-selector metadata.namespace=kube-system

# 리소스 사용량이 높은 네임스페이스 찾기
kubectl top pods --all-namespaces --sort-by=cpu
kubectl top pods --all-namespaces --sort-by=memory

4. 네트워크 정책 설정

# 문제: 특정 네임스페이스 간 통신 제어
kubectl get networkpolicies -A
kubectl describe networkpolicy policy-name -n namespace

# 네트워크 정책 생성 (템플릿 활용)
cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: secure-ns
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
EOF

시간 단축 팁

# 네임스페이스 관련 자주 사용하는 단축 명령어
alias kgns='kubectl get namespaces'
alias kns='kubectl config set-context --current --namespace'

# 현재 네임스페이스 확인
kubectl config view --minify --output 'jsonpath={..namespace}'

# 모든 네임스페이스의 리소스 빠른 조회
kubectl get all -A
kubectl get pods -A -o wide

# 리소스 할당량 빠른 확인
kubectl get resourcequotas -A
kubectl describe quota -n namespace-name

CKA 시험용 치트시트:

# 네임스페이스 생성
kubectl create ns NAME

# 리소스 할당량
kubectl create quota NAME --hard=requests.cpu=1,requests.memory=1Gi -n NS

# 리소스 제한 (앞의 LimitRange 매니페스트에서 namespace도 NS로 변경)
kubectl apply -f limit-range.yaml -n NS

# 네트워크 정책 (앞의 기본 차단 매니페스트에서 namespace도 NS로 변경)
kubectl apply -f deny-all-network-policy.yaml -n NS

# 네임스페이스 삭제
kubectl delete ns NAME --grace-period=0 --force

📊 모니터링과 운영 관리

네임스페이스 상태 대시보드

# 전체 네임스페이스 상태 요약
kubectl get namespaces -o custom-columns=\
NAME:.metadata.name,\
STATUS:.status.phase,\
AGE:.metadata.creationTimestamp,\
LABELS:.metadata.labels

# 네임스페이스별 리소스 사용량
for ns in $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}'); do
  echo "=== Namespace: $ns ==="
  kubectl top pods -n $ns 2>/dev/null || echo "No pods running"
  echo ""
done

# 리소스 할당량 현황
kubectl get resourcequotas -A -o custom-columns=\
NAMESPACE:.metadata.namespace,\
NAME:.metadata.name,\
CPU_USED:.status.used.requests\.cpu,\
CPU_HARD:.spec.hard.requests\.cpu,\
MEMORY_USED:.status.used.requests\.memory,\
MEMORY_HARD:.spec.hard.requests\.memory

자동화된 리포팅

다음 CronJob도 실행 권한과 이미지 내 도구를 별도로 준비해야 하는 구성 예시입니다. kubectl 조회 실패를 빈 목록으로 오인하지 않도록 오류 처리를 추가하고, 보고서의 “빈 네임스페이스”는 Pod가 없다는 뜻으로만 해석해야 합니다.

# namespace-report-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: namespace-report
  namespace: kube-system
spec:
  schedule: "0 9 * * 1"  # 매주 월요일 오전 9시
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: reporter
            image: bitnami/kubectl:latest
            command:
            - /bin/sh
            - -c
            - |
              echo "=== Weekly Namespace Report ===" > /tmp/report.txt
              echo "Generated: $(date)" >> /tmp/report.txt
              echo "" >> /tmp/report.txt
              
              # 네임스페이스 개수
              echo "Total Namespaces: $(kubectl get ns --no-headers | wc -l)" >> /tmp/report.txt
              
              # 팀별 네임스페이스 현황
              echo "" >> /tmp/report.txt
              echo "=== Namespaces by Team ===" >> /tmp/report.txt
              kubectl get ns -l team --no-headers -o custom-columns=TEAM:.metadata.labels.team,NAME:.metadata.name >> /tmp/report.txt
              
              # 리소스 사용량 TOP 10
              echo "" >> /tmp/report.txt
              echo "=== Top 10 CPU Usage ===" >> /tmp/report.txt
              kubectl top pods -A --sort-by=cpu | head -10 >> /tmp/report.txt
              
              # 빈 네임스페이스 식별
              echo "" >> /tmp/report.txt
              echo "=== Empty Namespaces ===" >> /tmp/report.txt
              for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
                pod_count=$(kubectl get pods -n $ns --no-headers 2>/dev/null | wc -l)
                if [ $pod_count -eq 0 ]; then
                  echo "- $ns" >> /tmp/report.txt
                fi
              done
              
              # 보고서 출력 (실제로는 이메일이나 Slack으로 전송)
              cat /tmp/report.txt
          restartPolicy: OnFailure

💡 고급 격리 패턴과 보안

1. 멀티 클러스터 전략

때로는 네임스페이스 격리로는 충분하지 않을 수 있습니다:

# cluster-isolation-strategy.yaml
# 환경별 클러스터 분리 전략 예시
clusters:
  development:
    purpose: "개발 및 테스트"
    security_level: "low"
    namespaces:
      - team-a-dev
      - team-b-dev
      - shared-dev
      
  staging:
    purpose: "통합 테스트 및 스테이징"
    security_level: "medium"
    namespaces:
      - team-a-staging
      - team-b-staging
      - shared-staging
      
  production:
    purpose: "운영 서비스"
    security_level: "high"
    namespaces:
      - team-a-prod
      - team-b-prod
      - monitoring
      - logging

클러스터 간 네임스페이스 동기화:

# 개발 클러스터에서 스테이징으로 네임스페이스 설정 동기화
kubectl get namespace team-a-dev -o yaml --context=dev-cluster | \
  sed 's/team-a-dev/team-a-staging/g' | \
  kubectl apply --context=staging-cluster -f -

# ResourceQuota도 함께 동기화 (운영에 맞게 조정)
kubectl get resourcequota -n team-a-dev -o yaml --context=dev-cluster | \
  sed 's/team-a-dev/team-a-staging/g' | \
  sed 's/requests.cpu: "2"/requests.cpu: "4"/g' | \
  kubectl apply --context=staging-cluster -f -

2. Pod Security Standards 적용

# pod-security-policies.yaml
# 네임스페이스별 보안 정책 설정
apiVersion: v1
kind: Namespace
metadata:
  name: secure-production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
    environment: production
    security-level: high
---
apiVersion: v1
kind: Namespace
metadata:
  name: development
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/warn: restricted
    environment: development
    security-level: low

3. 서비스 메시 통합

아래 규칙은 지정한 출처와 HTTP 메서드가 동시에 일치해야 허용합니다. Istio 설치와 인증된 출처 식별 구성이 전제입니다. Istio 권한 규칙의 OR/AND 구분

# istio-namespace-isolation.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: production-mesh
  labels:
    istio-injection: enabled
    environment: production
    mesh: enabled
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: namespace-isolation
  namespace: production-mesh
spec:
  action: ALLOW
  rules:
  - from:
    - source:
        namespaces: ["production-mesh", "ingress-gateway"]
    to:
    - operation:
        methods: ["GET", "POST"]

🛠️ 실전 운영 시나리오

시나리오: 대규모 마이크로서비스 환경

가정한 규모: 50개 팀, 200개 마이크로서비스, 3개 환경(dev/staging/prod). 설계 문제를 설명하기 위한 예시 수치이며, 실제 운영 규모나 성능 검증 결과가 아닙니다.

# 1. 네임스페이스 명명 규칙 정의
# 패턴: {team}-{service-category}-{environment}
# 예: payment-api-prod, user-frontend-dev, order-backend-staging

# 2. 자동화된 네임스페이스 생성 스크립트
cat << 'EOF' > create-microservice-ns.sh
#!/bin/bash

TEAM=$1
CATEGORY=$2
ENVIRONMENTS=("dev" "staging" "prod")

for ENV in "${ENVIRONMENTS[@]}"; do
  NS_NAME="${TEAM}-${CATEGORY}-${ENV}"
  
  # 네임스페이스 생성
  kubectl create namespace $NS_NAME
  
  # 라벨링
  kubectl label namespace $NS_NAME \
    team=$TEAM \
    category=$CATEGORY \
    environment=$ENV \
    managed-by=platform-team
    
  # 환경별 리소스 할당
  case $ENV in
    "dev")
      CPU_REQ="1"; MEM_REQ="2Gi"; CPU_LIM="2"; MEM_LIM="4Gi"; MAX_PODS="10"
      ;;
    "staging")
      CPU_REQ="2"; MEM_REQ="4Gi"; CPU_LIM="4"; MEM_LIM="8Gi"; MAX_PODS="20"
      ;;
    "prod")
      CPU_REQ="4"; MEM_REQ="8Gi"; CPU_LIM="8"; MEM_LIM="16Gi"; MAX_PODS="50"
      ;;
  esac
  
  # ResourceQuota 적용
  kubectl create quota ${NS_NAME}-quota \
    --hard=requests.cpu=${CPU_REQ},requests.memory=${MEM_REQ},limits.cpu=${CPU_LIM},limits.memory=${MEM_LIM},pods=${MAX_PODS} \
    -n $NS_NAME
    
  echo "Created namespace: $NS_NAME"
done
EOF

chmod +x create-microservice-ns.sh

# 3. 팀별 네임스페이스 일괄 생성
./create-microservice-ns.sh payment api
./create-microservice-ns.sh payment frontend
./create-microservice-ns.sh user api
./create-microservice-ns.sh user frontend
./create-microservice-ns.sh order backend

가정한 문제와 대응 예시:

# 문제 1: 특정 팀의 개발 환경이 과도한 리소스 사용
kubectl top pods -A | grep payment-api-dev
# payment-api-dev 네임스페이스가 CPU 과다 사용

# 해결: 리소스 할당량 조정
# 기존 Pod 사용량을 즉시 낮추지는 않으며 이후 생성·변경 요청을 제한
kubectl patch resourcequota payment-api-dev-quota -n payment-api-dev -p '
{
  "spec": {
    "hard": {
      "limits.cpu": "1",
      "limits.memory": "2Gi"
    }
  }
}'

# 문제 2: 스테이징에서 운영 데이터에 접근
# 해결: 네트워크 정책으로 환경 간 격리 강화
kubectl apply -f - << EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: env-isolation
  namespace: payment-api-prod
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          environment: prod
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: monitoring
EOF

📚 필수 명령어 정리

네임스페이스 관련 핵심 명령어

# 네임스페이스 기본 조작
kubectl create namespace <name>
kubectl get namespaces
kubectl describe namespace <name>
kubectl delete namespace <name>

# 네임스페이스 라벨링
kubectl label namespace <name> key=value
kubectl get namespaces --show-labels
kubectl get namespaces -l key=value

# 컨텍스트와 네임스페이스
kubectl config set-context --current --namespace=<name>
kubectl config view --minify --output 'jsonpath={..namespace}'

# 네임스페이스별 리소스 조회
kubectl get all -n <namespace>
kubectl get pods --all-namespaces
kubectl get services -A

# 리소스 할당량 관리
kubectl create quota <name> --hard=requests.cpu=1,requests.memory=1Gi -n <ns>
kubectl get resourcequotas -A
kubectl describe resourcequota <name> -n <ns>

# 네트워크 정책
kubectl get networkpolicies -A
kubectl describe networkpolicy <name> -n <ns>

# 트러블슈팅
kubectl get events -n <namespace>
kubectl top pods -n <namespace>
kubectl auth can-i <verb> <resource> -n <namespace>

실용적인 alias 설정

# ~/.bashrc 또는 ~/.zshrc에 추가
alias k='kubectl'
alias kgns='kubectl get namespaces'
alias kns='kubectl config set-context --current --namespace'
alias kga='kubectl get all'
alias kgaa='kubectl get all --all-namespaces'

🚀 다음 학습 계획

이 글은 네임스페이스별로 ResourceQuota, LimitRange와 NetworkPolicy를 구성하는 예제를 정리했습니다. 팀 간 격리가 실제로 적용되는지는 권한과 네트워크 플러그인, 함께 적용된 정책까지 확인해야 합니다.

다음 학습 주제는 외부 요청을 클러스터 내부 서비스로 전달하는 방법입니다.

다음 주제들

  • Ingress를 통한 외부 트래픽 관리와 라우팅 - 클러스터의 정문 만들기
  • 스토리지와 PersistentVolume 관리 - 애플리케이션의 데이터를 영구적으로 보관하기
  • RBAC과 보안 설정 - 사용자별로 세밀한 권한 부여하기
  • 모니터링과 로깅 시스템 구축 - 클러스터와 애플리케이션의 건강 상태 관찰하기

개인 학습 목표

  • 다양한 네임스페이스 설계 패턴을 실제 프로젝트에 적용해보기
  • 복잡한 네트워크 정책을 YAML로 능숙하게 작성하는 능력 숙달
  • 자동화된 네임스페이스 관리 스크립트를 만들어 운영 효율 높이기
  • RBAC과 네임스페이스를 연동하여 팀별 권한 체계 구축 경험

다음 글에서는 외부 HTTP/HTTPS 요청을 라우팅하는 Ingress를 다룹니다.


🔗 참고 자료:


yellow.log · 2025.08.27에 작성 · 2026.09.29에 수정

CKA 준비 전체 8편

  1. 1.Pod 생성과 관리 - 쿠버네티스의 기본 단위 이해하기
  2. 2.ReplicaSet과 Deployment로 Pod 관리하기 - 확장성과 가용성 확보
  3. 3.Service를 통한 Pod 네트워킹 - 안정적인 접근 경로 만들기
  4. 4.ConfigMap과 Secret으로 설정 관리하기 - 환경별 설정 분리
  5. 5.Pod 리소스 제한과 요청 설정 - 안정적인 클러스터 운영을 위한 리소스 관리
  6. 6.Liveness와 Readiness Probe 구성 - 헬스체크와 자동 복구
  7. 7.네임스페이스를 통한 리소스 격리와 다중 테넌시 - 팀별, 환경별 격리읽는 중
  8. 8.Ingress를 통한 외부 트래픽 관리와 라우팅 - 클러스터의 똑똑한 관문 구축