이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

클라우드/Kubernetes

40. Flannel CNI Networking 분석

이쿠우우 2020. 11. 7. 13:00
반응형

 

 

 

Flannel CNI Networking

 


 

CNI 란?

CNI : Container Network Interface

컨테이너 간의 네트워킹을 제어할 수 있는 플러그인을 만들기 위한 표준.

Kubernetes Cluster 내부는 Master Node 에 의해 여러 컨테이너가 생성 삭제 복구를 반복하고 있음

그에 따라 각 컨테이너의 고정적이지 않고 재할당이 빈번함.

이러한 특징을 해결하기 위해 Kubernetes Cluster는 가상 네트워크가 구성되어 있는데 

기본적으로는 Worker Node 의 kube-proxy 가 네트워크를 관리하지만

보다 효율적인 네트워크 환경을 구성하기 위해

다양한 네트워크 관련 Addon 이 제공됨

종류)

  • Ingress, Flannel, ACI, Calico, Canal, Cilium, CNI-Genie, Contiv, Multus, NSX-T, Nuage, Romana, Weave Net


 

Flannel 이란?

서로 다른 노드에 있는 pod 간 통신을 완성하기 위해서는 관련 기능을 제공하는 CNI가 필요함

Flannel 은 대표적인 CNI 종류 중 하나.

Flannel은 Kubernetes 용으로 설계된 오버레이 네트워크(overlay network)

L3 네트워크를 구성하는 가장 간단하고 쉬운 방법을 제공함.

 

Kubernetes에 Flannel을 적용하게 되면 모든 Node에서 flanneld라는 에이전트를 실행하고

각 Node에 flannel.1 인터페이스를 할당함.

Flannel은 Kubernetes API 통해 etcd에

네트워크 구성, Pod에 할당된 IP 정보 등을 저장함.

Flannel은 VXLAN를 사용하여 원래의 패킷을 한번 더 감싸서 서로 다른 Node간 통신이 되도록 함.

실제로 각 Node 의 

cni0 인터페이스 =  VXLAN의 vSwitch와 같은 역할을 수행함.

flannel.1 인터페이스 =  VXLAN의 VTEP과 같은 역할을 수행함.

 

 

오버레이 네트워크

물리 네트워크 위에 성립 되는 가상의 컴퓨터 네트워크.

실제 노드 간의 네트워크 위에 별도 Flat한 네트워크를 구성하는 것을 의미.

쉽게 비유를 하자면 

서울에서 부산까지 가는데 

차로 가게 되면

기존의 도로망 체제를 유지하면서

신호등도 거치고 여러 톨게이트를 거쳐야해서 복잡한데

비행기를 타면

김포공항에서 부산행 비행기 티켓을 끊고 한방에 가는 것과 같은 원리

 

 

VXLAN

 

[등장배경]

가상화 기반의 서버에서는 다량의 MAC Address Table을 보유하게 되는데

네트워크 Switch에서 최대 수용할 수 있는 MAC에 한계,

가상화 환경에서 네트워크 단일 도메인의 VLAN 숫자의 한계라는 문제가 발생함.

이러한 가상화 기술로 인해 발생하는 여러 네트워크 문제점을 해결하기 위해 

VXLAN이 등장함.

 

[VXLAN 특징]

VLAN에 X (eXtensible)을 더한 것으로 L2 Network 의 확장성을 의미함

VXLAN Header + UDP + IP 기반으로 전송.

VXLAN Header는 24bit VXLAN Network ID로 구성됨.

학습하지 못한 목적지 VM MAC은 VXLAN기술 기반으로 IP Mulicast를 이용하여

목적지 VM MAC 주소가 있는 스위치에 전송

(Broadcast, Multicast Unknown destination)

VM MAC은 VXLAN기반의 Encapsulation된 패킷을 받아서 목적지

VM ARP Table을 학습하는 방식.

학습한 목적지 VM MAC은 P2P Tunnel로 직접 해당 스위치와 통신.

 

 

[VXLAN Address Learning 과정]

 

 

[VXLAN Unicast 과정]

 

 


 

 

