当前位置: 首页 > news >正文

如何实现一个K8S DevicePlugin?

什么是device plugin

k8s允许限制容器对资源的使用,比如CPU内存,并以此作为调度的依据。

当其他非官方支持的设备类型需要参与到k8s的工作流程中时,就需要实现一个device plugin

Kubernetes提供了一个设备插件框架,你可以用它来将系统硬件资源发布到Kubelet

供应商可以实现设备插件,由你手动部署或作为 DaemonSet 来部署,而不必定制 Kubernetes 本身的代码。

目标设备包括 GPU、高性能 NIC、FPGA、 InfiniBand 适配器以及其他类似的、可能需要特定于供应商的初始化和设置的计算资源。

更多云原生、K8S相关文章请点击【专栏】查看!

发现插件

一个新的device plugin是如何被kubelet发现的?

device plugin通过gRPC的方式与kubelet通信,kubelet实现了Register接口,用于注册插件。

service Registration {rpc Register(RegisterRequest) returns (Empty) {}
}

通过这个接口, 向kubelet提交当前插件的信息,包括插件的名称、版本、socket路径等。

已注册的插件信息并不会被持久化下来, 也就是说当kubelet重启后,插件需要重新调用Register方法。

kuelet重启时会删除插件的socket文件, 插件通过监听socket文件的方式来感知kubelet的重启并重新注册。

成功注册后,设备插件就向 kubelet 发送它所管理的设备列表,然后 kubelet 负责将这些资源发布到 API 服务器,作为 kubelet 节点状态更新的一部分。

当插件注册成功后, 根据插件中的配置与定义, 可能会有类似下面的pod配置以使用插件中的资源。

apiVersion: v1
kind: Pod
metadata:name: demo-pod
spec:containers:- name: demo-container-1image: registry.k8s.io/pause:2.0resources:limits:hardware-vendor.example/foo: 2
#
# 这个 pod 需要两个 hardware-vendor.example/foo 设备
# 而且只能够调度到满足需求的节点上
#
# 如果该节点中有 2 个以上的设备可用,其余的可供其他 Pod 使用

在这里插入图片描述

AMD GPU插件源码解析

插件的实现并不复杂, 只需要实现几个接口函数即可。

service DevicePlugin {// GetDevicePluginOptions 返回与设备管理器沟通的选项。// kuelet 在每次方法调用前都会调用这个方法,来获取可用的设备插件选项。rpc GetDevicePluginOptions(Empty) returns (DevicePluginOptions) {}// ListAndWatch 返回 Device 列表构成的数据流。// 当 Device 状态发生变化或者 Device 消失时,ListAndWatch会返回新的列表。rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}// Allocate 在容器创建期间调用,这样设备插件可以运行一些特定于设备的操作,// 并告诉 kubelet 如何令 Device 可在容器中访问的所需执行的具体步骤rpc Allocate(AllocateRequest) returns (AllocateResponse) {}// GetPreferredAllocation 从一组可用的设备中返回一些优选的设备用来分配,// 所返回的优选分配结果不一定会是设备管理器的最终分配方案。// 此接口的设计仅是为了让设备管理器能够在可能的情况下做出更有意义的决定。rpc GetPreferredAllocation(PreferredAllocationRequest) returns (PreferredAllocationResponse) {}// PreStartContainer 在设备插件注册阶段根据需要被调用,调用发生在容器启动之前。// 在将设备提供给容器使用之前,设备插件可以运行一些诸如重置设备之类的特定于具体设备的操作,rpc PreStartContainer(PreStartContainerRequest) returns (PreStartContainerResponse) {}
}

以下源码解析以AMD GPU插件为例。

代码版本 0.12.0

仓库地址 https://github.com/ROCm/k8s-device-plugin

源码解析

插件启动流程

AMD GPU插件的框架,是使用的"github.com/kubevirt/device-plugin-manager/pkg/dpm"这个包。

AMD的插件确实实现的很粗糙, 这里我们只用它分析实现一个插件需要做什么。

程序启动时实例化Manager对象, 并调用Run方法。

func main() {// ...// Lister用于传递心跳与资源更新l := Lister{ResUpdateChan: make(chan dpm.PluginNameList),Heartbeat:     make(chan bool),}manager := dpm.NewManager(&l)// ...// 启动管理器manager.Run()
}

Run方法中启动了gRPC服务, 并注册了AMD GPU插件。

