Hero Image
cilium中的datapth简解

cilium收发包是极其复杂的过程,本节将介绍数据包是如何穿过 network datapath(网络数据路径)的:包括从硬件到内核,再到用户空间 本文中只讨论收包的过程,涉及到的知识点比较多,望君耐心看完,多读几遍,定会颇有收获 网卡驱动 驱动:网卡需要有驱动才能工作,驱动是加载到内核中的模块,负责衔接网卡和内核的网络模块,驱动在加载的时候将自己注册进网络模块,当相应的网卡收到数据包时,网络模块会调用相应的驱动程序处理数据 模块:是在内核空间运行的程序,实际上是一种目标对象文件,没有链接,不能独立运行,但可以装载到系统中作为内核一部分运行,从而动态扩充内核的功能 Linux下对于一个硬件的驱动,可以有两种方式: 1:直接加载到内核代码中,启动内核时就会驱动此硬件设备 2:以模块方式,编译生成一个.o文件,当应用程序需要时再加载进内核空间运行,比如执行命令:insmod SHT21.ko 网卡(NIC): 硬件,内核通过网卡驱动与网卡交互,网卡本身是有内存的,每个网卡一般都有4k以上的内存(fifo队列),用来发送、接受数据。 数据发送:数据从主内存搬到网卡之后,要先在网卡自身的内存中排队,再按先后顺序发送 数据接受:数据从以太网传递到网卡时,网卡也是先把数据存储到自身的内存中,每收到一帧数据,就经过中断,以DMA方式从网卡内存拷贝至内核内存 tap/tun设备 TUN与TAP是操作系统内核中的虚拟网络设备,操作系统通过TUN/TAP设备向绑定该设备的用户空间的程序发送数据,反之,用户空间的程序使用标准网络接口socket API操作tun/tap设备发送数据,它们都是从/dev/net/tun字符设备进行读取数据(2.6+) 1:Tun 是三层网络设备,从/dev/net/tun字符设备上读取的是IP数据包,写入的也只能是IP数据包,因此不能进行二层操作,如发送ARP请求和以太网广播 2:Tap 是二层网络设备,处理的是二层数据帧,从 /dev/net/tun 字符设备上读取的是数据帧,写入的也只能是数据帧 示例: # 创建 tap ip tuntap add dev tap0 mode tap # 创建 tun ip tuntap add dev tun0 mode tun # 删除 tap ip tuntap del dev tap0 mode tap # 删除 tun ip tuntap del dev tun0 mode tun 数据发送流程:

Hero Image
基于Ubuntu20.04版本的cilium1.10.1安装使用

基础概念 linux的内核空间和系统空间 linux系统分为内核空间和用户空间并且相互隔离,内核空间运行内核相关的指令,可以执行任意指令(比如cpu的特权指令的使用,或者驱动程序运行等),用户空间运行非内核的进程(比如自己平常写的java代码等),若用户空间的程序需要调用底层相关的指令(比如说读取文件,分配回收内存等),此时需要调用内核提供的接口来完成对应的有限的操作,这个过程叫做系统调用。如果我们用户空间的程序要直接操作内核并没有提供接口的指令时,通常是需要修改内核代码来满足需求,但后来内核提供了一个内核模块(LKM)来满足此种需求,lkm直接将指令加载至内核执行,不需要再通过系统调用的方式来完成,运行时加载,不需要编译内核也不需要重启系统,但此方法若操作不当,也会直接让内核崩溃,进而增加了安全维护成本. ​ BPF 伯克利包过滤器(Berkeley Packet Filter,缩写 BPF): 是类Unix系统上数据链路层的一种原始接口,提供原始链路层封包的收发 最初是在1992年构思的,目的是提供一种过滤数据包的方法,并避免从内核到用户空间的无用数据包复制,从而极大地提高性能。它最初包含一个简单的字节码,该字节码从用户空间注入到内核中,并由验证程序进行检查(以防止内核崩溃或安全问题)并附加到套接字,然后在每个接收到的数据包上运行 tcpdump就是基于BPF技术实现的,FreeBSD和WinPcap在内的一些平台,使用即时编译(JIT)编译器来把BPF指令转换为原始字节码,以进一步提高性能。Linux有一个BPF JIT编译器,但被默认禁用。 ​ EBPF 随着现代硬件及指令的发展,BPF对于一些硬件上的指令支持有限,因此,Alexei Starovoitov引入了扩展的BPF设计,从3.18版本开始,Linux 内核提供了一种扩展的BPF虚拟机,被称为“extended BPF”,简称为eBPF。利用现代硬件的优势,允许将eBPF指令更紧密地映射到ISA,以提高性能,它也能够被用于非网络相关的功能,比如附在不同的tracepoints上,从而获取当前内核运行的许多信息 架构图如下 工作原理 eBPF程序“附加”到内核中的指定代码路径,遍历代码路径时,将执行所有附加的eBPF程序,为了解决LKM这种安全性的问题,eBPF 程序需要满足一系列的需求,才能被加载到内核。Verifier 会遍历对 eBPF 程序在内核中可能的执行路径进行遍历, 确保程序能够在不出现导致内核锁定的循环的情况下运行完成。除此之外还有其它必须满足的检查,例如有效的寄存器状态、程序大小以及越界等,如果所有的检查都通过了,eBPF 程序被加载并编译到内核中,并监听特定的信号。该信号以事件 的形式出现,会被传递给被加载的 eBPF 程序。一旦被触发,字节码就会根据其中的指令执行并收集信息。 简单说下eBPF 的工作流程: 1:把 eBPF 程序编译成字节码。 2:在载入到 Hook 之前,在虚拟机中对程序进行校验。 3:把程序附加到内核之中,被特定事件触发。 4:JIT 编译。 5:在程序被触发时,调用辅助函数处理数据。 6:在用户空间和内核空间之间使用键值对共享数据。 ​ cilium 如果要实现对流量的监控和规则处理,则我们需要去编写对应的EBPF程序来实现,cilium是基于EBPF来实现的容器管理平台部署的应用程序之间的网络和api连接管理工具,由于eBPF在Linux内核中运行,因此可以在不更改应用程序代码或容器配置的情况下应用和更新Cilium安全策略 ​ Hubble Hubble是一个完全分布式的网络和安全性可观察性平台。它建立在Cilium和eBPF之上,以完全透明的方式深入了解服务以及网络基础结构的通信和行为。 ​ Hubble可以查看以下功能的信息: 服务依赖关系和相互通信的展示: 1:哪些服务正在相互通信?多久一次?服务依赖关系图是什么样的? 2:正在进行哪些HTTP调用?服务从哪些卡夫卡主题中消费或产生什么? 网络监控和警报: