1. 主机在同一局域网 数据包传输
    • 二层交换机
    • 基于mac转发
    • 在本机查找 ARP 缓存表, 没有的话发送一个 ARP 广播包(询问对方mac地址是多少)
    • 四元组: 源 IP, 源 MAC ,目的 IP ,目的 MAC
    • 路由器每个端口都是一个 VLAN,隔离广播,因此收不到 ARP 广播包
  2. 主机在不同局域网 数据传输
    • vlan1 192.168.31.0/24
    • vlan3 192.168.32.0/24
    • 路由表
    • 目的 192.168.32.0/24 网关 接口

      CNI 标准

  • 一个pod 一个ip
  • 所有pod可以与其他pod直接通信,无需使用NAT映射
  • 所有节点可以与所有 pod 直接通信,无需使用 NAT 映射
  • pod 内部获取到的 IP 地址与其他 pod 或节点通信时的 IP 是同一个

    Flannel

  1. CoreOS 维护的一个网络组建
  2. 为每个 pod 提供全局唯一的 IP
  3. 使用 ETCD 存储 pod 子网 与 node IP 之间的关系(每个node 不同子网)
  4. flanneld 守护进程,维护本地路由规则和etcd 信息 daemonset方式 保证每个node有一个守护进程
  5. /etc/cni /var/run/flannel/subnet.env 子网配置文件
  6. 网桥方式实现同节点
  7. 设置子网与工作模式image.png
  8. flannel支持多种数据转发方式
    1. UDP : 早期,性能差,目前已启用 路由方案
    2. VXLAN:Overlay Network 方案,源数据包封装到另一种网络数据包中,进行路由转发和通信,两种网络数据包 隧道方案
    3. Host-GW:flannel通过在各个节点上的Agent进程,将容器网路的路由信息刷新到主机的路由表上,这样所有的主机都有整个容器网络的路由数据了
  9. 配置
    /var/run/flannel/subnet.env flannel子网配置信息 从下面配置信息拿IP 为pod分配 子网不要与物理网络有冲突
    image.png
    /opt/kubernetes/cfg/kube-controller-manager.conf
    启用下面两个参数 允许node自动分配 下面要与fannel 子网对应上
    image.png
    /opt/kubernetes/cfg/kubelet.conf启用cni支持
    image.png