Flannel Port

 

UDP = 8285

Flannel이 UDP 백엔드를 사용하여 캡슐화 된 패킷을 보내기 위해서 사용.

 

UDP = 8472

커널이 vxlan 백엔드를 사용하여 캡슐화 된 패킷을 보내기 위해서 사용.

예시 환경에서는 8472만 사용.

 


 

Flannel이 필요한 이유.

 

Kuberentes Default Network 구조를 사용하게 되면

상위 그림과 같이 Worker Node 가 2개 생성될 시 

Pod 에 부여되는 IP주소가 동일하여 

Worker Node 1 의 Pod 에서 Worker Node 2 Pod 로 통신을 할 시 IP가 같아서 문제 발생.

쉽게 말해서 다른 Worker Node 에 있는 Pod 간의 네트워크 통신에 문제가 생김.

 

kubernetes 에서는 다른 Worker Node 의 Pod 간 통신 문제점을 해결하기 위해 Kubernetes Addon 중 CNI 를 사용.

대표적으로 사용되는 CNI 는 flannel 이 있음.

flannel을 사용하면 상위 그림과 같이 다른 Worker Node 간 Pod의 IP가 동일하지 않아서 

라우터를 거쳐서 Pod 간 통신이 가능해짐.

flannel CNI를 설치 후 ifconfig 확인 시 

아래와 같이 flannel 과 cni0 장치가 추가됨을 확인 가능.

 

Pod 의 Ip를 확인해 보면 더이상 Docker 의 네트워크를 사용하지 않고 

Flannel 장치를 사용해서 Ip가 할당되는 것을 확인 할 수 있음.

 

Master Node의 bridge Network를 예로 확인해보면

생성된 2개의 Pod의 veth 가상 네트워크 인터페이스가 

cni0 에 바인딩된 것을 확인할 수 있음.

참고) flannel을 사용하지 않았다면 docker0 에 바인딩됨.

 

 


 

 

 

 

Flannel Network 구조 확인

 

구조 확인을 위한 예시 환경

아래와 같이 2개의 Pod가

서로 다른 Worker Node에 존재하고 있음

iksoon-deployment-tomcat = Worker Node 1

iksoon-deployment-mysql = Worker Node 2

 

[Worker Node 1과 2는 서로 다른 subnet를 가지고 있음]

Worker Node 1 = 10.244.1.0/24

Worker Node 2 = 10.244.2.0/24

 

 

Worker Node에 배포된 Pod 정보 확인

[IP 확인] : pod의 eth0

iksoon-deployment-tomcat = 10.244.1.96

iksoon-deployment-mysql = 10.244.2.108

 

[MAC 확인] : pod의 eth0

iksoon-deployment-tomcat = 76:b6:ae:e6:46:27

iksoon-deployment-mysql = 56:f3:bb:53:86:45

 

[veth 확인] : 각 Pod의 eth0 해당하는 veth 확인

iksoon-deployment-tomcat = vethd75fcd5d (Worker Node 1)

iksoon-deployment-mysql = vethd13b09a4 (Worker Node 2)

 

veth 란?

Virtual Ethernet.

linux namespace를 할당 받으면

network namespace도 생성되는데

network namespace에는 오직 veth만 할당 받을 수 있음

veth는 항상 쌍으로 생성이 되는데

한쪽에서 입력된 데이터는 다른쪽에서 수신할 수 있음

해당 Container가 할당받은 veth 경우는

한쪽은 물리적인 네트워크 인터페이스와 연결되어있고

다른 한쪽은 linux network namespace 와 연결되어

Container와 host간에 통신이 가능해짐

 

 

[ cni0 bridge 확인] : cni0 bridge에 매칭되어있는 veth 확인 ]

 

Worker Node 1

 

Worker Node 2

 

확인 결과

생성된 Pod의 eth0 인터페이스는

배포된 Worker Node의 veth에 연결이 되어있고

veth 는 Worker Node의 cni0 bridge에 연결이 되어있음.

그리고 각 Node에 생성된 flannel.1 과 cnio bridge 의 subnet이 동일함.

