1. 개요

VXLAN(Virtual eXtensible LAN)은 Ethernet 프레임을 UDP 패킷에 통째로 넣어 IP 망 너머로 나르는 터널 기술이다. 원래 프레임은 손대지 않고, 바깥에 노드 사이 배달용 헤더를 덧씌운다. 중간 장비는 바깥 헤더만 보고 배달하므로 안쪽 주소를 몰라도 된다.

12345작은 것부터 차례로 안에 넣는다1바깥 Ethernet노드 A 의 MAC → 다음 장비 MAC · 14B2바깥 IP노드 A → 노드 B · 20B3바깥 UDP목적지 포트 4789 (flannel 은 8472) · 8B4VXLAN 헤더VNI — 어느 가상 망인지 · 8B5원래 프레임Pod A → Pod B 의 Ethernet 프레임 그대로원래 프레임은 손대지 않고, 노드 사이 배달용 헤더 네 겹을 덧씌운다

라우터에서 끝나야 할 LAN 을 라우터 너머까지 이어 붙이는 셈이다. 그래서 VXLAN 처럼 실제 망 위에 가상의 망을 얹는 방식을 오버레이(overlay) 라고 부른다.

2. 헤더 구조

바깥 Ethernet14B바깥 IP20B바깥 UDP8BVXLAN8B원래 Ethernet 프레임안쪽 MAC · IP · 데이터바깥 헤더 50바이트 (14 + 20 + 8 + 8)FlagsI=1예약24비트VNI24비트 · 약 1,677만 개예약8비트Flags — I 비트가 1 이면 "VNI 칸이 유효하다". 나머지 비트와 예약 칸은 0VNI — VLAN 의 VID(12비트) 자리에 해당한다. 24비트라 망을 약 1,677만 개까지 나눌 수 있다바깥 UDP 의 출발지 포트는 안쪽 프레임으로 계산한 값 — 중간 장비가 여러 경로로 나눠 보내기 쉽게배달은 바깥 세 장이, 구분은 VNI 가 맡는다

바깥 헤더는 평범한 Ethernet · IP · UDP 다. 중간 장비 입장에서는 노드 A 가 노드 B 에게 보내는 UDP 패킷 하나일 뿐이다.

3. VTEP

VTEP(VXLAN Tunnel End Point)은 프레임을 감싸고 벗기는 터널의 양 끝이다. 보내는 쪽 VTEP 이 원래 프레임에 바깥 헤더를 씌우고, 받는 쪽 VTEP 이 벗겨서 원래 목적지로 넘긴다. VTEP 은 리눅스 커널의 가상 장치일 수도, 데이터센터 스위치일 수도 있다.

Pod AVTEPVTEPPod B123노드 A노드 B① VTEP 이 Pod 의 프레임에바깥 헤더 네 겹을 씌운다② 노드 A → 노드 B 로 배달중간 장비는 노드 주소만 본다③ 노드 B 의 VTEP 이 벗겨Pod B 에게 넘긴다예시 주소Pod A 10.244.1.5 → Pod B 10.244.2.7노드 A 192.168.10.11 → B .12VTEP = 노드의 flannel.1 장치Pod 주소를 모르는 중간 네트워크 위로, 노드 주소가 적힌 봉투에 넣어 나른다

4. UDP 포트

IANA 가 VXLAN 에 배정한 표준 포트는 UDP 4789 다. 리눅스 커널은 표준이 정해지기 전에 쓰던 8472 를 기본값으로 남겨 두었고, flannel 도 리눅스에서는 이 기본값(8472)을 쓴다. 방화벽이나 클라우드 보안 그룹에서 노드 사이 이 포트가 막혀 있으면 다른 노드의 Pod 와 통신이 안 된다.

5. MTU

바깥 헤더가 붙는 만큼 안쪽에 담을 수 있는 크기가 줄어든다. 노드의 MTU 가 1500 이면 Pod 쪽 MTU 는 1450 이어야 봉투째 1500 안에 들어간다. CNI 는 Pod 의 인터페이스 MTU 를 이 값으로 낮춰 둔다.

노드 MTU 1500맞춤바깥 헤더 50Pod 의 IP 패킷 ≤ 1450Pod MTU 1450 — 봉투째 1500 안에 들어간다어긋남바깥 헤더 50Pod 의 IP 패킷 1500+50Pod MTU 1500 그대로 — 50바이트가 넘쳐 큰 패킷만 버려진다바깥 헤더 50 = 바깥 IP 20 + UDP 8 + VXLAN 8 + 안쪽 Ethernet 14 (바깥 Ethernet 은 MTU 에 안 센다)봉투 두께만큼 Pod 쪽 MTU 를 줄여야 한다 — 작은 요청은 되는데 큰 응답만 멈추면 이것부터 본다

