Search

CNI와 Flannel

Tags
k8s
cni
flannel
Created
2024/09/06 08:54
Created time
2024/09/05 23:54
category
kubernetes

개요

Flannel을 통해 CNI를 학습하고 아래 내용을 탐구
CNI의 정의와 동작 방식
Flannel, Calico, Cilium의 간단한 특징
로컬, 리모트 노드 간의 Pod 통신 과정
Flannel의 통신 환경 3가지와 podCIDR 라우팅 정보 획득 방법

k8s 네트워크 모델

k8s 네트워크 모델은 아래 요구사항을 만족
NAT 없는 Pod 간 통신 지원
kubelet 및 데몬 등의 노드 에이전트는 Pod와 통신 가능
중복 없는 서비스 클러스터 IP 대역과 Pod IP 대역
k8s 네트워크 모델은 아래 문제를 해결
Pod 내 컨테이너들은 루프백으로 통신
Pod 간 통신 지원
클러스터 내부에서 서비스를 통해 통신 가능
클러스터 외부에서 서비스를 통해 통신 가능
→ 이와 같은 통신을 지원하기 위해 CNI를 정의

CNI

개념

CNI는 컨테이너 런타임과 통합하여 컨테이너의 네트워크 인터페이스를 추가하고 IP를 할당하는 역할을 담당
오로지 컨테이너의 네트워크 연결성과 컨테이너 삭제 시 관련 네트워크 리소스 해제에만 관여하기에, 어떤 컨테이너 런타임을 이용하든 무관
CNI 소개명세를 참고하고, CNI의 구성 요소 분석은 여기를 참고

명세

컨테이너는 리눅스 네트워크 네임스페이스 안에 존재
도커와 같은 컨테이너는 실행 마다 새로운 네임스페이스를 생성
CNI 정의서는 JSON으로 표기
CNI 정의서는 표준 입력, 매개 변수는 환경 변수로 CNI 플러그인에 전달
CNI 플러그인은 실행 파일로 구현
CNI 플러그인은 컨테이너 네트워크 연결을 위한 모든 작업에 책임 존재
CNI 플러그인은 IPAM (IP 주소 할당 및 라우팅 정보 입력) 책임도 존재
Pod에 IP가 할당되기 까지 과정은 여기를 참고

플러그인

CNCF에서 기술한 위의 명세를 준수하여 구현한 것을 CNI 플러그인이라 지칭
다양한 플러그인이 있지만 대표적으로 Flannel, Calico, Cilium이라는 CNI 플러그인을 이용
Flannel : VXLAN을 사용하여 간단하게 동작하는 오버레이 네트워크
Calico : BGP를 사용하여 다양한 기능을 제공하는 오버레이 네트워크
Cilium : eBPF 기반으로 동작하는 오버레이 네트워크
언더레이 네트워크는 실제 장비를 이용하여 통신하는 기술이며, 오버레이 네트워크는 네트워크를 가상화 하여 통신하는 기술을 지칭

Pod 간 통신

Pause 컨테이너를 선행적으로 학습

구성 요소와 특징

Pod는 자체적인 네트워크 네임스페이스를 구축하고, 이는 루트 네트워크 네임스페이스와 격리된 별개의 네임스페이스
Pod는 네임스페이스 단위로 IP 주소가 할당되는데, 컨테이너들은 동일한 네트워크 네임스페이스와 IP 주소를 공유
Pod 간 통신 시 eth0끼리 통신이 필요한데 네트워크 네임스페이스가 다르기에, 루트 네트워크 네임스페이스를 경유하여 통신을 수행
따라서 각 Pod는 루트 네트워크 네임스페이스로의 접근 권한이 필요하고, 이는 각 Pod가 사용하는 인터페이스가 veth (Virtual Ethernet Pair)로 연결되어 만족
Virtual Ethernet Pair는 두 개의 인터페이스를 서로 연결하는 가상의 네트워크 케이블과 같은 역할을 수행
cni0는 Pod 네트워크 인터페이스들을 묶어 Pod 간 통신을 관리하는 가상의 브릿지로, Pod 네트워크 인터페이스와 호스트 네트워크 인터페이스를 연결하여 외부로의 접근도 허용
브릿지는 네트워크 인터페이스들을 하나의 네트워크로 묶어서 통신이 가능하도록 돕는데, 위의 경우 veth 사이의 트래픽이 루트 네트워크 네임 스페이스를 통과할 수 있도록 돕는 일종의 가상화된 2계층 Switch로 동작

동일 노드 간 Pod 통신

1.
Pod A와 Pod B는 동일한 네트워크 네임스페이스를 사용하는 것이 아니므로, Pod A에서 출발한 패킷은 Pod A의 eth0 인터페이스로 이동
2.
Pod A의 eth0와 연결된 veth0로 전달되어 루트 네트워크 네임스페이스로 전달
3.
cni0 브릿지로 전달된 패킷을 전달하기 위해 Pod B의 IP 주소에 해당되는 MAC 주소를 ARP로 탐색
4.
veth1로 패킷을 전달하고, 이와 연결된 Pod B의 eth0로 전달

다른 노드 간 Pod 통신

