MasQuerading eBPF-based vs iptables-based
- 포드에 사용되는 IPv4 주소는 일반적으로 RFC1918 개인 주소 블록에서 할당되므로 공개적으로 라우팅할 수 없습니다.
- Pod에 사용되는 IP 주소는 보통 아래와 같은 사설 IP 대역에서 나옵니다:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
→ 이들을 RFC1918 Private IP라고 부릅니다.
- 이 IP들은 인터넷(공용망)에서는 사용되지 않고,
내부 네트워크(VPC, 사무실 LAN, 클러스터 내부 등) 전용이에요. - 그래서 이 IP들로는 직접 인터넷에 접근하거나 인터넷에서 접근받을 수 없습니다.
- 인터넷으로 나갈 땐 NAT(Network Address Translation)을 통해 공인 IP로 바뀌어야 해요.
- 외부에서 들어올 땐 로드밸런서나 인그레스 컨트롤러를 통해 라우팅되어야 해요.

- Cilium은 노드의 IP 주소가 이미 네트워크에서 라우팅 가능하기 때문에 클러스터를 떠나는 모든 트래픽의 소스 IP 주소를 자동으로 masquerade 합니다.
- 네트워크에서 masquerading은
➡ 실제 IP 주소를 숨기고 다른 IP로 바꿔서 보내는 행위를 뜻합니다. - 즉, NAT(Network Address Translation)의 한 종류입니다.
→ 출발지 IP 주소를 변경해서 외부로 나가는 것을 의미합니다.
📦 상황
- Pod가 10.244.1.5라는 사설 IP를 가지고 있어요.
- 외부 인터넷에 접속해서 google.com에 요청을 보냅니다.
🚧 문제
- 10.244.1.5는 RFC1918 사설 IP이므로 인터넷에서는 라우팅 불가능합니다.
🎭 해결: Masquerade
- 노드가 10.244.1.5에서 오는 요청을 받아서,
- 자신의 공인 IP 주소(예: 203.0.113.10)로 출발지 IP를 바꿔서 인터넷으로 내보냅니다.
→ 이게 바로 masquerading입니다.
eBPF-based : bpf.masquerade=true
kubectl exec -it -n kube-system ds/cilium -c cilium-agent -- cilium status | grep Masquerading
🎭 bpf.masquerade= true
Masquerading: BPF [eth0, eth1] 172.20.0.0/16 [IPv4: Enabled, IPv6: Disabled]
- 포드에서 외부 주소로 전송된 패킷에는 Masquerading 된다는것을 의미함.
- 지정되지 않은 경우, 프로그램은 BPF NodePort 장치 감지 메커니즘에 의해 선택된 장치에 자동으로 연결됩니다.
- 기본적으로 ipv4-native-routing-cidr 범위를 벗어난 IP 주소로 향하는 포드의 모든 패킷은 Masquerading되지만, 다른 (클러스터) 노드(Node IP)로 향하는 패킷은 제외됩니다. eBPF 마스커딩이 활성화되면 포드에서 클러스터 노드의 External IP로의 트래픽도 마스커레이딩되지 않습니다.
#
cilium config view | grep ipv4-native-routing-cidr
ipv4-native-routing-cidr 172.20.0.0/16
# 노드 IP로 통신 시 확인
tcpdump -i eth1 icmp -nn
kubectl exec -it curl-pod -- ping 192.168.10.101
...
Masquerading 실습환경 소개 1.

router : 사내망 10.10.0.0/16 대역 통신과 연결, k8s 에 join 되지 않은 (Web) 서버, loop1/loop2 dump 인터페이스 배치
🎭 현재 상태 확인
# 현재 설정 확인
kubectl exec -it -n kube-system ds/cilium -c cilium-agent -- cilium status | grep Masquerading
Masquerading: BPF [eth0, eth1] 172.20.0.0/16 [IPv4: Enabled, IPv6: Disabled]
#
cilium config view | grep ipv4-native-routing-cidr
ipv4-native-routing-cidr 172.20.0.0/16
# 통신 확인
kubectl exec -it curl-pod -- curl -s webpod | grep Hostname
kubectl exec -it curl-pod -- curl -s webpod | grep Hostname
router ( 192.168.10.200 ) 통신 확인
# 터미널 2개 사용
[k8s-ctr] tcpdump -i eth1 icmp -nn 혹은 hubble observe -f --pod curl-pod
[router] tcpdump -i eth1 icmp -nn
# router eth1 192.168.10.200 로 ping >> IP 확인해보자!
kubectl exec -it curl-pod -- ping 192.168.10.101
kubectl exec -it curl-pod -- ping 192.168.10.200
...
ctr에 worker 101번 으로 통신하는것과 router VM (non k8s) 로 통신하는것 모두 통신이 잘됨 ICMP

ctr에 worker 101번 으로 통신하는것과 router VM (non k8s) 로 통신하는것 모두 통신이 잘됨 TCP
---
# 터미널 2개 사용
[k8s-ctr] tcpdump -i eth1 tcp port 80 -nnq 혹은 hubble observe -f --pod curl-pod
[router] tcpdump -i eth1 tcp port 80 -nnq
# router eth1 192.168.10.200 로 curl >> IP 확인해보자!
kubectl exec -it curl-pod -- curl -s webpod
kubectl exec -it curl-pod -- curl -s webpod
kubectl exec -it curl-pod -- curl -s 192.168.10.200
...

