Flannel CNI

Uk·2024년 9월 7일
0

Intro

CloudNet@ - KANS 3기 2주차 스터디

CNI (Container Network Interface)

Kubernetes 클러스터 내의 네트워크를 설정하고 관리하기 위한 표준 인터페이스

4가지 요구사항

  1. 파드와 파드 간 통신시 NAT 없이 통신 가능
  2. 노드의 에이전트(kubelet, system daemon)는 파드와 통신 가능
  3. 호스트 네트워크를 사용하는 파드는 NAT 없이 파드와 통신 가능
  4. 서비스 클러스터 IP 대역과 파드가 사용하는 IP 대역은 중복 X

4가지 문제 해결 요구

  1. 파드 내 컨테이너는 루프백을 통한 통신 가능
  2. 파드 간 통신 가능
  3. 클러스터 내부에서 서비스를 통한 통신 가능
  4. 클러스터 외부에서 서비스를 통한 통신 가능

kubelet을 통해 신규 파드가 생성되면 네트워크 관련 설정 추가

CNI 플러그인은 전달되는 설정 정의서를 보고 실제 파드가 통신하기 위한 네트워크 설정 실행

IPAM(IP Address Management), IP 할당 관리를 수행하며, 파드 간 통신을 위한 라우팅 설정 처리

Flannel

Kubernetes 클러스터 내 네트워크를 설정하기 위한 간단하고 효율적인 CNI 플러그인

Flannel CNI 구축

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  labels:
    mynode: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    controllerManager:
      extraArgs:
        bind-address: 0.0.0.0
    etcd:
      local:
        extraArgs:
          listen-metrics-urls: http://0.0.0.0:2381
    scheduler:
      extraArgs:
        bind-address: 0.0.0.0
  - |
    kind: KubeProxyConfiguration
    metricsBindAddress: 0.0.0.0
- role: worker
  labels:
    mynode: worker
- role: worker
  labels:
    mynode: worker2
networking:
  disableDefaultCNI: true

kind create cluster --config kind-cni.yaml --name myk8s --image kindest/node:v1.30.4`

아직 CNI가 없기 때문에 IP를 못 받고 pending 상태

docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump iputils-ping htop git nano -y'
docker exec -it myk8s-worker  sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump iputils-ping -y'
docker exec -it myk8s-worker2 sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump iputils-ping -y'
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

# 확인
kubectl get ns --show-labels
kubectl get ds,pod,cm -n kube-flannel
kubectl describe cm -n kube-flannel kube-flannel-cfg

kubectl describe pod -n kube-system -l k8s-app=kube-dns

kind를 사용했을 때 bridge 파일이 없다는 에러가 있으므로 다음 참고

#
docker exec -it myk8s-control-plane bash
---------------------------------------
apt install golang -y
git clone https://github.com/containernetworking/plugins
cd plugins
chmod +x build_linux.sh

#
./build_linux.sh
Building plugins
  bandwidth
  firewall
  portmap
  sbr
  tuning
  vrf
  bridge
  host-device
  ipvlan
  loopback
  macvlan
  ptp
  vlan
  dhcp
  host-local
  static

# 파일 권한 확인 755
ls -l bin
-rwxr-xr-x 1 root root  4559683 Sep  3 04:54 bridge
...

exit
---------------------------------------

# 자신의 PC에 복사 : -a 권한 보존하여 복사(755)
docker cp -a myk8s-control-plane:/plugins/bin/bridge .
ls -l bridge

docker cp bridge myk8s-control-plane:/opt/cni/bin/bridge
docker cp bridge myk8s-worker:/opt/cni/bin/bridge
docker cp bridge myk8s-worker2:/opt/cni/bin/bridge
docker exec -it myk8s-control-plane  chmod 755 /opt/cni/bin/bridge
docker exec -it myk8s-worker         chmod 755 /opt/cni/bin/bridge
docker exec -it myk8s-worker2        chmod 755 /opt/cni/bin/bridge
docker exec -it myk8s-control-plane  chown root root /opt/cni/bin/bridge
docker exec -it myk8s-worker         chown root root /opt/cni/bin/bridge
docker exec -it myk8s-worker2        chown root root /opt/cni/bin/bridge
# flannel 정보 확인 : 대역, MTU
for i in myk8s-control-plane myk8s-worker myk8s-worker2; do echo ">> node $i <<"; docker exec -it $i cat /run/flannel/subnet.env ; echo; done

docker exec -it myk8s-worker        bash

flannel pod의 ip는 노드 서버의 ip 와 동일합니다.

network namespace를 공유하기 때문.

# 라우팅 정보 확인 : 다른 노드의 파드 대역(podCIDR)의 라우팅 정보가 업데이트되어 있음을 확인		
ip -c route

default via 172.18.0.1 dev eth0 
10.244.0.0/24 via 10.244.0.0 dev flannel.1 onlink 
10.244.1.0/24 dev cni0 proto kernel scope link src 10.244.1.1 
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink 
172.18.0.0/16 dev eth0 proto kernel scope link src 172.18.0.3 

iptables -t filter -S | grep 10.244.0.0
iptables -t nat -S | grep 'flanneld masq' | grep -v '! -s'

위와 같이 확인해보면 kubectl → CNI → iptables 이야기 했던 바와 같이 룰들을 설정해놓은 걸 알 수 있습니다.

# [터미널1,2] 워커 노드1,2 - 모니터링
docker exec -it myk8s-worker  bash
docker exec -it myk8s-worker2 bash
-----------------------------
watch -d "ip link | egrep 'cni|veth' ;echo; brctl show cni0"
-----------------------------

# [터미널3] cat & here document 명령 조합으로 즉석(?) 리소스 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  labels:
    app: pod
spec:
  nodeSelector:
    kubernetes.io/hostname: myk8s-worker
  containers:
  - name: netshoot-pod
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
    app: pod
spec:
  nodeSelector:
    kubernetes.io/hostname: myk8s-worker2
  containers:
  - name: netshoot-pod
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

# 파드 확인 : IP 확인
kubectl get pod -o wide

cni0 interface(bridge) 생성 → veth interface 부착 + peer 정보

  • cni0 dump 확인

  • 외부 통신할 때 flannel.1 거치지 않는 모습
    업로드중..

⇒ flannel interface는 다른 노드의 파드와 통신할 때 VXLAN으로 오버레이 네트워크가 필요할 때만 사용합니다.

  • Pod 1 → Pod 2를 통할 때

eth0 (서버의 인터페이스) 에서 tcpdump를 해도 보이지 않는다. (기존 패킷을 감싸버린 UDP 이기 때문)

0개의 댓글