BPF 管理器 bpfman 简介

news2024/11/27 8:38:34

1. 背景

Fedora 40 提案建议将 bpfman 作为默认的程序管理器 ,开源项目 bpfman 可以实现对 eBPF 运行状态的深入了解,从而实现更轻松地管理 eBPF 程序(包括加载、卸载、运行状态查看等)。该提案还需要 Fedora 工程和指导委员会 (FESCo) 的批准,如果顺利很可能会在 4 月份出现在 Fedora 40 中以增强 eBPF 管理。

img
img

那么 bpfman 到底是一个什么样的项目呢?本文将带你简单了解 bpfman 及其工作原理。

2. bpfman 介绍

bpfman 早期名字为 bpfd,基于 Rust Aya 库开发,开发语言是 Rust。bpfman 项目用于简化 Kubernetes 集群或单主机上的 eBPF 程序的加载、卸载、修改和监控等。bpfman 项目由单机系统守护进程 bpfman、eBPF CRD、bpfman-agent 和 bpfman-operator 等构成,其中 CRD、bpfman-agent 和 bpfman-operator 都是围绕 Kubernetes 环境分布式部署的相关组件:

  • bpfman:单主机的系统守护进程,对外提供 gRPC API,可支持 eBPF 程序加载、卸载、修改和监控;
  • eBPF CRDS:提供两种类别的 CRD :部署 CRD 和 BPF 程序状态查看 CRD。部署相关 CRD (如 XdpProgram、TcProgram 等),用于加载不同类型的 eBPF 程序。程序状态查看类 CRD (BpfProgram),用于管理加载到内核的 eBPF 程序的运行状态;
  • bpfman-agent:运行在 bpfman 守护进程的容器中,用于确保选择节点 eBPF 程序处于声明的状态;
  • bpfman-operator:使用 Operator SDK 构建的 Operator,用于管理 Kubernetes 集群中 bpfman-agent 和 CRD 的安装和生命周期。

3. 单机部署流程

单机上部署 bpfman,其工作流程如下,其中 bpfman 二进制既可作为服务端部署也作为客户端程序使用。除了使用 bpfman 客户端程序外,用户也可以在用户空间的程序代码与 bpfman 服务端交互完各种管理操作:

image-20240130154830668
image-20240130154830668
  1. 当 go-xdp-counter 用户空间启动时,其通过 unix 套接字向 bpfman 发送 gRPC 请求,请求 bpfman 加载位于磁盘上的 go-xdp-counter eBPF 字节码(bpfman/examples/go-xdp-counter/bpf_bpfel.o), 优先级为 50,程序作用与 ens3 接口;
  2. bpfman 接收到请求后,将加载对应的 eBPF 程序(go-xdp-counter),并返回运行的程序的 UUID;
  3. 用户可以通过 bpfman list 可用于显示系统管理的 eBPF 程序;
  4. 完成 eBPF 字节码(go-xdp-counter)加载工作后,触发运行的 eBPF 程序就会将数据包计数和字节计数写入共享 map 结构;
  5. go-xdp-counter 对应的用户空间程序定期从共享 map 中读取计数器并记录该值。

加载的字节码也可以是远程镜像的,如 sudo ./go-xdp-counter -iface ens3 -image quay.io/bpfman-bytecode/go-xdp-counter:latest,字节码的镜像需要有一定规范。

4. Kubernetes 集群部署架构和流程

在 Kubernetes 集群分布式环境中部署和管理 eBPF 程序将更加复杂,bpfman 重点解决了以下挑战:

  • 管理 eBPF 启用应用所需的权限和能力;
  • 解决同一挂钩函数上多个 eBPF 程序的问题以及生命周期管理(特别是 xdp 模式下的多次挂载,内核默认不支持);
  • 简化 Kubernetes 中的部署和程序生命周期的复杂性;
  • 旨在安全性、可视性、多程序支持和生产力方面实现优化。

