🎯 8장 - 쿠버네티스 보안과 자원관리

📑 목차


1. RBAC (Role-Based Access Control): 역할 기반 접근 제어

이전 강의 복습

RBAC는 08_01에서 자세히 다뤘습니다. 여기서는 핵심 구성요소만 간략히 정리합니다.

📋 RBAC 구성요소 요약

구성요소역할스코프
Role특정 네임스페이스 내 권한 정의네임스페이스
ClusterRole클러스터 전체 권한 정의클러스터
RoleBindingRole과 사용자 연결네임스페이스
ClusterRoleBindingClusterRole과 사용자 연결클러스터

✅ 실습 결과 확인

  • dev1-hoon: get, list 권한만 보유 ✅
  • dev2-moon: get, create, delete 권한 보유 ✅
  • 크로스 네임스페이스 접근 차단 ✅

2. ResourceQuota - 시스템 자원 사용 관리

핵심 목적

네임스페이스별로 리소스 사용량을 제한하여 멀티테넌트 환경에서 공정한 자원 분배를 보장합니다. **“한 팀이 모든 리소스를 독점하지 못하게 하는 것”**이 핵심입니다.

🤔 왜 ResourceQuota가 필요한가?

📋 문제 상황 예시

시나리오: 회사에서 쿠버네티스 클러스터 하나를 여러 팀이 공유
- 개발팀 A: 대용량 ML 모델 학습 (CPU 16코어, RAM 64GB 요구)
- 개발팀 B: 웹 애플리케이션 개발 (CPU 2코어, RAM 4GB면 충분)
- 개발팀 C: 마이크로서비스 테스트 (여러 개의 작은 Pod들)

문제: 팀 A가 ML 학습을 시작하면 → 클러스터 리소스 모두 소진 → 팀 B, C 작업 불가

💡 ResourceQuota 동작 원리

🔍 할당량 vs 사용량 개념

실생활 비유

  • 할당량(Hard Limit): 은행 계좌의 “신용카드 한도”
  • 사용량(Used): 현재까지 “사용한 금액”
  • 남은 할당량: “아직 쓸 수 있는 금액”
# 📊 ResourceQuota 상세 설정
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-dev1
  namespace: dev1
spec:
  hard:
    # 1. 객체 개수 제한
    pods: "10"                          # 최대 Pod 10개
    persistentvolumeclaims: "2"         # 최대 PVC 2개
    services: "5"                       # 최대 Service 5개
    secrets: "10"                       # 최대 Secret 10개
    configmaps: "10"                    # 최대 ConfigMap 10개
    
    # 2. 컴퓨팅 리소스 제한
    requests.cpu: "4"                   # CPU 요청 총합 4코어
    requests.memory: "8Gi"              # 메모리 요청 총합 8GB
    limits.cpu: "8"                     # CPU 제한 총합 8코어
    limits.memory: "16Gi"               # 메모리 제한 총합 16GB
    
    # 3. 스토리지 리소스 제한
    requests.storage: "50Gi"            # 스토리지 요청 총합 50GB
    persistentvolumeclaims: "5"         # PVC 개수 제한
    
    # 4. 특정 스토리지 클래스 제한
    requests.nvidia.com/gpu: "2"        # GPU 개수 제한

💻 ResourceQuota 적용 과정 분석

📊 단계별 적용 결과 확인

# 1. 초기 상태 (아무것도 없음)
kubectl describe resourcequota quota-dev1 -n dev1
Name:                   quota-dev1
Namespace:              dev1
Resource                Used  Hard
--------                ----  ----
persistentvolumeclaims  0     2      # PVC: 0개 사용 / 2개 허용
pods                    0     10     # Pod: 0개 사용 / 10개 허용
requests.storage        0     2Gi    # 스토리지: 0GB 사용 / 2GB 허용

📊 Pod 생성 후 상태 변화

# test-pod 생성 후
kubectl describe resourcequota quota-dev1 -n dev1
Name:                   quota-dev1
Namespace:              dev1
Resource                Used  Hard
--------                ----  ----
persistentvolumeclaims  0     2      # PVC는 아직 생성 안함
pods                    1     10     # Pod 1개 생성됨 (9개 더 가능)
requests.storage        0     2Gi    # 스토리지는 아직 사용 안함

📊 PVC 생성 후 상태 변화