eth0-veth-cni0-flannel.1 으로 연결되어 있음

 

 

 

 


 

 

 

Flannel CNI Routing 분석 1.

동일한 Worker Node에 있는 Pod 네트워크

 

 

동일한 Worker Node라면 통신과정이 매우 간단함.

컨테이너A가 같은 Worker Node에 있는 컨테이너B와 통신한다면

 

1. 컨테이너A의 veth인터페이스를 통해 트래픽이 Worker Node의 cni0 bridge로 push됨. 

 

2. cni0 bridge는 ARP Broadcast를 해서 컨테이너B의 VM MAC을 가져 오려고 시도함. 

 

3. 동일한 Worker Noded에 컨테이너B가 있기 때문에 성공적으로 컨테이너B의 VM MAC을 가져옴.

 

4. 가져온 MAC을 확인하고 cni0 ARP Table에 저장한 뒤 cni0 bridge를 통해 통신함.

 

동일한 workerNode에 있는 Pod로 네트워킹 할 경우

cni0 인터페이스가 패킷을 전달함.

 

trace 명령으로 확인해본 결과.

 

 

 

 


 

 

 

 

Flannel CNI Routing 분석 2.

서로 다른 Worker Node에 있는 Pod 네트워크

 

 

 

Worker Node 1에 배포되어 있는 Pod의 컨테이너A가 

Worker Node 2에 배포되어 있는 Pod의 컨테이너B에 ping을 한다면.

 

 

1. 

컨테이너A가 ICMP packet 을 만듬

[ ICMP Pack의 정보 ]

[MAC 정보]
출발지 : 76:b6:ae:e6:46:27 (컨테이너A의 MAC)
도착지 : ???? (컨테이너 B의 MAC)

[IP주소 정보]