bpfman 在 Kubernetes 环境中管理 eBPF 程序可分为两个阶段:

  1. 运行在内核中的 eBPF 字节码程序管理;
  2. 与内核空间对应的 eBPF 用户空间程序的部署和数据读取,用户空间程序通常用于读取运行时数据或加载配置,需要单独部署用户空间程序(通过 CSI 方式挂载并读取数据)。

bpfman 在 Kubernetes 中部署和管理的流程图如下所示:

go-xdp-counter On Kubernetes
go-xdp-counter On Kubernetes
  1. 编写 CR 资源类型 XdpProgram ,定义部署机器标签、 eBPF 字节码相关的参数(例如接口、优先级和 BPF 字节码镜像等 )。本例中的 XdpProgram 资源名称是 go-xdp-counter-example。然后可使用 kbueclt apply -f bytecode.yaml 提交到集群生效。完整的 yaml 文件如下所示:

    # cat examples/config/base/go-xdp-counter/bytecode.yaml
    apiVersion: bpfman.io/v1alpha1
    kind: XdpProgram
    metadata:
      labels:
        app.kubernetes.io/name: xdpprogram
      name: go-xdp-counter-example
    spec:
      name: xdp_stats
      # Select all nodes
      nodeselector: {}
      interfaceselector:
        primarynodeinterface: true
      priority: 55
      bytecode:
        image:
          url: quay.io/bpfman-bytecode/go-xdp-counter:latest
  2. bpfman-agent 运行在预期的节点上,监听对应的 CR 资源对象 XdpProgram。bpfman-agent 确保创建或修改的 XdpProgram 对象会生成一个对应 BpfProgram 对象。 BpfProgram 对象的名称是 XdpProgram 附加节点名称/接口/连接点信息的组合。

    $ kubectl get xdpprogram
    NAME                     PRIORITY   DIRECTION
    go-xdp-counter-example   55

    $
     kubectl get xdpprograms go-xdp-counter-example -o yaml
    apiVersion: bpfman.io/v1alpha1
    kind: XdpProgram
    ...
    status:
      conditions:
      - lastTransitionTime: "2023-11-06T21:05:21Z"
        message: bpfProgramReconciliation Succeeded on all nodes
        reason: ReconcileSuccess
        status: "True"
        type: ReconcileSuccess

    在上述对象 XdpProgram 的 staus 字段中,我们可以看到已经将程序成功分发到了目标节点。

  3. bpfman-agent 通过 gRPC 调用 bpfman 来根据需要加载或卸载 eBPF 字节码程序。 bpfman 行为与单机运行示例中描述的相同。

  4. 最后,由 bpfman-agent 更新 BpfProgram 对象的状态。

    $ kubectl get bpfprograms
    NAME                                                                                  AGE
    go-xdp-counter-example-bpfman-deployment-control-plane-eth0                           60m

    $
     kubectl get go-xdp-counter-example-bpfman-deployment-control-plane-eth0 -o yaml
    apiVersion: bpfman.io/v1alpha1
    kind: BpfProgram
    ....
    spec:
      type: xdp
    status:
      conditions:
      - lastTransitionTime: "2023-11-06T21:05:21Z"
        message: Successfully loaded bpfProgram
        reason: bpfmanLoaded
        status: "True"
        type: Loaded
  5. bpfman-operator 监视所有 BpfProgram 对象,并更新 XdpProgram 对象的状态,用户展示 eBPF 程序是否已应用于所对应的节点。

但是细心的读者有可能已经注意到,上述流程只是完成了 eBPF 字节码在内核中的加载(bpfman 充当了 eBPF 加载器),但是运行时暴露的数据和指标还未完成采集,因此还需要单独部署一个用户空间程序完成数据读取(上述图中为 map 数据结构)。

这里,我们需要单独部署了一个用户空间程序来消费 eBPF 计数器程序生成的 map 数据。bpfman 提供容器存储接口 (CSI) 驱动程序,用于将 eBPF map 暴露到用户空间容器中。为了避免必须将包含 map 固定文件的主机目录装载到容器中并强制容器具有访问该主机目录的权限,CSI 驱动程序将 map 装载到容器中的指定位置。