# PVC 1개 생성 후 (1Gi 크기)
kubectl apply -f quota-1G-pvc1.yaml
kubectl describe resourcequota quota-dev1 -n dev1
Name:                   quota-dev1
Namespace:              dev1
Resource                Used  Hard
--------                ----  ----
persistentvolumeclaims  1     2      # PVC 1개 사용됨 (1개 더 가능)
pods                    1     10     # Pod 1개 사용 중
requests.storage        1Gi   2Gi    # 스토리지 1GB 사용됨 (1GB 더 가능)

⚠️ ResourceQuota 제한 동작 확인

🚨 할당량 초과 시 어떻게 되는가?

# 📊 2GB 초과하는 PVC 생성 시도
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-too-large
  namespace: dev1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi    # 할당량(2Gi) 초과!

📊 예상되는 에러 메시지

kubectl apply -f pvc-too-large.yaml
Error from server (Forbidden): error when creating "pvc-too-large.yaml": 
persistentvolumeclaims "pvc-too-large" is forbidden: 
exceeded quota: quota-dev1, requested: requests.storage=3Gi, 
used: requests.storage=1Gi, limited: requests.storage=2Gi

에러 메시지 해석

  • 요청한 것: requests.storage=3Gi
  • 이미 사용 중: used: requests.storage=1Gi
  • 전체 할당량: limited: requests.storage=2Gi
  • 결과: 1Gi + 3Gi = 4Gi > 2Gi 이므로 거부됨

💡 ResourceQuota 고급 활용

📊 우선순위 클래스별 할당량

# 📊 우선순위에 따른 차등 할당
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-high-priority
  namespace: dev1
spec:
  hard:
    pods: "5"
    requests.cpu: "10"
    requests.memory: "20Gi"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["high-priority"]
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-low-priority
  namespace: dev1
spec:
  hard:
    pods: "20"
    requests.cpu: "2"
    requests.memory: "4Gi"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values: ["low-priority"]

📊 실시간 모니터링 명령어

# 모든 네임스페이스의 ResourceQuota 확인
kubectl get resourcequota --all-namespaces
 
# 특정 리소스 사용량 감시
watch kubectl describe resourcequota quota-dev1 -n dev1
 
# JSON 형태로 상세 정보 확인
kubectl get resourcequota quota-dev1 -n dev1 -o json | jq '.status'

🎯 실전에서의 ResourceQuota 설계

🤔 질문: “팀별로 어떻게 할당량을 나눠야 할까?”

📋 할당량 계산 방법

실제 계산 과정

전체 클러스터 리소스: CPU 32코어, RAM 128GB, Storage 1TB

팀별 특성 분석:

  • 개발팀 A (ML): 고사양 필요, 작업 수 적음
  • 개발팀 B (웹): 중간 사양, 여러 환경 필요
  • 개발팀 C (마이크로서비스): 저사양, Pod 수 많음

할당 전략:

# 팀 A (ML팀)
requests.cpu: "12"      # 전체의 37.5%
requests.memory: "48Gi" # 전체의 37.5%
pods: "5"               # 적은 수의 고사양 Pod
 
# 팀 B (웹팀) 
requests.cpu: "8"       # 전체의 25%
requests.memory: "32Gi" # 전체의 25%
pods: "15"              # 중간 수의 Pod
 
# 팀 C (마이크로서비스팀)
requests.cpu: "8"       # 전체의 25%
requests.memory: "32Gi" # 전체의 25%
pods: "50"              # 많은 수의 소형 Pod
 
# 시스템 예약
남은 12.5% = 시스템 Pod 및 예비 할당량

📊 동적 할당량 조정 스크립트

#!/bin/bash
# 📊 사용률 기반 할당량 모니터링
 
NAMESPACE="dev1"
QUOTA_NAME="quota-dev1"
 
# 현재 사용률 확인
USED_PODS=$(kubectl get resourcequota $QUOTA_NAME -n $NAMESPACE -o jsonpath='{.status.used.pods}')
HARD_PODS=$(kubectl get resourcequota $QUOTA_NAME -n $NAMESPACE -o jsonpath='{.status.hard.pods}')
 
USAGE_PERCENT=$((USED_PODS * 100 / HARD_PODS))
 
echo "Pod 사용률: $USAGE_PERCENT% ($USED_PODS/$HARD_PODS)"
 
