이 글에서는 Cilium의 핵심 기능 중 하나인 네트워크 정책 설정에 대해 알아보겠습니다. 특히 L3(IP) 및 L4(포트) 수준에서 트래픽을 제어하는 CiliumNetworkPolicy 리소스의 기본 사용법과 실제 적용 방법을 실습을 통해 상세히 다룹니다. 전체 트래픽을 차단하는 기본 정책부터 시작하여 특정 Pod와 포트 기반의 허용 정책 작성, 그리고 정책 적용 후 상태 확인 및 로그 분석 방법까지 실무에 바로 적용할 수 있는 내용을 소개합니다.
📌 네트워크 정책의 필요성
쿠버네티스 환경에서는 기본적으로 모든 Pod 간 통신이 허용됩니다. 이는 개발 편의성을 제공하지만, 보안 측면에서는 큰 위험 요소가 될 수 있습니다.
✅ 기본 통신 정책의 문제점
쿠버네티스의 기본 네트워킹 모델은 다음과 같은 특징을 가집니다:
# 쿠버네티스 기본 네트워킹 특성
# 1. 모든 Pod는 NAT 없이 다른 모든 Pod에 접근 가능
# -> 어떤 Pod든 기본적으로 다른 모든 Pod와 자유롭게 통신 가능함
# 2. 노드의 에이전트(kubelet 등)는 해당 노드의 모든 Pod와 통신 가능
# -> 노드에서 실행되는 시스템 구성요소가 모든 Pod에 접근 가능함
# 3. 호스트 네트워크에서 실행되는 Pod는 다른 모든 Pod와 통신 가능
# -> hostNetwork: true로 설정된 Pod는 제한 없이 통신 가능함
이러한 "기본 허용(Default Allow)" 정책은 다음과 같은 보안 문제를 야기할 수 있습니다:
- 수평적 이동 위험: 하나의 Pod가 침해되면 클러스터 내 다른 모든 Pod로 공격이 확산될 수 있습니다.
- 불필요한 통신 허용: 애플리케이션 로직상 필요하지 않은 통신 경로가 열려 있습니다.
- 규정 준수 문제: 많은 보안 규정은 최소 권한 원칙(Principle of Least Privilege)을 요구합니다.
✅ Cilium의 네트워크 정책 접근 방식
Cilium은 eBPF를 기반으로 한 고성능 네트워크 정책을 제공합니다:
- 마이크로서비스 지향: 서비스 간 통신을 세밀하게 제어할 수 있습니다.
- 다층적 보호: L3/L4(IP, 포트) 뿐만 아니라 L7(애플리케이션 계층)까지 정책 적용이 가능합니다.
- 최소 오버헤드: eBPF를 활용하여 커널 레벨에서 정책을 적용함으로써 성능 저하를 최소화합니다.
📌 CiliumNetworkPolicy 개요
CiliumNetworkPolicy는 Cilium에서 네트워크 정책을 정의하는 주요 리소스입니다.
✅ 기본 구조
CiliumNetworkPolicy의 기본 구조는 다음과 같습니다:
# CiliumNetworkPolicy의 기본 구조
apiVersion: "cilium.io/v2" # Cilium API 버전 - v2는 현재 안정화된 API 버전
kind: CiliumNetworkPolicy # 리소스 종류 - Cilium 고유의 네트워크 정책 리소스
metadata:
name: "policy-name" # 정책 이름 - 해당 네임스페이스 내에서 고유한 이름
namespace: "namespace" # 정책이 적용될 네임스페이스 - 정책의 적용 범위 지정
spec:
endpointSelector: # 정책이 적용될 대상 Pod 선택 - 이 부분이 정책의 핵심
matchLabels: # 레이블 기반 선택 - 쿠버네티스 레이블로 Pod 대상 지정
app: "app-name" # app=app-name 레이블을 가진 Pod에 정책 적용
ingress: # 인바운드 트래픽 규칙 (들어오는 트래픽) - 생략 시 모든 인바운드 트래픽 차단
- fromEndpoints: # 어떤 출발지로부터 오는 트래픽인지 - Pod 간 통신 정의
- matchLabels: # 레이블로 출발지 Pod 선택
app: "client-app" # app=client-app 레이블을 가진 Pod의 트래픽만 허용
toPorts: # 허용할 포트와 프로토콜 - 없으면 모든 포트 허용
- ports: # 포트 목록 정의
- port: "80" # 포트 번호 - 문자열로 작성 (숫자 또는 이름)
protocol: TCP # 프로토콜(TCP/UDP) - 명시적으로 프로토콜 지정
egress: # 아웃바운드 트래픽 규칙 (나가는 트래픽) - 생략 시 모든 아웃바운드 트래픽 차단
- toEndpoints: # 어떤 목적지로 가는 트래픽인지 - Pod 간 통신 정의
- matchLabels: # 레이블로 목적지 Pod 선택
app: "service-app" # app=service-app 레이블을 가진 Pod로의 트래픽만 허용
toPorts: # 허용할 포트와 프로토콜 - 없으면 모든 포트 허용
- ports: # 포트 목록 정의
- port: "80" # 포트 번호 - 문자열로 작성
protocol: TCP # 프로토콜 - TCP 또는 UDP 지정
✅ 핵심 구성 요소
CiliumNetworkPolicy의 주요 구성 요소를 자세히 살펴보겠습니다:
- EndpointSelector: 정책이 적용될 대상 Pod를 지정합니다.
- 쿠버네티스 레이블을 기반으로 선택합니다.
- 정책의 영향을 받을 Pod를 정확히 타겟팅할 수 있습니다.
- Ingress 규칙: Pod로 들어오는 트래픽을 제어합니다.
- fromEndpoints: 특정 출발지에서 오는 트래픽만 허용
- fromCIDR: 특정 IP 대역에서 오는 트래픽 허용
- toPorts: 특정 포트 및 프로토콜 허용
- Egress 규칙: Pod에서 나가는 트래픽을 제어합니다.
- toEndpoints: 특정 목적지로 가는 트래픽만 허용
- toCIDR: 특정 IP 대역으로 가는 트래픽 허용
- toPorts: 특정 포트 및 프로토콜 허용
- Labels: 정책 자체를 식별하는 레이블도 지정할 수 있습니다.
- 다른 정책에서 이 정책을 참조할 때 사용 가능합니다.
✅ 정책 평가 방식
Cilium이 네트워크 정책을 평가하는 방식을 이해하는 것이 중요합니다:
- 화이트리스트 방식: 명시적으로 허용된 트래픽만 통과하고 나머지는 차단됩니다.
- 누적 평가: 여러 정책이 있는 경우, 각 정책의 규칙을 모두 검사하여 하나라도 매치되면 허용합니다.
- 빈 정책 처리: ingress/egress 섹션이 비어있는 경우 해당 방향의 모든 트래픽을 차단합니다.
📌 실습 환경 구성
실습을 위한 샘플 애플리케이션을 배포하겠습니다.
✅ 테스트 네임스페이스 생성
# 네트워크 정책 테스트를 위한 네임스페이스 생성
# 이 네임스페이스에서 모든 실습이 진행됩니다
# 별도의 네임스페이스를 사용하면 기존 워크로드에 영향을 주지 않고 안전하게 실습 가능합니다
kubectl create namespace cilium-test
✅ 테스트 애플리케이션 배포
다양한 유형의 트래픽을 테스트할 수 있는 애플리케이션을 배포합니다:
# 백엔드 웹 서버 배포
kubectl -n cilium-test apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app # 배포 이름
namespace: cilium-test # 배포할 네임스페이스
spec:
selector:
matchLabels:
app: web # 이 레이블을 가진 Pod를 관리
replicas: 2 # 2개의 복제본 실행 (고가용성)
template:
metadata:
labels:
app: web # Pod에 적용할 레이블 - 네트워크 정책에서 이 레이블로 Pod 선택
spec:
containers:
- name: web
image: nginx:1.19.6 # Nginx 웹 서버 이미지 사용
ports:
- containerPort: 80 # 80 포트 노출 (HTTP)
---
apiVersion: v1
kind: Service
metadata:
name: web-service # 서비스 이름
namespace: cilium-test
spec:
selector:
app: web # app=web 레이블을 가진 Pod를 타겟팅
ports:
- port: 80 # 서비스 포트
targetPort: 80 # 목적지 Pod 포트
EOF
# API 서버 배포
kubectl -n cilium-test apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-app # 배포 이름
namespace: cilium-test
spec:
selector:
matchLabels:
app: api # 이 레이블을 가진 Pod를 관리
replicas: 2 # 2개의 복제본 실행
template:
metadata:
labels:
app: api # 기본 앱 레이블
tier: backend # 추가 레이블 - 복합 선택자 테스트에 사용
spec:
containers:
- name: api
image: mendhak/http-https-echo:29 # HTTP 요청을 에코하는 간단한 API 서버
ports:
- containerPort: 8080 # 8080 포트 노출 (HTTP)
---
apiVersion: v1
kind: Service
metadata:
name: api-service # 서비스 이름
namespace: cilium-test
spec:
selector:
app: api # app=api 레이블을 가진 Pod를 타겟팅
ports:
- port: 8080 # 서비스 포트
targetPort: 8080 # 목적지 Pod 포트
EOF
# 데이터베이스 배포
kubectl -n cilium-test apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: db-app # 배포 이름
namespace: cilium-test
spec:
selector:
matchLabels:
app: db # 이 레이블을 가진 Pod를 관리
replicas: 1 # DB는 1개 복제본만 실행 (상태 유지형 애플리케이션)
template:
metadata:
labels:
app: db # 기본 앱 레이블
tier: database # 추가 레이블 - 데이터베이스 계층 식별
spec:
containers:
- name: db
image: mongo:4.4 # MongoDB 데이터베이스 이미지
ports:
- containerPort: 27017 # MongoDB 기본 포트
---
apiVersion: v1
kind: Service
metadata:
name: db-service # 서비스 이름
namespace: cilium-test
spec:
selector:
app: db # app=db 레이블을 가진 Pod를 타겟팅
ports:
- port: 27017 # 서비스 포트
targetPort: 27017 # 목적지 Pod 포트
EOF
# 클라이언트 Pod 배포
kubectl -n cilium-test apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: client # Pod 이름
namespace: cilium-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;" ] # Pod를 계속 실행 상태로 유지
EOF
✅ 애플리케이션 상태 확인
# Pod 상태 확인
# 모든 Pod가 Running 상태인지 확인
kubectl get pods -n cilium-test
# 서비스 상태 확인
# 모든 서비스가 올바른 포트와 타겟으로 구성되었는지 확인
kubectl get svc -n cilium-test
✅ 초기 연결성 테스트
정책을 적용하기 전에 기본 연결성을 테스트합니다. 기본적으로 모든 통신이 허용되어 있어야 합니다:
# client Pod에서 web-service 연결 테스트
# 웹 서버에 HTTP 요청을 보내 응답 확인
kubectl -n cilium-test exec client -- curl -s web-service
# client Pod에서 api-service 연결 테스트
# API 서버에 HTTP 요청을 보내 응답 확인
kubectl -n cilium-test exec client -- curl -s api-service:8080
# client Pod에서 db-service 연결 테스트
# MongoDB 서버에 연결 확인 (인증 없이는 접속이 거부될 수 있음)
kubectl -n cilium-test exec client -- curl -s db-service:27017
모든 서비스에 정상적으로 연결되는 것을 확인할 수 있습니다(MongoDB는 연결은 되지만 인증 오류가 발생할 수 있습니다).
📌 전체 차단 정책 적용하기
먼저 모든 트래픽을 차단하는 기본 정책을 적용해 보겠습니다. 이는 "기본 거부(Default Deny)" 정책의 시작점입니다.
✅ 전체 차단 정책 작성
# deny-all.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # Cilium 네트워크 정책 리소스
metadata:
name: "deny-all" # 정책 이름 - 해당 네임스페이스에서 고유해야 함
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
# 모든 Pod에 적용되도록 빈 endpointSelector 사용
endpointSelector:
matchLabels:
# 기존에 배포한 모든 앱을 포함하기 위해 빈 셀렉터 사용
# 빈 셀렉터는 네임스페이스 내 모든 Pod에 매치됨
# 특정 레이블을 명시하지 않아 네임스페이스 내 모든 Pod에 적용됨
# 인그레스 규칙 없음 - 모든 들어오는 트래픽 차단
# 빈 배열은 "아무 규칙 없음"을 의미하여 모든 인그레스 트래픽을 차단함
ingress: []
# 이그레스 규칙 없음 - 모든 나가는 트래픽 차단
# 빈 배열은 "아무 규칙 없음"을 의미하여 모든 이그레스 트래픽을 차단함
egress: []
# 정책 적용
# 이 명령으로 위의 deny-all.yaml 파일을 클러스터에 적용
kubectl apply -f deny-all.yaml
✅ 차단 효과 확인
# web-service 연결 테스트 (실패해야 함)
# 타임아웃 설정은 실패 시 무한정 기다리는 것을 방지하기 위함
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 web-service
# api-service 연결 테스트 (실패해야 함)
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 api-service:8080
# db-service 연결 테스트 (실패해야 함)
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 db-service:27017
모든 요청이 타임아웃 되는 것을 확인할 수 있습니다. 이는 정책이 성공적으로 모든 트래픽을 차단하고 있음을 의미합니다.
✅ Hubble로 차단된 트래픽 관찰
Hubble을 사용하여 차단된 트래픽을 관찰해 봅시다:
# 차단된 트래픽 관찰
# --namespace: 특정 네임스페이스의 트래픽만 필터링
# --verdict DROPPED: 차단된 트래픽만 필터링하여 표시
hubble observe --namespace cilium-test --verdict DROPPED
다음과 같은 출력을 볼 수 있습니다:
Dec 7 15:23:45.634: client:34651 -> web-service:80 Policy denied DROPPED
Dec 7 15:23:47.123: client:34652 -> api-service:8080 Policy denied DROPPED
Dec 7 15:23:48.456: client:34653 -> db-service:27017 Policy denied DROPPED
📌 특정 Pod에 대한 인그레스(Ingress) 정책 설정
이제 특정 Pod로의 인그레스 트래픽을 허용하는 정책을 작성해 보겠습니다.
✅ Web 서버에 대한 접근 허용 정책
# allow-web-ingress.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # 리소스 종류
metadata:
name: "allow-web-ingress" # 정책 이름
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
# 정책을 적용할 대상 - app=web 레이블을 가진 Pod
# 이 정책은 웹 서버 Pod에만 적용됨 (다른 Pod는 영향 받지 않음)
endpointSelector:
matchLabels:
app: web
# 인그레스 규칙 - 들어오는 트래픽 허용 조건
ingress:
- fromEndpoints: # 어떤 출발지로부터의 트래픽을 허용할지
- matchLabels: # app=client 레이블을 가진 Pod로부터의 트래픽만 허용
app: client # client 앱에서 오는 트래픽만 허용 (다른 Pod에서 오는 트래픽은 계속 차단)
toPorts: # 허용할 포트 지정
- ports:
- port: "80" # 80 포트로의 트래픽 허용 (HTTP)
protocol: TCP # TCP 프로토콜만 허용 (UDP는 차단)
# 정책 적용
kubectl apply -f allow-web-ingress.yaml
✅ 정책 적용 확인
# client Pod에서 web-service 연결 테스트 (성공해야 함)
# 정책에 의해 이 연결은 허용되어야 함
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 web-service
# client Pod에서 api-service 연결 테스트 (실패해야 함)
# api-service로의 통신을 허용하는 정책이 아직 없으므로 실패해야 함
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 api-service:8080
client Pod에서 web-service로의 연결은 성공하지만, api-service로의 연결은 여전히 실패합니다. 이는 우리가 설정한 정책이 정확히 적용되고 있음을 의미합니다.
✅ API 서버에 대한 접근 허용 정책 추가
이제 API 서버에 대한 액세스도 허용해 보겠습니다:
# allow-api-ingress.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # 리소스 종류
metadata:
name: "allow-api-ingress" # 정책 이름
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
# 정책을 적용할 대상 - app=api 레이블을 가진 Pod
# 이 정책은 API 서버 Pod에만 적용됨
endpointSelector:
matchLabels:
app: api
# 인그레스 규칙
ingress:
- fromEndpoints: # client Pod로부터의 트래픽 허용
- matchLabels:
app: client # client 앱에서 오는 트래픽만 허용
toPorts: # 8080 포트로의 연결 허용
- ports:
- port: "8080" # API 서버 포트
protocol: TCP # TCP 프로토콜만 허용
# 정책 적용
kubectl apply -f allow-api-ingress.yaml
# client Pod에서 api-service 연결 테스트 (성공해야 함)
# 새로 추가한 정책에 의해 이 연결은 이제 허용되어야 함
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 api-service:8080
이제 API 서비스로의 연결도 성공합니다.
📌 이그레스(Egress) 정책 설정
이번에는 특정 Pod에서 나가는 트래픽을 제어하는 이그레스 정책을 설정해 보겠습니다.
✅ Client Pod의 이그레스 트래픽 제어
# allow-client-egress.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # 리소스 종류
metadata:
name: "allow-client-egress" # 정책 이름
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
# 정책을 적용할 대상 - app=client 레이블을 가진 Pod
# 이 정책은 클라이언트 Pod에서 나가는 트래픽을 제어
endpointSelector:
matchLabels:
app: client
# 이그레스 규칙 - 나가는 트래픽 허용 조건
egress:
- toEndpoints: # 어떤 목적지로 가는 트래픽을 허용할지
- matchLabels: # app=web 레이블을 가진 Pod로의 트래픽 허용
app: web # 웹 서버로의 트래픽 허용
toPorts: # 허용할 포트 지정
- ports:
- port: "80" # 80 포트로의 트래픽 허용 (HTTP)
protocol: TCP
- toEndpoints: # app=api 레이블을 가진 Pod로의 트래픽도 허용
- matchLabels:
app: api # API 서버로의 트래픽 허용
toPorts:
- ports:
- port: "8080" # 8080 포트로의 트래픽 허용 (API 서버 포트)
protocol: TCP
# kube-dns로의 트래픽 허용 (DNS 해결을 위해 필요)
# DNS 요청이 차단되면 서비스 이름 해석이 불가능하므로 반드시 허용해야 함
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system # kube-system 네임스페이스
k8s-app: kube-dns # kube-dns 앱 레이블
toPorts:
- ports:
- port: "53" # DNS UDP 포트
protocol: UDP
- port: "53" # DNS TCP 포트
protocol: TCP
# 정책 적용
kubectl apply -f allow-client-egress.yaml
✅ 이그레스 정책 효과 확인
# client Pod에서 web-service 연결 테스트 (성공해야 함)
# 이그레스 정책에서 web 서비스로의 트래픽을 허용했으므로 성공해야 함
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 web-service
# client Pod에서 api-service 연결 테스트 (성공해야 함)
# 이그레스 정책에서 api 서비스로의 트래픽을 허용했으므로 성공해야 함
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 api-service:8080
# client Pod에서 db-service 연결 테스트 (실패해야 함)
# 이그레스 정책에서 db 서비스로의 트래픽을 허용하지 않았으므로 실패해야 함
kubectl -n cilium-test exec client -- curl -s --connect-timeout 5 db-service:27017
web-service와 api-service로의 연결은 성공하지만, db-service로의 연결은 실패합니다. 이는 이그레스 정책이 의도한 대로 작동하고 있음을 보여줍니다.
📌 포트 기반 정책 설정
특정 포트와 프로토콜에 대한 더 세밀한 제어가 필요한 경우가 많습니다. 이제 포트 기반 정책을 설정해 보겠습니다.
✅ API 서버의 다중 포트 허용
API 서버에 여러 포트를 개방하는 정책을 설정해 보겠습니다:
# multi-port-api.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # 리소스 종류
metadata:
name: "multi-port-api" # 정책 이름
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
# 정책을 적용할 대상 - app=api 레이블을 가진 Pod
# API 서버 Pod에만 적용되는 정책
endpointSelector:
matchLabels:
app: api
# 인그레스 규칙 - 복수 포트 허용
ingress:
- fromEndpoints: # client Pod로부터의 트래픽만 허용
- matchLabels:
app: client
toPorts:
- ports:
- port: "8080" # 주 API 포트 - REST API 요청용
protocol: TCP
- port: "8443" # HTTPS API 포트 - 보안 연결용
protocol: TCP
- port: "9090" # 메트릭 포트 - Prometheus 메트릭 수집용
protocol: TCP
# 정책 적용
kubectl apply -f multi-port-api.yaml
✅ 포트 범위 정책 설정
포트 범위를 지정하는 정책도 작성할 수 있습니다:
# port-range-policy.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # 리소스 종류
metadata:
name: "port-range-policy" # 정책 이름
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
endpointSelector: # API 서버 Pod 선택
matchLabels:
app: api
ingress:
- fromEndpoints: # client Pod로부터의 트래픽만 허용
- matchLabels:
app: client
toPorts:
- ports:
- port: "8000-9000" # 8000부터 9000까지의 포트 범위 허용
# 이 범위는 다양한 마이크로서비스나 디버깅 포트를 포함할 수 있음
protocol: TCP # TCP 프로토콜만 허용
# 정책 적용
kubectl apply -f port-range-policy.yaml
📌 레이블 및 표현식을 활용한 고급 선택자
보다 복잡한 애플리케이션 환경에서는 다양한 선택자를 활용하여 정책을 세밀하게 제어할 필요가 있습니다.
✅ 복합 레이블 선택자 사용
여러 레이블 조건을 조합하여 더 구체적인 Pod 선택이 가능합니다:
# complex-selector.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # 리소스 종류
metadata:
name: "complex-selector" # 정책 이름
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
# 복합 선택자 - app=api AND tier=backend 레이블을 가진 Pod 선택
# 두 조건을 모두 만족하는 Pod에만 정책 적용 (AND 조건)
endpointSelector:
matchLabels:
app: api # API 앱 레이블
tier: backend # 백엔드 계층 레이블
ingress:
- fromEndpoints:
- matchLabels: # app=client 레이블을 가진 Pod로부터의 트래픽 허용
app: client
toPorts:
- ports:
- port: "8080" # 8080 포트 허용
protocol: TCP
# 정책 적용
kubectl apply -f complex-selector.yaml
✅ 부정 매치 표현식 사용
특정 레이블을 가지지 않은 Pod를 선택하는 정책도 작성할 수 있습니다:
# not-match-expression.yaml
apiVersion: "cilium.io/v2" # Cilium API 버전
kind: CiliumNetworkPolicy # 리소스 종류
metadata:
name: "not-match-expression" # 정책 이름
namespace: cilium-test # 정책이 적용될 네임스페이스
spec:
# tier=database 레이블이 없는 Pod 선택
# matchExpressions는 보다 복잡한 레이블 선택 조건을 지정할 수 있음
endpointSelector:
matchExpressions:
- key: tier # 레이블 키
operator: NotIn # NotIn 연산자 - 지정된 값이 없어야 함
values:
- "database" # database 값이 없어야 함
ingress:
- fromEndpoints:
- matchLabels:
app: client # client Pod로부터의 트래픽 허용
# 정책 적용
kubectl apply -f not-match-expression.yaml
이 정책은 tier: database 레이블이 없는 모든 Pod에 적용됩니다.
📌 정책 상태 확인 및 로그 분석
네트워크 정책을 적용한 후에는 정책이 제대로 작동하는지 확인하고 문제를 진단하는 것이 중요합니다.
✅ 정책 상태 확인
# 적용된 CiliumNetworkPolicy 목록 확인
# 현재 네임스페이스에 적용된 모든 Cilium 네트워크 정책 조회
kubectl get ciliumnetworkpolicies -n cilium-test
# 특정 정책의 상세 정보 확인
# 정책의 상세 내용과 상태 확인
kubectl describe ciliumnetworkpolicy allow-web-ingress -n cilium-test
✅ Cilium 엔드포인트 확인
# Cilium 엔드포인트 목록 확인
# Cilium에서 관리하는 모든 엔드포인트(Pod) 확인
cilium endpoint list -n cilium-test
# 특정 Pod의 엔드포인트 ID 확인
# 1. 클라이언트 Pod 이름 가져오기
CLIENT_POD=$(kubectl get pods -n cilium-test -l app=client -o jsonpath='{.items[0].metadata.name}')
# 2. 해당 Pod의 엔드포인트 ID 가져오기
ENDPOINT_ID=$(cilium endpoint list -n cilium-test | grep $CLIENT_POD | awk '{print $1}')
# 엔드포인트 상세 정보 확인
# 정책 식별자, 레이블, 상태 등 자세한 정보 확인
cilium endpoint get $ENDPOINT_ID
이 명령은 해당 Pod에 적용된 정책 및 식별자 정보를 보여줍니다.
✅ Hubble을 사용한 트래픽 모니터링
Hubble을 사용하여 정책에 의해 허용되거나 차단된 트래픽을 관찰할 수 있습니다:
# 허용된 트래픽 확인
# 정책에 의해 허용된 트래픽 흐름만 필터링
hubble observe --namespace cilium-test --verdict FORWARDED
# 차단된 트래픽 확인
# 정책에 의해 차단된 트래픽 흐름만 필터링
hubble observe --namespace cilium-test --verdict DROPPED
# 특정 Pod 간 트래픽 확인
# 출발지와 목적지를 레이블 기반으로 필터링
hubble observe --namespace cilium-test --from-label app=client --to-label app=web
✅ 정책 문제 해결
정책이 예상대로 작동하지 않을 때 문제를 해결하는 방법:
- 로그 확인:
# Cilium 에이전트 로그 확인
# 정책 처리 중 발생할 수 있는 오류나 경고 확인
kubectl logs -n kube-system -l k8s-app=cilium --tail=100
- 정책 추적 활성화:
# 특정 엔드포인트에 대한 정책 추적 활성화
# 해당 엔드포인트와 관련된 정책 결정 과정을 추적하도록 설정
cilium endpoint config $ENDPOINT_ID PolicyTracing=Enabled
# 추적 결과 확인
# 특정 통신 경로에 대한 정책 평가 결과 추적
# src-k8s-pod: 출발지 Pod
# dst-k8s-pod: 목적지 Pod
# dport: 목적지 포트
cilium policy trace --src-k8s-pod cilium-test/client --dst-k8s-pod cilium-test/web-app-xyz --dport 80
📌 정책 관리 우수 사례
실무에서 네트워크 정책을 효과적으로 관리하기 위한 몇 가지 우수 사례를 소개합니다.
✅ 정책 단계적 적용
프로덕션 환경에서는 정책을 점진적으로 적용하는 것이 안전합니다:
- 관찰 모드 사용: 정책을 실제로 적용하기 전에 어떤 트래픽이 차단될지 확인합니다.
- 테스트 환경에서 먼저 적용: 프로덕션에 적용하기 전에 테스트 환경에서 충분히 검증합니다.
- 작은 범위부터 시작: 전체 환경에 적용하기 전에 작은 서브셋에 먼저 적용합니다.
✅ 정책 템플릿화 및 자동화
대규모 환경에서는 정책 관리를 자동화하는 것이 중요합니다:
- Helm 차트 사용: 애플리케이션 배포와 함께 네트워크 정책을 패키징합니다.
- GitOps 활용: 정책을 코드로 관리하고 Git 기반 워크플로우로 적용합니다.
- CI/CD 파이프라인 통합: 정책 테스트 및 배포를 자동화합니다.
✅ 정책 문서화 및 감사
정책의 목적과 효과를 문서화하고 정기적으로 검토합니다:
- 주석 사용: 정책 YAML 파일에 상세한 주석을 추가합니다.
- 정기적 검토: 불필요하거나 중복된 정책이 없는지 검토합니다.
- 정책 테스트 자동화: 예상대로 작동하는지 자동으로 검증합니다.
📌 Summary
이번 글에서는 Cilium의 L3/L4 네트워크 정책 설정에 대해 알아보았습니다. 주요 내용을 정리하면 다음과 같습니다:
- CiliumNetworkPolicy는 Cilium에서 네트워크 트래픽을 제어하는 주요 리소스입니다.
- 기본적으로 화이트리스트 방식으로 작동하여, 명시적으로 허용된 트래픽만 통과시킵니다.
- endpointSelector를 통해 정책이 적용될 Pod를 레이블 기반으로 선택합니다.
- ingress 규칙은 Pod로 들어오는 트래픽을, egress 규칙은 Pod에서 나가는 트래픽을 제어합니다.
- 포트 및 프로토콜 수준까지 세밀하게 트래픽을 제어할 수 있습니다.
- 복합 레이블 선택자 및 표현식을 통해 더 정교한 정책을 작성할 수 있습니다.
- Hubble을 사용하여 정책 적용 결과를 실시간으로 관찰하고 문제를 진단할 수 있습니다.
- 실무에서는 단계적 적용, 템플릿화, 자동화 등의 우수 사례를 따르는 것이 좋습니다.
'Kubernetes Tools > Cilium' 카테고리의 다른 글
EP08. L7 정책 실습 (HTTP 제어) | Path, Host, Method 기반 제어 (0) | 2025.03.22 |
---|---|
EP07. Cilium vs Kubernetes NetworkPolicy 비교 | 동작 차이 완벽 이해 (0) | 2025.03.22 |
EP05. Hubble 설치 및 구성 | 쿠버네티스 네트워크 가시성 확보 (0) | 2025.03.22 |
EP04. Cilium 설치하기 | Docker Desktop 기반 실습 환경 구성 (0) | 2025.03.22 |
EP03. Cilium 아키텍처 이해하기 | Agent, Hubble, Operator (0) | 2025.03.22 |