#cat config/base/go-xdp-counter/deployment.yaml
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: go-xdp-counter-ds
  namespace: go-xdp-counter
  labels:
    k8s-app: go-xdp-counter
spec:
  :
  template:
    :
    spec:
       :
      containers:
      - name: go-xdp-counter
        :
        volumeMounts:
        - name: go-xdp-counter-maps                        <==== 2) VolumeMount in container
          mountPath: /run/xdp/maps                         <==== 2a) Mount path in the container
          readOnly: true
      volumes:
      - name: go-xdp-counter-maps                          <==== 1) Volume describing the map
        csi:
          driver: csi.bpfman.io                             <==== 1a) bpfman CSI Driver
          volumeAttributes:
            csi.bpfman.io/program: go-xdp-counter-example   <==== 1b) eBPF Program owning the map
            csi.bpfman.io/maps: xdp_stats_map               <==== 1c) Map to be exposed to the container

至此,我们介绍了在 Kubernetes 环境中使用 bpfman 部署 xdp 类型程序的完整流程,相对于单机部署,分布式环境中的管理更加复杂。

5. 总结

这里我们针对 bpfman 进行了简单介绍,更多的细节请参考 https://bpfman.io/。从我个人的使用和测试流程来看,以下几点个人体会:

  • bpfman 采用 Rust 开发,在云原生领域中略有些小众;

  • 在 K8s 环境中 eBPF 加载和数据读取单独分离,通过 CSI 接口挂载,这里无论是从部署安装还是使用层面都有些不太流畅,未来可能会有更优的解法。

  • 项目基于 libxdp 库实现了单接口多次 XDP 程序加载和 Daemonless 化的部署也算一个特色功能。

无论如何,bpfman 还是为单机或 Kubernetes 分布式环境管理分发 eBPF 程序提供了一个完整的架构实现,值得学习。

附录:bpfman 单机验证

在 Fedora 发行版中可直接通过 rmp 包安装。在 Ubuntu 系统中需要通过源码方式安装。

开发环境搭建

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  stable-x86_64-unknown-linux-gnu installed - rustc 1.75.0 (82e1608df 2023-12-21)

.....
Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, run:
source "$HOME/.cargo/env"

$
  source "$HOME/.cargo/env"

$
 rustup toolchain install nightly -c rustfmt,clippy,rust-src
...
info: installing component 'rustfmt'

  nightly-x86_64-unknown-linux-gnu installed - rustc 1.77.0-nightly (5518eaa94 2024-01-29)

info: checking for self-update

下载代码和编译 bpfman

$ git clone https://github.com/bpfman/bpfman.git && cd bpfman
$ cargo xtask build-ebpf --libbpf-dir=/home/dave/test/libbpf-bootstrap-1/libbpf

#
 构建 bpfman,编译成功后位于 ./target/debug/bpfman 
$ cargo build

$
 file ./target/debug/bpfman
./target/debug/bpfman: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e3028a97943b1dafcadbd7c9e9c99d9fb49aa5fe, for GNU/Linux 3.2.0, with debug_info, not stripped


$
 ./target/debug/bpfman --help
An eBPF manager focusing on simplifying the deployment and administration of eBPF programs.

Usage: bpfman <COMMAND>

Commands:
  load    Load an eBPF program from a local .o file
  unload  Unload an eBPF program using the program id
  list    List all eBPF programs loaded via bpfman
  get     Get an eBPF program using the program id
  image   eBPF Bytecode Image related commands
  system  Run bpfman as a service
  help    Print this message or the help of the given subcommand(s)

Options:
  -h, --help
          Print help (see a summary with '-h')
  
#
 单机进程运行  
$ RUST_LOG=info ./target/debug/bpfman system service --timeout 0

#
 或者安装为系统服务
$ sudo ./scripts/setup.sh install
Copy CLI TAB Completion files:
  CLI TAB Completion files not generated yet. Use "cargo xtask build-completion" to generate.
Copy Manpage files:
  CLI Manpage files not generated yet. Use "cargo xtask build-man-page" to generate.
