이 글에서는 CiliumClusterwideNetworkPolicy를 사용하여 네임스페이스에 상관없이 클러스터 전체 범위의 네트워크 정책을 적용하는 방법에 대해 알아보겠습니다. 지금까지 살펴본 Cilium 네트워크 정책들이 주로 특정 네임스페이스 내에서 적용되었다면, 이번에는 클러스터 전체에 적용되는 글로벌 정책을 통해 여러 네임스페이스에 걸친 일관된 보안 규칙을 구현하는 방법을 실습합니다. matchLabels를 활용한 타겟 선택 방법과 함께 실무에서 유용하게 활용할 수 있는 다양한 클러스터 전체 정책 패턴을 살펴보겠습니다.
📌 CiliumClusterwideNetworkPolicy의 필요성
✅ 기존 네트워크 정책의 한계
지금까지 살펴본 CiliumNetworkPolicy는 해당 리소스가 생성된 네임스페이스 내의 Pod들에만 정책을 적용할 수 있습니다. 이러한 네임스페이스 범위의 정책은 다음과 같은 한계가 있습니다:
- 여러 네임스페이스에 동일한 정책을 적용하려면 각 네임스페이스마다 같은 정책을 반복해서 생성해야 함
- 모든 네임스페이스에 일관된 보안 규칙을 적용하기 어려움
- 신규 네임스페이스가 생성될 때마다 정책을 수동으로 추가해야 함
- 클러스터 관리자와 네임스페이스 관리자 간의 권한 분리가 어려움
✅ CiliumClusterwideNetworkPolicy의 장점
CiliumClusterwideNetworkPolicy는 클러스터 전체 범위에서 작동하는 네트워크 정책으로, 다음과 같은 장점을 제공합니다:
- 모든 네임스페이스에 일관된 보안 규칙 적용 가능
- 특정 라벨을 가진 네임스페이스나 Pod만 선택적으로 대상으로 지정 가능
- 클러스터 보안 표준을 중앙에서 관리 가능
- 네임스페이스 관리자가 수정할 수 없는 강제 정책 적용 가능
- 기본 거부 정책 등 클러스터 전체 기본 정책 구현 가능
📌 CiliumClusterwideNetworkPolicy 구조 이해하기
✅ CiliumNetworkPolicy와의 차이점
CiliumClusterwideNetworkPolicy는 기본적으로 CiliumNetworkPolicy와 동일한 구조를 가지지만, 다음과 같은 차이점이 있습니다:
- API 그룹: cilium.io/v2 API 그룹 사용
- 범위: 특정 네임스페이스가 아닌 클러스터 전체에 적용됨
- 저장 위치: 네임스페이스에 종속되지 않고 클러스터 수준에서 저장됨
- 권한: 일반적으로 클러스터 관리자만 생성 및 관리 가능
- 우선순위: 네임스페이스 수준의 정책보다 먼저 평가됨
✅ 기본 YAML 구조
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "cluster-wide-policy-name" # 정책 이름 (클러스터 전체에서 고유해야 함)
spec:
# 여기부터는 CiliumNetworkPolicy와 동일한 구조
endpointSelector: # 정책이 적용될 대상 Pod 선택
matchLabels:
key: value
ingress: # 인바운드(들어오는) 트래픽 규칙
- fromEndpoints:
- matchLabels:
key: value
toPorts:
- ports:
- port: "80"
protocol: TCP
egress: # 아웃바운드(나가는) 트래픽 규칙
- toEndpoints:
- matchLabels:
key: value
toPorts:
- ports:
- port: "53"
protocol: UDP
📌 테스트 환경 구성
✅ 여러 네임스페이스와 Pod 생성
클러스터 전체 정책을 테스트하기 위해 여러 네임스페이스와 다양한 Pod를 생성해 봅시다:
# test-namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
name: frontend # 프론트엔드 애플리케이션용 네임스페이스
labels:
environment: production # 프로덕션 환경 레이블 추가
---
apiVersion: v1
kind: Namespace
metadata:
name: backend # 백엔드 애플리케이션용 네임스페이스
labels:
environment: production # 프로덕션 환경 레이블 추가
---
apiVersion: v1
kind: Namespace
metadata:
name: database # 데이터베이스용 네임스페이스
labels:
environment: production # 프로덕션 환경 레이블 추가
---
apiVersion: v1
kind: Namespace
metadata:
name: testing # 테스트 환경용 네임스페이스
labels:
environment: testing # 테스트 환경 레이블 추가
네임스페이스를 생성합니다:
kubectl apply -f test-namespaces.yaml
각 네임스페이스에 테스트용 Pod를 배포합니다:
# frontend-pods.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-app # 프론트엔드 애플리케이션
namespace: frontend # frontend 네임스페이스에 배포
spec:
selector:
matchLabels:
app: frontend # 이 라벨을 가진 Pod 관리
replicas: 2
template:
metadata:
labels:
app: frontend # Pod에 적용되는 라벨
tier: web # 티어 정보 추가
spec:
containers:
- name: nginx
image: nginx:1.19 # 웹 서버로 Nginx 사용
ports:
- containerPort: 80 # 웹 서버 포트
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service # 프론트엔드 서비스
namespace: frontend # frontend 네임스페이스에 생성
spec:
selector:
app: frontend # 이 라벨을 가진 Pod로 트래픽 전달
ports:
- port: 80 # 서비스 포트
targetPort: 80 # 대상 Pod 포트
# backend-pods.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-app # 백엔드 애플리케이션
namespace: backend # backend 네임스페이스에 배포
spec:
selector:
matchLabels:
app: backend # 이 라벨을 가진 Pod 관리
replicas: 2
template:
metadata:
labels:
app: backend # Pod에 적용되는 라벨
tier: app # 티어 정보 추가
spec:
containers:
- name: httpd
image: httpd:2.4 # 웹 서버로 Apache 사용
ports:
- containerPort: 80 # 웹 서버 포트
---
apiVersion: v1
kind: Service
metadata:
name: backend-service # 백엔드 서비스
namespace: backend # backend 네임스페이스에 생성
spec:
selector:
app: backend # 이 라벨을 가진 Pod로 트래픽 전달
ports:
- port: 80 # 서비스 포트
targetPort: 80 # 대상 Pod 포트
# database-pods.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: database-app # 데이터베이스 애플리케이션
namespace: database # database 네임스페이스에 배포
spec:
selector:
matchLabels:
app: database # 이 라벨을 가진 Pod 관리
replicas: 1
template:
metadata:
labels:
app: database # Pod에 적용되는 라벨
tier: db # 티어 정보 추가
spec:
containers:
- name: postgres
image: postgres:13 # 데이터베이스로 PostgreSQL 사용
ports:
- containerPort: 5432 # 데이터베이스 포트
env:
- name: POSTGRES_PASSWORD
value: "password" # 간단한 패스워드 설정 (실제 운영에서는 Secret 사용 권장)
---
apiVersion: v1
kind: Service
metadata:
name: database-service # 데이터베이스 서비스
namespace: database # database 네임스페이스에 생성
spec:
selector:
app: database # 이 라벨을 가진 Pod로 트래픽 전달
ports:
- port: 5432 # 서비스 포트
targetPort: 5432 # 대상 Pod 포트
# testing-pods.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: testing-app # 테스트 애플리케이션
namespace: testing # testing 네임스페이스에 배포
spec:
selector:
matchLabels:
app: testing # 이 라벨을 가진 Pod 관리
replicas: 1
template:
metadata:
labels:
app: testing # Pod에 적용되는 라벨
spec:
containers:
- name: curl
image: curlimages/curl:7.80.0 # 네트워크 테스트를 위한 curl 이미지
command: ["sleep", "3600"] # 컨테이너를 1시간 동안 실행 상태로 유지
위의 모든 매니페스트를 적용합니다:
kubectl apply -f frontend-pods.yaml
kubectl apply -f backend-pods.yaml
kubectl apply -f database-pods.yaml
kubectl apply -f testing-pods.yaml
이제 여러 네임스페이스에 다양한 애플리케이션이 배포되었습니다. 서로 다른 네임스페이스 간의 통신을 테스트해 봅시다:
# 테스트 Pod의 이름 가져오기
TEST_POD=$(kubectl get pods -n testing -l app=testing -o jsonpath='{.items[0].metadata.name}')
# frontend 서비스 접근 테스트
kubectl exec -n testing $TEST_POD -- curl -s frontend-service.frontend.svc.cluster.local
# backend 서비스 접근 테스트
kubectl exec -n testing $TEST_POD -- curl -s backend-service.backend.svc.cluster.local
# database 서비스 접근 테스트 (연결만 확인)
kubectl exec -n testing $TEST_POD -- nc -zv database-service.database.svc.cluster.local 5432
기본적으로 모든 네임스페이스 간의 통신이 허용되는 것을 확인할 수 있습니다. 이제 클러스터 전체 정책을 적용하여 이 통신을 제어해 보겠습니다.
📌 기본 CiliumClusterwideNetworkPolicy 적용
✅ 클러스터 전체 기본 거부 정책
먼저 클러스터 전체에 기본 거부 정책을 적용해 보겠습니다. 이 정책은 명시적으로 허용하지 않은 모든 통신을 차단합니다:
# default-deny-clusterwide.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "default-deny-all" # 정책 이름
spec:
endpointSelector: {} # 빈 선택자는 모든 엔드포인트에 적용됨
ingress: # 인바운드 규칙
# 규칙이 없음 = 모든 인바운드 트래픽 차단
egress: # 아웃바운드 규칙
# 규칙이 없음 = 모든 아웃바운드 트래픽 차단
정책을 적용하기 전에, 먼저 이 정책의 의미를 이해해 봅시다:
- endpointSelector: {}: 빈 선택자는 클러스터의 모든 Pod에 정책이 적용됨을 의미합니다.
- 빈 ingress/egress 규칙: 규칙이 없으면 해당 방향의 모든 트래픽이 차단됩니다.
정책을 적용합니다:
kubectl apply -f default-deny-clusterwide.yaml
이제 이전에 수행했던 동일한 테스트를 다시 실행해 봅시다:
# frontend 서비스 접근 테스트
kubectl exec -n testing $TEST_POD -- curl -s --connect-timeout 5 frontend-service.frontend.svc.cluster.local
# 차단되어 타임아웃 발생
# backend 서비스 접근 테스트
kubectl exec -n testing $TEST_POD -- curl -s --connect-timeout 5 backend-service.backend.svc.cluster.local
# 차단되어 타임아웃 발생
# database 서비스 접근 테스트
kubectl exec -n testing $TEST_POD -- nc -zv -w 5 database-service.database.svc.cluster.local 5432
# 차단되어 타임아웃 발생
모든 네임스페이스 간 통신이 차단된 것을 확인할 수 있습니다. 이는 클러스터 전체에 적용된 기본 거부 정책이 작동하고 있음을 보여줍니다.
✅ DNS 및 쿠버네티스 API 서버 접근 허용
기본 거부 정책이 적용된 상태에서는 DNS 조회나 쿠버네티스 API 서버 접근과 같은 필수 기능이 작동하지 않습니다. 이를 허용하는 클러스터 전체 정책을 추가해 봅시다:
# allow-essential-clusterwide.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "allow-essential-traffic" # 정책 이름
spec:
endpointSelector: {} # 모든 엔드포인트에 적용
egress: # 아웃바운드 규칙
- toEndpoints: # kube-dns로의 트래픽 허용
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts: # DNS 포트 허용
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
- toEntities: # 쿠버네티스 API 서버로의 트래픽 허용
- kube-apiserver
toPorts: # API 서버 포트 허용
- ports:
- port: "443"
protocol: TCP
정책을 적용합니다:
kubectl apply -f allow-essential-clusterwide.yaml
이제 DNS 조회와 쿠버네티스 API 서버 접근이 다시 가능해졌는지 확인해 봅시다:
# DNS 조회 테스트
kubectl exec -n testing $TEST_POD -- nslookup kubernetes.default.svc.cluster.local
# 정상적으로 작동해야 함
# API 서버 접근 테스트 (인증 문제로 실패할 수 있으나, 연결 자체는 성공)
kubectl exec -n testing $TEST_POD -- curl -k https://kubernetes.default.svc.cluster.local
기본적인 DNS와 API 서버 접근이 복구된 것을 확인할 수 있습니다.
📌 네임스페이스 기반 정책 구성
✅ 프로덕션 환경 네임스페이스 간 통신 허용
이제 environment: production 레이블을 가진 네임스페이스 간의 통신을 허용하는 정책을 추가해 봅시다:
# allow-production-traffic.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "allow-production-namespaces" # 정책 이름
spec:
endpointSelector: # 프로덕션 환경의 모든 Pod에 적용
matchExpressions:
- key: "k8s:io.kubernetes.pod.namespace"
operator: In
values:
- frontend
- backend
- database
ingress: # 인바운드 규칙
- fromEndpoints: # 프로덕션 환경 네임스페이스의 Pod에서 오는 트래픽 허용
- matchExpressions:
- key: "k8s:io.kubernetes.pod.namespace"
operator: In
values:
- frontend
- backend
- database
egress: # 아웃바운드 규칙
- toEndpoints: # 프로덕션 환경 네임스페이스의 Pod로 가는 트래픽 허용
- matchExpressions:
- key: "k8s:io.kubernetes.pod.namespace"
operator: In
values:
- frontend
- backend
- database
대안으로, 네임스페이스 레이블을 사용하여 더 유연하게 정책을 구성할 수도 있습니다:
# allow-production-labels.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "allow-production-communication" # 정책 이름
spec:
endpointSelector: # 프로덕션 환경 라벨을 가진 네임스페이스의 모든 Pod에 적용
matchLabels:
"k8s:environment": production
ingress: # 인바운드 규칙
- fromEndpoints: # 프로덕션 환경 라벨을 가진 네임스페이스의 Pod에서 오는 트래픽 허용
- matchLabels:
"k8s:environment": production
egress: # 아웃바운드 규칙
- toEndpoints: # 프로덕션 환경 라벨을 가진 네임스페이스의 Pod로 가는 트래픽 허용
- matchLabels:
"k8s:environment": production
레이블 기반 정책을 적용합니다:
kubectl apply -f allow-production-labels.yaml
이제 프로덕션 환경 네임스페이스 간의 통신을 테스트해 봅시다:
# 테스트를 위해 frontend 네임스페이스에 임시 Pod 생성
kubectl run -n frontend temp-curl --image=curlimages/curl:7.80.0 --rm -it -- sh
# frontend에서 backend 서비스 접근 테스트
curl -s backend-service.backend.svc.cluster.local
# 정상적으로 작동해야 함
# frontend에서 database 서비스 접근 테스트
nc -zv database-service.database.svc.cluster.local 5432
# 정상적으로 작동해야 함
# Pod 종료
exit
프로덕션 환경 네임스페이스 간의 통신이 다시 허용된 것을 확인할 수 있습니다. 그러나 테스트 환경에서 프로덕션 환경으로의 접근은 여전히 차단되어야 합니다:
# testing 네임스페이스에서 frontend 서비스 접근 테스트
kubectl exec -n testing $TEST_POD -- curl -s --connect-timeout 5 frontend-service.frontend.svc.cluster.local
# 차단되어 타임아웃 발생
📌 티어 기반 정책 구성
✅ 애플리케이션 티어 간 통신 제어
이제 애플리케이션 티어 간의 통신을 세부적으로 제어하는 정책을 구성해 봅시다. 웹 티어는 앱 티어에 접근할 수 있고, 앱 티어는 DB 티어에 접근할 수 있지만, 웹 티어가 DB 티어에 직접 접근하는 것은 차단하는 정책입니다:
# tier-based-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "tier-based-access-control" # 정책 이름
spec:
# 웹 티어 규칙
endpointSelector: # 웹 티어 Pod 선택
matchLabels:
tier: web
egress: # 웹 티어의 아웃바운드 규칙
- toEndpoints: # 앱 티어로만 접근 허용
- matchLabels:
tier: app
toPorts: # 웹 서버 포트로만 접근 허용
- ports:
- port: "80"
protocol: TCP
---
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "app-to-db-access" # 정책 이름
spec:
# 앱 티어 규칙
endpointSelector: # 앱 티어 Pod 선택
matchLabels:
tier: app
ingress: # 앱 티어의 인바운드 규칙
- fromEndpoints: # 웹 티어에서만 접근 허용
- matchLabels:
tier: web
toPorts: # 웹 서버 포트로만 접근 허용
- ports:
- port: "80"
protocol: TCP
egress: # 앱 티어의 아웃바운드 규칙
- toEndpoints: # DB 티어로만 접근 허용
- matchLabels:
tier: db
toPorts: # 데이터베이스 포트로만 접근 허용
- ports:
- port: "5432"
protocol: TCP
---
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "db-tier-access" # 정책 이름
spec:
# DB 티어 규칙
endpointSelector: # DB 티어 Pod 선택
matchLabels:
tier: db
ingress: # DB 티어의 인바운드 규칙
- fromEndpoints: # 앱 티어에서만 접근 허용
- matchLabels:
tier: app
toPorts: # 데이터베이스 포트로만 접근 허용
- ports:
- port: "5432"
protocol: TCP
티어 기반 정책을 적용합니다:
kubectl apply -f tier-based-policy.yaml
이제 티어 간 통신 규칙을 테스트해 봅시다:
# frontend (웹 티어)에서 backend (앱 티어) 접근 테스트
kubectl run -n frontend temp-curl --image=curlimages/curl:7.80.0 --rm -it -- curl -s backend-service.backend.svc.cluster.local
# 정상적으로 작동해야 함
# backend (앱 티어)에서 database (DB 티어) 접근 테스트
kubectl run -n backend temp-curl --image=curlimages/curl:7.80.0 --rm -it -- nc -zv database-service.database.svc.cluster.local 5432
# 정상적으로 작동해야 함
# frontend (웹 티어)에서 database (DB 티어) 직접 접근 테스트
kubectl run -n frontend temp-curl --image=curlimages/curl:7.80.0 --rm -it -- nc -zv -w 5 database-service.database.svc.cluster.local 5432
# 차단되어 타임아웃 발생
티어 기반 정책이 예상대로 작동하는 것을 확인할 수 있습니다. 웹 티어는 앱 티어에 접근할 수 있고, 앱 티어는 DB 티어에 접근할 수 있으며, 웹 티어에서 DB 티어로의 직접 접근은 차단됩니다.
📌 보안 그룹 수준의 정책 구성
✅ PCI 컴플라이언스 정책 예시
결제 카드 산업(PCI) 컴플라이언스를 위한 정책 예시를 살펴보겠습니다. 이 정책은 security: pci 레이블이 있는 Pod들을 격리하고, 특별한 보안 규칙을 적용합니다:
# pci-compliance-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "pci-compliance-policy" # 정책 이름
spec:
description: "PCI 규정 준수를 위한 격리 정책"
# PCI 규정 준수 대상 Pod 선택
endpointSelector: # security: pci 레이블이 있는 모든 Pod 선택
matchLabels:
security: pci
ingress: # 인바운드 규칙
- fromEndpoints: # 같은 PCI 레이블을 가진 Pod에서만 접근 허용
- matchLabels:
security: pci
- fromEndpoints: # 승인된 관리자 Pod에서만 접근 허용
- matchLabels:
role: admin
access: pci-approved
egress: # 아웃바운드 규칙
- toEndpoints: # 같은 PCI 레이블을 가진 Pod로만 접근 허용
- matchLabels:
security: pci
- toEndpoints: # DNS 서버 접근 허용
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts: # DNS 포트만 허용
- ports:
- port: "53"
protocol: UDP
- toEntities: # 승인된 외부 엔드포인트만 접근 허용
- kube-apiserver
- toCIDR: # 결제 처리 서비스 IP에만 접근 허용
- "203.0.113.0/24" # 가상의 결제 서비스 IP 범위
toPorts: # HTTPS 포트만 허용
- ports:
- port: "443"
protocol: TCP
이러한 정책은 PCI DSS와 같은 규정 준수 요구사항에 부합하는 네트워크 분리를 제공합니다. 실제로 적용하기 전에 PCI 컴플라이언스 요구사항에 맞게 조정해야 합니다.
✅ 레이블 선택자 활용하기
클러스터 전체 정책에서 다양한 레이블 선택자를 활용하는 방법을 살펴보겠습니다:
# label-selector-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "advanced-label-selector-policy" # 정책 이름
spec:
# 정확한 레이블 매칭
endpointSelector: # 여러 레이블을 동시에 만족하는 Pod 선택
matchLabels:
app: backend
environment: production
ingress:
- fromEndpoints:
# matchExpressions를 사용한 고급 선택자
- matchExpressions:
- key: app
operator: In
values:
- frontend
- gateway
- key: environment
operator: In
values:
- production
- staging
# 특정 값을 가지지 않는 Pod 선택
- matchExpressions:
- key: role
operator: NotIn
values:
- testing
- development
# 특정 레이블이 존재하는 Pod 선택
- matchExpressions:
- key: security-approved
operator: Exists
# 특정 레이블이 없는 Pod 선택
- matchExpressions:
- key: restricted
operator: DoesNotExist
이처럼 matchLabels와 matchExpressions를 조합하여 매우 세밀한 선택자를 구성할 수 있습니다.
📌 고급 클러스터 전체 정책 패턴
✅ 계층형 정책 구조
클러스터 전체 정책과 네임스페이스 정책을 계층적으로 구성하여, 기본 규칙과 예외 규칙을 함께 관리할 수 있습니다:
# hierarchical-policy.yaml
# 1. 클러스터 전체 기본 거부 정책
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "tier-1-default-deny" # 계층 1: 기본 거부
spec:
endpointSelector: {} # 모든 Pod에 적용
ingress: [] # 빈 규칙 = 모든 트래픽 차단
egress: [] # 빈 규칙 = 모든 트래픽 차단
---
# 2. 필수 서비스 접근 허용 정책
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "tier-2-essential-services" # 계층 2: 필수 서비스 허용
spec:
endpointSelector: {} # 모든 Pod에 적용
egress:
- toEndpoints: # DNS 접근 허용
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
- toEntities: # API 서버 접근 허용
- kube-apiserver
---
# 3. 환경별 기본 정책
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "tier-3-env-production" # 계층 3: 환경별 기본 정책
spec:
endpointSelector: # 프로덕션 환경 Pod에 적용
matchLabels:
"k8s:environment": production
ingress:
- fromEndpoints: # 같은 환경 내 통신 허용
- matchLabels:
"k8s:environment": production
egress:
- toEndpoints: # 같은 환경 내 통신 허용
- matchLabels:
"k8s:environment": production
---
# 4. 애플리케이션별 상세 정책
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "tier-4-app-specific" # 계층 4: 애플리케이션별 상세 정책
spec:
endpointSelector: # 특정 앱에 적용
matchLabels:
app: frontend
"k8s:environment": production
# 애플리케이션별 상세 규칙 정의
# ...
이러한 계층 구조를 통해 클러스터 전체의 일관된 보안 정책을 유지하면서, 필요에 따라 세부적인 정책을 추가할 수 있습니다.
✅ 모니터링 및 감사 정책
모니터링 및 감사 목적의 정책을 구성하여, 트래픽을 차단하지 않고 기록만 할 수도 있습니다:
# audit-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "audit-all-traffic" # 감사 정책 이름
spec:
endpointSelector: {} # 모든 Pod에 적용
ingress:
- {} # 모든 인바운드 트래픽 허용 및 기록
egress:
- {} # 모든 아웃바운드 트래픽 허용 및 기록
이 정책은 트래픽을 차단하지 않고 허용하면서, Hubble과 같은 도구를 통해 모든 트래픽 흐름을 기록하고 분석할 수 있게 합니다.
✅ 운영 중 정책 변경 관리
클러스터 전체 정책을 운영 중에 변경할 때는 주의가 필요합니다. 다음과 같은 접근 방식을 고려해 볼 수 있습니다:
- 단계적 적용: 먼저 모니터링 모드로 정책을 적용하여 영향을 분석한 후, 실제 모드로 전환합니다.
- 백업 계획: 정책 적용 전에 현재 상태를 백업하고, 빠르게 복구할 수 있는 계획을 수립합니다.
- 점진적 접근: 작은 변경부터 시작하여 점진적으로 더 제한적인 정책으로 전환합니다.
- 관리 네임스페이스 예외: 관리자가 문제 해결을 위해 사용하는 네임스페이스에는 특별한 예외 규칙을 적용합니다.
# management-exception.yaml
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "management-exception" # 관리 예외 정책 이름
spec:
# 관리 네임스페이스의 특정 Pod에만 적용
endpointSelector:
matchLabels:
"k8s:io.kubernetes.pod.namespace": management
role: admin
ingress:
- {} # 모든 인바운드 트래픽 허용
egress:
- {} # 모든 아웃바운드 트래픽 허용
이를 통해 긴급 상황에서 관리자가 문제를 해결할 수 있는 접근 경로를 유지합니다.
📌 Hubble을 활용한 클러스터 전체 정책 모니터링
✅ 클러스터 전체 트래픽 흐름 분석
Hubble을 사용하여 클러스터 전체 정책에 의한 트래픽 흐름을 모니터링하고 분석할 수 있습니다:
# 모든 네임스페이스의 거부된 트래픽 관찰
hubble observe --verdict DROPPED
# 특정 네임스페이스 간의 트래픽 관찰
hubble observe --namespace frontend --to-namespace backend
# 특정 레이블을 가진 Pod 간의 트래픽 관찰
hubble observe --label "tier=web" --to-label "tier=app"
# 특정 정책에 의해 차단된 트래픽 분석
hubble observe --verdict DROPPED --json | jq '.[].policy'
Hubble UI를 사용하면 더 직관적인 시각화가 가능합니다. 네트워크 흐름 그래프에서 클러스터 전체 통신 패턴을 확인하고, 문제가 있는 연결을 식별할 수 있습니다.
✅ 정책 디버깅 및 문제 해결
클러스터 전체 정책이 예상대로 작동하지 않을 때, 다음과 같은 방법으로 문제를 진단할 수 있습니다:
- 정책 상태 확인:
- kubectl get ciliumclusterwidenetworkpolicies kubectl describe ciliumclusterwidenetworkpolicy <policy-name>
- Cilium 상태 확인:
- cilium status --all-namespaces
- 특정 Pod의 정책 확인:
- kubectl -n <namespace> exec -it <cilium-pod> -- cilium endpoint list kubectl -n <namespace> exec -it <cilium-pod> -- cilium endpoint get <endpoint-id> -o json
- 정책 시뮬레이션:
- kubectl -n <namespace> exec -it <cilium-pod> -- cilium policy trace --src-k8s-pod <namespace>:<pod> --dst-k8s-pod <namespace>:<pod> -d TCP/<port>
- 임시 허용 정책 추가: 문제 해결을 위해 임시로 허용 정책을 추가할 수 있습니다.
- # debug-policy.yaml apiVersion: "cilium.io/v2" kind: CiliumClusterwideNetworkPolicy metadata: name: "temporary-debug-policy" spec: endpointSelector: matchLabels: app: problematic-app ingress: - {} # 모든 인바운드 트래픽 임시 허용 egress: - {} # 모든 아웃바운드 트래픽 임시 허용
📌 실무 적용 시 고려사항
✅ 정책 관리 모범 사례
- 정책 명명 규칙: 일관된 명명 규칙을 사용하여 정책을 쉽게 식별할 수 있게 합니다.예: tier-1-global-default-deny, tier-2-production-web-access
- tier-<level>-<scope>-<purpose>
- 주석 및 설명 활용: 정책의 목적과 효과를 명확히 문서화합니다.
- metadata: name: "policy-name" annotations: description: "상세한 정책 설명" owner: "팀 이름" contact: "연락처 정보"
- Git 기반 관리: 모든 정책을 Git 저장소에서 관리하고, CI/CD 파이프라인을 통해 적용합니다.
- 정책 테스트: 비프로덕션 환경에서 정책을 먼저 테스트하고, 점진적으로 프로덕션에 적용합니다.
✅ 성능 고려사항
- 정책 수 관리: 너무 많은 수의 세부 정책은 성능에 영향을 줄 수 있으므로, 가능한 한 정책을 최적화하고 통합합니다.
- 선택자 최적화: 광범위한 선택자보다 구체적인 선택자를 사용하여 평가 속도를 높입니다.
- 모니터링 설정: Prometheus 메트릭을 사용하여 정책 평가 성능을 모니터링합니다.
- # Cilium 정책 메트릭 확인 kubectl -n kube-system exec -it <cilium-pod> -- cilium metrics list | grep policy
- 캐싱 활용: Cilium의 정책 캐싱 메커니즘을 이해하고 활용합니다.
✅ 조직 내 협업 전략
- 정책 소유권 정의: 누가 클러스터 전체 정책을 관리하고 승인할 권한이 있는지 명확히 정의합니다.
- 변경 관리 프로세스: 정책 변경을 위한 명확한 프로세스와 승인 절차를 수립합니다.
- 교육 및 지식 공유: 팀원들에게 Cilium 정책의 동작 방식과 디버깅 방법을 교육합니다.
- 문서화: 조직의 네트워크 정책 전략과 원칙을 명확히 문서화합니다.
📌 Summary
이번 글에서는 Cilium의 CiliumClusterwideNetworkPolicy를 활용하여 클러스터 전체 범위의 네트워크 정책을 구성하는 방법을 살펴보았습니다:
✅ CiliumClusterwideNetworkPolicy의 주요 특징:
- 네임스페이스에 상관없이 클러스터 전체에 적용
- 중앙 집중식 보안 정책 관리 가능
- 일관된 규칙을 모든 네임스페이스에 적용 가능
✅ 주요 정책 패턴:
- 클러스터 전체 기본 거부 정책
- 네임스페이스 및 레이블 기반 정책
- 애플리케이션 티어 기반 정책
- 보안 그룹 수준의 정책
- 계층형 정책 구조
✅ 실무 적용 시 고려사항:
- 점진적 및 단계적 적용 접근법
- 정책 명명 및 관리 모범 사례
- 성능 영향 최소화
- 조직 내 협업 전략
✅ 모니터링 및 문제 해결:
- Hubble을 활용한 트래픽 흐름 분석
- 정책 디버깅 및 문제 해결 방법
- 임시 허용 정책 활용
CiliumClusterwideNetworkPolicy를 효과적으로 활용하면 복잡한 클러스터 환경에서도 일관되고 세밀한 네트워크 보안을 구현할 수 있습니다. 이를 통해 조직의 보안 요구사항을 충족하면서도 애플리케이션의 원활한 통신을 보장할 수 있습니다.
'Kubernetes Tools > Cilium' 카테고리의 다른 글
EP13. Hubble CLI & UI 고급 사용법 | 네트워크 분석 실무 활용 (0) | 2025.03.23 |
---|---|
EP12. ID 기반 정책과 보안 강화 | Identity 기반 접근 제어 이해 (0) | 2025.03.23 |
EP10. CIDR, Entity 기반 정책 구성 | 외부 접근 정밀 제어 (0) | 2025.03.22 |
EP09. L7 정책 실습 (Kafka, DNS 등) | HTTP 요청이 아닌 트래픽 제어 (0) | 2025.03.22 |
EP08. L7 정책 실습 (HTTP 제어) | Path, Host, Method 기반 제어 (0) | 2025.03.22 |