# 80% 초과 시 알림
if [ $USAGE_PERCENT -gt 80 ]; then
    echo "⚠️  경고: Pod 할당량이 80%를 초과했습니다!"
    echo "📊 확장을 검토해주세요."
fi

이제 ResourceQuota가 어떻게 작동하는지, 왜 필요한지, 어떻게 설계해야 하는지 명확해졌나요? 💡


3. LimitRange - 리소스 제한 정책

활용법

개별 리소스 객체에 대한 최소/최대 사용량을 설정하여 리소스 남용을 방지합니다.

💻 LimitRange 설정 예시

# 📊 dev1 네임스페이스 리소스 제한 정책
apiVersion: v1
kind: LimitRange
metadata:
  name: limitrange-dev1
  namespace: dev1
spec:
  limits:
  - default:              # 기본 제한값
      memory: "512Mi"
      cpu: "500m"
    defaultRequest:       # 기본 요청값
      memory: "256Mi"
      cpu: "250m"
    type: Container
  - max:                 # 최대값
      storage: "1Gi"
    min:                 # 최소값
      storage: "100Mi"
    type: PersistentVolumeClaim

📊 LimitRange 효과 확인

Pod 생성 시 리소스 명시를 하지 않으면 자동으로 기본값이 적용됩니다:

kubectl describe pod test-pod -n dev1
Requests:
  cpu:        250m      # 기본 요청값 자동 적용
  memory:     256Mi     # 기본 요청값 자동 적용
Limits:
  cpu:        500m      # 기본 제한값 자동 적용
  memory:     512Mi     # 기본 제한값 자동 적용

4. NetworkPolicy - 네트워크 보안 🛡️

핵심 목적

NetworkPolicy는 **“Pod 간의 네트워크 통신을 세밀하게 제어”**하는 방화벽 같은 역할을 합니다. **“누가, 어디서, 어떤 Pod에 접근할 수 있는가”**를 정의합니다.

🤔 왜 NetworkPolicy가 필요한가?

📋 보안 위험 시나리오

상황: 마이크로서비스 환경
- 웹 프론트엔드 Pod
- API 서버 Pod  
- 데이터베이스 Pod
- 결제 처리 Pod (민감한 정보)

문제: 기본적으로 모든 Pod가 서로 자유롭게 통신 가능
→ 웹 프론트엔드에서 직접 데이터베이스 접근 가능 (보안 취약점)
→ 공격자가 하나의 Pod를 해킹하면 모든 Pod에 접근 가능

🎯 NetworkPolicy의 핵심 원칙

기본 동작 방식

  1. 기본 상태: 모든 트래픽 허용 (관대한 정책)
  2. NetworkPolicy 적용: 명시적으로 허용된 것만 통신 (엄격한 정책)
  3. 화이트리스트 방식: 허용 목록에 있는 것만 통과

💡 NetworkPolicy 핵심 개념

🔍 Ingress vs Egress - 쉬운 이해법

💡 나의 집 관점에서 생각해보자!

내가 database Pod라고 상상해보세요.

Ingress (들어오는 것):

  • 다른 Pod가 나(database)에게 와서 데이터를 요청하는 것
  • “누가 나한테 올 수 있나요?”
  • API Pod → 나(Database) ✅ 허용
  • Web Pod → 나(Database) ❌ 차단

Egress (나가는 것):

  • 내(database)가 다른 곳으로 나가는 것
  • “내가 어디로 갈 수 있나요?”
  • 나(Database) → 로그 서버 ✅ 허용
  • 나(Database) → 인터넷 ❌ 차단

📊 구체적인 예시로 이해하기

# 상황: 웹쇼핑몰 시스템
# - web-pod (웹페이지) 
# - api-pod (API 서버)
# - db-pod (데이터베이스)
 
# 시나리오 1: 고객이 상품 목록을 보고 싶어함
1. 웹브라우저 web-pod (HTTP 요청)
2. web-pod api-pod (상품 목록 요청) 
3. api-pod db-pod (DB 쿼리)
4. db-pod api-pod (결과 리턴)
5. api-pod web-pod (결과 리턴)
6. web-pod 웹브라우저 (화면 표시)

🎯 각 Pod 입장에서 생각해보기

# db-pod 입장에서:
# "나는 데이터베이스야. 나한테 누가 올 수 있지?"
 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-policy
