1

K8s | K8s跨主机通信原理

 5 months ago
source link: https://jiac3366.github.io/2021/11/17/Kubernetes/K8s%E8%B7%A8%E4%B8%BB%E6%9C%BA%E9%80%9A%E4%BF%A1%E5%8E%9F%E7%90%86/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

+c编程手记

Guangzhou, China

“跨主通信”的原理

  • Flannel 支持三种后端实现(本节介绍后2种)

    Flannel 项目本身只是一个框架,真正为我们提供容器网络功能的,是 Flannel 的后端实现。

    • host-gw

    • UDP(flanneld 扮演者路由器的角色)

      这个 UDP 包的源地址,就是flanneld 所在的 Node 1 的地址,目的地址是 container-2 所在的宿主机 Node 2 的地址
      每台宿主机上的 flanneld,都监听着8285 端口

      • 1、出现跨宿主机通信,包会被交给默认路由规则,进入 docker0 与宿主机的路由进行匹配,进入到一个叫作 flannel0的设备,接着交给Flannel进程(内核态向用户态的流动)
        在 Linux 中,TUN 设备是一种工作在三层(Network Layer)的虚拟网络设备,只负责在操作系统内核和用户应用程序之间传递 IP 包。

      • 2、flanneld 收到 IP 包的目的地址,就把它发送给了 Node 2宿主机, 它是如何知道这个 IP 地址对应的容器,是运行在 Node 2 上的?

        • 首先明白: Flannel 管理的容器网络里,一台宿主机上的所有容器,都属于该宿主机被分配的一个“子网”,子网与宿主机的对应关系,保存在 Etcd
          docker0 网桥的地址范围必须是 Flannel 为宿主机分配的子网

        • flanneld 处理flannel0 传入的 IP 包时,就可以根据目的 IP 的地址(比如100.96.2.3),匹配到对应的子网(比如 100.96.2.0/24),从 Etcd 中找到这个子网对应的宿主机的 IP 地址是 10.168.0.3

        • 若 Node 1 和 Node 2 是互通的,从Node1就可以发送给Node2

        • 相比于两台宿主机之间的直接通信,多了一个额外的步骤,即 flanneld 的处理过程:由于使用到了 flannel0 这个 TUN 设备,仅在发出 IP 包的过程中,就需要经过三次用户态与内核态之间的数据拷贝img
    • VXLAN

      Virtual Extensible LAN(虚拟可扩展局域网), Linux 内核本身就支持的一种网络虚似化技术,VXLAN 可以完全在内核态实现 UDP模式中在用户态进程flanneld:8285的封装和解封装的工作

      • 在现有的三层网络之上,“覆盖”一层虚拟的、由内核VXLAN 模块负责维护的二层网络
        为在二层网络上打通“隧道”,VXLAN 会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。
        这个设备就叫作 VTEP,即:VXLAN Tunnel End Point(虚拟隧道端点)作用和跟前面的 flanneld 进程十分类似
        ​差别在于封装和解封装的对象是二层数据帧;执行流程是在内核里完成的(因为 VXLAN 本身就是 Linux 内核中的一个模块)

      • Node 2 启动并加入 Flannel 网络之后, Node 1(以及所有其他节点)的flanneld 就会添加一条到 Node2 VTEP设备IP的路由规则
        flannel.1 设备( VTEP 设备)替代了原flannel0 设备和主机eth0

      • VTEP 设备收到docker0发来的“原始 IP包”要想办法加上一个目的 MAC 地址,封装成一个二层数据帧,然后发送给“目的 VTEP 设备”,那么目的 VTEP 设备”的 MAC 地址是什么?因为Node1已有到Node2 VTEP的IP,所以自然要使用ARP,需要的 ARP 记录,也是 flanneld 进程在 Node 2 节点启动时自动添加在 Node 1上
        (不依赖 L3 MISS 事件和 ARP 学习)可以通过 ip 命令查看——ip neigh show dev flannel.1
        ( VTEP 设备和宿主机都有MAC地址哦)

      • 加上“目的 VTEP 设备”的 MAC 地址,得到一个“内部数据帧”,但并不能在宿主机二层网络里传输img

      • Linux 内核还需要再把“内部数据帧”进一步封装成为宿主机网络里的一个普通的数据帧,让它载着完整的二层数据帧,通过宿主机的 eth0 网卡进行传输,把这次要封装出来的、宿主机对应的数据帧称为“外部数据帧”(Linux 内核会把这个数据帧封装进一个 UDP 包里发出去)
        Linux 内核会在“内部数据帧”前面,加上一个VXLAN 头表示“乘客”实际上是一个 VXLAN 要使用的数据帧,VXLAN 头里有个标志叫VNI,是 VTEP 设备识别某个数据帧是否归自己处理的重要标识。在 Flannel 中宿主机上的VTEP 设备都叫作 flannel.1 ,原因是这个“1”是VNI 标志的默认值

      • flannel.1 设备只知道另一端的 flannel.1 设备的 MAC 地址,却不知道对方的宿主机地址的IP地址, UDP 包该发给哪台宿主机呢?

        • flannel.1 设备实际扮演一个“网桥”的角色,在二层网络进行 UDP 包的转发。而在 Linux 内核里面,“网桥”设备进行转发的依据,来自一个叫FDB(Forwarding Database)的转发数据库(相当于交换机的MAC表),bridge fdb 命令可以查看对方宿主机的IP
          FDB 信息,也是 flanneld 进程负责维护的
          bridge fdb show flannel.1 | grep 5e:f8:4f:00:e3:37(对方 VTEP 设备的MAC,由ip neigh show dev flannel.1查出来的)
      • Linux封包发送(Node 2 的 MAC 地址,是 Node 1 的 ARP 表要学习的内容,无需 Flannel 维护)img

      • 对方接受img

    • 后两种模式其实都可以称作“隧道”机制,也是很多其他容器网络插件的基础。比如 Weave 的两种模式,以及 Docker 的 Overlay 模式。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK