Overview
Cilium은 eBPF 기반의 차세대 CNI 플러그인으로, 기존 kube-proxy와 함께 사용하거나 완전히 대체할 수 있다. 이 문서는 Cilium + kube-proxy 혼합 환경에서 발생하는 특수한 상황과 문제 해결 방법을 다룬다.
해당 실습은 Kubernetes 내부 네트워크 완벽 분석: IPVS 모드 환경에서의 패킷 플로우 추적 글의 실습환경과 동일하다.

환경 특성 파악
./network-test-info.sh
======================================
Kubernetes Network Test Environment
======================================
Service ClusterIP: 10.233.9.232
Client Pod:
IP: 10.233.66.94
Node: k8s-compute-02
Backend Pods:
nginx-54c98b4f84-ftvlg
IP: 10.233.66.111
Node: k8s-compute-02
nginx-54c98b4f84-tgmgh
IP: 10.233.65.212
Node: k8s-compute-01
nginx-54c98b4f84-vzgjc
IP: 10.233.67.86
Node: k8s-compute-03
Endpoints:
10.233.65.212 10.233.66.111 10.233.67.86
======================================
Useful Commands
======================================
# Export variables:
export SERVICE_IP=10.233.9.232
export CLIENT_IP=10.233.66.94
export BACKEND_IP=10.233.65.212
# IPVS rules on k8s-compute-02:
ssh k8s-compute-02 'sudo ipvsadm -Ln | grep -A 5 10.233.9.232'
# tcpdump on client pod:
kubectl exec -it client-pod -n network-test -- tcpdump -i any -nn "host 10.233.9.232 or host 10.233.65.212" -w /tmp/client.pcap
# tcpdump on node:
ssh k8s-compute-02 'sudo tcpdump -i any -nn "host 10.233.9.232 or host 10.233.65.212" -w /tmp/node.pcap'
Step 1: 현재 환경 확인
# 1. kube-proxy 실행 여부
kubectl get pods -n kube-system | grep kube-proxy
# 2. kube-proxy 모드
kubectl get cm kube-proxy -n kube-system -o yaml | grep mode
# 3. Cilium KubeProxyReplacement 설정
kubectl -n kube-system exec -it ds/cilium -- cilium status | grep KubeProxyReplacement
# 예상 출력
kube-proxy-6lw4l 1/1 Running 1 (70d ago) 103d
mode: ipvs
KubeProxyReplacement: False
Step 2: 환경 유형 판별
| kube-proxy | Mode | KubeProxyReplacement | 환경 유형 |
| ✅ Running | ipvs | False | Cilium + IPVS 혼합 |
| ✅ Running | iptables | False | Cilium + iptables 혼합 |
| ❌ Not Running | - | True | Cilium 완전 대체 |
| ✅ Running | ipvs | - | 순수 IPVS |
주요 증상: IPVS 통계가 0
증상 확인
sudo ipvsadm -Ln --stats | grep -A 5 "10.233.9.232"
# 출력
TCP 10.233.9.232:80 rr
-> 10.233.65.212:80 Masq 0 0 0
-> 10.233.66.111:80 Masq 0 0 0
-> 10.233.67.86:80 Masq 0 0 0
- 모든 통계가 0! 하지만 `curl http://nginx-service` 는 정상 작동한다
원인
Cilium eBPF가 Socket-level에서 먼저 처리하기 때문이다.
┌─────────────────────┐
│ 애플리케이션 (curl) │
└──────────┬──────────┘
│ syscall
▼
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ Cilium eBPF Hook │ ← 여기서 가로챔!
│ (Socket-level) │
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│
▼
┌────────────────────┐
│ Socket Layer │
└──────────┬─────────┘
│
▼
┌────────────────────┐
│ Transport (TCP) │
└──────────┬─────────┘
│
▼
┌────────────────────┐
│ Network (IP) │
└──────────┬─────────┘
│
▼
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ IPVS/Netfilter │ ← 패킷 못 받음!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│
▼
┌────────────────────┐
│ Data Link Layer │
└────────────────────┘
결과
- IPVS 규칙은 생성됨 (kube-proxy가 작동 중)
- 실제 패킷은 eBPF가 처리
- IPVS 통계는 항상 0
- Linux conntrack도 우회됨 (Socket-level 처리)
Cilium 환경 모니터링 방법
도구별 작동 여부 (실제 테스트 결과)
| 방법 | 작동 여부 | 추천도 | 비고 |
| cilium bpf lb list | 완벽 작동 | ⭐⭐⭐⭐⭐ | 가장 확실! |
| tcpdump | 완벽 작동 | ⭐⭐⭐⭐⭐ | 패킷 레벨 분석 |
| cilium monitor | 부분 작동 | ⭐⭐ | L7은 안 보임 |
| conntrack -L | 작동 안 함 | ⭐ | eBPF가 우회 |
| cilium service list | 비어있음 | ⭐ | 혼합 환경 비활성화 |
| ipvsadm --stats | 항상 0 | ⭐ | 참고용으로만 |
방법 1: eBPF 로드밸런싱 맵 확인 (★★★★)
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list | grep 10.233.9.232
# 출력
10.233.9.232:80/TCP (1) 10.233.67.86:80/TCP (79) (1)
10.233.9.232:80/TCP (3) 10.233.65.212:80/TCP (79) (3)
10.233.9.232:80/TCP (2) 10.233.66.111:80/TCP (79) (2)
10.233.9.232:80/TCP (0) 0.0.0.0:0 (79) (0) [ClusterIP, non-routable]
해석:
- `(0)`: Master entry (가상 서버)
- `(1), (2), (3)`: 백엔드 슬롯 번호
- `10.233.67.86:80, 10.233.65.212:80, 10.233.66.111:80`: 실제 백엔드 Pod IP
- `(79)`: RevNAT ID (응답 패킷 처리용)
방법 2: Cilium Service 목록 (★)
혼합 환경에서는 작동하지 않는다.
kubectl -n kube-system exec -it ds/cilium -- cilium service list | grep nginx
출력
# 아무것도 출력되지 않음
이유
- `KubeProxyReplacement: False` 환경에서는 Cilium이 Service를 직접 관리하지 않음
- kube-proxy가 Service 관리를 담당
- Cilium의 Service 목록은 비어있음
대신 `cilium bpf lb list` 를 사용하세요! ← 실제 eBPF 데이터플레인 조회
방법 3: conntrack 실시간 모니터링(★)
Cilium eBPF 환경에서는 작동하지 않는다.
# 시도 1
sudo conntrack -L -p tcp --dport 80 | grep 10.233.9.232
출력
conntrack v1.4.8 (conntrack-tools): 6 flow entries have been shown.
# Service IP 관련 연결 없음!
# 시도 2 (포트 필터 제거)
sudo conntrack -L | grep 10.233.9.232
출력
conntrack v1.4.8 (conntrack-tools): 888 flow entries have been shown.
# 여전히 Service IP 관련 연결 없음!
원인
- Cilium eBPF가 Socket-level에서 처리
- Linux 커널 네트워크 스택을 거치지 않음
- Netfilter conntrack을 완전히 우회
- Service IP(10.233.9.232)는 conntrack에 기록되지 않음
방법 4: tcpdump(★★★★)
언제나 작동하는 최고의 도구!
# Service IP 관련 모든 트래픽
sudo tcpdump -i any -nn host 10.233.9.232
터미널 1
ssh k8s-compute-02
sudo tcpdump -i any -nn "host 10.233.9.232 or port 80"
터미널 2
kubectl exec -it client-pod -n network-test -- bash -c "for i in {1..5}; do echo Request $i; curl -s http://nginx-service; sleep 1; done"
터미널 1 출력 예시
12:15:36.180603 In 10.233.66.94.34376 > 10.233.9.232.80: Flags [S], seq 1234567890
12:15:36.180621 Out 10.233.66.94.34376 > 10.233.65.212.80: Flags [S], seq 1234567890
12:15:36.180869 P 10.233.65.212.80 > 10.233.66.94.34376: Flags [S.], seq 9876543210
12:15:36.180901 Out 10.233.9.232.80 > 10.233.66.94.34376: Flags [S.], seq 9876543210
- DNAT/SNAT 전후 패킷을 모두 볼 수 있다!
방법 5: Cilium Monitor
제한적으로 작동한다.
kubectl -n kube-system exec -it ds/cilium -- cilium monitor
결과
- 일반 트래픽은 보임
- nginx Service 트래픽은 안 보임 (L7 visibility 비활성화)
# L7 트래픽 시도 (작동 안 할 수 있음)
kubectl -n kube-system exec -it ds/cilium -- cilium monitor --type l7
출력
Press Ctrl-C to quit
# nginx 관련 트래픽 없음
# 다른 애플리케이션 트래픽만 보임
원인
- `KubeProxyReplacement: False` 환경에서는 L7 visibility 비활성화
- eBPF가 Socket-level에서 너무 빨리 처리
실전 트러블슈팅
시나리오 1: Service 응답은 정상인데 IPVS 통계가 0
증상
# curl은 정상
kubectl exec -it client-pod -n network-test -- curl http://nginx-service
Backend POD-1: nginx-54c98b4f84-ftvlg
# IPVS 통계는 0
sudo ipvsadm -Ln --stats | grep 10.233.9.232
TCP 10.233.9.232:80 rr
-> 10.233.65.212:80 Masq 0 0 0
진단
# 1. Cilium eBPF 맵 확인 (가장 중요!)
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list | grep 10.233.9.232
# 2. tcpdump로 실제 패킷 확인
sudo tcpdump -i any -nn host 10.233.9.232 -c 10
결론: Cilium 혼합 환경에서는 정상 동작이다. IPVS 통계는 무시하면 된다.
시나리오 2: conntrack에 연결이 안 보임
증상
sudo conntrack -L | grep 10.233.9.232
conntrack v1.4.8 (conntrack-tools): 888 flow entries have been shown.
# 아무것도 없음
원인
- Cilium eBPF가 Socket-level에서 처리
- Linux conntrack을 완전히 우회
해결
# conntrack 대신 tcpdump 사용
sudo tcpdump -i any -nn "host 10.233.9.232 or port 80"
# 또는 Cilium eBPF 맵 확인
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list | grep 10.233.9.232
결론: conntrack이 안 나와도 정상이다. tcpdump를 사용하면 된다.
시나리오 3: Cilium monitor에 트래픽이 안 보임
증상
kubectl -n kube-system exec -it ds/cilium -- cilium monitor --type l7
# nginx 트래픽 없음
해결
# 일반 monitor 확인
kubectl -n kube-system exec -it ds/cilium -- cilium monitor
# 또는 tcpdump 사용
sudo tcpdump -i any -nn port 80
결론: L7 monitor에 안 나와도 정상이다.
시나리오 4: Service 연결 실패
증상
kubectl exec -it client-pod -n network-test -- curl http://nginx-service
curl: (7) Failed to connect to nginx-service port 80: Connection timeout
진단 순서
# 1. Service 존재 확인
kubectl get svc nginx-service -n network-test
# 2. Endpoint 확인
kubectl get endpointslices -n network-test
# 3. Cilium eBPF 맵 확인 (가장 중요!)
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list | grep 10.233.9.232
# 4. IPVS 규칙 확인 (참고용)
sudo ipvsadm -Ln | grep 10.233.9.232
# 5. Pod 직접 접근 테스트
BACKEND_IP=$(kubectl get pods -n network-test -l app=nginx -o jsonpath='{.items[0].status.podIP}')
kubectl exec -it client-pod -n network-test -- curl http://$BACKEND_IP
# 6. tcpdump로 패킷 확인
sudo tcpdump -i any -nn host 10.233.9.232
가능한 원인과 해결
| 증상 | 원인 | 해결책 |
| Service 없음 | 미생성 | kubectl expose 재실행 |
| Endpoint 없음 | Pod 미실행 | Pod 상태 확인 |
| eBPF 맵 없음 | Cilium agent 문제 | Cilium 재시작 |
| 직접 접근 실패 | 네트워크 정책 | 정책 확인 |
| 패킷 안 보임 | CNI 문제 | CNI 로그 확인 |
Cilium agent 재시작
kubectl rollout restart ds/cilium -n kube-system
kubectl rollout status ds/cilium -n kube-system
패킷 플로우 비교
순수 IPVS 환경
┌──────────────┐
│ Client Pod │ 10.233.66.94
└──────┬───────┘
│ 10.233.66.94 → 10.233.9.232:80
▼
┌──────────────────┐
│ Network Stack │
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Netfilter │
│ PREROUTING │
└──────┬───────────┘
│
▼
┌──────────────────┐
│ IPVS │ ← DNAT 수행
│ 목적지 변환 │
└──────┬───────────┘
│ 10.233.66.94 → 10.233.65.212:80
▼
┌──────────────────┐
│ Pod Network │
└──────┬───────────┘
│
▼
┌──────────────┐
│ Backend Pod │ 10.233.65.212
└──────────────┘
Cilium 혼합 환경 (본 환경)
┌──────────────┐
│ Client Pod │ 10.233.66.94
└──────┬───────┘
│ curl syscall
▼
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ Cilium eBPF Hook │ ← DNAT 수행 (Socket-level)
│ 목적지 변환 │
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ 10.233.66.94 → 10.233.65.212:80
▼
┌──────────────────┐
│ Socket Layer │
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Network Stack │
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Netfilter/IPVS │ ← 규칙만 존재, 패킷 안 옴
│ (규칙만 존재) │
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Pod Network │
└──────┬───────────┘
│
▼
┌──────────────┐
│ Backend Pod │ 10.233.65.212
└──────────────┘
핵심 차이점
| 항목 | IPVS 환경 | Cilium 혼합 환경 |
| 처리 위치 | Netfilter (PREROUTING) | Socket-level (syscall) |
| 처리 시점 | 네트워크 스택 중간 | 애플리케이션 syscall 직후 |
| conntrack | 기록됨 | 우회됨 |
| IPVS 관여 | 실제 처리 | 규칙만 존재 |
| 성능 | 매우 빠름 | 더 빠름 (syscall 우회) |
| 모니터링 | ipvsadm, conntrack | tcpdump, cilium bpf |
유용한 명령어 모음
Cilium eBPF 맵 (가장 중요!)
# eBPF 로드밸런싱 맵 전체
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list
# 특정 Service IP 필터링
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list | grep 10.233.9.232
# 모든 Service 확인
kubectl get svc --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.clusterIP}{"\n"}{end}' | while read ns name ip; do
echo "=== $ns/$name ($ip) ==="
kubectl -n kube-system exec ds/cilium -- cilium bpf lb list 2>/dev/null | grep $ip | head -n 4
done
tcpdump
# Service IP 관련 모든 트래픽
sudo tcpdump -i any -nn host 10.233.9.232
# Client와 Service 간
sudo tcpdump -i any -nn "host 10.233.66.94 and host 10.233.9.232"
# HTTP 트래픽만
sudo tcpdump -i any -nn port 80
# 파일로 저장 후 분석
sudo tcpdump -i any -nn host 10.233.9.232 -w /tmp/capture.pcap
tcpdump -r /tmp/capture.pcap -nn -v
Cilium 상태 확인
# 전체 상태
kubectl -n kube-system exec -it ds/cilium -- cilium status
# KubeProxyReplacement 확인
kubectl -n kube-system exec -it ds/cilium -- cilium status | grep KubeProxyReplacement
# Cilium 버전
kubectl -n kube-system exec -it ds/cilium -- cilium version
Cilium Endpoint
# Endpoint 목록
kubectl -n kube-system exec -it ds/cilium -- cilium endpoint list
# 특정 IP로 검색
kubectl -n kube-system exec -it ds/cilium -- cilium endpoint list | grep 10.233.66.111
Cilium Monitor
# 모든 이벤트
kubectl -n kube-system exec -it ds/cilium -- cilium monitor
# Drop 이벤트
kubectl -n kube-system exec -it ds/cilium -- cilium monitor --type drop
IPVS (참고용)
# 규칙 확인
sudo ipvsadm -Ln | grep -A 5 "10.233.9.232"
# 통계 (항상 0)
sudo ipvsadm -Ln --stats
conntrack (작동 안 함)
# 시도는 해볼 수 있지만 Service IP는 안 보임
sudo conntrack -L | grep 10.233.9.232
환경별 권장 모니터링 전략
Cilium + IPVS 혼합 환경 (KubeProxyReplacement: False)
이 환경에서는 Cilium eBPF가 Socket-level에서 먼저 패킷을 처리하므로, 기존 IPVS/conntrack 기반 모니터링 도구가 제대로 작동하지 않는다.
1순위: tcpdump
# 가장 확실한 방법 - 항상 작동
sudo tcpdump -i any -nn "host $SERVICE_IP or port 80"
2순위: Cilium eBPF 맵
# Service 로드밸런싱 상태 확인
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list | grep $SERVICE_IP
3순위: Kubernetes 리소스
# EndpointSlice로 백엔드 상태 확인
kubectl get endpointslices -n $NAMESPACE -o wide
사용하지 말 것
- `ipvsadm --stats`: 항상 0 (참고용으로만)
- `conntrack -L`: Service IP 안 보임
- `cilium service list`: 혼합 환경에서 비어있음
Cilium 완전 대체 환경 (KubeProxyReplacement: True)
kube-proxy가 없고 Cilium이 모든 Service 처리를 담당하는 환경이다.
1순위: Cilium Service 목록
# 완전 대체 환경에서만 작동
kubectl -n kube-system exec -it ds/cilium -- cilium service list
2순위: Cilium eBPF 맵
kubectl -n kube-system exec -it ds/cilium -- cilium bpf lb list
3순위: Cilium Monitor
# L7 visibility 활성화 시 상세 정보 확인 가능
kubectl -n kube-system exec -it ds/cilium -- cilium monitor --type l7
혼합 환경 vs 완전 대체 환경
| 항목 | 혼합 환경 | 완전 대체 환경 |
| kube-proxy | 실행 중 | 없음 |
| KubeProxyReplacement | False | True |
| Service 관리 주체 | kube-proxy | Cilium |
| 실제 패킷 처리 | Cilium eBPF | Cilium eBPF |
| IPVS 규칙 | 존재하지만 미사용 | 없음 |
| cilium service list | 비어있음 | 작동 |
| cilium bpf lb list | 작동 | 작동 |
| 리소스 사용량 | 높음 (중복) | 낮음 |
| 복잡도 | 높음 | 낮음 |
혼합 환경의 장단점
장점
- 기존 환경에서 점진적 마이그레이션 가능
- Cilium 문제 시 kube-proxy로 폴백 가능 (이론적)
- 기존 모니터링 인프라 일부 유지
단점
- 리소스 중복 사용 (kube-proxy + Cilium 둘 다 실행)
- 모니터링 혼란 (IPVS 통계 0, conntrack 우회)
- 디버깅 복잡도 증가
- 실제로는 Cilium만 패킷 처리 (kube-proxy 무의미)
완전 대체 환경 권장 시나리오
다음 조건을 만족하면 Cilium 완전 대체를 고려할 만하다.
- Cilium 버전 1.12 이상
- Kubernetes 버전 1.24 이상
- 충분한 테스트 환경 확보
- Cilium 운영 경험 축적
- Network Policy를 Cilium으로 관리
마이그레이션 고려사항
혼합 환경에서 완전 대체로 전환
사전 점검
# Cilium 버전 확인
kubectl -n kube-system exec -it ds/cilium -- cilium version
# 현재 설정 확인
helm get values cilium -n kube-system
# 클러스터 상태 확인
kubectl -n kube-system exec -it ds/cilium -- cilium status --verbose
전환 시 주의사항
- 반드시 테스트 환경에서 먼저 검증
- 롤백 계획 수립
- 모니터링 대시보드 업데이트 (IPVS 메트릭 제거)
- Network Policy 호환성 확인
- NodePort, LoadBalancer 타입 Service 동작 검증
전환 후 확인
# kube-proxy 제거 확인
kubectl get pods -n kube-system | grep kube-proxy
# Cilium 완전 대체 확인
kubectl -n kube-system exec -it ds/cilium -- cilium status | grep KubeProxyReplacement
# Service 목록 확인 (이제 작동해야 함)
kubectl -n kube-system exec -it ds/cilium -- cilium service list
실습 환경 정리
실습이 완료되면 생성한 리소스를 정리한다.
# 테스트 네임스페이스 삭제
kubectl delete namespace network-test
# 로컬 파일 정리
rm -f client.pcap node.pcap backend.pcap network-test-info.sh
# 노드에서 캡처 파일 정리
ssh k8s-compute-02 'sudo rm -f /tmp/*.pcap'
삭제 확인
kubectl get all -n network-test
# 출력: No resources found in network-test namespace.
정리
핵심 내용 요약
Cilium + IPVS 혼합 환경의 특성
- Cilium eBPF가 Socket-level에서 패킷을 먼저 가로챔
- IPVS 규칙은 존재하지만 실제 패킷 처리에 관여하지 않음
- conntrack도 우회되어 연결 추적 불가
- 기존 모니터링 도구(ipvsadm, conntrack)가 무용지물
모니터링 전략
- tcpdump가 가장 확실한 도구
- cilium bpf lb list로 eBPF 로드밸런싱 맵 확인
- IPVS 통계가 0이어도 정상 동작
- conntrack에 Service IP가 없어도 정상
트러블슈팅 접근법
- 먼저 환경 유형 파악 (KubeProxyReplacement 값 확인)
- Cilium eBPF 맵에서 Service 등록 여부 확인
- tcpdump로 실제 패킷 플로우 추적
- Pod 직접 접근 테스트로 네트워크 문제 분리
권장사항
- 혼합 환경은 과도기적 상태로, 장기적으로 완전 대체 고려
- 모니터링 인프라를 Cilium 기반으로 전환
- IPVS 메트릭 기반 알림은 비활성화 또는 수정 필요
Reference
- Cilium Documentation - KubeProxyReplacement
- Cilium Documentation - eBPF Datapath
- Cilium Documentation - Troubleshooting
- Cilium Documentation - Service Load Balancing
- Kubernetes Documentation - Service
- Kubernetes Documentation - Virtual IPs and Service Proxies
- eBPF Documentation
- Linux Kernel - IPVS
- tcpdump Manual
Somaz | DevOps Engineer | Kubernetes & Cloud Infrastructure Specialist
'Container Orchestration > Kubernetes' 카테고리의 다른 글
| Kubernetes OOMKilled 대응 전략: 무작정 메모리만 늘리지 말자! (0) | 2026.06.10 |
|---|---|
| Kubernetes 클러스터로의 외부 트래픽 흐름 완벽 가이드 (0) | 2026.06.04 |
| Kubernetes 내부 네트워크 완벽 분석: IPVS 모드 환경에서의 패킷 플로우 추적 (0) | 2026.05.21 |
| ingress-nginx → nginx-gateway-fabric 마이그레이션 실전 기록 (온프레미스 K8s, 11개 인스턴스) (0) | 2026.05.14 |
| EKS 프로덕션 배포 가이드: 502 에러 제로 달성기 (0) | 2026.05.12 |