2주차 [3] - Flannel CNI

  • k8s 에서 정의하는 CNI란 무엇인지 이해한다.

  • Flannel CNI 동작과 통신흐름이해한다.

1. CNI 네트워크 모델 요구사항

쿠버네티스 네트워크 및 Flannel CNI 소개 - Gasida Seo님의 책

1.1 네트워크 모델 요구사항 4가지

  • 쿠버네티스 네트워크 모델은 4가지 요구사항이 있습니다.

    • pod와 pod간 통신시 NAT 없이 통신한다.

    • Kubelet 은 pod와 통신이 가능하다.

    • 호스트 네트워크를 사용하는 pod 는 NAT 없이 POD와 통신한다.

    • 서비스 클러스터 IP 대역과 POD가 사용하는 IP 대역은 중복되지 않아야한다.

1.2 네트워크 동작 4가지

쿠버네티스 네트워크 및 Flannel CNI 소개 - Gasida Seo님의 책
  • 파드내 컨테이너는 루프백을 통한 통신을 할 수 있어야한다.

  • 파드간 통신을 할 수 있어야한다.

  • 클러스터 내부에서 서비스를 통한 통신을 할 수 있어야한다.

  • 클러스터 외부에서 서비스를 통한 통신을 할 수 있어야한다.

1.3 노드의 파드들간 통신을 위한 VXLAN 네트워크 환경

  • VXLAN

    • 네트워크 오버레이 기술을 구현해주는 방법

    • 논리적인 가상의 네트워크 환경을 만들어준다.

    • 터널링 기법으로, 파드의 패킷을 감싸서 노드에서 빠져나가고, 목적지 노드에 도착해서 패킷에 감싸진 부분을 제거하고 목적지 파드에 전달하게 됩니다.

    • 이 제거하는 부분을 VTEP이라고 하고, FLANNEL 1 네트워크 인터페이스가 해당 역할을 합니다.

    • UDP 8472 포트를 사용합니다.

쿠버네티스 네트워크 및 Flannel CNI 소개 - Gasida Seo님의 책
  • 파드의 eth0 네트워크 인터페이스 호스트 네트워크 네임스페이스의 vethY 인터페이스와 페어로 연결된다.

  • vethY 인터페이스는 cniO 네트워크 브릿지로 연결 된다.

  • 동일 노드 내에서 파드들간 통신은 cni0 네트워크 브리지를 통해서 통신이 가능하다.

2. Flannel 이란?

  • Flannel은 K8S의 CNI로 모든 노드에 flannelld라는 에이전트를 생성합니다.

2.1 kind 와 Flannel 배포

#
cat <<EOF> kind-cni.yaml
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
EOF
kind create cluster --config kind-cni.yaml --name myk8s --image kindest/node:v1.30.4

# 배포 확인

kind get nodes --name myk8s
(⎈|kind-myk8s:N/A) root@kind:~# kind get nodes --name myk8s
myk8s-worker2
myk8s-worker
myk8s-control-plane

# 네트워크 확인
kubectl cluster-info dump | grep -m 2 -E "cluster-cidr|service-cluster-ip-range"
(⎈|N/A:N/A) root@kind:~# kubectl cluster-info dump | grep -m 2 -E "cluster-cidr|service-cluster-ip-range"
                            "--service-cluster-ip-range=10.96.0.0/16",
                            "--cluster-cidr=10.244.0.0/16",

# flannel 설치 및 namespace 확인
(⎈|kind-myk8s:N/A) root@kind:~# kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
(⎈|kind-myk8s:N/A) root@kind:~# kubectl get ns --show-labels
NAME                 STATUS   AGE     LABELS
default              Active   9m24s   kubernetes.io/metadata.name=default
kube-flannel         Active   9s      k8s-app=flannel,kubernetes.io/metadata.name=kube-flannel,pod-security.kubernetes.io/enforce=privileged
kube-node-lease      Active   9m24s   kubernetes.io/metadata.name=kube-node-lease
kube-public          Active   9m24s   kubernetes.io/metadata.name=kube-public
kube-system          Active   9m24s   kubernetes.io/metadata.name=kube-system
local-path-storage   Active   7m16s   kubernetes.io/metadata.name=local-path-storage