spec:
  podSelector:
    matchLabels:
      app: database     # 나는 database Pod이야
  policyTypes:
  - Ingress           # 누가 나한테 올 수 있는지만 제어
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api      # api-pod만 나한테 올 수 있어!
    ports:
    - protocol: TCP
      port: 3306        # MySQL 포트로만!

이해 포인트!

  • database-pod는 “받기만” 하는 역할 → Ingress만 설정
  • api-pod만 허용하고, web-pod는 직접 접근 차단
  • 이게 바로 “계층별 보안”!

📊 NetworkPolicy 구조 분석

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: example-policy
  namespace: production
spec:
  # 1. 어떤 Pod에 적용할지 선택 (필수)
  podSelector:
    matchLabels:
      app: database
  
  # 2. 어떤 방향의 트래픽을 제어할지 (필수)
  policyTypes:
  - Ingress    # 들어오는 트래픽 제어
  - Egress     # 나가는 트래픽 제어
  
  # 3. 허용할 Ingress 규칙 (선택)
  ingress:
  - from:      # 어디서 오는 트래픽을 허용할지
    - podSelector:
        matchLabels:
          app: api-server
    ports:     # 어떤 포트를 허용할지
    - protocol: TCP
      port: 5432
  
  # 4. 허용할 Egress 규칙 (선택)  
  egress:
  - to:        # 어디로 가는 트래픽을 허용할지
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 80

🎯 NetworkPolicy 단계별 실습

🎯 우리가 실습한 상황 다시보기

💡 복잡한 이론은 그만! 우리가 방금 테스트한 결과로 이해해봅시다!

실제 테스트 결과:

# ❌ 이건 막혔어요 (5초 후 타임아웃)
kubectl exec netshoot-pod -- curl --connect-timeout 5 http://172.16.0.169
 
# ✅ 이건 성공했어요 (nginx 페이지 나옴)  
kubectl exec netshoot-pod -- curl http://172.16.0.36

🤔 왜 이런 결과가 나왔을까요?

📊 Pod 정보 다시 확인

kubectl get pods -o wide --show-labels
Pod 이름IP 주소라벨결과
sensitive-pod172.16.0.169role=sensitive❌ 접근 차단
internal-pod172.16.0.36role=internal✅ 접근 성공

🔍 비밀은 여기에 있습니다!

# 우리가 적용한 NetworkPolicy 다시보기
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: networkpolicy-deny-all
spec:
  podSelector:
    matchLabels:
      role: sensitive    # 🎯 핵심! 이 라벨을 가진 Pod만!
  policyTypes:
  - Ingress
  - Egress
  # 허용 규칙이 없음 = 모든 접근 차단

🏠 집 문단속 비유로 이해하기

우리 동네에 집이 4개 있어요:

  • sensitive-pod 집 (172.16.0.169) → 🔒 문단속 완료 (NetworkPolicy 적용)
  • internal-pod 집 (172.16.0.36) → 🚪 문 열려있음 (정책 적용 안됨)
  • chk-info-pod 집 (172.16.0.249) → 🚪 문 열려있음
  • netshoot-pod 집 (172.16.0.34) → 🚪 문 열려있음

netshoot-pod가 방문하려고 할 때:

  • sensitive-pod 집: 🔒 “문이 잠겨있어서 못들어가요!” (차단)
  • internal-pod 집: 🚪 “문이 열려있어서 들어갈 수 있어요!” (허용)

🧠 핵심 포인트 3가지만 기억하세요!

  1. podSelector: “어떤 집에 문단속을 할까?”
    • role: sensitive = sensitive-pod만 선택
  2. policyTypes: “어떤 방향을 막을까?”
    • Ingress = 들어오는 사람 막기
    • Egress = 나가는 사람 막기
  3. 허용 규칙: “누구는 들어올 수 있을까?”
    • 없음 = 아무도 못들어옴 (완전 차단)

🎯 이제 직접 해봅시다!

Q1: 만약 role: internal 라벨을 가진 Pod도 막고 싶다면 어떻게 해야 할까요?

정답 보기
# 방법 1: 새로운 정책 추가
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: block-internal-too
spec:
  podSelector:
    matchLabels:
      role: internal    # internal-pod도 차단!
  policyTypes:
  - Ingress
  - Egress
 
# 방법 2: 기존 정책 수정 (여러 라벨 선택)
spec:
  podSelector:
    matchExpressions:
    - key: role
      operator: In
      values: ["sensitive", "internal"]

