[Project] Multi-Tenant K8s Cluster on ARM64 - (5) Zero-Trust Network Policy - 1

developowl·2026년 3월 6일
post-thumbnail
  • 현재 클러스터는 자원은 분리되어 있지만, 네트워크는 여전히 모두가 모두와 대화할 수 있는 상태
  • 이를 해결하기 위해 Zero-Trust 기반 Network Policy 설정을 진행

1. [기능 설명] Network Isolation

  • 쿠버네티스의 기본 네트워크 구조는 Flat Network
    • 네임스페이스가 달라도 서로의 IP만 알면 통신이 가능한 구조
  • Network Policy 는 파드로 드나드는 트래픽을 제어하는 L3/L4 방화벽 역할을 수행

1-1. 주요 설계 목표

  • 테넌트 간 통신 차단 : tenant-alpha 네임스페이스에 속한 파드들은 다른 테넌트 네임스페이스의 파드와 통신할 수 없어야 함
  • 내부 통신만 허용 (Intra-Namespace) : 같은 네임스페이스 안에 있는 파드들끼리는 자유롭게 데이터를 주고받을 수 있게 함

구조가 헷갈릴 수 있으나 정리를 하자면,
외부 트래픽은 막고(테넌트 간 통신 차단) - 내부 파드끼리는 통신 가능한(내부 통신만 허용) 구조입니다.

1-2. 필요한 쿠버네티스 기술 객체

NetworkPolicy

  • 어떤 트래픽을 허용(Allow) 할지 정의하는 규칙
    • 쿠버네티스 네트워크 정책은 기본적으로 허용되지 않은 모든 것은 거부(Deny) 하는 방식으로 작동함 → Default Deny 모델

📌 CNI(Coontainer Network Interface) 호환성

  • 설정이 실제로 동작하려면 클러스터에 Network Policy 를 지원하는 CNI 가 설치되어 있어야 함
  • 확인 사항 : 라즈베리파이에서 주로 사용하는 Flannel(현재 사용 중)은 기본적으로 Network Policy를 지원하지 않음..
    • CalicoCilium, 또는 Flannel 위에 Canal을 얹어서 사용 중이라면 정책이 즉시 반영됨.
  • 동작 원리 : 정책을 적용하는 순간, 해당 파드와 연결된 가상 인터페이스에 iptables 혹은 eBPF 규칙이 생성되어 패킷을 필터링 함
  • -> 우선 Flannel 에서 Calico 로 CNI 설정을 변경하도록 하겠습니다.

2. [기능 개발] 테넌트 간 격리 정책 작성

  • tenant-alpha 에 동일 네임스페이스가 아니면 다 차단하는 정책을 적용

2-1. 네임스페이스 레이블링

  • 네트워크 정책에서 네임스페이스를 구분하려면 각 네임스페이스에 Label(이름표 역할)이 붙어 있어야 함
# tenant-alpha 네임스페이스에 label 부착
kubectl label namespace tenant-alpha ns-name=tenant-alpha

2-2. 네트워크 격리 정의 (tenant-network-policy.yaml)

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-other-namespaces
  namespace: tenant-alpha
spec:
  podSelector: {} # {}는 이 네임스페이스 내의 모든 파드를 의미함
  policyTypes:
  - Ingress # 들어오는 트래픽 제어
  ingress:
  - from:
    - podSelector: {} # 동일 네임스페이스 내의 모든 파드로부터의 접속 허용
    - namespaceSelector:
        matchLabels:
          ns-name: tenant-alpha # 본인의 네임스페이스에서 오는 것만 허용
  • podSelector: {} 만 단독으로 있으면 ‘해당 네임스페이스 내의 모든 파드’를 의미

3. [검증 테스트] 차단 확인 절차

3-1. 정책 적용

kubectl apply -f tenant-network-policy.yaml

3-2. 테넌트 내 통신 (Intra-Namespace)

  • 시나리오: tenant-alpha 네임스페이스 내부의 local-tester 파드에서 웹 서버(limit-test-pod)로 접속을 시도
# 1. 대상 파드의 최신 IP 확인
TARGET_IP=$(kubectl get pod limit-test-pod -n tenant-alpha -o jsonpath='{.status.podIP}')

# 2. 내부 통신 시도 (성공 시 HTML 코드 출력)
kubectl exec local-tester -n tenant-alpha -- wget -qO- --timeout=2 $TARGET_IP

→ Nginx의 Welcome 메시지가 담긴 HTML 소스코드가 출력

3-3. 테넌트 간 통신 (Inter-Namespace / 침입 테스트)

  • 시나리오: default 네임스페이스에 임시 파드를 생성하여 tenant-alpha 내부의 웹 서버로 무단 접속을 시도
# 외부(default NS)에서 침입 시도 (차단 시 Timeout 발생)
kubectl run intruder -n default --image=busybox --restart=Never -it --rm -- wget -qO- --timeout=5 $TARGET_IP

wget: download timed out 메시지 출력 (격리 성공!)

Connection Refused 가 아닌 Timeout 이 발생하는 이유는, Network Policy 가 패킷이 들어오는 단계에서 조용히 드롭시키기 때문이다..

📌 Connection Refused vs. Timeout

  • Connection Refused
    • 서버까지 패킷은 도달했으나, 포트가 닫혀 있어 운영체제가 거절 응답(RST)을 보낸 경우
  • Timeout
    • 패킷이 방화벽(Network Policy)에 의해 입구에서 소멸(Drop)되어 서버가 패킷의 존재조차 모르는 상태.
    • Zero-Trust 관점에서는 내부 정보를 일절 노출하지 않는 이 방식이 더 안전하다..
profile
Don’t get mad at the computer.

0개의 댓글