Copy binaries:
  Copying "../target/debug/bpfman" to "/usr/sbin"
Copy service files:
  Copying "bpfman.socket"
  Copying "bpfman.service"
  Starting "bpfman.socket"
Created symlink /etc/systemd/system/sockets.target.wants/bpfman.socket → /lib/systemd/system/bpfman.socket.


$
 sudo  systemctl start bpfman
$ sudo systemctl status bpfman
● bpfman.service - Run bpfman as a service
     Loaded: loaded (/lib/systemd/system/bpfman.service; static)
     Active: active (running) since Tue 2024-01-30 16:10:28 CST; 2s ago
TriggeredBy: ● bpfman.socket
   Main PID: 1563623 (bpfman)
      Tasks: 23 (limit: 18814)
     Memory: 25.4M
        CPU: 237ms
     CGroup: /system.slice/bpfman.service
             └─1563623 /usr/sbin/bpfman system service

1 月 30 16:10:28 dave systemd[1]: Started Run bpfman as a service.
1 月 30 16:10:28 dave bpfman[1563623]: Log using journald
1 月 30 16:10:28 dave bpfman[1563623]: Has CAP_BPF: true
1 月 30 16:10:28 dave bpfman[1563623]: Has CAP_SYS_ADMIN: true
....

编译和加载 eBPF 程序

$ sudo apt-get install libbpf-dev
$ sudo go install github.com/cilium/ebpf/cmd/bpf2go@master

$
 cd bpfman/examples/
$ make generate
$ make build

测试程序管理功能

# cd bpfman/examples/go-xdp-counter
# ./go-xdp-counter -iface lo
2024/01/31 19:28:25 Using Input: Interface=lo Priority=50 Source=/home/dave/bpfman/examples/go-xdp-counter/bpf_bpfel.o
2024/01/31 19:28:30 Program registered with id 1872
2024/01/31 19:28:33 153212 packets received
2024/01/31 19:28:33 9993784 bytes received
...

除了运行用户空间程序外,也可以使用 bpfman load 的方式加载(支持从镜像加载)。

我们可以在 bpfman 进程运行日志中查看到加载的日志:

# RUST_LOG=info ./target/debug/bpfman system service --timeout 0
[INFO  bpfman::cli::system] Log using env_logger
[INFO  bpfman::cli::system] Has CAP_BPF: true
[INFO  bpfman::cli::system] Has CAP_SYS_ADMIN: true
[INFO  bpfman::serve] Using no inactivity timer
[INFO  bpfman::serve] Using default Unix socket
[INFO  bpfman::serve] Listening on /run/bpfman/sock/bpfman.sock
[INFO  bpfman::oci_utils::cosign] Starting Cosign Verifier, downloading data from Sigstore TUF repository

....
[INFO  bpfman::command] Loading program bytecode from file: /home/dave/bpfman/examples/go-xdp-counter/bpf_bpfel.o
[INFO  bpfman::oci_utils::cosign] The bytecode image: quay.io/bpfman/xdp-dispatcher:v2 is signed
[INFO  bpfman::bpf] Added xdp program with name: xdp_stats and id: 1872

可以使用 bpfman list 查看加载的程序:

# bpfman list
 Program ID  Name       Type  Load Time
 1872        xdp_stats  xdp   2024-01-31T19:28:30+0800

如果需要卸载则直接运行 bpfman unload 1872

或通过 bpfman get pid 查看具体的执行详情:

# bpfman get 1872
 Bpfman State
 Name:          xdp_stats
 Path:          /home/dave/bpfman/examples/go-xdp-counter/bpf_bpfel.o
 Global:        None
 Metadata:      None
 Map Pin Path:  /run/bpfman/fs/maps/1872
 Map Owner ID:  None
 Maps Used By:  1872
 Priority:      50
 Iface:         lo
 Position:      0
 Proceed On:    pass, dispatcher_return

 Kernel State
 ID:                               1872
 Name:                             xdp_stats
 Type:                             xdp
 Loaded At:                        2024-01-31T19:28:30+0800
 Tag:                              4d23a1d7f3618653
 GPL Compatible:                   true
 Map IDs:                          [468]
 BTF ID:                           598
 Size Translated (bytes):          168
 JITted:                           true
 Size JITted:                      104
 Kernel Allocated Memory (bytes):  4096
 Verified Instruction Count:       21

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1425890.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.31学习总结

