본문 바로가기

컨테이너/쿠버네티스 네트워크

[Cilium] (11) 실리움 네트워킹 _ VXLAN Encapsulation

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 흐름

  1. Pod A(10.244.1.5)가 Pod B(10.244.2.8)로 패킷을 보냅니다.
  2. Cilium은 이 패킷을 VXLAN 헤더로 감쌉니다.
    (예: UDP 포트 8472 사용)
  3. 패킷은 Node A → Node B로 전달됩니다 (외부망에서는 단순한 UDP 패킷처럼 보임)
  4. Node B에서 VXLAN 헤더를 벗기고, 원래 IP 패킷을 Pod B로 전달합니다.
  5. 응답도 동일한 방식으로 터널을 통해 돌아옵니다.

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가 적혀있다.