VXLAN模式

  1. image.png
  2. VXLAN 隧道技术
    1. 在宿主机上设置一个特殊的网络设备作为“隧道”的两端,
    2. 这个设备叫作 VTEP 即 VXLAN Tunnel End Point (虚拟隧道端点)
  3. 容器通过 veth-pair 将数据包发出,相当于网线
  4. brctl show cni0 查看网桥 可以看到 pod veth的另一端插入到网桥中,作为一个接口 interface
    image.png
  5. flannel 没有用到 docker0 网桥,而是新建一个 cni0网桥 与docker0 一模一样,可能为了方便处理数据包
  6. ip route 查看路由表
  7. VXLAN 封装
    1. VTEP 设备(二层)之间组成二层网络必须要知道目的 MAC 地址
    2. MAC 地址从哪获取呢? 由 flannel 维护
    3. flanneld 进程启动后,会自动添加其他节点 ARP 记录
    4. 通过ip 命令查看ip neigh show dev flannel.1
      image.png
  8. 二次封包
    1. 知道 目的mac 地址,封装二层数据帧(容器源 IP 和目的 IP),对于宿主机来说,这个帧并没有实际意义
    2. 因此,接下来,Linux内核要把这个数据帧进一步封装成宿主机网络的一个普通数据帧,(就是由UDP 封装),目的:让数据包传递到目的容器
    3. 为什么要UDP 封装? 因为是不同子网,无法直接传输,要传输必须要通过路由器,因此封装为普通的数据帧
      image.png
      image.png
    4. 能直接发UDP数据包吗?我们目前只知道另一端flannel.1的MAC地址,却不知到宿主机地址是什么?上面UDP封包,如何通过容器目的 IP,知道UDP 要封装的宿主机目的 IP呢?
      1. flannel 维护者etcd数据及路由表,etcd存储着 宿主机ip 与 容器子网 对应关系image.png
      2. 这是因为flanneld进程维护着一个叫作 FDB 的转发数据库
      3. bridge fdb show dev flannel.1 查看宿主机 ip 对应的 MAC 地址image.png
      4. 因此VXLAN 封包如下,封装一层UDP
        注:第一个目的mac地址为 目的主机上的 flannel.1 设备(也就社VTEP)的mac地址(ip neigh show dev flannel.1 可查看)第二个目的mac地址为 目的主机 mac 地址 (有 FDB 转发数据库维护)image.png
      5. 如何能确定发送到 flannel.1 的VTEP 设备呢?一个宿主机上可能有多个 VTEP 设备
        在VXLAN封包头部加了VNI编号``,确保发送到确定的VTEP设备
  9. 数据到达目的宿主机
    1. Node1 的 eth0 网卡发出去,发现是 VXLAN 数据包,把它交给 flanneld.1 设备
    2. flannel.1 设备则会进一步拆包,取出原始二层数据帧包,发送 ARP 请求, 经过 cni0 网桥转发给容器
  10. 小结 重要

    1. 两次封包,降低性能,初始封包一次,VTEP 设备由封包一次
    2. 同样解封包也要两次
    3. 性能下降很多
    4. OverLay 网络:原始数据包又经过一次封包,然后通过二层网络可以发送数据包
    5. VXLAN 是在内核态封包接封包,而 UDP 模式是在用户态封解,因此弃用
    6. VXLAN 封两次包
      1. 第一次VXLAN封包,VTEP设备,目的mac地址由 fanneld 提供(目的mac地址并不是pod地址,而是VTEP 设备 mac地址)
      2. 第二次封包 封为宿主机普通数据帧,使用UDP封装,目的mac 为 对方主机的mac
      3. 为什么要二次封包
        1. 因为不同主机pod属于不同子网,需要三层设备转发(路由器),而VTEP是二层设备(基于mac)
        2. 所以采用 UDP 再次封包,封装为正常数据包,源ip 和 目的ip 都是主机ip,在同一子网,可使用二层转发

          Host-GW (Gateway) 模式

          image.png
  11. 直接添加路由,将目的主机当做网关,直接路由原始封包

  12. 不使用 flannel.1 封包了
  13. VXLAN 模式路由表 先转发到 flannel.1 设备
    image.png
    host-gateway模式路由表 直接转发到主机 **相当于把其他节点当做网关**
    image.png
  14. 相当于把每个节点当做网关,要求所有节点二层能通

    小结

  15. 二层能通的话,Host-GW 是最好方式

  16. 若主机不在同一VLAN,需要路由,VXLAN是最好方式

Calico

  1. 纯三层的数据中心网络方案
  2. 每个计算节点利用linux kernel 实现一个高效的虚拟路由器(vRouter)来负责数据转发
  3. vRouter 通过BGP 协议负责把子上运行的 workload 的路由信息向整个Calico网络传播
  4. 还实现kubernetes网络策略,提供ACL 功能

    BGP

  5. 与Flannel 的 host-gw 模式几乎一样,就是基于路由表来时先容器数据包的转发

  6. 不同与Flannel使用flanneld进程来维护路由信息的做法,Calico项目使用 BGP 协议自动维护整个集群的路由信息
  7. 全称 Border Gateway Protocol, 即边界网关协议,是一种自治系统间的动态路由发现协议,与其他BGP系统交换网络可达信息
  8. 自治系统
    - 自治系统间无来往
    - 要不同自治系统通信要求:内网ip地址不能相同,上层路由出口能互相学习到路由信息
    image.png
  9. BGP 来实现数据交换 动态协议
    Flannel 守护进程来维护
  10. Calico架构
    - 也是采用 veth 设备
    - 将宿主机当做虚拟路由器(BGP 协议)
    image.png
  11. Calico 主要由三部分构成:
    1. Felix:以DaemonSet方式部署,运行在每个Node节点上,主要负责维护宿主机上路由规则以及ACL规则
    2. BGP Client(BIRD):主要负责吧Felix写入Kernel的路由信息分发到集群Calico网络
    3. Etcd:分布式键值存储,保存Calico的策略和网络配置状态
    4. calicoctl:允许从简单的命令行界面实现高级策略和网络
  12. 无换行获取证书 cat /opt/etcd/ssl/ca.pem |base64 -w 0
  13. 删除网桥 ip link delete cni0 和 之前路由信息 ip route del 信息行
  14. 切换网络 pod需要重建
  15. 节点间相互建立长连接 共享路由信息
    命令查看:netstat -antp | grep bird
    image.png
  16. 配置文件默认位置 /etc/calico/calicoctl.cfg 指定etcd路径和连接证书
    calicoctl node status calicoctl get ippool