# kubectl describe pod -n kube-system -l k8s-app=kube-dns
# 브릿지 파일이 없어 오류가 생기고 있는것을 확인 할 수 있습니다!
  Warning  FailedCreatePodSandBox  25s                 kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "8ac0f67e7c8ac0b705f5f98b5678db797daf95b8c14223144df9c397d1c37df9": plugin type="flannel" failed (add): failed to delegate add: failed to find plugin "bridge" in path [/opt/cni/bin]
  Normal   SandboxChanged          21s (x12 over 32s)  kubelet            Pod sandbox changed, it will be killed and re-created.
  Warning  FailedCreatePodSandBox  20s (x4 over 24s)   kubelet            (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "25498fd6b78c74571f99295f7e4dd378f89e69f253196c51c02eb81f99876faf": plugin type="flannel" failed (add): failed to delegate add: failed to find plugin "bridge" in path [/opt/cni/bin]
  
  (⎈|kind-myk8s:N/A) root@kind:~# kubectl get pod -A -owide
NAMESPACE            NAME                                          READY   STATUS    RESTARTS   AGE     IP           NODE                  NOMINATED NODE   READINESS GATES
kube-flannel         kube-flannel-ds-8tqt6                         1/1     Running   0          3m23s   172.18.0.3   myk8s-control-plane   <none>           <none>
kube-flannel         kube-flannel-ds-9ftxz                         1/1     Running   0          3m23s   172.18.0.2   myk8s-worker2         <none>           <none>
kube-flannel         kube-flannel-ds-lzw85                         1/1     Running   0          3m23s   172.18.0.4   myk8s-worker          <none>           <none>
kube-system          coredns-7db6d8ff4d-g8n75                      1/1     Running   0          10m     10.244.0.3   myk8s-control-plane   <none>           <none>
kube-system          coredns-7db6d8ff4d-jwnn6                      1/1     Running   0          10m     10.244.0.2   myk8s-control-plane   <none>           <none>
kube-system          etcd-myk8s-control-plane                      1/1     Running   0          12m     172.18.0.3   myk8s-control-plane   <none>           <none>
kube-system          kube-apiserver-myk8s-control-plane            1/1     Running   0          12m     172.18.0.3   myk8s-control-plane   <none>           <none>
kube-system          kube-controller-manager-myk8s-control-plane   1/1     Running   0          12m     172.18.0.3   myk8s-control-plane   <none>           <none>
kube-system          kube-proxy-744r7                              1/1     Running   0          10m     172.18.0.3   myk8s-control-plane   <none>           <none>
kube-system          kube-proxy-cmphm                              1/1     Running   0          10m     172.18.0.2   myk8s-worker2         <none>           <none>
kube-system          kube-proxy-nbdg2                              1/1     Running   0          10m     172.18.0.4   myk8s-worker          <none>           <none>
kube-system          kube-scheduler-myk8s-control-plane            1/1     Running   0          12m     172.18.0.3   myk8s-control-plane   <none>           <none>
local-path-storage   local-path-provisioner-7d4d9bdcc5-8zsrx       1/1     Running   0          10m     10.244.0.4   myk8s-control-plane   <none>           <none>



2.2 통신 흐름 확인하기

  • 동일 노드간 통신을 확인합니다.

  • 통신이 되고있는데, UDP 라서, POD 간 통신은 잡히지 않음

  • 외부 통신을 확인합니다.

  • 다른 노드의 파드에 통신을 확인합니다.

2.3 파드에 어떻게 IP를 할당하게 될까요?

  • pod 생성

  • kubelet이 CRI Plugin 에게 pod 생성하라고 요청

  • CRI Plugin이 pod sandbox 생성 및 pod network namespace 생성한다. 그리고 cni에 요청한다.

  • CNI Plugin이 네트워크를 구성합니다.

    • flannel cni

    • bridge cni plugin

    • host local IPAM CNI Plugin

    • IP를 POD에 할당합니다.

  • Pause 컨테이너를 생성하고 network namspace에 할당합니다.

  • Kubelet이 CRI에 컨테이너 이미지를 요청합니다.

  • 컨테이너 이미지를 containerd를 이용하여 가져옵니다.

  • kubelet이 CRI Plugin에게 컨테이너를 시작하라고 요청합니다.

  • CRI Plugin은 containerd를 사용하여, 파드의 컨테이너의 cgroup과 namespace를 할당하고 시작합니다.

2.4 Flannel 은 모든 파드 위치와 IP 주소를 어떻게 알게 될까요?

  • 각 노드에서 Flannel DL은 ETCD의 IP 주소 할당을 동기화합니다.

  • ARP 테이블을 각각 ROOT NETNS에서 업데이트해줘서 어느 노드가 어떤 Pod의 IP를 가지고 있는지 알 수 있습니다. -> ARP 테이블의 최대크기를 넘어갈 수 있지 않을까?

Last updated