이 글에서는 Cilium의 네트워크 정책과 쿠버네티스 기본 NetworkPolicy의 차이점을 상세히 비교해 보겠습니다. 두 정책 유형은 같은 목적을 가지고 있지만, 리소스 정의 방식, 기능 범위, 그리고 내부 동작에 있어 중요한 차이가 있습니다. 이번 글에서는 각 정책 유형의 특징, 문법적 차이, 지원하는 기능의 범위, 그리고 실제 환경에서 두 정책을 함께 사용할 때 고려해야 할 호환성 사항까지 살펴보겠습니다.
📌 네트워크 정책의 기본 개념
쿠버네티스에서 네트워크 정책은 Pod 간의 통신을 제어하는 규칙을 정의합니다. 이를 통해 애플리케이션의 보안을 강화하고, "최소 권한 원칙"을 구현할 수 있습니다.
✅ 네트워크 정책의 필요성
쿠버네티스는 기본적으로 모든 Pod 간 통신을 허용하는 "플랫 네트워크" 모델을 사용합니다:
# 기본 쿠버네티스 네트워킹 특성
# 1. 모든 Pod는 다른 모든 Pod에 제한 없이 접근 가능
# -> 이는 보안 관점에서 위험할 수 있으며 의도하지 않은 접근을 허용함
# 2. 네임스페이스 구분이 없음 - 다른 네임스페이스의 Pod도 접근 가능
# -> 논리적 분리가 있어도 네트워크 분리는 기본적으로 없음
# 3. 클러스터 외부에서 오는 트래픽도 기본적으로 제한 없음
# -> 외부 공격에 취약할 수 있음
이러한 개방적인 모델은 개발 편의성을 제공하지만, 보안 측면에서는 취약점이 될 수 있습니다:
- 수평적 이동 위험: 하나의 Pod가 침해되면 클러스터 내 모든 곳으로 공격이 확산될 수 있습니다.
- 서비스 간 불필요한 통신: 서비스 간 의존성이 명확하지 않으면 불필요한 트래픽이 발생할 수 있습니다.
- 규정 준수 어려움: 많은 보안 표준은 네트워크 세분화를 요구합니다.
네트워크 정책은 이러한 문제를 해결하기 위한 솔루션입니다.
📌 쿠버네티스 기본 NetworkPolicy
쿠버네티스는 NetworkPolicy 리소스를 통해 기본적인 네트워크 정책 기능을 제공합니다.
✅ 기본 구조 및 특징
쿠버네티스 NetworkPolicy의 기본 구조는 다음과 같습니다:
# 기본 쿠버네티스 NetworkPolicy 예시
apiVersion: networking.k8s.io/v1 # 네트워킹 API 그룹의 v1 버전 사용
kind: NetworkPolicy # 리소스 종류는 NetworkPolicy
metadata:
name: test-network-policy # 정책 이름 - 식별을 위한 고유 이름
namespace: default # 정책이 적용될 네임스페이스 - 정책은 이 네임스페이스 내에서만 적용됨
spec:
podSelector: # 정책이 적용될 Pod 선택 (레이블 기반)
matchLabels:
role: db # role=db 레이블이 있는 Pod에 정책 적용 - 다른 Pod에는 적용되지 않음
policyTypes: # 정책 타입 지정 (Ingress, Egress 또는 둘 다)
- Ingress # 들어오는 트래픽에 대한 규칙 적용
- Egress # 나가는 트래픽에 대한 규칙 적용
ingress: # 인그레스(들어오는) 트래픽 규칙
- from: # 허용할 트래픽 출발지 목록 - 여러 조건은 OR 관계로 평가됨
- ipBlock: # IP 기반 허용 - 특정 IP 대역에서 오는 트래픽만 허용
cidr: 172.17.0.0/16 # 172.17.0.0/16 대역의 IP에서 오는 트래픽 허용
except: # 제외할 IP 대역 - 허용 대역 내에서 특정 부분만 제외
- 172.17.1.0/24 # 172.17.1.0/24 대역은 허용하지 않음
- namespaceSelector: # 네임스페이스 기반 허용 - 특정 레이블의 네임스페이스에서 오는 트래픽
matchLabels:
project: myproject # project=myproject 레이블이 있는 네임스페이스에서 오는 트래픽 허용
- podSelector: # Pod 레이블 기반 허용 - 특정 레이블의 Pod에서 오는 트래픽
matchLabels:
role: frontend # role=frontend 레이블이 있는 Pod에서 오는 트래픽 허용
ports: # 허용할 포트 목록 - 위의 출발지에서 이 포트로 들어오는 트래픽만 허용
- protocol: TCP # TCP 프로토콜만 허용
port: 6379 # 6379 포트만 허용 (Redis 포트)
egress: # 이그레스(나가는) 트래픽 규칙
- to: # 허용할 트래픽 목적지 목록
- ipBlock: # IP 기반 허용 - 특정 IP 대역으로 나가는 트래픽만 허용
cidr: 10.0.0.0/24 # 10.0.0.0/24 대역으로의 트래픽 허용
ports: # 허용할 포트 목록 - 위의 목적지의 이 포트로 나가는 트래픽만 허용
- protocol: TCP # TCP 프로토콜만 허용
port: 5978 # 5978 포트만 허용
✅ 주요 특징
쿠버네티스 NetworkPolicy의 주요 특징은 다음과 같습니다:
- 표준 쿠버네티스 리소스: 모든 쿠버네티스 클러스터에서 공통적으로 지원하는 API입니다.
- 지원하는 선택자 타입:
- podSelector: 특정 Pod를 선택
- namespaceSelector: 특정 네임스페이스의 모든 Pod를 선택
- ipBlock: IP CIDR 블록 기반 선택
- 지원하는 트래픽 방향:
- ingress: Pod로 들어오는 트래픽
- egress: Pod에서 나가는 트래픽
- L3/L4 수준 제어:
- IP 주소 (CIDR)
- 포트 번호
- 프로토콜 (TCP/UDP/SCTP)
- '화이트리스트' 방식: 명시적으로 허용된 트래픽만 통과시키고 나머지는 차단합니다.
✅ 제한 사항
쿠버네티스 기본 NetworkPolicy의 주요 제한 사항은 다음과 같습니다:
- L7 지원 부재: HTTP 헤더, 경로, 메서드와 같은 애플리케이션 계층(L7) 속성에 기반한 필터링을 지원하지 않습니다.
- 선택자 조합의 OR 연산 불가: podSelector와 namespaceSelector를 함께 사용할 때 AND 또는 OR 관계의 명확한 지정이 어려울 수 있습니다.
- 네임스페이스 간 정책 적용 어려움: 네임스페이스 기반의 접근 방식으로 인해 클러스터 전체 정책 적용이 복잡합니다.
- CNI 구현에 따른 차이: 실제 동작은 사용 중인 CNI 플러그인의 NetworkPolicy 구현에 의존합니다.
📌 Cilium의 NetworkPolicy
Cilium은 자체적인 CiliumNetworkPolicy CRD(Custom Resource Definition)를 제공하여 더 확장된 기능을 제공합니다.
✅ 기본 구조
CiliumNetworkPolicy의 기본 구조는 다음과 같습니다:
# CiliumNetworkPolicy 예시
apiVersion: "cilium.io/v2" # Cilium의 API 그룹 및 버전 - Cilium 전용 API
kind: CiliumNetworkPolicy # 리소스 종류는 CiliumNetworkPolicy - Cilium 전용 리소스
metadata:
name: "cidr-rule" # 정책 이름 - 식별을 위한 고유 이름
namespace: default # 정책이 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod 선택 - K8s의 podSelector와 유사하지만 용어가 다름
matchLabels:
app: myapp # app=myapp 레이블이 있는 Pod에 정책 적용
egress: # 이그레스(나가는) 트래픽 규칙
- toEndpoints: # 특정 엔드포인트로의 트래픽 - K8s의 to.podSelector와 유사
- matchLabels: # 레이블 기반 매칭 - 이 레이블을 가진 Pod로의 트래픽만 허용
app: redis # app=redis 레이블이 있는 Pod로의 트래픽 허용
toPorts: # 허용할 포트 목록 - K8s의 ports와 유사하지만 구조가 다름
- ports:
- port: "6379" # Redis 포트 - 문자열로 지정해야 함 (K8s는 숫자)
protocol: TCP # TCP 프로토콜만 허용
- toCIDR: # 특정 IP CIDR로의 트래픽 - K8s의 to.ipBlock과 유사
- 172.20.0.0/24 # 172.20.0.0/24 대역으로의 트래픽 허용
toPorts: # 허용할 포트 목록
- ports:
- port: "80" # HTTP 포트
protocol: TCP # TCP 프로토콜만 허용
ingress: # 인그레스(들어오는) 트래픽 규칙
- fromEndpoints: # 특정 엔드포인트로부터의 트래픽 - K8s의 from.podSelector와 유사
- matchLabels:
app: frontend # app=frontend 레이블이 있는 Pod에서 오는 트래픽 허용
toPorts: # 허용할 포트 목록
- ports:
- port: "8000" # API 포트
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 (HTTP) - K8s NetworkPolicy에는 없는 Cilium 고유 기능
http: # HTTP 프로토콜에 대한 L7 필터링
- method: "GET" # GET 메서드만 허용 - POST, PUT 등은 차단
path: "/api/v1/.*" # /api/v1/ 경로만 허용 - 정규식 사용 가능
✅ 고급 기능
Cilium의 네트워크 정책은 쿠버네티스 기본 정책보다 훨씬 많은 기능을 제공합니다:
- L7 프로토콜 인식:
- HTTP/gRPC: 메서드, 경로, 헤더 기반 필터링
- Kafka: 토픽, 클라이언트 ID 기반 필터링
- DNS: 도메인 이름 기반 필터링
- 기타: Cassandra, Memcached, MongoDB 등 지원
- 확장된 엔드포인트 식별자:
- toFQDNs: DNS 이름 기반 필터링
- toServices: 쿠버네티스 서비스 기반 필터링
- toEntities: 사전 정의된 엔티티(world, host 등) 기반 필터링
- 정밀한 선택자 지원:
- 복합 레이블 매칭
- 여러 선택자 간 OR 연산자 지원
- 클러스터 전체 정책:
- CiliumClusterwideNetworkPolicy를 통한 네임스페이스 독립적 정책
- 네트워크 정책 상태 피드백:
- 정책 실행 상태 확인 가능
- Hubble을 통한 정책 적용 결과 관찰
- 암호화 지원:
- WireGuard 또는 IPsec을 통한 Pod 간 통신 암호화
📌 주요 차이점 비교
이제 두 정책 유형 간의 주요 차이점을 표 형식으로 비교해 보겠습니다.
✅ 리소스 정의 비교
특징 | 쿠버네티스 NetworkPolicy | Cilium NetworkPolicy |
API 그룹 | networking.k8s.io/v1 | cilium.io/v2 |
리소스 종류 | NetworkPolicy | CiliumNetworkPolicy (또는 CiliumClusterwideNetworkPolicy) |
대상 선택자 | podSelector | endpointSelector |
소스/대상 지정 | from/to | fromEndpoints/toEndpoints, toCIDR 등 |
포트 지정 | ports | toPorts |
네임스페이스 범위 | 단일 네임스페이스만 | 단일 또는 클러스터 전체 |
✅ 기능 범위 비교
기능 | 쿠버네티스 NetworkPolicy | Cilium NetworkPolicy |
L3/L4 필터링 | ✅ 지원 | ✅ 지원 |
L7 필터링 | ❌ 미지원 | ✅ 지원 (HTTP, gRPC, Kafka, DNS 등) |
DNS 기반 필터링 | ❌ 미지원 | ✅ 지원 (toFQDNs) |
서비스 기반 필터링 | ❌ 미지원 | ✅ 지원 (toServices) |
특수 엔티티 | ❌ 미지원 | ✅ 지원 (world, host, remote-node 등) |
클러스터 전체 정책 | ❌ 미지원 | ✅ 지원 (CiliumClusterwideNetworkPolicy) |
정책 상태 피드백 | ❌ 미지원 | ✅ 지원 |
멀티 클러스터 지원 | ❌ 미지원 | ✅ 지원 (Cluster Mesh) |
✅ 구문 차이 예시
동일한 정책을 두 가지 방식으로 구현해 보겠습니다:
쿠버네티스 NetworkPolicy:
# 쿠버네티스 NetworkPolicy 예시
apiVersion: networking.k8s.io/v1 # 쿠버네티스 네트워킹 API 그룹
kind: NetworkPolicy # 쿠버네티스 기본 NetworkPolicy 리소스
metadata:
name: db-policy # 정책 이름
namespace: default # 적용될 네임스페이스
spec:
podSelector: # 정책이 적용될 대상 Pod 선택
matchLabels:
app: db # app=db 레이블이 있는 Pod에 적용
policyTypes:
- Ingress # 들어오는 트래픽에 대한 정책만 적용
ingress: # 인그레스 규칙 정의
- from: # 허용할 출발지 목록
- podSelector: # Pod 기반 선택
matchLabels:
app: backend # app=backend 레이블이 있는 Pod에서 오는 트래픽만 허용
ports: # 허용할 포트 목록
- protocol: TCP # TCP 프로토콜만 허용
port: 3306 # MySQL 포트(3306)만 허용
Cilium NetworkPolicy:
# 동일한 정책의 Cilium 버전
apiVersion: cilium.io/v2 # Cilium API 그룹
kind: CiliumNetworkPolicy # Cilium 전용 NetworkPolicy 리소스
metadata:
name: db-policy # 정책 이름 (쿠버네티스 정책과 동일)
namespace: default # 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod 선택 (쿠버네티스의 podSelector와 동일 역할)
matchLabels:
app: db # app=db 레이블이 있는 Pod에 적용 (쿠버네티스 정책과 동일)
ingress: # 인그레스 규칙 정의 (쿠버네티스 정책과 유사)
- fromEndpoints: # 허용할 출발지 목록 (쿠버네티스의 from.podSelector와 동일 역할)
- matchLabels:
app: backend # app=backend 레이블이 있는 Pod에서 오는 트래픽만 허용
toPorts: # 허용할 포트 목록 (쿠버네티스의 ports와 유사하지만 구조가 다름)
- ports:
- port: "3306" # MySQL 포트(3306)만 허용 - 문자열로 지정해야 함 (쿠버네티스는 숫자)
protocol: TCP # TCP 프로토콜만 허용 (쿠버네티스 정책과 동일)
두 정책은 기본적으로 같은 기능을 수행하지만, Cilium의 경우 추가 기능을 확장할 수 있습니다. 예를 들어, L7 필터링을 추가하면:
# L7 필터링이 추가된 Cilium 정책
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: db-policy
namespace: default
spec:
endpointSelector:
matchLabels:
app: db
ingress:
- fromEndpoints:
- matchLabels:
app: backend
toPorts:
- ports:
- port: "3306"
protocol: TCP
rules: # L7 규칙 추가 - 쿠버네티스 NetworkPolicy에서는 불가능한 기능
mysql: # MySQL 프로토콜에 대한 L7 필터링
- query: "SELECT *" # SELECT 쿼리만 허용 - INSERT, UPDATE, DELETE는 차단
database: "prod" # prod 데이터베이스만 접근 가능 - 다른 DB는 접근 불가
📌 선택자 로직 차이
두 정책 유형의 선택자 처리 방식에는 미묘하지만 중요한 차이가 있습니다.
✅ 쿠버네티스 NetworkPolicy의 선택자 로직
쿠버네티스 NetworkPolicy에서는 from 또는 to 블록 내에서 여러 선택자의 처리 방식이 명확하지 않을 수 있습니다.
# 쿠버네티스 선택자 예시
from:
- podSelector: # 첫 번째 선택자 - 별도의 항목으로 나열됨
matchLabels:
role: frontend
- namespaceSelector: # 두 번째 선택자 - 별도의 항목으로 나열됨
matchLabels:
purpose: testing
이 예시에서 두 선택자는 OR 관계로 해석됩니다. 즉, role: frontend 레이블이 있는 Pod 또는 purpose: testing 레이블이 있는 네임스페이스의 모든 Pod로부터의 트래픽이 허용됩니다.
그러나 다음과 같이 작성하면:
# 쿠버네티스 복합 선택자 예시
from:
- podSelector: # 첫 번째 선택자의 일부 - 같은 항목 안에 두 선택자가 함께 있음
matchLabels:
role: frontend
namespaceSelector: # 첫 번째 선택자의 일부 - 같은 항목 안에 두 선택자가 함께 있음
matchLabels:
purpose: testing
두 선택자는 AND 관계로 해석됩니다. role: frontend 레이블이 있고, purpose: testing 레이블이 있는 네임스페이스에 속한 Pod만 허용됩니다.
이 미묘한 차이는 혼란을 야기할 수 있습니다.
✅ Cilium의 선택자 로직
Cilium의 선택자 로직은 더 명확하고 직관적입니다:
# Cilium 선택자 예시
fromEndpoints:
- matchLabels: # 첫 번째 엔드포인트 선택자 - 명확히 구분된 항목
role: frontend
- matchLabels: # 두 번째 엔드포인트 선택자 - 명확히 구분된 항목
app: monitoring
여기서 두 선택자는 명확히 OR 관계로 해석됩니다. role: frontend 또는 app: monitoring 레이블이 있는 Pod로부터의 트래픽이 허용됩니다.
AND 관계를 표현하려면 단일 선택자에 여러 레이블을 포함시킵니다:
# Cilium AND 관계 선택자
fromEndpoints:
- matchLabels: # 하나의 선택자에 여러 레이블 - AND 관계 명확
role: frontend # role=frontend AND environment=production을 만족해야 함
environment: production
이 예시에서는 role: frontend와 environment: production 레이블이 모두 있는 Pod만 허용됩니다.
📌 실습: 두 정책 타입 비교
이제 실습을 통해 두 정책 타입을 비교해 보겠습니다. 먼저 테스트 환경을 설정합니다.
✅ 테스트 환경 설정
# 테스트 네임스페이스 생성
# 모든 테스트를 이 네임스페이스 내에서 진행하여 기존 워크로드에 영향을 주지 않음
kubectl create namespace policy-test
# 백엔드 애플리케이션 배포
kubectl -n policy-test apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend # 백엔드 애플리케이션 이름
namespace: policy-test # 배포할 네임스페이스
spec:
selector:
matchLabels:
app: backend # 이 레이블로 Pod 선택
replicas: 1 # 1개의 복제본만 실행
template:
metadata:
labels:
app: backend # Pod에 적용할 레이블 - 정책 타겟팅에 사용됨
spec:
containers:
- name: backend
image: nginx:1.19.6 # 간단한 웹 서버로 Nginx 사용
ports:
- containerPort: 80 # 80 포트 노출 (HTTP)
---
apiVersion: v1
kind: Service
metadata:
name: frontend # 프론트엔드 서비스 이름
namespace: policy-test # 서비스가 생성될 네임스페이스
spec:
selector:
app: frontend # 이 레이블을 가진 Pod를 서비스의 엔드포인트로 등록
ports:
- port: 80 # 서비스 포트
targetPort: 80 # 대상 Pod 포트
EOF
# 테스트 클라이언트 Pod 배포
kubectl -n policy-test apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: client # 클라이언트 Pod 이름
namespace: policy-test # 배포할 네임스페이스
labels:
app: client # Pod에 적용할 레이블 - 정책 타겟팅에 사용됨
spec:
containers:
- name: client
image: curlimages/curl:7.82.0 # curl 명령어가 포함된 이미지 - 네트워크 연결 테스트용
command: [ "/bin/sh", "-c", "--" ] # 컨테이너 시작 시 실행할 명령어
args: [ "while true; do sleep 30; done;" ] # 컨테이너를 계속 실행 상태로 유지
EOF
# 외부 테스트 Pod 배포 (다른 네임스페이스)
kubectl create namespace outside # 다른 네임스페이스 생성 - 네임스페이스 간 정책 테스트용
kubectl -n outside apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: external-client # 외부 클라이언트 Pod 이름
namespace: outside # 다른 네임스페이스에 배포
labels:
app: external-client # Pod에 적용할 레이블
spec:
containers:
- name: client
image: curlimages/curl:7.82.0 # curl 명령어가 포함된 이미지 - 네트워크 연결 테스트용
command: [ "/bin/sh", "-c", "--" ] # 컨테이너 시작 시 실행할 명령어
args: [ "while true; do sleep 30; done;" ] # 컨테이너를 계속 실행 상태로 유지
EOF
✅ 쿠버네티스 NetworkPolicy 테스트
쿠버네티스 기본 NetworkPolicy를 적용해 보겠습니다:
# 쿠버네티스 NetworkPolicy 예시
apiVersion: networking.k8s.io/v1 # 쿠버네티스 네트워킹 API 그룹
kind: NetworkPolicy # 쿠버네티스 기본 NetworkPolicy 리소스
metadata:
name: backend-policy # 정책 이름
namespace: policy-test # 정책이 적용될 네임스페이스
spec:
podSelector: # 정책이 적용될 Pod 선택
matchLabels:
app: backend # app=backend 레이블이 있는 Pod에 적용 (백엔드 앱)
policyTypes:
- Ingress # 들어오는 트래픽에 대한 정책만 정의
ingress: # 인그레스 규칙 정의
- from: # 허용할 출발지 목록
- podSelector: # Pod 기반 선택
matchLabels:
app: frontend # app=frontend 레이블이 있는 Pod에서 오는 트래픽만 허용
ports: # 허용할 포트 목록
- protocol: TCP # TCP 프로토콜만 허용
port: 80 # 80 포트만 허용 (HTTP)
이 정책을 적용한 후 테스트 결과:
# 프론트엔드에서 백엔드로의 연결 (성공해야 함)
# 정책에서 app=frontend 레이블을 가진 Pod에서 app=backend로의 트래픽을 허용했기 때문
kubectl -n policy-test exec frontend-xxxx -- curl -s backend
# 클라이언트에서 백엔드로의 연결 (실패해야 함)
# app=client 레이블을 가진 Pod는 정책에서 허용되지 않았기 때문
kubectl -n policy-test exec client -- curl -s --connect-timeout 5 backend
# 외부 클라이언트에서의 연결 (실패해야 함)
# 다른 네임스페이스(outside)에 있는 Pod도 정책에서 허용되지 않았기 때문
kubectl -n outside exec external-client -- curl -s --connect-timeout 5 backend.policy-test
✅ Cilium NetworkPolicy 테스트
이번에는 Cilium NetworkPolicy를 적용해 보겠습니다:
# Cilium NetworkPolicy 예시
apiVersion: cilium.io/v2 # Cilium API 그룹
kind: CiliumNetworkPolicy # Cilium 전용 NetworkPolicy 리소스
metadata:
name: backend-policy # 정책 이름
namespace: policy-test # 정책이 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 Pod 선택 (쿠버네티스의 podSelector와 동일 역할)
matchLabels:
app: backend # app=backend 레이블이 있는 Pod에 적용 (백엔드 앱)
ingress: # 인그레스 규칙 정의
- fromEndpoints: # 허용할 출발지 목록 (쿠버네티스의 from.podSelector와 동일 역할)
- matchLabels:
app: frontend # app=frontend 레이블이 있는 Pod에서 오는 트래픽만 허용
toPorts: # 허용할 포트 목록 (쿠버네티스의 ports와 유사하지만 구조가 다름)
- ports:
- port: "80" # 80 포트만 허용 (HTTP) - 문자열로 지정해야 함
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 (HTTP) - 쿠버네티스 NetworkPolicy에는 없는 추가 기능
http: # HTTP 프로토콜에 대한 L7 필터링
- method: "GET" # GET 메서드만 허용 (POST, PUT 등은 차단)
path: "/api/.*" # /api/ 경로만 허용 - 정규식 사용 가능
이 정책은 기본 NetworkPolicy와 유사하지만 L7 필터링을 추가했습니다. 결과는:
# GET /api/ 요청 (성공해야 함)
# 정책에서 허용한 GET 메서드와 /api/ 경로에 매칭됨
kubectl -n policy-test exec frontend-xxxx -- curl -s backend/api/v1/status
# GET / 요청 (실패해야 함 - 경로 불일치)
# 정책에서 /api/ 경로만 허용했기 때문에 루트 경로(/)는 차단됨
kubectl -n policy-test exec frontend-xxxx -- curl -s backend/
# POST 요청 (실패해야 함 - 메서드 불일치)
# 정책에서 GET 메서드만 허용했기 때문에 POST 요청은 차단됨
kubectl -n policy-test exec frontend-xxxx -- curl -s -X POST backend/api/v1/data
✅ 혼합 정책 적용 테스트
두 정책 유형을 함께 적용할 때의 동작을 살펴보겠습니다:
- 먼저 쿠버네티스 NetworkPolicy 적용:
# 쿠버네티스 NetworkPolicy 적용
# 이 정책은 app=frontend에서 app=backend로의 모든 HTTP 트래픽 허용
kubectl apply -f kubernetes-policy.yaml
- 그 다음 Cilium NetworkPolicy 적용:
# Cilium NetworkPolicy 적용
# 이 정책은 app=frontend에서 app=backend로의 GET /api/ 요청만 허용
kubectl apply -f cilium-policy.yaml
결과:
- 두 정책은 독립적으로 평가됩니다.
- 더 제한적인 정책이 우선됩니다.
- 예를 들어, 쿠버네티스 정책이 모든 HTTP 트래픽을 허용하고 Cilium 정책이 GET 메서드만 허용하면, 결과적으로 GET 메서드만 허용됩니다.
📌 호환성 및 최적 사용 전략
두 정책 타입을 효과적으로 함께 사용하기 위한 전략을 알아보겠습니다.
✅ 호환성 고려사항
- 정책 평가 순서:
- 두 정책 타입은 독립적으로 평가됩니다.
- 두 정책 모두에서 허용되어야 트래픽이 통과합니다.
- 기능 중복 관리:
- L3/L4 수준에서 중복된 정책을 정의하면 혼란을 야기할 수 있습니다.
- 각 정책 타입의 강점에 집중하는 것이 좋습니다.
- 디버깅 복잡성:
- 두 정책 타입을 혼합하면 문제 발생 시 디버깅이 더 복잡해질 수 있습니다.
✅ 권장 사용 패턴
- 기본 정책에 쿠버네티스 NetworkPolicy 사용:
- 기본적인 L3/L4 차단을 위해 쿠버네티스 표준 NetworkPolicy 사용
- 이는 이식성과 호환성을 높여줌
- 고급 기능에 Cilium NetworkPolicy 사용:
- L7 필터링, DNS 기반 정책 등 고급 기능이 필요할 때 Cilium 정책 사용
- 특정 서비스나 애플리케이션에 대해 더 세밀한 제어가 필요한 경우 사용
- 클러스터 전체 정책에 Cilium 사용:
- 네임스페이스를 초월한 정책이나 클러스터 전체 규칙에는 CiliumClusterwideNetworkPolicy 사용
- 마이그레이션 전략:
- 기존 쿠버네티스 NetworkPolicy에서 Cilium 정책으로 점진적으로 마이그레이션
- 기존 정책을 유지하면서 Cilium 정책으로 기능 확장
✅ 문서화 및 레이블링 전략
정책이 많아질수록 관리가 복잡해질 수 있으므로, 효과적인 문서화 및 레이블링이 중요합니다:
- 일관된 네이밍 규칙:
- metadata: name: "tier-backend-policy" # 대상 계층을 이름에 포함 - 쉽게 식별 가능
- 주석을 통한 문서화:
- metadata: annotations: description: "Frontend에서 Backend API로의 접근 제어" # 정책의 목적 설명 owner: "platform-team" # 관리 책임자/팀 명시 last-updated: "2023-03-15" # 마지막 업데이트 날짜 기록
- 레이블을 통한 분류:
- metadata: labels: policy-type: "security" # 정책 목적 (보안, 격리, 모니터링 등) tier: "backend" # 대상 계층 (백엔드, 프론트엔드, 데이터베이스 등) environment: "production" # 환경 구분 (개발, 테스트, 프로덕션 등)
📌 실제 운영에서의 선택 가이드
실제 운영 환경에서 어떤 정책 타입을 선택해야 할지 가이드를 제공합니다.
✅ 쿠버네티스 NetworkPolicy를 선택해야 할 때
다음과 같은 경우 쿠버네티스 NetworkPolicy를 선택하는 것이 좋습니다:
- 다양한 CNI와의 호환성이 필요한 경우:
- 여러 클러스터에서 동일한 정책을 사용해야 하는 경우
- CNI에 관계없이 일관된 정책 적용이 필요한 경우
- 기본적인 L3/L4 제어만 필요한 경우:
- IP, 포트, 프로토콜 기반의 단순한 정책만 필요한 경우
- 복잡한 애플리케이션 계층 필터링이 필요하지 않은 경우
- 표준 컴플라이언스가 중요한 경우:
- 쿠버네티스 표준 API만 사용해야 하는 환경
- 벤더 중립적인 접근이 필요한 경우
✅ Cilium NetworkPolicy를 선택해야 할 때
다음과 같은 경우 Cilium NetworkPolicy를 선택하는 것이 좋습니다:
- L7 필터링이 필요한 경우:
- HTTP 경로, 메서드, 헤더 기반 필터링 필요
- Kafka 토픽, DNS 이름 기반 필터링 필요
- 고급 네트워크 보안 기능이 필요한 경우:
- 마이크로서비스 간 세밀한 액세스 제어 필요
- 암호화된 통신 필요
- 네트워크 트래픽 가시성 향상 필요
- 클러스터 전체 또는 멀티 클러스터 정책이 필요한 경우:
- 네임스페이스 경계를 넘어서는 정책 적용 필요
- 여러 클러스터 간 일관된 정책 적용 필요
- DNS 기반 필터링이 필요한 경우:
- 도메인 이름 기반 외부 액세스 제어 필요
- FQDN 기반 이그레스 정책 필요
✅ 두 정책 타입을 함께 사용해야 할 때
다음과 같은 경우 두 정책 타입을 함께 사용하는 것이 좋습니다:
- 점진적인 마이그레이션 과정에서:
- 기존 쿠버네티스 정책에서 Cilium으로 단계적 전환
- 호환성 보장과 함께 새로운 기능 도입
- 다층 방어 전략을 구현할 때:
- 기본 정책은 쿠버네티스 NetworkPolicy로 구현
- 추가적인 특수 정책은 Cilium으로 구현
- 팀 간 책임 분담 시:
- 플랫폼 팀: 기본 쿠버네티스 정책 관리
- 앱 팀: 애플리케이션별 Cilium 정책 관리
📌 Summary
이번 글에서는 쿠버네티스 NetworkPolicy와 Cilium NetworkPolicy의 차이점을 상세히 비교해 보았습니다. 주요 내용을 정리하면 다음과 같습니다:
- 쿠버네티스 NetworkPolicy는 표준 API로, L3/L4 수준의 네트워크 정책을 제공합니다.
- Cilium NetworkPolicy는 확장된 기능을 제공하며, 특히 L7 필터링, DNS 기반 필터링, 클러스터 전체 정책 등 더 다양한 기능을 지원합니다.
- 두 정책 타입은 구문과 선택자 로직에 차이가 있으며, Cilium의 선택자 로직이 더 명확하고 직관적입니다.
- 실제 운영 환경에서는 상황에 맞게 두 정책 타입을 선택하거나 함께 사용하는 전략이 필요합니다.
- 효과적인 정책 관리를 위해서는 일관된 네이밍, 문서화, 레이블링 전략이 중요합니다.
'Kubernetes Tools > Cilium' 카테고리의 다른 글
EP09. L7 정책 실습 (Kafka, DNS 등) | HTTP 요청이 아닌 트래픽 제어 (0) | 2025.03.22 |
---|---|
EP08. L7 정책 실습 (HTTP 제어) | Path, Host, Method 기반 제어 (0) | 2025.03.22 |
EP06. 기본 L3/L4 정책 설정 | CiliumNetworkPolicy 기초 실습 (0) | 2025.03.22 |
EP05. Hubble 설치 및 구성 | 쿠버네티스 네트워크 가시성 확보 (0) | 2025.03.22 |
EP04. Cilium 설치하기 | Docker Desktop 기반 실습 환경 구성 (0) | 2025.03.22 |