Q2: 우리 테스트에서 internal-pod가 차단 안된 이유는?

답: internal-pod는 role: internal 라벨을 가지고 있는데, 우리 정책은 role: sensitive만 대상으로 하기 때문!


STEP 2: PodSelector 기반 선택적 허용

화이트리스트 방식

“특정 Pod에서 오는 트래픽만 허용” - 마치 초대장이 있는 사람만 입장 허용하는 것과 같습니다.

# 📊 선택적 허용 정책
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-specific-pods
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: internal        # 보호받을 Pod
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: chk-info     # 이 라벨을 가진 Pod에서만 접근 허용
    ports:
    - protocol: TCP
      port: 80             # HTTP 포트만 허용
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: chk-info     # 이 라벨을 가진 Pod로만 나갈 수 있음
    ports:
    - protocol: TCP
      port: 80

📊 통신 가능 여부 매트릭스

출발지 Pod목적지 Pod결과이유
netshoot-podinternal-pod❌ 차단netshoot-pod에 app: chk-info 라벨 없음
chk-info-podinternal-pod✅ 허용chk-info-pod가 화이트리스트에 포함
internal-podchk-info-pod✅ 허용egress 규칙에 명시됨
internal-podexternal-service❌ 차단egress 규칙에 없음

STEP 3: IP Block 기반 제어

실제 시나리오

“내부 네트워크(172.16.0.0/16)에서만 접근 허용하고, 특정 IP 대역(172.16.6.0/24)은 제외”

# 📊 IP 기반 접근 제어
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-internal-network
  namespace: default
spec:
  podSelector: {}           # 모든 Pod에 적용
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.16.0.0/16    # 내부 네트워크 허용
        except:
        - 172.16.6.0/24        # 특정 대역 제외
    ports:
    - protocol: TCP
      port: 80
  egress:
  - to:
    - ipBlock:
        cidr: 172.16.0.0/16    # 내부로만 나가기 허용
    ports:
    - protocol: TCP
      port: 80
  - to: {}                     # DNS 해석을 위해 모든 UDP 허용
    ports:
    - protocol: UDP
      port: 53

🔍 IP Block 정책 해석

접근 시도IP 주소결과이유
Pod → Pod172.16.0.100✅ 허용내부 네트워크 범위
Pod → Pod172.16.6.50❌ 차단except 범위에 포함
Pod → 외부8.8.8.8❌ 차단내부 네트워크 범위 밖
Pod → DNS172.16.0.10:53✅ 허용DNS용 UDP 허용

STEP 4: Namespace 간 통신 제어

네임스페이스 격리

“dev2 네임스페이스의 Pod들만 서로 통신 가능, 다른 네임스페이스와는 격리”

# 📊 네임스페이스 격리 정책
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: isolate-namespace
  namespace: dev2
spec:
  podSelector: {}               # dev2 네임스페이스의 모든 Pod
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:        # 같은 네임스페이스만 허용
        matchLabels:
          kubernetes.io/metadata.name: dev2
  egress:
  - to:
    - namespaceSelector:        # 같은 네임스페이스로만 허용
        matchLabels:
          kubernetes.io/metadata.name: dev2
  - to: {}                      # 외부 서비스 호출 허용
    ports:
    - protocol: TCP
      port: 443                 # HTTPS
    - protocol: UDP
      port: 53                  # DNS

🔧 NetworkPolicy 디버깅 방법

📊 문제 해결 단계

# 1. NetworkPolicy 확인
kubectl get networkpolicy -A
kubectl describe networkpolicy deny-all-traffic
 
# 2. Pod 라벨 확인
kubectl get pods --show-labels
 
# 3. 실시간 연결 테스트
kubectl exec -it netshoot-pod -- bash
# Pod 내부에서:
curl -v --connect-timeout 10 http://target-pod-ip
ping target-pod-ip
nslookup target-service
 
# 4. 네트워크 정책 적용 확인
kubectl logs -n kube-system -l app=cilium    # Cilium CNI 사용 시

🚨 자주 발생하는 문제들

문제증상해결 방법
DNS 해석 실패nslookup 안됨egress에 UDP 53포트 허용 추가
예상과 다른 차단허용되어야 할 통신 차단Pod 라벨과 selector 일치 확인
정책 적용 안됨모든 통신이 계속 허용됨CNI가 NetworkPolicy 지원하는지 확인
부분적 차단일부 연결만 차단됨ingress/egress 규칙 모두 확인