ctr에 Router에 대한 Static Routing 정보가 있음
# Nativing-Routing 환경에서 ip-masq 로 사내망과 NAT 없는 통신 설정 시,
# 각 Node 별 PodCIDR에 대한 라우팅 설정이 사내망 네트워크 장비에 필요합니다.
# Static Routing 은 사실상 Node가 많아 질 수록 운영 상 불가능합니다.
# ⇒ 그래서 BGP 를 사용하여 동적으로 라우팅 설정이 가능합니다. (5주차 스터디에서 다룸)
# 혹시 실 운영 환경에서 사용하고 계신가요?
(⎈|HomeLab:N/A) root@k8s-ctr:~# ip -c route | grep static
10.10.0.0/16 via 192.168.10.200 dev eth1 proto static
router에 접속
# router
ip -br -c -4 addr
loop1 UNKNOWN 10.10.1.200/24
loop2 UNKNOWN 10.10.2.200/24
...
# 터미널 2개 사용
[k8s-ctr] tcpdump -i eth1 tcp port 80 -nnq 혹은 hubble observe -f --pod curl-pod
[router] tcpdump -i eth1 tcp port 80 -nnq
# router eth1 192.168.10.200 로 curl >> IP 확인해보자!
kubectl exec -it curl-pod -- curl -s 10.10.1.200
kubectl exec -it curl-pod -- curl -s 10.10.2.200
loop1/ loop2: dump 용 인터페이스
의문: 어떻게 ??? loop 인터페이스로 통신이 되고 응답이 오나요?
핵심은 👉 라우팅 테이블과 IP 할당 방식입니다.
🔍 loop1, loop2 인터페이스란?
- 이름이 loop1, loop2라고 되어 있지만, 실제로는 lo(127.0.0.1)과는 다른 일반적인 로컬 인터페이스입니다.
- 이 인터페이스들은 로컬에 바인딩된 IP를 지정하기 위해 만든 dummy 혹은 loopback 인터페이스일 가능성이 높아요.
- 이런 IP들은 다음 용도로 자주 사용됩니다:
- VIP (Virtual IP)로 서비스 바인딩
- 여러 IP를 하나의 서버에 바인딩
- 외부 라우팅 없이 특정 IP로 트래픽 받아서 local 프로세스로 처리
✅ 즉, 10.10.2.200은 외부에서 접근 가능한 "가상의 로컬 IP"입니다.

- 사내망과 NAT 없는 통신 필요 시 해당 설정에 대역들 추가 할 것! , ClusterMesh 시 Native-Routing 설정 시에도 활용.
🔍 ipMasqAgent 설정
- If the configuration file is empty, the agent will provision the following non-masquerade CIDRs: → 설정값 없을 경우 기본 값!
# 아래 설정값은 cilium 데몬셋 자동 재시작됨
helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \
--set ipMasqAgent.enabled=true --set ipMasqAgent.config.nonMasqueradeCIDRs='{10.10.1.0/24,10.10.2.0/24}'
cilium hubble port-forward&
# ip-masq-agent configmap 생성 확인
kubectl get cm -n kube-system ip-masq-agent -o yaml | yq
kc describe cm -n kube-system ip-masq-agent
k9s
#
cilium config view | grep -i ip-masq
enable-ip-masq-agent true
#
kubectl -n kube-system exec ds/cilium -c cilium-agent -- cilium-dbg bpf ipmasq list
IP PREFIX/ADDRESS
10.10.1.0/24
10.10.2.0/24
169.254.0.0/16


🔍 예시 상황:
- 쿠버네티스 외부에 10.10.1.0/24, 10.10.2.0/24 대역을 가진 사내 웹 서버 또는 서비스가 있고
- 그 서버에서 들어온 요청의 원래 Pod IP를 알고 싶을 때
- 또는 NAT 없이 직접 통신이 가능한 신뢰망일 때
이럴 때, masquerade를 꺼야 라우팅/보안/로깅에서 Pod IP를 직접 인식할 수 있습니다.
# 터미널 2개 사용
[k8s-ctr] tcpdump -i eth1 tcp port 80 -nnq 혹은 hubble observe -f --pod curl-pod
[router] tcpdump -i eth1 tcp port 80 -nnq
# router eth1 192.168.10.200 로 curl >> IP 확인해보자!
kubectl exec -it curl-pod -- curl -s 10.10.1.200
kubectl exec -it curl-pod -- curl -s 10.10.2.200
# k8s-ctr : 노드의 PodCIDR 미리 확인
kubectl get ciliumnode -o json
# router 에 static route 설정 : 아래 노드별 PodCIDR에 대한 static routing 설정
ip route add 172.20.1.0/24 via 192.168.10.100
ip route add 172.20.0.0/24 via 192.168.10.101
ip -c route | grep 172.20
# router eth1 192.168.10.200 로 curl >> IP 확인해보자!
kubectl exec -it curl-pod -- curl -s 10.10.1.200
kubectl exec -it curl-pod -- curl -s 10.10.2.200
'컨테이너 > 쿠버네티스 네트워크' 카테고리의 다른 글
| [Cilium] (10) 실리움 네트워킹 _ Native Routing (0) | 2025.08.05 |
|---|---|
| [Cilium] (9) 실리움 네트워킹_ NodeLocalDNS, Cilium LRP (4) | 2025.07.29 |
| [Cilium] (7) 실리움 네트워킹 _ Routing (5) | 2025.07.29 |
| [Cilium] (6) 실리움 네트워킹 _ IPAM (2) | 2025.07.28 |
| [Cilium] (5) 실리움 네트워킹 _ observability with Prometeus & Grafana (3) | 2025.07.22 |