原理剖析 默认BGP模式

image.png

  1. 无网桥 虚拟路由
  2. 配置文件位置 /opt/cni/bin 子网配置信息 /etc/cni/net.d/10-calico.conflist
  3. pod1 访问pod2流程
    1. 数据包从容器1处到达veth pair另一端(在宿主机上,以cali前缀开头 ifconfig)
    2. 宿主机根据路由规则,将数据包转发给吓一跳(网关)
    3. 达到 node2,根据路由规则将数据包转发给cali设备,从而到达容器2
    4. image.png
    5. 最核心“下一跳”路由规则:由Calico的Felix进程负责维护
    6. 这些路由规则信息,是通过BGP Client也就是BIRD组件,使用BGP 协议传输而来的
    7. Calico项目实际上将集群里的所有节点,都当做是边界路由来处理,他们一起组成了一个全连通的网络,互相之间通过BGP协议交换路由规则。这些节点,我们称之为 BGP Peer
  4. BGP 模式要求二层互通

    Route Reflector 模式(RR)

  5. Calico 维护的网络默认使(Node-to-Node Mesh)全互联模式,节点间都会建立连接用于路由交换,因此需要建n(n-1)/2条连接。

  6. 随着集群规模的扩大,mesh模式将形成一个巨大的服务网格,连接数成倍增加
  7. RR (路由器反射)模式解决上述问题
    image.png
  8. 配置
    1. 关闭node-to-node 网格模式
    2. 配置指定节点充当路由器反射器
  9. 解决集群过大时,BGP的消耗

    IPIP 模式

  10. 解决 “要求集群宿主机之间是二层连通的”的问题,例如 Flannel host-gw也有同样的限制

  11. 架构 增加了 tunl0image.png
  12. pod1 访问pod2 大致流程

    1. 数据包从容器1出 达到veth pair 另一端(在宿主机上,以cali前缀开头)
    2. 进入IP 隧道设备(thnl0),有Linux内核IPIP驱动封装在宿主机网络的IP包中(新的IP包目的地址是原IP包的吓一跳地址,即192.168.31.53),这样,就成了 Node1 到 Node2 的数据包
    3. 数据包经过路由器三层转发到 Node2
    4. Node2 收到数据包后,网络协议栈会使用 IPIP驱动进行解包,从中拿到原始IP包
    5. 然后根据路由规则,将数据包转发给cali设备,从而到达容器2
    6. 额外封包解包

      小结

  13. 细粒度访问控制
    flannel 不支持,calico支持 ACL

  14. 追求网络性能
    路由方案 Flannel中的 host-gw Calico中的BGP
  15. 服务器之间是否可以跑BGP协议?
    很多公有云不支持
  16. 集群规模多大?
    集群规模小 几十台 Flannel
  17. 是否有维护能力?
    BGP 路由表条目多 难维护 难排错

    问题

  18. Calico IP如何分配

  19. Mesh 与 Calico架构有什么区别

    办公网络如何与k8s网络互通?

  20. k8s集群测试环境在办公网络子网
    ip route add 10.244.0.0/16 via dev A

  21. k8s集群与办公网络在不同VLAN,不同机房

    1. 前提:三层可达
    2. 路由器上添加路由表 10.244.0.0?16
    3. 路由器 BGP 与路由反射器 BGP 建立连接

      网络策略

  22. 为什么需要网络隔离?
    cni插件解决了不同node节点pod互通问题,从而形成一个扁平化网络

  23. 网络访问策略
    Flannel 不能,Calico可以
    Calico 没有固定IP,通过一些手段可以