출발지 : 10.244.1.96  (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

하지만 정보중에 도착지 컨테이너B의 MAC주소를 아직 모름.

 

2. 

컨테이너A는 목적지의 network subnet을 보고 다른 Worker Node에 있다는것을 인지함.

목적지로 가고싶지만 ARP Table이 없음.

따라서 통신을 위해 패킷을 기본 게이트웨이 즉 cni0 bridge로 보내야함.

Worker Node 1의 cni0 인터페이스 IP = 10.244.1.1

결과적으로 POD1은 cni0 즉 10.244.1.1의 MAC 주소를

얻기 위해 ARP Request (Layer 2 Broadcast)를 보냄.

 

 

3. 

Worker Node 1의 cni0가 ARP Request를 받고 

cni0의 MAC주소 : 7a:cc:a8:18:fa:12 를

respone함.

 

4. 

컨테이너A는 respone을 받아서 ICMP Packet을 완성함.

도착지의 MAC 정보가 cni0로 설정됨.

 

[ ICMP Pack의 정보 ]

[MAC 정보]
출발지 : 76:b6:ae:e6:46:27 (컨테이너A의 MAC)
도착지 : 7a:cc:a8:18:fa:12 (Worker Node1의 cni0 MAC)

[IP주소 정보]

출발지 : 10.244.1.96  (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

 

 

5. 

ICMP가 전달되기 시작.

Worker Node 1의 cni0에서 tcpdump로 ICMP를 확인해보면 아래와 같이 정보를 확인할 수 있음.

[명령어]

tcpdump -i cni0 -ne icmp -vv -c 1

[MAC 정보]
출발지 : 76:b6:ae:e6:46:27 (컨테이너A의 MAC)
도착지 : 7a:cc:a8:18:fa:12 (Worker Node 1 cni0 의 MAC)

[IP주소 정보]

출발지 : 10.244.1.96  (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

 

6. 

Routing Table확인

10.244.2.0/24 대역대의 서브넷은 flannel1.1 인터페이스로 Static Routing 되어있는 것을 확인가능

 

 

7. 

Worker Node 1의 cni0는 패킷을 Switching/ IP Rewrite를 해서 

flannel.1 인터페이스로 보냄

[명령어]

tcpdump -i flannel.1 -ne icmp -vv -c 1

[MAC 정보]
출발지 : 4a:b3:de:c2:2b:be  (Worker Node 1의 flannel.1인터페이스 MAC주소)
도착지 : 52:be:91:fd:4c:ea  (Worker Node 2의 flannel.1인터페이스 MAC주소)

[IP주소 정보]

출발지 : 10.244.1.96  (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

(참고)

Worker Node 1의 flannel.1인터페이스 MAC주소

Worker Node 2의 flannel.1인터페이스 MAC주소

 

 

도착지 Worker Node 2의 flannel.1의 MAC은 어떻게 알아낸걸까?

Flannel은 VXLAN 기반으로 동작하고 있음.

도착지의 MAC 정보도 VXLAN을 통해서 알아낸것임.

Worker Node 2의 VTEP IP 즉 flannel.1의 IP : 10.244.2.0 에 대한 정보는

Worker Node 1의 에서 실행되는 Flannel Pod의 ARP Table에 학습되고 기록됨.

 

Worker Node 1이 Worker Node 2의 flannel.1 MAC 주소를 알아온 과정 요약

[ 1. ]

Worker Node 1의 cni0 (VXLAN의 vSwitch역할과 동일)인터페이스가 

패킷을 받으면 목적지 IP를 확인하고

이에 매칭되는 MAC값이 있는지 ARP Table을 확인함 

하지만 최초 시도이기 때문에 매칭되는 MAC주소가 없음

cni0는 MAC주소를 알아오기 위해 ARP Request를 Flannel.1로 보냄

 

[ 2. ]

Worker Node 1의 Flannel.1(VXLEN의 VTEP 역할과 동일) 인터페이스가 

Multicast 를 통해 연결되어있는 모든 Worker Node에게 ARP Request 를 날림.

 

[ 3. ]

해당 ARP Request를 받은 모든 Worker Node는 

ARP Request 정보 중 출발지 정보를 보고 

Worker Node 1의 Flannel.1 인터페이스의 MAC주소를

각자 자신의 cni0 ARP Table에 저장함.

 

[ 4. ]

많은 Worker Node 중에 2가 자신에게 해당 IP와 매칭이 되는 Pod가 배포되어있는것을 확인함.

Worker Node 2는 Unicast로 Worker Node 1에 ARP Respone을 보냄

ARP Respone에는 목적지 IP에 해당하는 MAC주소

즉 Worker Node 2의 Flannel.1 인터페이스의 MAC주소가 포함되어있음

 

[ 5. ]

Worker Node 1에서 해당 ARP Respone을 받고 

ARP Table에 Worker Node 2의 Flannel.1 인터페이스의 MAC주소를 저장함.

 

[ 6. ]

그 뒤로 Worker Node 1과 2는 Unicast로 통신됨.

 

 

실제로 Worker Node 1의 Flannel Pod에서 ARP Table확인해봄.

 kubetl get pod -o wide -n kube-system

명령으로 Worker Node 1에서 동작 중인 Flannel Pod를 확인

kubectl -it exec kube-flannel-ds-amd64-47fjz -n kube-system  --arp -a

명령으로 Worker Node 1 Flannel 의 ARP Table확인

 

 

 

8. 

Worker Node 1의 cni0 보낸 패킷을 Flannel.1 인터페이스가 받음.

Flannel.1 인터페이스는 VXLAN에서 VTEP과 동일한 역할을 수행하는데 

그 작업으로 받은 패킷을 VXLAN 패킷으로 만들기 위해 

패킷을 UDP를 사용하여 실제 네트워크를 통해 전송하기 위해 L3패킷으로 encapsulated (캡슐화)함.

UDP Header에는 출발지와 목적지 정보가 저장되어있고 Port는 8285 혹은 8472로 설정되어있음.

 

[VXLAN 패킷 예제]

 

 

 

9. 

Worker Node 1 Flannel.1 인터페이스가 ens192로 

VXLAN 캡슐화된 패킷을 보냄

 

[명령어]

tcpdump -i ens192 -ne udp -vv -c 1

Outer-packet

[MAC 정보]

출발지 : 00:0c:2a:8c:0e:30 (Worker Node 1의 ens192인터페이스의 MAC)

도착지 : 00:0c:2a:8c:0e:31 (Worker Node 2의 ens192인터페이스의 MAC)

 

[IP주소 정보]

출발지 : 10.2.13.128 (Worker Node 1의 IP)

도착지 : 10.2.13.129 (Worker Node 2의 IP)

 

[Port 정보]

출발지 : 36473

도착지 : 8472

 

VXLAN으로 캡슐화 된 패킷 정보

[MAC 정보]

출발지 : 4a:b3:de:c2:2b:be (Worker Node 1의 flannel.1인터페이스 MAC주소)

도착지 : 52:be:91:fd:4c:ea  (Worker Node 2의 flannel.1인터페이스 MAC주소)

 

[IP주소 정보]

출발지 : 10.244.1.96 (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

[ 패킷의 특징 ]

외부로 나가는 Packet의 경우 

목적지 Port가 8472 또는 8285로 설정되는데

위 예시에서는 8472로 설정됨

 

그리고 해당 패킷을 보면 

출발지 컨테이너A의 MAC 주소는(76:b6:ae:e6:46:27)

찾아볼 수 없음

 

 

10.

ens192 인터페이스가 패킷을 Worker Node 2 로 보내기 위해

먼저 패킷을 ens192와 연결되어 있는 default Router로 전송함.

 

 

11.

Router는 패킷을 Worker Node 2로 전송하게 되고 

보낼때와 역순으로

Worker Node2 의 

ens192 -> flannel.1 -> cni0 -> veth0 -> eth0 로 전달됨.

 

Outer-packet

[MAC 정보]

출발지 : 00:0c:2a:8c:0e:30 (Worker Node 1의 ens192인터페이스의 MAC)

도착지 : 00:0c:2a:8c:0e:31 (Worker Node 2의 ens192인터페이스의 MAC)

 

[IP주소 정보]

출발지 : 10.2.13.128 (Worker Node 1의 IP)

도착지 : 10.2.13.129 (Worker Node 2의 IP)

 

[Port 정보]

출발지 : 36473

도착지 : 8472

 

 

VXLAN으로 캡슐화 된 패킷 정보


[MAC 정보]

출발지 : 4a:b3:de:c2:2b:be (Worker Node 1의 flannel.1인터페이스 MAC주소)

도착지 : 52:be:91:fd:4c:ea  (Worker Node 2의 flannel.1인터페이스 MAC주소)

 

[IP주소 정보]

출발지 : 10.244.1.96 (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

[MAC 정보]
출발지 : 4a:b3:de:c2:2b:be  (Worker Node 1의 flannel.1인터페이스 MAC주소)
도착지 : 52:be:91:fd:4c:ea  (Worker Node 2의 flannel.1인터페이스 MAC주소)

[IP주소 정보]

출발지 : 10.244.1.96  (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

 

 

[MAC 정보]
출발지 : 0e:c5:40:04:31:42 (Worker Node 2 cni0 의 MAC)
도착지 : 56:f3:bb:53:86:45 (컨테이너B의 MAC)

[IP주소 정보]

출발지 : 10.244.1.96  (컨테이너A의 IP)

도착지 : 10.244.2.108 (컨테이너B의 IP)

 

 

 


제 글을 복사할 시 출처를 명시해주세요.
글에 오타, 오류가 있다면 댓글로 알려주세요! 바로 수정하겠습니다!


 

 

 

참고

[Flannel network]

https://medium.com/@abhishek.amjeet/a-closer-look-at-networking-with-kubernetes-45710a3889e1

https://itnext.io/kubernetes-journey-up-and-running-out-of-the-cloud-flannel-c01283308f0e

https://jonnung.dev/kubernetes/2020/02/24/kubernetes-pod-networking/

https://docker-k8s-lab.readthedocs.io/en/latest/docker/docker-flannel.html

 

 

 

[ VXLAN ]

https://atthis.tistory.com/6

https://youngmind.tistory.com/entry/Network-Overlay-VXLAN-%EB%B6%84%EC%84%9D-1

 

 

 

반응형