RFC 7348 은 VTEP 이 VXLAN 패킷을 조각내지 말라고 정한다. MTU 가 어긋나면 큰 패킷이 조용히 버려지고, 작은 요청은 되는데 큰 응답만 멈추는 증상이 나온다.

6. 상대 VTEP 찾기

보내는 VTEP 은 “Pod B 의 MAC 이 어느 노드 뒤에 있는지” 를 알아야 바깥 IP 를 정할 수 있다. 이 표를 채우는 방법은 셋이다.

멀티캐스트로 묻기
RFC 7348 의 기본 방식. 모르는 MAC 의 프레임을 멀티캐스트 그룹에 뿌리고, 답이 오면 "이 MAC 은 저 VTEP 뒤" 를 배운다. 중간 망이 멀티캐스트를 지원해야 한다
미리 적어 두기 (flannel)
각 노드의 VTEP MAC·IP 가 쿠버네티스 Node 에 기록된다. flanneld 가 이걸 읽어 flannel.1 의 ARP 표와 FDB 에 직접 넣는다. 묻고 배우는 과정이 없다
BGP EVPN
데이터센터 스위치들이 BGP 로 "어느 MAC 이 어느 VTEP 뒤에 있는지" 를 주고받는다

7. 쿠버네티스의 VXLAN

flannel 의 VXLAN 모드는 노드마다 flannel.1 이라는 VXLAN 장치(VNI 1)를 만든다. 다른 노드의 Pod 서브넷으로 가는 경로가 이 장치를 가리키고, 이 장치로 들어간 프레임이 감싸져 노드의 실제 인터페이스로 나간다.

ip route | grep flannel.1           # 10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
ip -d link show flannel.1           # vxlan id 1 local 192.168.10.11 dev eth0 dstport 8472
ip neigh show dev flannel.1         # 다른 노드 VTEP 의 MAC (flannel 이 직접 넣은 줄)
bridge fdb show dev flannel.1       # 그 MAC 이 어느 노드 IP 뒤에 있는지
# 노드 사이 선 위에서 실제 VXLAN 패킷 보기
tcpdump -i eth0 -n -T vxlan udp port 8472   # "VXLAN, flags [I] (0x08), vni 1" 뒤로 안쪽 Pod 주소가 보인다

-T vxlan 을 빼면 tcpdump 는 8472 번 포트를 다른 프로토콜(OTV)로 해석한다. 4789 번이면 지정하지 않아도 VXLAN 으로 읽는다.

Calico 는 기본적으로 라우팅(BGP)으로 노드를 잇고, 필요할 때만 VXLAN 을 켠다. Cilium 도 VXLAN 터널 모드를 지원한다.

8. VLAN 과의 비교

이름이 비슷하지만 하는 일은 반대다. VLAN 은 한 LAN 을 나누고, VXLAN 은 떨어진 LAN 을 잇는다.

VLAN — 한 판을 나눈다VLAN 10VLAN 20스위치 1대VXLAN — 떨어진 판을 잇는다VNI 1VNI 1IP 망 (라우터 너머)나누는 단위: VLAN 은 VID 12비트 (4094개), VXLAN 은 VNI 24비트 (약 1,677만 개)VLAN 은 스위치 안에서 끝나고, VXLAN 은 라우터를 건너간다

9. 관련 문서

  • VLAN — 같은 스위치 안에서 LAN 을 나누는 12비트 태그
  • LAN — VXLAN 이 라우터 너머로 늘이는 대상
  • CNI — VXLAN 장치를 만들고 경로를 넣는 플러그인 규격
  • Network & K8s.01-2 Across the Network — Pod 사이 패킷이 봉투에 담기는 과정

10. 출처

VXLAN 은 RFC 7348 이 정의한다. VNI 크기, 표준 포트, 조각내기 금지가 모두 여기 있다.

“Each VXLAN segment is identified through a 24-bit segment ID, termed the “VXLAN Network Identifier (VNI)”. This allows up to 16 M VXLAN segments to coexist within the same administrative domain.”

“IANA has assigned the value 4789 for the VXLAN UDP port, and this value SHOULD be used by default as the destination UDP port.”

“VTEPs MUST NOT fragment VXLAN packets.”

flannel 문서는 리눅스 기본 포트가 커널 기본값 8472 라고 밝힌다.

“On Linux, defaults to kernel default, currently 8472, but on Windows, must be 4789.”