VXLAN Encapsulation

mkdir cilium-lab && cd cilium-lab
curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/cilium-study/4w/Vagrantfile
vagrant up
✅ VXLAN 모드란?
Pod 간 통신 시 패킷을 IP-over-UDP 터널로 감싸서 전송하는 방식입니다.
즉, 각 노드 간에 VXLAN 터널을 생성하고, Pod 간 트래픽을 그 터널을 통해 전달합니다.
📦 상황
- Pod A (10.244.1.5)가 Node A에 존재
- Pod B (10.244.2.8)가 Node B에 존재
- 각 Node는 서로 다른 서브넷에 있음 (예: AWS VPC 환경 등에서 흔함)
- 라우터가 Pod CIDR(10.244.0.0/16)을 라우팅하지 못함 ← 핵심
❗ 왜 VXLAN이 필요한가요?
➡ 외부 네트워크 장비가 Pod IP 대역을 모르거나, 라우팅하지 않는 환경에서는
→ Native Routing이 불가능하기 때문에,
→ VXLAN 터널을 통해 노드 간 트래픽을 encapsulation(캡슐화) 하여 전달합니다.
🎯 VXLAN 흐름
- Pod A(10.244.1.5)가 Pod B(10.244.2.8)로 패킷을 보냅니다.
- Cilium은 이 패킷을 VXLAN 헤더로 감쌉니다.
(예: UDP 포트 8472 사용) - 패킷은 Node A → Node B로 전달됩니다 (외부망에서는 단순한 UDP 패킷처럼 보임)
- Node B에서 VXLAN 헤더를 벗기고, 원래 IP 패킷을 Pod B로 전달합니다.
- 응답도 동일한 방식으로 터널을 통해 돌아옵니다.
Encapsulation VXLAN 설정 방법
# [커널 구성 옵션] Requirements for Tunneling and Routing
grep -E 'CONFIG_VXLAN=y|CONFIG_VXLAN=m|CONFIG_GENEVE=y|CONFIG_GENEVE=m|CONFIG_FIB_RULES=y' /boot/config-$(uname -r)
CONFIG_FIB_RULES=y # 커널에 내장됨
CONFIG_VXLAN=m # 모듈로 컴파일됨 → 커널에 로드해서 사용
CONFIG_GENEVE=m # 모듈로 컴파일됨 → 커널에 로드해서 사용
# 커널 로드
lsmod | grep -E 'vxlan|geneve'
modprobe vxlan # modprobe geneve
lsmod | grep -E 'vxlan|geneve'
for i in w1 w0 ; do echo ">> node : k8s-$i <<"; sshpass -p 'vagrant' ssh vagrant@k8s-$i sudo modprobe vxlan ; echo; done
for i in w1 w0 ; do echo ">> node : k8s-$i <<"; sshpass -p 'vagrant' ssh vagrant@k8s-$i sudo lsmod | grep -E 'vxlan|geneve' ; echo; done
# k8s-w1 노드에 배포된 webpod 파드 IP 지정
export WEBPOD1=$(kubectl get pod -l app=webpod --field-selector spec.nodeName=k8s-w1 -o jsonpath='{.items[0].status.podIP}')
echo $WEBPOD1
# 반복 ping 실행해두기
kubectl exec -it curl-pod -- ping $WEBPOD1
# 업그레이드
helm upgrade cilium cilium/cilium --namespace kube-system --version 1.18.0 --reuse-values \
--set routingMode=tunnel --set tunnelProtocol=vxlan \
--set autoDirectNodeRoutes=false --set installNoConntrackIptablesRules=false
kubectl rollout restart -n kube-system ds/cilium
# 설정 확인
cilium features status
cilium features status | grep datapath_network
kubectl exec -it -n kube-system ds/cilium -- cilium status | grep ^Routing
cilium config view | grep tunnel

중간에 살짞 핑이 빠지네요?

# cilium_vxlan 확인
ip -c addr show dev cilium_vxlan
for i in w1 w0 ; do echo ">> node : k8s-$i <<"; sshpass -p 'vagrant' ssh vagrant@k8s-$i ip -c addr show dev cilium_vxlan ; echo; done
# 라우팅 정보 확인 : k8s node 간 다른 네트워크 대역에 있더라도, 파드의 네트워크 대역 정보가 라우팅에 올라왔다!
ip -c route | grep cilium_host
172.20.0.0/24 via 172.20.0.134 dev cilium_host proto kernel src 172.20.0.134
172.20.0.134 dev cilium_host proto kernel scope link
172.20.1.0/24 via 172.20.0.134 dev cilium_host proto kernel src 172.20.0.134 mtu 1450
172.20.2.0/24 via 172.20.0.134 dev cilium_host proto kernel src 172.20.0.134 mtu 1450
for i in w1 w0 ; do echo ">> node : k8s-$i <<"; sshpass -p 'vagrant' ssh vagrant@k8s-$i ip -c route | grep cilium_host ; echo; done
cilium_host는 Cilium이 노드에 자동으로 생성하는 가상 인터페이스로, 터널링, 정책 처리, 패킷 포워딩, IPAM 등의 다양한 기능에서 핵심 역할을 합니다.
✅ cilium_host란?
cilium_host는 노드와 Cilium datapath 사이의 가상 네트워크 인터페이스입니다.
이 인터페이스는 Pod ↔ 외부, Pod ↔ Pod 트래픽이 지나가는 게이트웨이 역할을 합니다.📘 참고
- Native Routing 모드(tunnel=disabled)에서도 cilium_host는 존재합니다.
다만 터널링보다는 정책, NAT, 게이트웨이 역할이 강조됩니다.- cilium_host는 Kubernetes의 cbr0(bridge)와 유사한 위치에 있으며, BPF 프로그램이 연결되어 있어 트래픽 제어가 가능합니다.