1.31 1.线段树 2.Bad Hair Day S&#xff08;单调栈&#xff09; 3.01迷宫(BFS连通块问题剪枝)&#xff08;连通性问题的并查集解法&#xff09; 4.健康的荷斯坦奶牛 Healthy Holsteins&#xff08;DFS&#xff09; 线段树与树状数组 线段树和树状数组的功能相似&#xff0c;但…

社交买量:归因统计的核心要素与工具

在当今的社交App推广领域&#xff0c;广告买量已成为企业获取用户的重要手段。然而&#xff0c;如何准确衡量这些买量活动的成效&#xff0c;即用户从广告访问到安装后行为的完整转化路径&#xff0c;一直是运营人员关注的焦点。归因统计是一种评估营销效果的关键技术方案&…

制造业实施QMS质量管理系统的作用是什么?

QMS质量管理系统是一个关键的组织管理工具&#xff0c;用于确保产品和服务的质量符合预期标准&#xff1b;通过有效地实施万界星空科技QMS&#xff0c;组织可以确保产品和服务的质量符合预期标准&#xff0c;提升客户满意度&#xff0c;增强市场竞争力。 一、QMS系统的特点&…

找出最可疑的嫌疑人 - 华为机试真题题解

考试平台&#xff1a; 时习知 分值&#xff1a; 100分&#xff08;第一题&#xff09; 考试时间&#xff1a; 2024-01-31 &#xff08;两小时&#xff09; 题目描述 民警侦办某商场店面盗窃案时&#xff0c;通过人脸识别针对嫌疑人进行编号1-100000。 现在民警在监控记录中发…

Prometheus---图形化界面grafana(二进制)

前言 Prometheus是一个开源的监控以及报警系统。整合zabbix的功能&#xff0c;系统&#xff0c;网络&#xff0c;设备。 proetheus可以兼容网络&#xff0c;设备。容器的监控。告警系统。因为他和k8s是一个项目基金开发的产品&#xff0c;天生匹配k8s的原生系统。容器化和云原…

运动编辑学习笔记

目录 跳舞重建&#xff1a; 深度运动重定向 Motion Preprocessing Tool anim_utils MotionBuilder 跳舞重建&#xff1a; https://github.com/Shimingyi/MotioNet 深度运动重定向 https://github.com/DeepMotionEditing/deep-motion-editin 游锋生/deep-motion-editin…

Three.js学习1:threejs简介及文档本地部署

开一个天坑&#xff0c;Three.js 我觉得未来3D页面一定是一个趋势。 -----------------------------华丽的分割线------------------------- github&#xff1a;https://github.com/mrdoob/three.js/ 官网&#xff1a;Three.js – JavaScript 3D Library Threejs官网中文文…

自学Java的第十八天

一&#xff0c;每日收获 1.数组拷贝 2.数组反转 3.数组添加/扩容 二&#xff0c;新名词与小技巧 三&#xff0c;今天学习中所遇到的困难 一&#xff0c;每日收获 1.数组拷贝 编写代码 实现数组拷贝 将 int[] arr1 {10,20,30}; 拷贝到 arr2 数组 , 要求数据空间是独…

LVGL部件4

一.列表部件 1.知识概览 2.函数接口 1.lv_list_add_btn lv_list_add_btn 是 LittlevGL&#xff08;LVGL&#xff09;图形库中的一个函数&#xff0c;用于向列表&#xff08;list&#xff09;对象中添加一个按钮&#xff08;button&#xff09;。 函数原型为&#xff1a;lv_ob…

DRV8301 踩坑记,Status1 D10 老是 Fault