1.
동일 노드 간 Pod 통신 1, 2번을 동일하게 수행
2.
노드 내 통신이 아니므로 노드 네트워크 통과를 위해 추가 홉이 필요하고, 노드 1의 eth0에서 노드 2의 eth0로 전달
3.
노드 2의 eth0로 전달된 패킷을 노드2의 cni0 브릿지가 받음
4.
동일 노드 간 Pod 통신 3, 4번을는 동일하게 수행
→ 오버레이 네트워크는 가상화된 네트워크로 Pod들이 같은 네트워크에 있는 것처럼 쉽게 통신할 수 있도록 돕고, 물리적인 네트워크로 전달될 때 트래픽을 특정 형태로 Encap / Decap을 수행
→ Pod 간 통신 시 노드를 벗어나야 하는 경우에 Pod가 타겟팅하는 노드를 알 수 있도록 돕게 오버레이 네트워크를 적용할 수 있는데, 이와 같은 역할을 하는 것이 Flannel과 같은 CNI 플러그인
모든 CNI 플러그인이 오버레이 네트워크를 지원하는 것은 아님

Flannel

개념

Flannel은 단일 바이너리 에이전트인 flanneld가 각 노드에서 동작하고, 작은 규모의 클러스터에서 Pod 간 통신 가능한 환경을 구성하는 CNI 플러그인
위 Pod 통신 환경에서 노드의 eth0와 cni0 브릿지 사이에 새로운 인터페이스로써 존재하고, VXLAN과 같은 기술을 통해 트래픽이 캡슐화 되어 전달
즉, Flannel은 노드 내에서의 통신 보다는 다른 노드 사이의 Pod 간 통신을 지원하기 위한 노드 단위의 가상 네트워크 인터페이스
따라서 해당 계층을 지나 캡슐화된 패킷은 Pod의 IP 주소가 아닌 노드의 IP 주소를 이용하는 식으로 치환
Flannel이 모든 Pod를 대상으로 해당 Pod가 위치한 노드와 IP 주소를 알 수 있는 것은 노드에서 동작 중인 flanneld가 etcd 분산 데이터베이스를 통해 ARP 테이블을 업데이트 하여 IP 주소 결정을 동기화하는 구조 때문

네트워크 환경

오버레이 네트워크를 구현하는 대표적인 방법인 VXLAN
권장
오버레이 네트워크 없이 노드에 있는 Pod 네트워크 대역을 라우팅 테이블에 업데이트하여 직접 라우팅을 수행하는 host-gw
모든 노드가 동일한 서브넷에 있어야 해서, 퍼블릭 클라우드에서 사용이 어려워 비권장
오래된 리눅스 커널에서 사용할 수 있는 오버레이 네트워크 기법인 UDP
비권장
자료 1자료 2를 참고하여 더 자세한 특징 학습

실습 흐름

Flannel 적용

클러스터 생성
networking.disableDefaultCNI를 true로 설정
레포지토리 클론 및 bridge 플러그인 빌드 및 /opt/cni/bin 경로 배치
manifest 이용하여 Flannel 배포

Flannel 확인

kubectl get no -o jsonpath='{.items[*].spec.podCIDR}'
Flannel이 각 노드에 서브넷 할당을 어떻게 했는지 Pod CIDR 범위를 통해 확인
kubectl describe no | grep -A3 Annotations | grep flannel.alpha.coreos.com/public-ip
노드가 Flannel 네트워크 참여시 사용하는 공개 IP 주소 확인
lsns -p $(pgrep flanneld)
Flannel은 별도의 네트워크 네임스페이스를 이용하지 않음에 따라 클러스터와 동일한 네트워크 네임스페이스를 이용
Flannel은 클러스터 단위에 걸쳐 노드들의 네트워크 설정을 관리하기 때문에 격리 없이 호스트 네트워크 이용
lsns -p $(pgrep kube-proxy)
kube-proxy는 클러스터 네트워크에서 서비스로 트래픽을 라우팅
kube-proxy는 네트워크 네임스페이스를 init 프로세스와 동일하게 이용하여 호스트 네트워크와 직접 상호작용
Pod 직접 생성하여 cni0와 flannel.1 인터페이스를 확인
brctl show cni0 → cni0에 연결된 veth들을 확인
bridge link → 상태가 정상인 veth가 flannel.1 네트워크에 연결되어 cni0 하위 인터페이스임을 확인
bridge vlan → vlan을 확인하고 cni0와 그 하위 인터페이스들이 vlan에 속함을 확인
tree /var/lib/cni/networks/cbr0 → 컨테이너에 할당한 마지막으로 예약된 IP 주소 기록 (last_reserved_ip.0)와 다른 프로세스에서 cbr0 네트워크 상태 업데이트 할 때 충돌 방지를 위한 파일 (lock)을 확인 가능
아래 명령어들을 이용하여 다른 노드에 배포된 Pod 간 통신 / 외부 인터넷 IP 접속 / 외부 인터넷 도메인 접속 / GW IP 인터페이스 (cni0)를 확인
tcpdump -i cni0 -nn icmp와 ping을 조합
tcpdump -i flannel.1 -nn icmp와 ping을 조합
tcpdump -i eth0 -nn icmp 와 ping을 조합

Reference

CNI가 왜 필요하고 구성이 어떻게 되는지와 Flannel이 어떤 역할을 해주는지, 그리고 Flannel 적용 실습 및 분석이 상세히 기록되어 있음