🎯 실전 NetworkPolicy 설계 패턴

Pattern 1: 계층별 보안 (3-Tier Architecture)

# 📊 웹 계층 → API 계층만 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-layer-policy
spec:
  podSelector:
    matchLabels:
      tier: api
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: web
    ports:
    - protocol: TCP
      port: 8080
 
---
# 📊 API 계층 → DB 계층만 허용  
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-layer-policy
spec:
  podSelector:
    matchLabels:
      tier: database
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: api
    ports:
    - protocol: TCP
      port: 5432

Pattern 2: 환경별 격리 (개발/스테이징/프로덕션)

# 📊 프로덕션 환경 완전 격리
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: production-isolation
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          env: production
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          env: production

🚨 실무에서의 NetworkPolicy 관리 - 복잡도 해결하기

현실적 문제

“Pod가 수십개, 수백개 되면 어떻게 관리하지? 뭘 놓치고 있는지도 모르겠어…”

이런 고민이 정말 현실적이고 중요합니다! 🎯

🔍 실무에서 사용하는 해결책들

1. 라벨링 전략 - 체계적 분류

회사에서 실제 사용하는 라벨 체계

# 🏷️ 표준 라벨링 규칙
metadata:
  labels:
    # 계층 구분
    tier: "web|api|database|cache"
    # 환경 구분  
    env: "dev|staging|prod"
    # 팀 구분
    team: "frontend|backend|devops|ml"
    # 보안 등급
    security-level: "public|internal|confidential|restricted"
    # 애플리케이션
    app: "user-service|order-service|payment-service"

2. 네트워크 정책 템플릿화

# 📋 Template 1: 기본 계층별 보안
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tier-based-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      tier: database
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: api    # API 계층에서만 DB 접근 가능
    ports:
    - protocol: TCP
      port: 3306
 
---
# 📋 Template 2: 환경별 격리
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy  
metadata:
  name: env-isolation
  namespace: staging
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          env: staging    # 같은 환경끼리만
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          env: staging

3. NetworkPolicy 시각화 도구

# 🔍 실무에서 사용하는 검증 도구들
 
# 1. NetworkPolicy 현황 파악
kubectl get networkpolicy --all-namespaces -o wide
 
# 2. Pod 라벨 한눈에 보기  
kubectl get pods --all-namespaces --show-labels | grep -E "(tier|env|team)"
 
# 3. 네트워크 연결 테스트 자동화
#!/bin/bash
# network-test.sh
PODS=$(kubectl get pods -o name)
for pod in $PODS; do
  echo "Testing connectivity from $pod"
  kubectl exec $pod -- timeout 5 nc -zv target-ip 80 || echo "BLOCKED"
done

4. GitOps + IaC로 관리

# 📁 네트워크 정책을 코드로 관리
# infrastructure/
# ├── network-policies/
# │   ├── base/
# │   │   ├── deny-all.yaml
# │   │   ├── allow-dns.yaml  
# │   │   └── allow-monitoring.yaml
# │   ├── environments/
# │   │   ├── dev/
# │   │   ├── staging/
# │   │   └── prod/
# │   └── applications/
# │       ├── web-tier.yaml
# │       ├── api-tier.yaml
# │       └── db-tier.yaml

🎯 단계별 도입 전략 (현실적 접근)

Phase 1: 기본 보안 적용

# 1. 일단 모든 네임스페이스에 기본 규칙만 적용
kubectl apply -f base-security-policies.yaml
# base-security-policies.yaml
# 🚨 최소한의 보안 - DNS만 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-only
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to: []
    ports:
    - protocol: UDP
      port: 53    # DNS만 허용

Phase 2: 점진적 세분화

# 높은 위험도부터 세분화
# 1. 데이터베이스 먼저
# 2. 결제 시스템 
# 3. 사용자 인증
# 4. 일반 API

Phase 3: 모니터링 & 검증

# 🔍 정기적 검증 스크립트
#!/bin/bash
echo "=== NetworkPolicy 검증 레포트 ==="
echo "1. 보호되지 않은 데이터베이스 Pod:"
kubectl get pods -l tier=database --all-namespaces -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | while read ns name; do
  if ! kubectl get networkpolicy -n $ns | grep -q $name; then
    echo "⚠️  $ns/$name - 정책 없음!"
  fi