✅ cilium status --all-addresses 명령어 요약
이 명령어는 Cilium 클러스터의 IP 주소 관리(IPAM) 상태를 상세히 보여줍니다.
📌 주요 기능
- IPAM 설정 확인
→ Cilium이 설정한 IPAM 모드(CRD, Cluster Pool 등)가 올바르게 동작하는지 검증 - IP 할당 문제 디버깅
→ 엔드포인트에 IP가 제대로 할당되었는지, 충돌/고갈 여부 확인 - 리소스 사용량 모니터링
→ 할당된/가용 IP 개수 파악 → 용량 계획에 도움
(⎈|HomeLab:N/A) root@k8s-ctr:~# kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium status --all-addresses | grep router
kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- cilium status --all-addresses | grep router
kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- cilium status --all-addresses | grep router
172.20.0.134 (router)
172.20.1.25 (router)
172.20.2.31 (router)
termshark 수행 -> packet capture
# 통신 확인
kubectl exec -it curl-pod -- curl webpod | grep Hostname
kubectl exec -it curl-pod -- sh -c 'while true; do curl -s --connect-timeout 1 webpod | grep Hostname; echo "---" ; sleep 1; done'
# k8s-w0 노드에 배포된 webpod 파드 IP 지정
export WEBPOD=$(kubectl get pod -l app=webpod --field-selector spec.nodeName=k8s-w0 -o jsonpath='{.items[0].status.podIP}')
echo $WEBPOD
# 신규 터미널 [router]
tcpdump -i any udp port 8472 -nn

termshark
꼭 써보세요 너무 편합니다.
# 반복 접속
kubectl exec -it curl-pod -- curl webpod | grep Hostname
kubectl exec -it curl-pod -- sh -c 'while true; do curl -s --connect-timeout 1 webpod | grep Hostname; echo "---" ; sleep 1; done'
# 신규 터미널 [router]
tcpdump -i any udp port 8472 -w /tmp/vxlan.pcap
tshark -r /tmp/vxlan.pcap -d udp.port==8472,vxlan
termshark -r /tmp/vxlan.pcap
termshark -r /tmp/vxlan.pcap -d udp.port==8472,vxlan
# 신규 터미널 [k8s-ctr] hubble flow log 모니터링 : overlay 통신 모드 확인!
hubble observe -f --protocol tcp --pod curl-pod
Aug 3 00:02:26.403: default/curl-pod:40332 (ID:23926) -> default/webpod-697b545f57-76lt6:80 (ID:12438) to-overlay FORWARDED (TCP Flags: SYN)
Aug 3 00:02:26.405: default/curl-pod:40332 (ID:23926) <- default/webpod-697b545f57-76lt6:80 (ID:12438) to-endpoint FORWARDED (TCP Flags: SYN, ACK)
Aug 3 00:02:26.405: default/curl-pod:40332 (ID:23926) -> default/webpod-697b545f57-76lt6:80 (ID:12438) to-overlay FORWARDED (TCP Flags: ACK)
termshark 도구를 활용하여 udp port 8472 tcpdump 결과를 확인해보면
패킷이 캡슐화 되어 패킷 헤더의 Src, Dst IP가 노드의 eth1 IP임을 확인할 수 있다.

src / Destination은 파드의 IP가 적혀있다.

'컨테이너 > 쿠버네티스 네트워크' 카테고리의 다른 글
| [Cilium] (13) 실리움 네트워킹 _ BGP Control Plane (8) | 2025.08.12 |
|---|---|
| [Cilium] (12) 실리움 네트워킹 _ Service LB-IPAM (4) | 2025.08.06 |
| [Cilium] (10) 실리움 네트워킹 _ Native Routing (0) | 2025.08.05 |
| [Cilium] (9) 실리움 네트워킹_ NodeLocalDNS, Cilium LRP (4) | 2025.07.29 |
| [Cilium] (8) 실리움 네트워킹 _ Masquerading (4) | 2025.07.29 |