第九课 k8s网络CNI插件学习-Flannel网络插件

第九课 k8s网络CNI插件学习-Flannel网络插件

tags:

  • k8s网络
  • Vxlan
  • IPIP
  • IPAM

第一节 Flannel学习准备

1.1 Flannel环境

  1. CentOS 7 内核升级 [升级前请务必确认自己环境,商业环境慎用!]
  2. Linux的kernel需要在4.4+以上,才能提供稳定的ipvlan方案。
  3. 升级kernel:升级为最新版本的kernel(可以指定升级到稳定版本)
uname -r
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
yum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml -y
grub2-set-default 0
reboot
uname -r
  1. 安装k8s集群。至少在1.18.0版本之上。
## 指定版本安装1.19.0 现阶段最稳定
sudo yum install -y kubelet-1.19.0 kubeadm-1.19.0 kubectl-1.19.0
sudo systemctl restart kubelet && systemctl enable kubelet
# 初始化集群
kubeadm init \
--apiserver-advertise-address=192.168.44.129 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.19.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
# 集群快照创建,每次网络试验后还原一下。防止一些环境残留。
# 先下载,需要修改不同的backend进行实验https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
  1. 其他工具eNSP、wireshark和virtualbox。
yum -y install bridge-utils
  1. 配置不同的backend选择不同Flannel模式,默认是VxLNA模式
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
   
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
   
          "type": "flannel",
          "delegate": {
   
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
   
          "type": "portmap",
          "capabilities": {
   
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
   
      "Network": "10.244.0.0/16",
      "Backend": {
   
        "Type": "vxlan"   # backend:ipip,vxlan,udp,host-gw#
      }
    }

1.2 CNI的设计介绍

在这里插入图片描述

  1. 虚拟网桥:创建一个虚拟网卡对(veth pair),一头在容器内,一头在宿主机的root namespace内。这样一来,容器内发出的网络数据包,可以通过网桥进入宿主机网络栈,而发往容器的网络数据包也可以经过网桥进入容器。
  2. 多路复用:使用一个中间网络设备,暴露多个虚拟网卡接口,容器网卡都可以接入这个中间设备,并通过mac地址/IP地址来区分packet应该转发给哪一个容器设备。
  3. 硬件交换:还有个“比较直接”的方法就是为每个Pod分配一个虚拟网卡,这样一来,Pod与Pod之间的连接关系就会变的非常清晰,因为近乎物理机之间的通信基础。如今大多数网卡都支持SR-IOV功能,该功能将单一的物理网卡虚拟成多个VF接口,每个VF接口都有单独虚拟PCle通道,这些虚拟PCle通道共用物理网卡的PCle通道。
  4. CNI设计思路。
      1. 建立完整的网络通路。1.使用虚拟网桥实现。2.使用多路复用实现。3.使用SRIOV by pass内核。
      1. 对地址的管理,回收。
  5. 任何一种CNI都有两个重要目录,它们是CNI的一种标准。
cd /etc/cni/net.d/ # 配置目录后面会讲解
cd /opt/cni/bin/ # CNI的一些二进制工具文件

第二节 Flannel的UDP模式

2.1 UDP的模式环境

  1. UDP 模式:第一步我们需要在 Flannel 的配置文件中指定 Backend type 为 upd,可以直接修改 Flannel 的方式实现:
# kubectl edit cm kube-flannel-cfg -n kube-system 或者部署时候修改
apiVersion: v1
data:
  cni-conf.json: |
    {
      "cniVersion": "0.2.0",
      "name": "cbr0",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
        {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "udp"  # 修改后端类型为 UDP
      }
    }
  1. 第二步:需要将 Backend 的类型更改为 udp,采用 UDP 模式时后端默认为端口为 8285,即 Flanneld 的监听端口。当采用 UDP 模式时,Flanneld 进程在启动时会通过打开 /dev/net/tun 的方式生成一个 TUN 设备,TUN 设备可以简单理解为 Linux 当中提供的一种内核网络与用户空间通信的一种机制,即应用可以通过直接读写 TUN 设备的方式收发 RAW IP 包。所以我们还需要将宿主机的 /dev/net/tun 文件挂载到容器中去:
# kubectl edit ds kube-flannel-ds-amd64 -n kube-system
......
  volumeMounts:
    - mountPath: /run/flannel
    name: run
    - mountPath: /etc/kube-flannel/
    name: flannel-cfg # 添加这个
    - mountPath: /dev/net
    name: tun
......
volumes:
- hostPath:
    path: /run/flannel
    type: ""
  name: run
- hostPath:
    path: /etc/cni/net.d
    type: ""
  name: cni
- hostPath: # 添加这个
    path: /dev/net  # 挂载宿主机的 /dev/net/tun 文件
    type: ""
  name: tun
  1. 保存pod自动重启, 后查看一下damonset的pod的日志。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nettools
spec:
  selector:
    matchLabels:
      app: nettools
  replicas: 3
  template:
    metadata:
      labels:
        app: nettools
    spec:
      containers:
      - name: nettools
        image: burlyluo/nettoolbox:v3
        ports:
        - containerPort: 80

2.2 UDP的模式介绍

  1. UDP 是最开始支持的最简单的但是却是性能最差的一种方式,因此基本上在正式使用的时候不会使用这种方式,不过该方式由于非常简单所有可以有助于我们来理解容器跨主机网络通信的实现原理,所以我们先来和大家了解下 UDP 方式的实现方式
  2. UDP是与Docker网桥模式最相似的实现模式。不同的是,UDP模式在虚拟网桥基础上引入了TUN设备(flannel0)。TUN设备的特殊性在于它可以把数据包转给创建它的用户空间进程,从而实现内核到用户空间的拷贝。在Flannel中,flannel0由flanneld进程创建,因此会把容器的数据包转到flanneld,然后由flanneld封包转给宿主机发向外部网络。
  3. UDP转发的过程为:Node1的Pod-1发起的IP包(目的地址为Node2的Pod-2)通过容器网关发到cni0,宿主机根据本地路由表将该包转到flannel0,接着发给flanneld。Flanneld根据目的容器容器子网与宿主机地址的关系(由etcd维护)获得目的宿主机地址,然后进行UDP封包,转给宿主机网卡通过物理网络传送到目标节点。在UDP数据包到达目标节点后,根据对称过程进行解包,将数据传递给目标Pod。
    在这里插入图片描述
  4. UDP模式使用了Flannel自定义的一种包头协议,实现三层网络Overlay网络处理跨主通信的问题。但是由于数据在内核和用户态经过了多次拷贝:容器是用户态,cni0和flannel0是内核态,flanneld是用户态,最终又要通过内核将数据发到外部网络,因此性能损耗较大,对于有数据传输有要求的在线业务并不适用。
  5. 查看flanneld该用户空间的进程:端口号使用8285.
netstat -ulnp | grep flanneld
  1. 每台主机的flanneld都监听着8285端口,所以flanneld只要把UDP发给其它Node的8285端口就可。然后该Node的flanneld再把IP包发送给它所管理的TUN设备flannel0,flannel0再发给cni0最后由cni0网桥发给对应的Pod。
  2. 同一节点同一pod内的容器。一个容器直接使用另外一个已经存在容器的网络配置:IP信息和网络端口等所有网络相关的信息都是共享的。需要注意的是:这两个容器的计算和存储资源还是隔离的。kubernetes的pod就是用这个实现的。同一个pod中的容器共一个network namespace,container网络模式用于容器和容器直接频繁交流的情况。

2.3 同一节点不同pod内的通信

  1. 通常情况下,在Flannel上解决同节点Pod之间的通信依赖的是Linux Bridge和我们在Docker中不同的是,在Kubernetes Flannel的环境中使用的Linux Bridge为cni0,而不是原来的docker0。可通过brctl show查看对应的Linux Bridge的bridge name和interfaces。
# node查看网桥对应的cni0对应的网卡 
brctl show
kubectl exec -it nettools-66b897f8d7-4s8r7 bash
ethtool -S eth0 # 可以查看网卡对端的索引 peer_ifindex: 7
  1. 过程:我们知道用户空间是没有办法进行数据报文的封装的。从一个pod的容器的用户空间出来送到cni0内核空间在送到另外一个pod的容器的用户空间。
  2. Veth Pair的Linux的网卡点对点实验实现通信。
# 对于此种模式我们普通Linux中 在之前环境做过 
# 创建 namespace
ip netns a ns1
ip netns a ns2

# 创建一对 veth-pair veth0 veth1
ip l a veth0 type veth peer name veth1

# 将 veth0 veth1 分别加入两个 ns
ip l s veth0 netns ns1
ip l s veth1 netns ns2

# 给两个 veth0 veth1 配上 IP 并启用
ip netns exec ns1 ip a a 10.1.1.2/24 dev veth0
ip netns 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值