done
 
echo "2. 외부 접근 가능한 Pod:"
# 외부 IP로 접근 가능한 Pod 검사 로직

🛠️ 실무 팁 & 트릭

1. 디버깅용 임시 정책

# 🚧 문제 해결용 - 모든 것 허용 (임시)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: debug-allow-all
  annotations:
    purpose: "debugging-only"
    expires: "2025-12-01"
spec:
  podSelector:
    matchLabels:
      debug: "true"
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - {}
  egress:
  - {}

2. 점검 체크리스트

# 📋 NetworkPolicy 배포 전 체크리스트
 
- [ ] DNS 해석이 가능한가? (UDP 53 허용)
- [ ] 모니터링 시스템 접근 가능한가?
- [ ] Health check 엔드포인트 접근 가능한가?
- [ ] 로그 수집 시스템 접근 가능한가?
- [ ] 필수 외부 API 호출 가능한가?
 
# 🧪 테스트 스크립트
kubectl exec test-pod -- nslookup google.com     # DNS 체크
kubectl exec test-pod -- curl health-check-url   # Health 체크  
kubectl exec test-pod -- wget monitoring-url     # 모니터링 체크

3. 응급 상황 대응

# 🚨 네트워크 정책으로 인한 장애 시 응급 대응
 
# 1. 특정 정책 즉시 비활성화
kubectl patch networkpolicy problematic-policy -p '{"spec":{"podSelector":{"matchLabels":{"disabled":"true"}}}}'
 
# 2. 전체 네임스페이스 정책 임시 해제
kubectl get networkpolicy -n problem-namespace -o name | xargs kubectl delete
 
# 3. 긴급 허용 정책 적용
kubectl apply -f emergency-allow-all.yaml

🎯 실무 권장 사항

큰 조직에서 실제 사용하는 방법

1. 조직별 책임 분담

  • 플랫폼팀: 기본 정책 템플릿 제공
  • 보안팀: 보안 요구사항 정의
  • 개발팀: 애플리케이션별 세부 정책

2. 도구 활용

  • Helm: 정책 템플릿 배포
  • ArgoCD: GitOps로 정책 관리
  • OPA Gatekeeper: 정책 준수 강제
  • Cilium: 고급 네트워크 정책

3. 단계적 적용

  • 먼저 관찰 모드로 시작
  • 점진적으로 엄격하게 변경
  • 충분한 모니터링과 알림 설정

결론: NetworkPolicy는 혼자 관리하는게 아니라, 도구와 프로세스로 체계적으로 관리하는 것! 🎯

복잡하다고 포기하지 마시고, 작은 것부터 체계적으로 시작하는게 핵심입니다! 😊


🎯 실전 예시

💡 멀티테넌트 환경 보안 설정

🤔 질문: “개발팀별로 리소스를 분리하고 보안을 적용하려면?”

📋 구체적인 시나리오

실제 상황

  1. 문제: dev1팀과 dev2팀이 같은 클러스터를 사용하는데 서로의 리소스에 접근 가능
  2. 요구사항: 팀별 격리, 리소스 할당량 제한, 네트워크 격리
  3. 해결방법: RBAC + ResourceQuota + NetworkPolicy 조합
  4. 결과: 안전하고 공정한 멀티테넌트 환경 구축

💻 통합 보안 설정

# 1. RBAC 설정
kubectl apply -f ns-sa-dev-both.yaml
kubectl apply -f dev1/role-get-dev1.yaml
kubectl apply -f dev1/rolebinding-dev1.yaml
 
# 2. 리소스 할당량 설정
kubectl apply -f ResourceQuota.yaml
 
# 3. 리소스 제한 정책 설정
kubectl apply -f LimitRange.yaml
 
# 4. 네트워크 보안 정책 설정
kubectl apply -f 1-2-NetworkPolicy-deny-all.yaml
 
# 검증
kubectl get resourcequota,limitrange,networkpolicy -n dev1

📊 보안 정책 효과 측정

보안 영역적용 전적용 후개선 효과
권한 관리모든 사용자가 전체 접근역할별 최소 권한🔒 권한 격리
리소스 사용무제한 사용 가능팀별 할당량 제한⚖️ 공정한 분배
네트워크모든 통신 허용정책 기반 차단🛡️ 네트워크 격리