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

目前国内做情趣最好的网站b站引流推广

目前国内做情趣最好的网站,b站引流推广,天价域名排名100,如何做好品牌网站建设什么是device plugin k8s允许限制容器对资源的使用,比如CPU和内存,并以此作为调度的依据。 当其他非官方支持的设备类型需要参与到k8s的工作流程中时,就需要实现一个device plugin。 Kubernetes提供了一个设备插件框架,你可以用…

什么是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文件变化, 重新注册插件。

代码实现

待补充…

http://www.ds6.com.cn/news/12321.html

相关文章:

  • 北京最大的软件开发公司seo关键词排名优化软件怎么选
  • 哪个网站可以学做咸菜牡丹江网站seo
  • 高仿卡西欧手表网站百度入口
  • 成都网站制作报价百度收录量
  • pc网站转换wap网站淘宝怎么做引流和推广
  • 政府网站建设推进线上营销公司
  • 大型网站开发什么书籍好今日的头条新闻
  • 滁州做网站优化seo咨询岳阳
  • 东阳做网站的公司seo优化运营
  • 建一独立网站需多少钱seo公司系统
  • 建网站自己与租云服务器哪个好新闻发布平台有哪些
  • 工程项目编号查询系统怎么做好seo推广
  • 安徽住房与城乡建设门户网站营销公关
  • 虚拟主机可以做视频网站嘛seo快速优化软件
  • 山东电商运营公司排名徐州自动seo
  • 建网站合同为什么不建议去外包公司上班
  • 企业网站怎么建设自助建站工具
  • 17Z一起做网站广州站上海aso优化公司
  • 网管软件排名前十名seo推广代理
  • 怎么制作网站后台查看域名每日ip访问量
  • 下载app 的网站 如何做建站模板
  • 微信php网站开发流程图百度权重提升
  • 铁岭做网站一般多少钱真正永久免费的建站系统有哪些
  • 网络服务提供者不履行法律行政法规规定的信息网络安全上海seo优化公司
  • 云网站建设 优帮云中国楼市最新消息
  • 网站如何优化推广网页设计页面
  • 手机网站开发软件有哪些建立网站怎么搞
  • 网站建设公司上海做网站公司排名深圳百度推广排名优化
  • 开发公司如何编写意向书性能优化工具
  • 环球设计官网网站台湾搜索引擎