func (dpm *Manager) Run() {// ...// 监听socket文件变化(kubelet会在重启时删除)fsWatcher, _ := fsnotify.NewWatcher()defer fsWatcher.Close()// DevicePluginPath = "/var/lib/kubelet/device-plugins/"fsWatcher.Add(pluginapi.DevicePluginPath)// 启动插件监听方法, // 实际是将上面传入Liste.ResUpdateChan的数据转发到这个chan中pluginsCh := make(chan PluginNameList)defer close(pluginsCh)go dpm.lister.Discover(pluginsCh)
HandleSignals:for {select {case newPluginsList := <-pluginsCh:// 创建新的插件服务, 并启动服务dpm.handleNewPlugins(pluginMap, newPluginsList)case event := <-fsWatcher.Events:if event.Name == pluginapi.KubeletSocket {// kubelet重启时, 重新注册插件if event.Op&fsnotify.Create == fsnotify.Create {dpm.startPluginServers(pluginMap)}if event.Op&fsnotify.Remove == fsnotify.Remove {dpm.stopPluginServers(pluginMap)}}case s := <-signalCh:switch s {case syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT:// 优雅退出dpm.stopPlugins(pluginMap)break HandleSignals}}}
}

创建插件服务会返回一个devicePlugin对象:

// dpm.handleNewPlugins(pluginMap, newPluginsList) 最终会调用这个方法
func newDevicePlugin(resourceNamespace string, pluginName string, devicePluginImpl PluginInterface) devicePlugin {return devicePlugin{DevicePluginImpl: devicePluginImpl,// DevicePluginPath = "/var/lib/kubelet/device-plugins/"// resourceNamespace = "amd.com"Socket:           pluginapi.DevicePluginPath + resourceNamespace + "_" + pluginName,ResourceName:     resourceNamespace + "/" + pluginName,Name:             pluginName,Starting:         &sync.Mutex{},}
}
type devicePlugin struct {// 实现的deviceplugin serverDevicePluginImpl PluginInterfaceResourceName     stringName             string// socket文件路径Socket           stringServer           *grpc.ServerRunning          boolStarting         *sync.Mutex
}

启动服务最终会由StartServer这个方法来完成。

func (dpi *devicePlugin) StartServer() error {// ...if dpi.Running {return nil}// 启动grpc服务err := dpi.serve()if err != nil {return err}// 调用Register方法向kubelet注册插件err = dpi.register()if err != nil {dpi.StopServer()return err}dpi.Running = truereturn nil
}
func (dpi *devicePlugin) serve() error {// ...// 可以看见是以socket文件启动的grpc服务sock, err := net.Listen("unix", dpi.Socket)if err != nil {glog.Errorf("%s: Failed to setup a DPI gRPC server: %s", dpi.Name, err)return err}dpi.Server = grpc.NewServer([]grpc.ServerOption{}...)pluginapi.RegisterDevicePluginServer(dpi.Server, dpi.DevicePluginImpl)go dpi.Server.Serve(sock)// ...return nil
}
func (dpi *devicePlugin) register() error {// KubeletSocket = DevicePluginPath + "kubelet.sock"// "/var/lib/kubelet/device-plugins/kubelet.sock"// 与kubelet通信conn, err := grpc.Dial(pluginapi.KubeletSocket, grpc.WithInsecure(),grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {return net.DialTimeout("unix", addr, timeout)}))defer conn.Close()client := pluginapi.NewRegistrationClient(conn)// 向kubelet注册插件reqt := &pluginapi.RegisterRequest{Version:      pluginapi.Version,Endpoint:     path.Base(dpi.Socket),ResourceName: dpi.ResourceName,Options:      options,}_, err = client.Register(context.Background(), reqt)// ...return nil
}

socket文件默认会放在/var/lib/kubelet/device-plugins目录下, 所以当以daemonset的方式部署插件时,需要将这个目录挂载到容器中。

服务实现

AMD GPU插件只实现了两个关键方法(因为不同设备插件的实现都不一样,所以这里不展开):

  • ListAndWatch
  • Allocate

所以它的GetDevicePluginOptions方法返回的是一个空结构体

func (p *Plugin) GetDevicePluginOptions(ctx context.Context, e *pluginapi.Empty) (*pluginapi.DevicePluginOptions, error) {return &pluginapi.DevicePluginOptions{}, nil
}
type DevicePluginOptions struct {// 是否需要调用 PreStartContainer 方法PreStartRequired bool `protobuf:"varint,1,opt,name=pre_start_required,json=preStartRequired,proto3" json:"pre_start_required,omitempty"`// 是否需要调用 GetPreferredAllocation 方法GetPreferredAllocationAvailable bool     `protobuf:"varint,2,opt,name=get_preferred_allocation_available,json=getPreferredAllocationAvailable,proto3" json:"get_preferred_allocation_available,omitempty"`
}

服务部署

设备插件可以作为节点操作系统的软件包来部署、作为 DaemonSet 来部署或者手动部署。

如果你将设备插件部署为 DaemonSet, /var/lib/kubelet/device-plugins 目录必须要在插件的 PodSpec 中声明作为 卷(Volume)被挂载到插件中。

实现一个设备插件

  1. 实现一个虚假设备, 用于测试插件。(可选)
  2. 实现DevicePlugin接口。 我们可以仅实现ListAndWatchAllocate两个关键方法。
  3. 注册gRPC服务, 并向kubelet注册插件。
  4. 监听kubelet的socket文件变化, 重新注册插件。

代码实现

待补充…

相关文章:

如何实现一个K8S DevicePlugin?

什么是device plugin k8s允许限制容器对资源的使用&#xff0c;比如CPU和内存&#xff0c;并以此作为调度的依据。 当其他非官方支持的设备类型需要参与到k8s的工作流程中时&#xff0c;就需要实现一个device plugin。 Kubernetes提供了一个设备插件框架&#xff0c;你可以用…...

Android LruCache源码分析

文章目录 Android LruCache源码分析概述LruCache和LinkedHashMap关系源码分析属性写入数据读取数据删除缓存 Android LruCache源码分析 概述 LruCache&#xff08;Least Recently Used Cache&#xff0c;最近最少使用缓存&#xff09;是 Android 中的一种缓存机制。 根据数据…...

如何使用Inno Setup制作Unity构建程序的Windows安装程序

1. 准备 &#xff08;1&#xff09;准备好Unity构建的程序集合 必须包括&#xff1a; Data文件夹&#xff08;xxx_Data&#xff09; Mono文件夹&#xff08;MonoBleedingEdge&#xff09; 打包的应用程序文件&#xff08;xxx.exe&#xff09; Unity播放器dll文件&#xff…...

linux 面试题

1.linux操作系统的常用指令可以详细说下吗,平常哪些用的比较多 文件目录操作命令: ls cd more cat tail mkdir touch rm rmdir 拷贝复制: cp mv 打包解包压缩解压: tar -z 解亚压缩 -c 打包 -x 解包 -v 显示过程 -f 指定文件名 文本编辑: vi vim 查找: find 查找文件 gre…...

嵌入式中逻辑分析仪基本操作方法

前期准备 1.一块能触摸的屏对应的主板机 2.逻辑分析仪对应的软件工具 3.对应的拓展板 4.确定拓展板的引脚分布情况 第一步&#xff1a;逻辑分析仪j基本操作 1.数据捕捉需要先进行对应软件安装,并按照需求进行配置 2.这里以A20为例:此手机使用显示驱动芯片CST148,触摸屏分辨…...

ONLYOFFICE 桌面编辑器 v8.0 更新内容详细攻略

文章目录 引言PDF 表单RTL 支持电子表格中的新增功能Moodle 集成用密码保护 PDF 文件从“开始”菜单快速创建文档本地界面主题下载安装桌面编辑工具总结 引言 官网链接&#xff1a; ONLYOFFICE 官方网址 ONLYOFFICE 桌面编辑器是一款免费的文档处理软件&#xff0c;适用于 Li…...

2024-2-22 作业

作业要求&#xff1a; 复习前面知识点(指针、结构体、函数)整理思维导图顺序表(按位置插入、按位置删除和去重、重新写)理解链表的代码&#xff0c;尝试写一下链表的尾插和输出 1.复习前面知识点(指针、结构体、函数) 2.整理思维导图 3.顺序表(按位置插入、按位置删除和去重、…...

2.1 RK3399项目开发实录-升级固件介绍(物联技术666)

1. 介绍 1.1. 前言 AIO-3399J 出厂默认安装Android操作系统&#xff0c;如果用户要运行其他操作系统&#xff0c;需要使用对应的固件烧写到主板。 AIO-3399J 有灵活的启动方式。一般情况下&#xff0c;除非硬件损坏&#xff0c;AIO-3399J 开发板是不会变砖的。 如果在升级过…...

Uniapp + VUE3.0 实现双向滑块视频裁剪效果

效果图 <template><view v-if"info" class"all"><video:src"info.videoUrl"class"video" id"video" :controls"true" object-fit"fill" :show-fullscreen-btn"false"play-btn…...

【算法小讲堂】#1 贪心算法

引入——关于贪心算法 我们先来做一个小游戏——现在假设自己是一个小偷&#xff0c;桌上有一些物品&#xff0c;包括一台iPhone15、一个充电宝、一个眼罩和一个溜溜梅。此时&#xff0c;你听说警察即将到来&#xff0c;那么你会先带走哪个东西呢&#xff1f; 一般来讲&#xf…...

判断当前shell版本

查看$SHELL环境变量&#xff1a; echo $SHELL输出的结果将是当前使用的shell的路径。例如&#xff0c;如果输出为 /bin/bash&#xff0c;则表示当前使用的是Bash shell。 查看ps命令输出&#xff1a; ps -p $$上述命令将显示当前终端进程的信息&#xff0c;其中 $$ 代表当前进…...

如何实现两个电脑之间通过以太网(网线)实现文件互传

如何实现两个电脑之间通过以太网&#xff08;网线&#xff09;实现文件互传 本帖目的&#xff1a;介绍如何通过以太网&#xff08;网线&#xff09;连接两台电脑&#xff0c;通过文件夹共享的方式&#xff0c;实现两台电脑之间的文件互传。 本帖以笔者实际工作上遇到的场景为例…...

Jenkins 中部署Nodejs插件并使用,并构建前端项目(3)

遇到多个版本nodeJS需要构建的时候 1、第一种就是一个配置安装&#xff0c;然后进行选中配置 2、第二种就是插件&#xff1a;nvm-wrapper&#xff0c;我们还是选用NodeJS插件&#xff1a; &#xff08;1&#xff09;可以加载任意npmrc文件&#xff1b; &#xff08;2&#x…...

VUE为什么有的属性要加冒号

<el-menu-item :index "/item.menuClick" v-for"(item,i) in menu"><i class"item.menuIcon" ></i><span slot"title">{{item.menuName}}</span></el-menu-item>不加不行 加了好像是吧整体作为…...

微信小程序 --- wx.request网络请求封装

网络请求封装 网络请求模块难度较大&#xff0c;如果学习起来感觉吃力&#xff0c;可以直接学习 [请求封装-使用 npm 包发送请求] 以后的模块 01. 为什么要封装 wx.request 小程序大多数 API 都是异步 API&#xff0c;如 wx.request()&#xff0c;wx.login() 等。这类 API 接口…...

通义千问Qwen-7B-Chat Windows本地部署教程-详细认真版

通义千问本地部署教程&#x1f680; 本专栏的第四弹&#xff0c;在实现了联网调用通义千问模型进行多轮对话&#xff0c;流式输出&#xff0c;以及结合LangChain实现自建知识库之后&#xff0c;开始准备考虑实现对大模型进行本地部署&#xff0c;网上找不到看着比较舒服的教程&…...

探索C语言位段的秘密

位段 1. 什么是位段2. 位段的内存分配3. 位段的跨平台问题4. 位段的应用4. 使用位段的注意事项 1. 什么是位段 我们使用结构体实现位段&#xff0c;位段的声明和结构体是类似的&#xff0c;有两个不同&#xff1a; 位段的成员必须是int&#xff0c;unsigned int&#xff0c;或…...

数据库-数据库设计-社交关系

佛 每有一个新方案&#xff0c;就要考虑有什么影响增删改查可扩展性 MySQL 根据ER图设计表 create table follow(id bigint unsigned not null auto_increment comment 主键,gmt_create datetime null default current_timestamp,gmt_modified null default current_timest…...

YOLO算法改进Backbone系列之:EfficientViT

EfficientViT: Memory Effificient Vision Transformer with Cascaded Group Attention 摘要&#xff1a;视觉transformer由于其高模型能力而取得了巨大的成功。然而&#xff0c;它们卓越的性能伴随着沉重的计算成本&#xff0c;这使得它们不适合实时应用。在这篇论文中&#x…...

JANGOW: 1.0.1

kali:192.168.223.128 主机发现 nmap -sP 192.168.223.0/24 端口扫描 nmap -p- 192.168.223.154 开启了21 80端口 web看一下&#xff0c;有个busque.php参数是buscar,但是不知道输入什么&#xff0c;尝试文件包含失败 扫描目录 dirsearch -u http://192.168.223.154 dirse…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...