加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 云计算 > 正文

你要知道的七个核心问题

发布时间:2022-07-30 15:49:48 所属栏目:云计算 来源:互联网
导读:过去一年,ARMS基于eBPF技术打造了Kubernetes监控,提供多语言无侵入的应用性能,系统性能,网络性能观测能力,验证了eBPF技术的有效性。eBPF技术和生态发展很好,未来前景广大,作为该技术的实践者,本文目标是通过回答7个核心问题介绍eBPF技术本身,为大家
  ​过去一年,ARMS基于eBPF技术打造了Kubernetes监控,提供多语言无侵入的应用性能,系统性能,网络性能观测能力,验证了eBPF技术的有效性。eBPF技术和生态发展很好,未来前景广大,作为该技术的实践者,本文目标是通过回答7个核心问题介绍eBPF技术本身,为大家解开eBPF的面纱。
 
  eBPF是什么?
  eBPF是一个能够在内核运行沙箱程序的技术,提供了一种在内核事件和用户程序事件发生时安全注入代码的机制,使得非内核开发人员也可以对内核进行控制。随着内核的发展,eBPF 逐步从最初的数据包过滤扩展到了网络、内核、安全、跟踪等,而且它的功能特性还在快速发展中,早期的 BPF 被称为经典 BPF,简称cBPF,正是这种功能扩展,使得现在的BPF被称为扩展BPF,简称eBPF。
 
  eBPF的应用场景是什么?
  网络优化
  eBPF兼具高性能和高可扩展特性,使得其成为网络方案中网络包处理的优选方案:
 
  安全控制
  eBPF可以看到所有系统调用,所有网络数据包和socket网络操作,一体化结合进程上下文跟踪,网络操作级别过滤,系统调用过滤,可以更好地提供安全控制。
 
  性能监控
  相比于传统的系统监控组件比如sar,只能提供静态的counters和gauges,eBPF支持可编程地动态收集和边缘计算聚合自定义的指标和事件,极大地提升了性能监控的效率和想象空间。
 
  eBPF为什么会出现?
  eBPF的出现本质上是为了解决内核迭代速度慢和系统需求快速变化的矛盾,在eBPF领域常用的一个例子是eBPF相对于Linux Kernel类似于Javascript相对于HTML,突出的是可编程性。一般来说可编程性的支持通常会带来一些新的问题,比如内核模块其实也是为了解决这个问题,但是他没有提供很好的边界,导致内核模块会影响内核本身的稳定性,在不同的内核版本需要做适配等。eBPF采用以下策略,使得其成为一种安全高效地内核可编程技术:
 
  安全
  eBPF 程序必须被验证器校验通过后才能执行,且不能包含无法到达的指令;eBPF 程序不能随意调用内核函数,只能调用在 API 中定义的辅助函数;eBPF 程序栈空间最多只有 512 字节,想要更大的存储,就必须要借助映射存储。
 
  高效
  借助即时编译器(JIT),且因为 eBPF 指令依然运行在内核中,无需向用户态复制数据,大大提高了事件处理的效率。
 
  标准
  通过BPF Helpers,BTF,PERF MAP提供标准的接口和数据模型供开发者使用。
 
  功能强大
  eBPF 不仅扩展了寄存器的数量,引入了全新的 BPF 映射存储,还在 4.x 内核中将原本单一的数据包过滤事件逐步扩展到了内核态函数、用户态函数、跟踪点、性能事件(perf_events)以及安全控制等领域。
 
  eBPF怎么用?
  图片
 
  5个步骤
  1.使用 C 语言开发一个 eBPF 程序;
 
  即插桩点触发事件时要调用的eBPF沙箱程序,该程序会在内核态运行。
 
  2.借助 LLVM 把 eBPF 程序编译成 BPF 字节码;
 
  eBPF 程序编译成 BPF 字节码,用于后续在eBPF虚拟机内验证并运行。
 
  3.通过 bpf 系统调用,把 BPF 字节码提交给内核;
 
  在用户态通过bpf系统,将BPF字节码加载到内核。
 
  4.内核验证并运行 BPF 字节码,并把相应的状态保存到 BPF 映射中;
 
  内核验证BPF字节码安全,并且确保对应事件发生时调用正确的eBPF程序,如果有状态需要保存,则写入对应BPF映射中,比如监控数据就可以写到BPF映射中。
 
  5.用户程序通过 BPF 映射查询 BPF 字节码的运行状态。
 
  用户态通过查询BPF映射的内容,获取字节码运行的状态,比如获取抓取到的监控数据。
 
  一个完整的 eBPF 程序,通常包含用户态和内核态两部分:用户态程序需要通过 BPF 系统调用跟内核进行交互,进而完成 eBPF 程序加载、事件挂载以及映射创建和更新等任务;而在内核态中,eBPF 程序也不能任意调用内核函数,而是需要通过 BPF 辅助函数完成所需的任务。尤其是在访问内存地址的时候,必须要借助 bpf_probe_read 系列函数读取内存数据,以确保内存的安全和高效访问。在 eBPF 程序需要大块存储时,我们还需要根据应用场景,引入特定类型的 BPF 映射,并借助它向用户空间的程序提供运行状态的数据。
 
  eBPF程序分类和使用场景
  复制
  bpftool feature probe | grep program_type
  1.
  以上命令可以查看系统支持的eBPF程序类型,一般有如下类型:
 
  复制
  eBPF program_type socket_filter is available
  eBPF program_type kprobe is available
  eBPF program_type sched_cls is available
  eBPF program_type sched_act is available
  eBPF program_type tracepoint is available
  eBPF program_type xdp is available
  eBPF program_type perf_event is available
  eBPF program_type cgroup_skb is available
  eBPF program_type cgroup_sock is available
  eBPF program_type lwt_in is available
  eBPF program_type lwt_out is available
  eBPF program_type lwt_xmit is available
  eBPF program_type sock_ops is available
  eBPF program_type sk_skb is available
  eBPF program_type cgroup_device is available
  eBPF program_type sk_msg is available
  eBPF program_type raw_tracepoint is available
  eBPF program_type cgroup_sock_addr is available
  eBPF program_type lwt_seg6local is available
  eBPF program_type lirc_mode2 is NOT available
  eBPF program_type sk_reuseport is available
  eBPF program_type flow_dissector is available
  eBPF program_type cgroup_sysctl is available
  eBPF program_type raw_tracepoint_writable is available
  eBPF program_type cgroup_sockopt is available
  eBPF program_type tracing is available
  eBPF program_type struct_ops is available
  eBPF program_type ext is available
  eBPF program_type lsm is available
 
  cilium基本用了所有的hook点。
 
  安全和其他
  lsm,用于安全,其他还有flow_dissector, lwt_in都是一些不怎么常用的,不再赘述。
 
  eBPF的最佳实践是什么?
  寻找内核的插桩点
  从前面可以看出来eBPF程序本身并不困难,困难的是为其寻找合适的事件源来触发运行。对于监控和诊断领域来说,跟踪类eBPF程序的事件源包含3类:内核函数(kprobe)、内核跟踪点(tracepoint)或性能事件(perf_event)。此时有2个问题需要回答:
 
  1.内核中都有哪些内核函数、内核跟踪点或性能事件?
 
  使用调试信息获取内核函数、内核跟踪点
  复制
  sudo ls /sys/kernel/debug/tracing/events
  1.
  使用bpftrace获取内核函数、内核跟踪点
  复制
 
  # 查询所有内核插桩和跟踪点
  sudo bpftrace -l
   复制
  sudo perf list tracepoint
  1.
  2.对于内核函数和内核跟踪点,在需要跟踪它们的传入参数和返回值的时候,又该如何查询这些数据结构的定义格式呢?
 
  使用调试信息获取
  复制
  sudo cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/format
  1.
  使用bpftrace获取
  具体如何使用以上信息,请参考bcc。
 
  寻找应用的插桩点
  1.如何查询用户进程的跟踪点?
 
  静态编译语言通过-g编译选项保留调试信息,应用程序二进制会包含DWARF(Debugging With Attributed Record Format),有了调试信息,可以通过  readelf、objdump、nm  等工具,查询可用于跟踪的函数、变量等符号列表
  复制
  # 查询符号表
  readelf -Ws /usr/lib/x86_64-linux-gnu/libc.so.6
 
  上面说的是静态编译语言,他和内核的跟踪类似,应用程序的符号信息可以存放在 ELF 二进制文件中,也可以以单独文件的形式,放到调试文件中;而内核的符号信息除了可以存放到内核二进制文件中之外,还会以  /proc/kallsyms  和  /sys/kernel/debug  等形式暴露到用户空间。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读