Split View: Cilium 네트워크 정책 엔진: L3/L4/L7 필터링 구현
Cilium 네트워크 정책 엔진: L3/L4/L7 필터링 구현
Cilium 네트워크 정책 엔진: L3/L4/L7 필터링 구현
개요
Cilium의 네트워크 정책 엔진은 쿠버네티스 NetworkPolicy를 확장하여 L3/L4/L7 수준의 세밀한 트래픽 제어를 제공합니다. eBPF와 Envoy 프록시를 결합한 하이브리드 아키텍처로 고성능과 유연성을 동시에 달성합니다.
1. 정책 리포지토리와 규칙 컴파일
1.1 정책 소스
Cilium은 여러 소스에서 네트워크 정책을 수집합니다.
정책 소스:
1. Kubernetes NetworkPolicy
- 표준 L3/L4 정책
- Cilium이 자동으로 변환하여 적용
2. CiliumNetworkPolicy (CNP)
- 네임스페이스 범위 Cilium 확장 정책
- L7, FQDN, Identity 기반 등 고급 기능
3. CiliumClusterwideNetworkPolicy (CCNP)
- 클러스터 전체에 적용되는 정책
- 기본 거부 정책, 공통 보안 규칙
4. CiliumEnvoyConfig (CEC)
- Envoy 프록시의 L7 트래픽 관리 규칙
1.2 정책 리포지토리
Agent 내부의 정책 리포지토리가 모든 정책을 통합 관리합니다.
정책 수집 흐름:
K8s API Server
|
v
[Watcher: NetworkPolicy] -> 정책 리포지토리
[Watcher: CNP] -> 정책 리포지토리
[Watcher: CCNP] -> 정책 리포지토리
|
v
[정책 계산 엔진]
|
v
[엔드포인트별 정책 집합]
|
v
[BPF 프로그램 컴파일]
1.3 정책에서 BPF 맵으로의 변환
CiliumNetworkPolicy YAML
|
v
정책 파싱 및 정규화
|
v
셀렉터 매칭: 영향받는 엔드포인트 결정
|
v
Identity 기반 허용 목록 생성
|
v
BPF 정책 맵 업데이트:
cilium_policy_<endpoint_id> 맵에 항목 추가
키: (Identity, 포트, 프로토콜)
값: (허용/거부, 프록시 포트)
|
v
엔드포인트 BPF 프로그램 재생성 (필요시)
2. Identity 기반 적용 vs IP 기반 적용
2.1 Identity 기반 적용
Cilium의 기본 정책 적용 방식입니다. IP 주소 대신 수치 Identity를 사용합니다.
전통적 IP 기반 방화벽:
허용: 10.244.1.5 -> 10.244.2.10:8080
문제: Pod가 재시작되면 IP가 변경됨
Cilium Identity 기반:
허용: Identity 48291 (app=frontend) -> Identity 52103 (app=backend):8080
장점: IP 변경에 무관하게 정책 유지
# 정책 맵 내용 확인 (엔드포인트 ID 기준)
cilium bpf policy get 1234
# 출력 예시:
# POLICY DIRECTION IDENTITY PORT/PROTO PROXY PORT ENTRY TYPE
# Allow Ingress 48291 8080/TCP 0 allow
# Allow Ingress 52103 443/TCP 0 allow
# Allow Egress 0 53/UDP 0 allow (DNS)
2.2 정책 맵 구조
// 정책 맵 키 (개념적)
struct policy_key {
__u32 identity; // 소스/목적지 Identity
__u16 dport; // 목적지 포트 (0 = 모든 포트)
__u8 protocol; // TCP, UDP, ICMP
__u8 direction; // ingress(1), egress(2)
};
// 정책 맵 값
struct policy_entry {
__u8 action; // allow(1), deny(2), audit(3)
__u16 proxy_port; // L7 프록시 포트 (0 = 프록시 없음)
__u8 auth_type; // 인증 타입 (mTLS 등)
__u64 packets; // 매칭 패킷 카운터
__u64 bytes; // 매칭 바이트 카운터
};
2.3 정책 룩업 알고리즘
패킷 수신 시 정책 룩업:
1. 소스 IP에서 Identity 조회 (ipcache)
2. 정책 맵에서 (Identity, Port, Protocol) 조합 룩업
3. 정확한 매칭 시도:
- (src_identity, dst_port, protocol) 확인
4. 와일드카드 매칭:
- (src_identity, ANY_PORT, protocol) 확인
- (ANY_IDENTITY, dst_port, protocol) 확인
5. Deny 규칙 우선 확인:
- Deny가 있으면 무조건 거부
6. 결과: Allow / Deny / Audit
3. L3/L4 적용: eBPF에서의 고속 필터링
3.1 L3 정책 (네트워크 레이어)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l3-policy-example
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
- fromCIDR:
- 10.0.0.0/8
- fromEntities:
- world
egress:
- toEndpoints:
- matchLabels:
app: database
- toCIDR:
- 0.0.0.0/0
toCIDRSet:
- cidr: 0.0.0.0/0
except:
- 169.254.169.254/32
3.2 L4 정책 (전송 레이어)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l4-policy-example
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: '8080'
protocol: TCP
- port: '8443'
protocol: TCP
egress:
- toEndpoints:
- matchLabels:
app: database
toPorts:
- ports:
- port: '5432'
protocol: TCP
- toCIDR:
- 0.0.0.0/0
toPorts:
- ports:
- port: '443'
protocol: TCP
3.3 eBPF에서의 L3/L4 적용 흐름
패킷: src=10.244.1.5:34567 dst=10.244.2.10:8080 TCP
1. [from-container 또는 to-container BPF 프로그램]
2. 소스 Identity 조회:
ipcache[10.244.1.5] -> Identity: 48291
3. 정책 맵 룩업:
policy_map[endpoint_id] 에서 검색:
key = (identity=48291, port=8080, proto=TCP, dir=ingress)
4. 결과:
- Allow: 패킷 전달 계속
- Deny: 패킷 드롭 + 모니터 이벤트
- L7 Redirect: Envoy 프록시 포트로 리디렉션
4. L7 적용: Envoy 프록시 통합
4.1 L7 정책 개요
L7 정책은 애플리케이션 프로토콜 수준의 필터링을 제공합니다.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-http-policy
spec:
endpointSelector:
matchLabels:
app: api-server
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: '8080'
protocol: TCP
rules:
http:
- method: GET
path: '/api/v1/users'
- method: GET
path: '/api/v1/products'
- method: POST
path: '/api/v1/orders'
headers:
- 'Content-Type: application/json'
4.2 L7 리디렉션 메커니즘
L7 정책이 적용된 트래픽 흐름:
Pod A -> [from-container BPF]
|
v (정책 맵: L7 프록시 리디렉션 필요)
|
v
[tc redirect to Envoy proxy port]
|
v
[Envoy Proxy (노드당 1개)]
- HTTP/gRPC/Kafka 파싱
- L7 규칙 매칭
- 허용/거부 결정
|
v (허용된 경우)
|
v
[BPF를 통해 목적지로 전달]
|
v
Pod B
4.3 지원 프로토콜
| 프로토콜 | 필터링 가능 필드 |
|---|---|
| HTTP | method, path, headers, host |
| gRPC | service, method |
| Kafka | topic, clientID, apiKey, apiVersion |
| DNS | query name pattern (matchName, matchPattern) |
4.4 Kafka L7 정책 예시
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kafka-policy
spec:
endpointSelector:
matchLabels:
app: kafka-consumer
egress:
- toEndpoints:
- matchLabels:
app: kafka-broker
toPorts:
- ports:
- port: '9092'
protocol: TCP
rules:
kafka:
- role: consume
topic: 'orders'
- role: consume
topic: 'events'
5. FQDN 정책: DNS 프록시 연동
5.1 FQDN 정책 동작 원리
FQDN 정책 흐름:
1. 정책 정의:
toFQDNs:
- matchName: "api.example.com"
2. Cilium DNS 프록시 활성화:
- Pod의 DNS 트래픽을 투명하게 인터셉트
- DNS 응답에서 IP 주소 학습
3. IP 캐시 업데이트:
DNS 응답: api.example.com -> 203.0.113.10, 203.0.113.11
|
v
ipcache에 IP -> FQDN 매핑 추가
BPF 정책 맵에 해당 IP에 대한 허용 규칙 추가
4. 트래픽 허용/차단:
- 학습된 IP로의 트래픽만 허용
- DNS TTL에 따라 매핑 만료 및 갱신
5.2 FQDN 정책 예시
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: fqdn-policy
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchName: 'api.external-service.com'
toPorts:
- ports:
- port: '443'
protocol: TCP
- toFQDNs:
- matchPattern: '*.storage.googleapis.com'
toPorts:
- ports:
- port: '443'
protocol: TCP
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: '53'
protocol: UDP
rules:
dns:
- matchPattern: '*'
5.3 DNS 프록시 내부 동작
DNS 쿼리 처리:
Pod -> DNS 쿼리 (api.example.com)
|
v
[from-container BPF: DNS 포트 감지]
|
v (DNS 트래픽을 Cilium DNS 프록시로 리디렉션)
|
v
[Cilium DNS 프록시]
- 쿼리를 업스트림 DNS 서버로 전달
- 응답 수신
- IP 주소 학습 (A/AAAA 레코드)
- FQDN-to-IP 매핑 업데이트
- BPF 맵 업데이트
- 응답을 Pod에 전달
|
v
Pod <- DNS 응답 수신
6. CiliumNetworkPolicy vs CiliumClusterwideNetworkPolicy
6.1 범위 차이
CiliumNetworkPolicy (CNP):
- 네임스페이스 범위
- endpointSelector로 같은 네임스페이스의 Pod 선택
- fromEndpoints/toEndpoints에 namespaceSelector로 교차 네임스페이스 참조
CiliumClusterwideNetworkPolicy (CCNP):
- 클러스터 범위
- nodeSelector로 특정 노드 선택 가능
- 모든 네임스페이스에 적용
- 클러스터 수준 기본 정책에 적합
6.2 CCNP 활용 예시
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: default-deny-ingress
spec:
endpointSelector: {}
ingress:
- fromEntities:
- cluster
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: allow-dns
spec:
endpointSelector: {}
egress:
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: '53'
protocol: UDP
rules:
dns:
- matchPattern: '*'
6.3 호스트 정책
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-firewall
spec:
nodeSelector:
matchLabels:
node-role.kubernetes.io/worker: ''
ingress:
- fromEntities:
- remote-node
- health
toPorts:
- ports:
- port: '10250'
protocol: TCP
- fromCIDR:
- 10.0.0.0/8
toPorts:
- ports:
- port: '22'
protocol: TCP
7. 정책 감사 모드 (Policy Audit Mode)
7.1 감사 모드 동작
감사 모드에서는 정책 위반 트래픽을 차단하지 않고 로그만 기록합니다.
# 엔드포인트를 감사 모드로 설정
cilium endpoint config 1234 PolicyAuditMode=Enabled
# 전역 감사 모드 설정
cilium config PolicyAuditMode=true
# 감사 로그 확인
cilium monitor --type policy-verdict
# 출력 예시:
# Policy verdict log: flow ... action audit
# -> Would be DROPPED by policy (ingress)
# Identity: 48291 -> 52103, port 8080/TCP
7.2 감사에서 적용으로 전환
감사 모드 활용 워크플로:
1단계: 감사 모드 활성화
-> 모든 트래픽 허용, 위반 기록
2단계: Hubble로 트래픽 패턴 분석
-> 실제 필요한 통신 경로 파악
3단계: 정책 작성 및 감사 결과와 비교
-> 의도하지 않은 차단이 없는지 확인
4단계: 감사 모드 비활성화
-> 실제 정책 적용 시작
8. 엔드포인트 재생성과 정책 변경
8.1 정책 변경 시 재생성 프로세스
정책 변경 감지:
|
v
영향받는 엔드포인트 결정:
- 셀렉터가 매칭하는 모든 엔드포인트
- Identity 참조를 통한 간접 영향도 포함
|
v
정책 맵 재계산:
- 새 허용/거부 규칙 집합 생성
- 기존 정책 맵과 비교 (변경분만 적용)
|
v
BPF 맵 업데이트:
- cilium_policy 맵에 새 항목 추가/삭제
- 원자적 업데이트로 패킷 손실 최소화
|
v
BPF 프로그램 재컴파일 (필요시):
- L7 리디렉션 추가/제거 시
- 프로그램 로직 변경이 필요한 경우
|
v
엔드포인트 상태 업데이트: Ready
8.2 재생성 성능 최적화
최적화 기법:
1. 증분 업데이트:
- 전체 재컴파일 대신 BPF 맵만 업데이트
- 대부분의 정책 변경은 맵 업데이트만으로 충분
2. 배치 재생성:
- 짧은 시간 내 여러 정책 변경을 배치 처리
- 불필요한 중복 재생성 방지
3. 선택적 재생성:
- 영향받는 엔드포인트만 재생성
- Identity 기반으로 영향 범위 정확히 계산
# 재생성 상태 모니터링
cilium endpoint list
# 재생성 통계
cilium metrics list | grep regeneration
# 주요 메트릭:
# cilium_endpoint_regenerations_total
# cilium_endpoint_regeneration_time_stats_seconds
# cilium_policy_regeneration_total
9. Deny 정책
9.1 Deny 규칙 동작
Cilium은 명시적 Deny 규칙을 지원하며, Deny는 항상 Allow보다 우선합니다.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: deny-specific-cidr
spec:
endpointSelector:
matchLabels:
app: backend
egressDeny:
- toCIDR:
- 169.254.169.254/32
toPorts:
- ports:
- port: '80'
protocol: TCP
egress:
- toCIDR:
- 0.0.0.0/0
toPorts:
- ports:
- port: '443'
protocol: TCP
9.2 정책 우선순위
정책 평가 순서:
1. Deny 규칙 확인
- 매칭하는 Deny 규칙이 있으면 즉시 거부
- Allow 규칙 무시
2. Allow 규칙 확인
- 매칭하는 Allow 규칙이 있으면 허용
3. 기본 동작
- 해당 방향(ingress/egress)에 정책이 있으면: 기본 거부
- 정책이 전혀 없으면: 기본 허용
10. 정책 트러블슈팅
10.1 디버깅 명령
# 적용된 정책 확인
cilium policy get
# 엔드포인트별 정책 상태
cilium endpoint get 1234
# 정책 맵 내용 확인
cilium bpf policy get 1234
# Identity에서 레이블 확인
cilium identity get 48291
# 정책 verdict 모니터링
cilium monitor --type policy-verdict
# 드롭된 패킷 확인
cilium monitor --type drop
10.2 일반적인 문제와 해결
문제: Pod 간 통신이 차단됨
원인 가능성:
1. Identity가 올바르게 할당되지 않음
-> cilium identity list로 확인
2. 정책 셀렉터가 올바르지 않음
-> cilium policy get으로 적용 정책 확인
3. DNS 이그레스 정책이 누락됨
-> FQDN 정책 사용 시 DNS 허용 필수
문제: L7 정책이 적용되지 않음
원인 가능성:
1. Envoy 프록시가 정상 동작하지 않음
-> cilium status에서 Proxy 상태 확인
2. toPorts 아래 rules 구문 오류
-> cilium policy get으로 파싱 결과 확인
정리
Cilium의 네트워크 정책 엔진은 다층적 보안 모델을 통해 강력한 트래픽 제어를 제공합니다.
- Identity 기반 적용: IP 주소가 아닌 레이블 기반으로 정책을 적용하여 동적 환경에서도 안정적
- eBPF 고속 필터링: L3/L4 정책을 커널에서 직접 적용하여 최소 지연
- Envoy L7 통합: HTTP, gRPC, Kafka 등 애플리케이션 수준 필터링
- FQDN 정책: DNS 프록시를 통한 도메인 기반 이그레스 제어
- Deny 우선: 명시적 거부 규칙이 항상 우선하여 보안 강화
- 감사 모드: 정책 적용 전 영향도 사전 파악 가능
- 증분 업데이트: 최소한의 재생성으로 정책 변경 적용
Cilium Network Policy Engine: L3/L4/L7 Filtering Implementation
Cilium Network Policy Engine: L3/L4/L7 Filtering Implementation
Overview
Cilium's network policy engine extends Kubernetes NetworkPolicy to provide fine-grained traffic control at L3/L4/L7 levels. It combines eBPF with Envoy proxy in a hybrid architecture that achieves both high performance and flexibility.
1. Policy Repository and Rule Compilation
1.1 Policy Sources
Cilium collects network policies from multiple sources:
Policy sources:
1. Kubernetes NetworkPolicy
- Standard L3/L4 policies
- Automatically translated and applied by Cilium
2. CiliumNetworkPolicy (CNP)
- Namespace-scoped Cilium extended policy
- Advanced features: L7, FQDN, Identity-based
3. CiliumClusterwideNetworkPolicy (CCNP)
- Cluster-wide policies
- Default deny policies, common security rules
4. CiliumEnvoyConfig (CEC)
- Envoy proxy L7 traffic management rules
1.2 Policy Repository
The policy repository within the Agent manages all policies in a unified manner:
Policy collection flow:
K8s API Server
|
v
[Watcher: NetworkPolicy] -> Policy Repository
[Watcher: CNP] -> Policy Repository
[Watcher: CCNP] -> Policy Repository
|
v
[Policy Computation Engine]
|
v
[Per-Endpoint Policy Set]
|
v
[BPF Program Compilation]
1.3 Translation from Policy to BPF Maps
CiliumNetworkPolicy YAML
|
v
Parse and normalize policy
|
v
Selector matching: determine affected endpoints
|
v
Generate Identity-based allow list
|
v
Update BPF policy maps:
Add entries to cilium_policy_<endpoint_id> map
Key: (Identity, port, protocol)
Value: (allow/deny, proxy port)
|
v
Regenerate endpoint BPF programs (if needed)
2. Identity-Based vs IP-Based Enforcement
2.1 Identity-Based Enforcement
This is Cilium's default policy enforcement method, using numeric Identities instead of IP addresses:
Traditional IP-based firewall:
Allow: 10.244.1.5 -> 10.244.2.10:8080
Problem: IP changes when Pod restarts
Cilium Identity-based:
Allow: Identity 48291 (app=frontend) -> Identity 52103 (app=backend):8080
Advantage: Policy persists regardless of IP changes
# Check policy map contents (by endpoint ID)
cilium bpf policy get 1234
# Example output:
# POLICY DIRECTION IDENTITY PORT/PROTO PROXY PORT ENTRY TYPE
# Allow Ingress 48291 8080/TCP 0 allow
# Allow Ingress 52103 443/TCP 0 allow
# Allow Egress 0 53/UDP 0 allow (DNS)
2.2 Policy Map Structure
// Policy map key (conceptual)
struct policy_key {
__u32 identity; // Source/destination Identity
__u16 dport; // Destination port (0 = all ports)
__u8 protocol; // TCP, UDP, ICMP
__u8 direction; // ingress(1), egress(2)
};
// Policy map value
struct policy_entry {
__u8 action; // allow(1), deny(2), audit(3)
__u16 proxy_port; // L7 proxy port (0 = no proxy)
__u8 auth_type; // Auth type (mTLS, etc.)
__u64 packets; // Matched packet counter
__u64 bytes; // Matched byte counter
};
2.3 Policy Lookup Algorithm
Policy lookup on packet receive:
1. Look up Identity from source IP (ipcache)
2. Search in policy map for (Identity, Port, Protocol) combination
3. Exact match attempt:
- Check (src_identity, dst_port, protocol)
4. Wildcard match:
- Check (src_identity, ANY_PORT, protocol)
- Check (ANY_IDENTITY, dst_port, protocol)
5. Check Deny rules first:
- If Deny exists, unconditionally deny
6. Result: Allow / Deny / Audit
3. L3/L4 Enforcement: High-Speed Filtering in eBPF
3.1 L3 Policy (Network Layer)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l3-policy-example
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
- fromCIDR:
- 10.0.0.0/8
- fromEntities:
- world
egress:
- toEndpoints:
- matchLabels:
app: database
- toCIDR:
- 0.0.0.0/0
toCIDRSet:
- cidr: 0.0.0.0/0
except:
- 169.254.169.254/32
3.2 L4 Policy (Transport Layer)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l4-policy-example
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: '8080'
protocol: TCP
- port: '8443'
protocol: TCP
egress:
- toEndpoints:
- matchLabels:
app: database
toPorts:
- ports:
- port: '5432'
protocol: TCP
3.3 L3/L4 Enforcement Flow in eBPF
Packet: src=10.244.1.5:34567 dst=10.244.2.10:8080 TCP
1. [from-container or to-container BPF program]
2. Source Identity lookup:
ipcache[10.244.1.5] -> Identity: 48291
3. Policy map lookup:
Search in policy_map[endpoint_id]:
key = (identity=48291, port=8080, proto=TCP, dir=ingress)
4. Result:
- Allow: Continue packet delivery
- Deny: Drop packet + monitor event
- L7 Redirect: Redirect to Envoy proxy port
4. L7 Enforcement: Envoy Proxy Integration
4.1 L7 Policy Overview
L7 policies provide application protocol-level filtering:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-http-policy
spec:
endpointSelector:
matchLabels:
app: api-server
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: '8080'
protocol: TCP
rules:
http:
- method: GET
path: '/api/v1/users'
- method: GET
path: '/api/v1/products'
- method: POST
path: '/api/v1/orders'
headers:
- 'Content-Type: application/json'
4.2 L7 Redirect Mechanism
Traffic flow with L7 policy applied:
Pod A -> [from-container BPF]
|
v (policy map: L7 proxy redirect needed)
|
v
[tc redirect to Envoy proxy port]
|
v
[Envoy Proxy (1 per node)]
- HTTP/gRPC/Kafka parsing
- L7 rule matching
- Allow/deny decision
|
v (if allowed)
|
v
[Forward to destination via BPF]
|
v
Pod B
4.3 Supported Protocols
| Protocol | Filterable Fields |
|---|---|
| HTTP | method, path, headers, host |
| gRPC | service, method |
| Kafka | topic, clientID, apiKey, apiVersion |
| DNS | query name pattern (matchName, matchPattern) |
4.4 Kafka L7 Policy Example
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kafka-policy
spec:
endpointSelector:
matchLabels:
app: kafka-consumer
egress:
- toEndpoints:
- matchLabels:
app: kafka-broker
toPorts:
- ports:
- port: '9092'
protocol: TCP
rules:
kafka:
- role: consume
topic: 'orders'
- role: consume
topic: 'events'
5. FQDN Policies: DNS Proxy Integration
5.1 How FQDN Policies Work
FQDN policy flow:
1. Policy definition:
toFQDNs:
- matchName: "api.example.com"
2. Cilium DNS proxy activation:
- Transparently intercept Pod DNS traffic
- Learn IP addresses from DNS responses
3. IP cache update:
DNS response: api.example.com -> 203.0.113.10, 203.0.113.11
|
v
Add IP -> FQDN mapping to ipcache
Add allow rules for those IPs to BPF policy map
4. Traffic allow/block:
- Only allow traffic to learned IPs
- Mapping expires and refreshes based on DNS TTL
5.2 FQDN Policy Example
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: fqdn-policy
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchName: 'api.external-service.com'
toPorts:
- ports:
- port: '443'
protocol: TCP
- toFQDNs:
- matchPattern: '*.storage.googleapis.com'
toPorts:
- ports:
- port: '443'
protocol: TCP
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: '53'
protocol: UDP
rules:
dns:
- matchPattern: '*'
6. CiliumNetworkPolicy vs CiliumClusterwideNetworkPolicy
6.1 Scope Differences
CiliumNetworkPolicy (CNP):
- Namespace scope
- endpointSelector selects Pods in the same namespace
- Cross-namespace via namespaceSelector in fromEndpoints/toEndpoints
CiliumClusterwideNetworkPolicy (CCNP):
- Cluster scope
- Can select specific nodes with nodeSelector
- Applies across all namespaces
- Suitable for cluster-level default policies
6.2 CCNP Example
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: default-deny-ingress
spec:
endpointSelector: {}
ingress:
- fromEntities:
- cluster
6.3 Host Policy
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-firewall
spec:
nodeSelector:
matchLabels:
node-role.kubernetes.io/worker: ''
ingress:
- fromEntities:
- remote-node
- health
toPorts:
- ports:
- port: '10250'
protocol: TCP
- fromCIDR:
- 10.0.0.0/8
toPorts:
- ports:
- port: '22'
protocol: TCP
7. Policy Audit Mode
7.1 Audit Mode Operation
In audit mode, policy-violating traffic is not blocked but only logged:
# Set endpoint to audit mode
cilium endpoint config 1234 PolicyAuditMode=Enabled
# Global audit mode
cilium config PolicyAuditMode=true
# Check audit logs
cilium monitor --type policy-verdict
# Example output:
# Policy verdict log: flow ... action audit
# -> Would be DROPPED by policy (ingress)
# Identity: 48291 -> 52103, port 8080/TCP
7.2 Transitioning from Audit to Enforcement
Audit mode workflow:
Step 1: Enable audit mode
-> All traffic allowed, violations logged
Step 2: Analyze traffic patterns with Hubble
-> Identify actual required communication paths
Step 3: Write policies and compare with audit results
-> Verify no unintended blocks
Step 4: Disable audit mode
-> Actual policy enforcement begins
8. Endpoint Regeneration and Policy Changes
8.1 Regeneration Process on Policy Change
Policy change detected:
|
v
Determine affected endpoints:
- All endpoints matching the selector
- Including indirect impact via Identity references
|
v
Recompute policy maps:
- Generate new allow/deny rule set
- Compare with existing policy map (apply diff only)
|
v
Update BPF maps:
- Add/delete entries in cilium_policy map
- Atomic updates to minimize packet loss
|
v
Recompile BPF programs (if needed):
- When L7 redirect is added/removed
- When program logic changes are required
|
v
Update endpoint state: Ready
8.2 Regeneration Performance Optimization
Optimization techniques:
1. Incremental updates:
- Update only BPF maps instead of full recompilation
- Most policy changes only need map updates
2. Batch regeneration:
- Batch multiple policy changes in a short timeframe
- Prevent unnecessary duplicate regenerations
3. Selective regeneration:
- Only regenerate affected endpoints
- Precisely calculate impact scope based on Identity
9. Deny Policies
9.1 Deny Rule Behavior
Cilium supports explicit Deny rules, which always take precedence over Allow:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: deny-specific-cidr
spec:
endpointSelector:
matchLabels:
app: backend
egressDeny:
- toCIDR:
- 169.254.169.254/32
toPorts:
- ports:
- port: '80'
protocol: TCP
egress:
- toCIDR:
- 0.0.0.0/0
toPorts:
- ports:
- port: '443'
protocol: TCP
9.2 Policy Priority
Policy evaluation order:
1. Check Deny rules
- If matching Deny rule exists, immediately deny
- Ignore Allow rules
2. Check Allow rules
- If matching Allow rule exists, allow
3. Default behavior
- If policies exist for that direction (ingress/egress): default deny
- If no policies at all: default allow
10. Policy Troubleshooting
10.1 Debugging Commands
# Check applied policies
cilium policy get
# Per-endpoint policy state
cilium endpoint get 1234
# Policy map contents
cilium bpf policy get 1234
# Look up labels from Identity
cilium identity get 48291
# Policy verdict monitoring
cilium monitor --type policy-verdict
# Check dropped packets
cilium monitor --type drop
10.2 Common Issues and Solutions
Issue: Pod-to-Pod communication blocked
Possible causes:
1. Identity not correctly assigned
-> Verify with cilium identity list
2. Policy selector is incorrect
-> Check applied policies with cilium policy get
3. DNS egress policy missing
-> DNS allow is required when using FQDN policies
Issue: L7 policy not applied
Possible causes:
1. Envoy proxy not functioning properly
-> Check Proxy status in cilium status
2. Syntax error in rules under toPorts
-> Check parsed result with cilium policy get
Summary
Cilium's network policy engine provides robust traffic control through a multi-layered security model:
- Identity-Based Enforcement: Applies policies based on labels, not IP addresses, ensuring stability in dynamic environments
- eBPF High-Speed Filtering: L3/L4 policies applied directly in the kernel for minimal latency
- Envoy L7 Integration: Application-level filtering for HTTP, gRPC, Kafka
- FQDN Policies: Domain-based egress control through DNS proxy
- Deny Precedence: Explicit deny rules always take priority for stronger security
- Audit Mode: Assess impact before enforcing policies
- Incremental Updates: Apply policy changes with minimal regeneration