波形如上&#xff1a; 看第一个时钟出来的数据&#xff08;Status1 读完自动清除&#xff1f;&#xff09;&#xff0c;因此数据是&#xff1a;0x20 输入结构体解析&#xff1a; 可以看到&#xff0c;FETHA_OC了也就是A桥上管过流了&#xff1b; 检查一下硬件看看&#xff1…

【git】git update-index --assume-unchanged(不改动.gitignore实现忽略文件)

文章目录 原因分析&#xff1a;添加忽略文件(取消跟踪)的命令&#xff1a;取消忽略文件(恢复跟踪)的命令&#xff1a;查看已经添加了忽略文件(取消跟踪)的命令&#xff1a; 原因分析&#xff1a; 已经维护的项目&#xff0c;文件已经被追踪&#xff0c;gitignore文件不方便修…

天梯算法Day1整理

Nanami and Arithmetic Sequence 题面 思路 炸鱼题 只有n1的时候&#xff0c;只有一个等差数列&#xff1b; 其余时候&#xff0c;都是都有无数个等差数列。 代码 #include <iostream> using namespace std;int main() {int t, n;cin >> t;while (t--) {cin…

如何使用淘宝客?

1.定义&#xff1a;是一种按成交计费的推广工具&#xff0c;由淘宝客帮助商家推广商品&#xff0c;买家通过推广链接进入完成交易后&#xff0c;商家按照设置佣金支付给淘宝客费用。 2.优势&#xff1a; &#xff08;1&#xff09;展示、点击全免费。 &#xff08;2&#xf…

防御保护---防火墙双机热备直路部署(上下三层接口)

防御保护---防火墙双机热备直路部署&#xff08;上下三层接口&#xff09; 一、根据网段划分配置IP地址和安全区域二、配置动态路由OSPF三、配置双机热备四、测试&#xff1a;4.1 测试一&#xff1a;查看状态和路由器路由表&#xff08;双机热备&#xff09;前后对比4.2 测试二…

Ant-design-vue(v4.1.1) 创建并初始化前端项目

前提&#xff1a; 先安装 node.js (安装node.js后&#xff0c;在安装目录下的node-modles下会有一个 npm) 直接官网下载&#xff0c;直接点击安装&#xff0c;不勾选tools&#xff0c;选非c盘&#xff08;之后会用npm来下载东西&#xff09; 验证安装是否成功 cmd : node -v …

【Vue3 + Vite】Vite搭建 项目解构 Vue快速学习 第一期

文章目录 Vue3介绍Vue3通过Vite实现工程化&#xff1a;一、Vite创建Vue3工程化项目1.1 ViteVue3项目的创建、启动、停止1.2 ViteVue3项目的目录结构 二、ViteVue3 项目组件(SFC入门)2.1 什么是VUE的组件 ?2.2 什么是.vue文件 ?2.3 工程化vue项目如何组织这些组件? 三、ViteV…

易优CMS采集插件使用教程

本易优CMS采集教程说明如何使用易优CMS采集插件&#xff0c;批量获取互联网上的文章数据&#xff0c;并自动更新到易优cms&#xff08;eyoucms&#xff09;网站&#xff0c;快速丰富网站的内容。 目录 1. 下载并安装易优CMS采集插件 2. 对接网页文章采集工具 3. 采集数据发…

12nm工艺,2.5GHz频率,低功耗Cortex-A72处理器培训

“ 12nm工艺&#xff0c;2.5GHz频率&#xff0c;低功耗Cortex-A72处理器培训” 本项目是真实项目实战培训&#xff0c;低功耗UPF设计&#xff0c;后端参数如下&#xff1a; 工艺&#xff1a;12nm 频率&#xff1a;2.5GHz 资源&#xff1a;2000_0000 instances 为了满足更多…

Git系列---标签管理

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1.理解标签2.创建标签…

Python之数据可视化(地图)

目录 一 基础地图应用 二 全国疫情图 一 数据准备 二 数据处理 二 湖北省疫情图 一 数据准备 二 数据处理 一 基础地图应用 导入map地图对象 from pyecharts.charts import Map map Map() 写入数据 data [("北京市",100),("上海市"…