国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

深度學(xué)習(xí)批任務(wù)處理調(diào)度器與kubernetes默認(rèn)調(diào)度器融合

dcr309duan / 1505人閱讀

摘要:這樣就會(huì)有一個(gè)問題一個(gè)任務(wù)要起個(gè),每個(gè)需要一張卡,總共需要張卡,而集群中只有張空閑的卡,這樣默認(rèn)的調(diào)度器會(huì)如何處理因?yàn)槟J(rèn)調(diào)度器是一個(gè)一個(gè)調(diào)度的,只會(huì)檢查單個(gè)資源夠不夠,這樣前個(gè)都能成功,最后一個(gè)調(diào)度失敗。

kubernetes集群三步安裝
什么是批處理任務(wù)

深度學(xué)習(xí)中經(jīng)常會(huì)出現(xiàn)多機(jī)多卡的任務(wù),也就是同事會(huì)起多個(gè)pod,但是這多個(gè)pod屬于同一個(gè)任務(wù)。

這樣就會(huì)有一個(gè)問題

一個(gè)任務(wù)要起100個(gè)pod,每個(gè)pod需要一張卡,總共需要100張GPU卡,而集群中只有99張空閑的GPU卡,這樣默認(rèn)的k8s調(diào)度器會(huì)如何處理?

因?yàn)槟J(rèn)調(diào)度器是一個(gè)一個(gè)pod調(diào)度的,只會(huì)檢查單個(gè)pod資源夠不夠,這樣前99個(gè)都能成功,最后一個(gè)pod調(diào)度失敗。

這樣非常有可能造成

任務(wù)跑不了

前99個(gè)占著GPU不釋放,新的任務(wù)無法調(diào)度

嚴(yán)重時(shí)整個(gè)集群死鎖,都“占著茅坑不拉屎”

所以需要在調(diào)度時(shí)對(duì)整個(gè)task所需所有資源進(jìn)行檢查,當(dāng)集群總體資源不夠時(shí),一個(gè)pod都得不到調(diào)度。

社區(qū)提供了一個(gè)能支持這種特性的調(diào)度器
但是這個(gè)調(diào)度器是沒辦法和原生調(diào)度器很好的配合工作的

最大的問題在于兩個(gè)調(diào)度器都有cache,這樣cache的內(nèi)容會(huì)沖突,導(dǎo)致調(diào)度混亂

這個(gè)調(diào)度器沒法和原生調(diào)度器同時(shí)起作用,這樣用了這個(gè)batch調(diào)度器后就沒法用親和性什么的特性了

所以我們做的事是將兩者特性融合,選擇的方法是定制化開發(fā)kube-scheduler

其實(shí)scheduler是可以通過extender擴(kuò)展的,但是extender還是太弱了,它僅能在預(yù)選和優(yōu)選過程中加入自己的過濾策略,而這對(duì)于批處理任務(wù)遠(yuǎn)遠(yuǎn)不夠。

實(shí)現(xiàn)難點(diǎn)
需要優(yōu)選時(shí)加batch任務(wù)檢查
拿到一個(gè)pod ---> 如果是一個(gè)batchpod ---> 查詢集群資源是否滿足batch任務(wù)--->否調(diào)度失敗

需要保障batch任務(wù)中其它pod能得到調(diào)度

如果集群資源能滿足這個(gè)batch任務(wù)直接去bind有個(gè)問題:
假設(shè)調(diào)度隊(duì)列是這樣,假設(shè)集群中有三個(gè)GPU,而batch任務(wù)需要三個(gè)GPU:

A batch pod -> pod -> pod -> A batch pod -> A batch pod
集群資源夠 調(diào)度成功 調(diào)度了別的pod 調(diào)度了別的pod GPU被別的pod占用 GPU不夠 失敗 GPU不夠 失敗

所以最終結(jié)果是A批任務(wù)占用了一個(gè)GPU但是整個(gè)任務(wù)是調(diào)度失敗的,那一個(gè)GPU還得不到釋放

所以需要修改pod調(diào)度隊(duì)列里的順序?讓A batch pod連續(xù)調(diào)度? 沒這么簡(jiǎn)單,

pod調(diào)度是創(chuàng)建協(xié)程并發(fā)調(diào)度的,這樣即便去調(diào)整任務(wù)隊(duì)列里pod的順序也不一定能保證batch任務(wù)其它pod能得到優(yōu)先調(diào)度。

go wait.Until(sched.scheduleOne, 0, sched.config.StopEverything)
只要batch pod走到Bind邏輯了就沒有回頭路了

batch任務(wù)中所有pod先進(jìn)行assume調(diào)度,其中任意一個(gè)失敗就清理掉其它已經(jīng)bind但是還沒實(shí)際進(jìn)行調(diào)度的pod。 并把所有pod扔回隊(duì)列,或者直接返回調(diào)度失敗清理改任務(wù)的pod,讓上層重新觸發(fā)?

scheduler流程 scheduler/sheduler.go scheduleOne邏輯:

選節(jié)點(diǎn)->cache assume pod on node-> 創(chuàng)建協(xié)程bind

所以在assume時(shí)去檢查,不滿足退還已經(jīng)調(diào)度的pod是不可行的,因?yàn)橹癰atch任務(wù)中的pod可能已經(jīng)bind過了, 所以只能batch任務(wù)中最后一個(gè)pod得到確認(rèn)才能去bind前面的pod

預(yù)占用策略
預(yù)占用策略: 第一個(gè)batch pod任務(wù)來時(shí),檢查集群資源是不是夠,如果夠進(jìn)行預(yù)占,把其它幾個(gè)node打上標(biāo)記,讓接下來pod無法占用其它的node,這樣batch任務(wù)其實(shí)pod過來就有節(jié)點(diǎn)可用。

回到了不能bind的問題。。。

這種問題有兩點(diǎn):

如何知道batch任務(wù)中其它pod需要什么樣的節(jié)點(diǎn),如果pod都一樣問題可簡(jiǎn)化
如果后面的pod失敗了,第一個(gè)pod還是已經(jīng)bind,還是會(huì)出現(xiàn)一樣的問題
最終還是在所有pod assume之前不能bind單個(gè)pod

綜上,需要在幾個(gè)地方處理

隊(duì)列最好用優(yōu)先級(jí)隊(duì)列,把正在調(diào)度的pod的關(guān)聯(lián)pod優(yōu)先級(jí)提高
選節(jié)點(diǎn)時(shí)做判斷,看集群資源是否夠
選好節(jié)點(diǎn)assume pod時(shí)檢查,如果自己不夠或者pod組不夠就不去bind
問題是之前的pod已經(jīng)走了bind流程,所以最重要的是如何解決讓之前的pod不去bind,延遲bind

最終方案 - 延遲綁定

方案:在batch任務(wù)bind時(shí)進(jìn)行特殊處理

如果是batch任務(wù)扔進(jìn)task cache,不進(jìn)行binding

如果batch任務(wù)最后一個(gè)pod扔進(jìn)task cache,該task ready,放進(jìn)bind隊(duì)列

在bind隊(duì)列里取task 進(jìn)行bind,task互斥鎖與普通pod bind時(shí)互斥

使用
batch任務(wù)使用,pod增加兩個(gè)注解:
      annotations:
        scheduling.k8s.io/group-name: qj-1
        scheduling.k8s.io/group-pod-num: 3

pod加上這兩個(gè)注解表示屬于同一個(gè)task, num表示task里有多少pod。

本來是再定義一個(gè)CRD去描述這個(gè)task,耦合會(huì)小一些,但是實(shí)現(xiàn)麻煩些,需要多監(jiān)聽一個(gè)CRD,偷懶就沒這樣做

實(shí)現(xiàn)

延遲綁定流程:

如果是普通的pod,找到節(jié)點(diǎn)后assume就直接bind

如果是批處理任務(wù),直接扔到批處理緩存中返回

有個(gè)協(xié)程一直檢查批緩存中是否有成功的task (pod都齊了)

成功的task扔進(jìn)binding隊(duì)列,worker取成功的task進(jìn)行批量綁定,綁定時(shí)與普通pod互斥

batch scheduler接口與成員

Run 起一個(gè)協(xié)程檢查成功的task并塞入隊(duì)列
RunBind 起一個(gè)task綁定協(xié)程
PodQuePriority 去動(dòng)態(tài)修改pod隊(duì)列的優(yōu)先級(jí),讓同task的pod優(yōu)先調(diào)度

執(zhí)行流程:

延遲綁定

scheduler/scheduler.go:

    //fanux if it is a batch pod, return
    if sched.Config.BatchScheduler.IsBatchPod(assumedPod) {
        err = sched.Config.BatchScheduler.HandleBatchPod(assumedPod)
        if err != nil {
            glog.Errorf("schedule batch pod failed: %v", assumedPod.Namespace, assumedPod.Name)
        }
        return
    }

增加綁定互斥,防止batch任務(wù)和普通pod同事binding:

    go func() {
        //fanux add bind mutex
        sched.Config.BatchScheduler.Lock()
        defer sched.Config.BatchScheduler.UnLock()

        err := sched.bind(assumedPod, &v1.Binding{
檢查資源是否充足CheckResourceIsEnough

should"t use filterFunc, needs nodelist

scheduler/util/batch.go

package util

import "api/core/v1"

//CheckResourceIsEnough is
func CheckResourceIsEnough(pod *v1.Pod, nodes []*v1.Node) (bool, error) {
    return false, nil
}

scheduler/core/generic_scheduler.go

    //fanux add checkBatchPodResource
    flag, err := util.CheckResourceIsEnough(pod, filteredNodes)
    if !flag || err != nil {
        return "", err
    }

    trace.Step("Prioritizing")

處理資源不足時(shí)的情況

    suggestedHost, err := sched.schedule(pod)

    //fanux add handle if resource not enough
    if strings.Contains(err.Error(), common.BatchResourceNotEnough) {
        sched.Config.BatchScheduler.HandleResourceNotEnough(pod)
    } else if err != nil {
如何獲取節(jié)點(diǎn)已經(jīng)分配GPU的數(shù)量

nodeInfo allocatableResource - requestedResource is avaliavle resource

    requestedResource *Resource
    nonzeroRequest    *Resource
    allocatableResource *Resource

GPU 是 ScalarResources, 資源名稱叫 : NVIDIAGPUResourceName = "nvidia.com/gpu"

type Resource struct {
    MilliCPU         int64
    Memory           int64
    EphemeralStorage int64
    // We store allowedPodNumber (which is Node.Status.Allocatable.Pods().Value())
    // explicitly as int, to avoid conversions and improve performance.
    AllowedPodNumber int
    // ScalarResources
    ScalarResources map[v1.ResourceName]int64
}
增加podupdater,可更新podcondition狀態(tài)
    batchScheduler := batch.NewBatchScheduler(c.schedulerCache, c.podQueue, &binder{c.client}, &podConditionUpdater{c.client})
需要把batch scheduler的cache給generic_scheduler資源檢查時(shí)需要用

需要知道已經(jīng)有哪些pod已經(jīng)assume過了,把這個(gè)數(shù)量減掉才是batch任務(wù)還需要多少GPU

core/generic_scheduler.go

    //fanux add batch Cache
    //check batch pod resource is enough need batch scheduler cache
    BatchCache common.TaskCache
    //fanux add checkBatchPodResource
    flag, err := common.CheckResourceIsEnough(pod, filteredNodes, g.cachedNodeInfoMap, g.BatchCache)

factory.go

    //fanux check batch resource is enough need batch scheduler cache
    batchCache := batchScheduler.GetTaskCache()

    algo := core.NewGenericScheduler(
        ...
        batchCache,
    )

then checkresource :

    //shoud not use metadata, need use metadata - assumed pod num in batch cache
    _, podNum := GetPodBathMeta(pod)
    podNum -= batchCache.GetTaskAssumedPodNum(pod)
檢查資源是否充足詳細(xì)算法:

有很多細(xì)節(jié)

//獲取pod需要多少GPU,這個(gè)需要把pod里容器配額加起來
func GetPodGPUCount(pod *v1.Pod) (count int) {
    for _, c := range pod.Spec.Containers {
        limit, ok := c.Resources.Limits[NVIDIAGPUResourceName]
        l, okay := limit.AsInt64()
        if !ok || !okay {
            continue
        }
        count += int(l)
    }

    glog.Infof("Pod [%s] need GPU [%d]", pod.GetName(), count)

    return
}

//獲取節(jié)點(diǎn)空閑GPU,需要把可分配的減去已經(jīng)申請(qǐng)的
func GetNodeFreeGPU(nodeInfo *cache.NodeInfo) int {
    if nodeInfo == nil {
        return 0
    }

    allocatable, ok := nodeInfo.AllocatableResource().ScalarResources[NVIDIAGPUResourceName]
    if !ok {
        glog.Errorf("can"t fetch allocatable GPU : %v", nodeInfo)
        return 0
    }
    glog.Infof("node [%s] allocatable GPU [%d]", nodeInfo.Node().Name, allocatable)

    requested, ok := nodeInfo.RequestedResource().ScalarResources[NVIDIAGPUResourceName]
    if !ok {
        //glog.Errorf("can"t fetch requested GPU : %v", nodeInfo)
        //return 0
        requested = 0
    }
    glog.Infof("node [%s] requested GPU [%d]", nodeInfo.Node().Name, requested)

    available := allocatable - requested

    glog.Infof("available node [%s] GPU : [%d]", nodeInfo.Node().Name, available)

    return int(available)
}

//這里最關(guān)鍵的點(diǎn)是需要把a(bǔ)nnotations里面獲取的task pod總數(shù)減去已經(jīng)assume過的batch pod,這樣才是真實(shí)所需
func CheckResourceIsEnough(pod *v1.Pod, nodes []*v1.Node, cachedNodeInfoMap map[string]*cache.NodeInfo, batchCache TaskCache) (bool, error) {
    //if is not batch pod, return true,nil
    if !IsBatch(pod) {
        glog.Infof("pod %s is not batch pod", pod.GetName())
        return true, nil
    }

    //shoud not use metadata, need use metadata - ready pod num in batch cache
    _, podNum := GetPodBathMeta(pod)
    podNum -= batchCache.GetTaskAssumedPodNum(pod)

    everyPodNeedsGPU := GetPodGPUCount(pod)
    if everyPodNeedsGPU == 0 {
        glog.Infof("pod %s require 0 GPU", pod.GetName())
        return true, nil
    }

    // TODO maybe check nodes[1:], node[0] already allocate a pod, CPU and other metric may reach limit
    for _, node := range nodes {
        nodeInfo, ok := cachedNodeInfoMap[node.Name]
        if !ok {
            continue
        }
        nodeFree := GetNodeFreeGPU(nodeInfo)
        podNum -= nodeFree / everyPodNeedsGPU
        glog.Infof("pod: [%s] node: [%s] podNum [%d] nodeFree [%d] podNeed [%d]", pod.GetName(), node.Name, podNum, nodeFree, everyPodNeedsGPU)
        if podNum <= 0 {
            return true, nil
        }
    }

    return false, fmt.Errorf("BatchResourceNotEnough : pod name is %s", pod.GetName())
}

//判斷是不是batch pod
func IsBatch(pod *v1.Pod) bool {
    g, n := GetPodBathMeta(pod)
    if g == "" || n == 0 {
        glog.Infof("The pod"s group name is empty string,pod name is %v.", pod.GetName())
        return false
    }
    return true
}
關(guān)于GPU的使用與發(fā)現(xiàn)

資源包

這里包含docker nv-docker GPU-device plugin
install.sh...

/etc/docker/daemon.json

[root@compute-gpu006 ~]# cat /etc/docker/daemon.json
{
    "default-runtime":"nvidia",
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

kubectl describe node xxx:

Capacity:
 cpu:                72
 ephemeral-storage:  222779Mi
 hugepages-1Gi:      0
 hugepages-2Mi:      2Gi
 memory:             791014684Ki
 nvidia.com/gpu:     2                # 這里就能看到GPU了
 pods:               110
Allocatable:
 cpu:                72
 ephemeral-storage:  210240641086
 hugepages-1Gi:      0
 hugepages-2Mi:      2Gi
 memory:             788815132Ki
 nvidia.com/gpu:     2
 pods:               110
總結(jié)

原生調(diào)度器的設(shè)計(jì)就是pod one by one,所以做這個(gè)功能的開發(fā)還是改動(dòng)非常大的,也是比較困難的,工作量不大,但是需要找到一個(gè)優(yōu)雅的方案,
合理的架構(gòu)比較麻煩,想了很久做了這個(gè)侵入不太大的實(shí)現(xiàn)方案,歡迎大家一起討論

公眾號(hào):

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/32813.html

相關(guān)文章

  • 深度學(xué)習(xí)任務(wù)處理調(diào)度kubernetes默認(rèn)調(diào)度融合

    摘要:這樣就會(huì)有一個(gè)問題一個(gè)任務(wù)要起個(gè),每個(gè)需要一張卡,總共需要張卡,而集群中只有張空閑的卡,這樣默認(rèn)的調(diào)度器會(huì)如何處理因?yàn)槟J(rèn)調(diào)度器是一個(gè)一個(gè)調(diào)度的,只會(huì)檢查單個(gè)資源夠不夠,這樣前個(gè)都能成功,最后一個(gè)調(diào)度失敗。 kubernetes集群三步安裝 什么是批處理任務(wù) 深度學(xué)習(xí)中經(jīng)常會(huì)出現(xiàn)多機(jī)多卡的任務(wù),也就是同事會(huì)起多個(gè)pod,但是這多個(gè)pod屬于同一個(gè)任務(wù)。 這樣就會(huì)有一個(gè)問題 一個(gè)任務(wù)要起...

    xiao7cn 評(píng)論0 收藏0
  • 阿里巴巴為什么選擇Apache Flink?

    摘要:從長(zhǎng)遠(yuǎn)來看,阿里決定用做一個(gè)統(tǒng)一的通用的大數(shù)據(jù)引擎作為未來的選型。在阿里的現(xiàn)狀基于在阿里巴巴搭建的平臺(tái)于年正式上線,并從阿里巴巴的搜索和推薦這兩大場(chǎng)景開始實(shí)現(xiàn)。目前阿里巴巴所有的業(yè)務(wù),包括阿里巴巴所有子公司都采用了基于搭建的實(shí)時(shí)計(jì)算平臺(tái)。 本文主要整理自阿里巴巴計(jì)算平臺(tái)事業(yè)部資深技術(shù)專家莫問在云棲大會(huì)的演講。 合抱之木,生于毫末 隨著人工智能時(shí)代的降臨,數(shù)據(jù)量的爆發(fā),在典型的大數(shù)據(jù)的業(yè)...

    CoderBear 評(píng)論0 收藏0
  • 阿里云容服務(wù)新增支持Kubernetes編排系統(tǒng),性能重大提升

    摘要:年底首次開啟阿里云容器服務(wù)公測(cè)年月正式商業(yè)化年月成為國(guó)內(nèi)唯一合作伙伴并推出專有云企業(yè)版,月實(shí)現(xiàn)產(chǎn)品國(guó)際化。阿里云容器服務(wù)為增加了阿里云云盤和等分布式存儲(chǔ)服務(wù)支持。阿里云容器服務(wù)為此進(jìn)一步提升了易用性,降低了部署管理和應(yīng)用開發(fā)門檻。 摘要: 作為容器編排系統(tǒng)的兩大流派, Kubernetes和Swarm的重要性不言而喻。融合了兩大高性能集成的阿里云容器服務(wù),不僅可以降低50%的基礎(chǔ)架構(gòu)成...

    keelii 評(píng)論0 收藏0
  • PB 級(jí)數(shù)據(jù)處理挑戰(zhàn),Kubernetes如何助力基因分析?

    摘要:阿里云基因數(shù)據(jù)服務(wù)不斷提升極致彈性的計(jì)算能力,和大規(guī)模并行處理能力,以及海量高速存儲(chǔ)來幫助基因公司快速自動(dòng)化處理每天幾十上百的下機(jī)數(shù)據(jù),并產(chǎn)通過標(biāo)準(zhǔn)產(chǎn)出高質(zhì)量的變異數(shù)據(jù)。 摘要:?一家大型基因測(cè)序功能公司每日會(huì)產(chǎn)生 10TB 到 100TB 的下機(jī)數(shù)據(jù),大數(shù)據(jù)生信分析平臺(tái)需要達(dá)到 PB 級(jí)別的數(shù)據(jù)處理能力。這背后是生物科技和計(jì)算機(jī)科技的雙向支撐:測(cè)序應(yīng)用從科研逐步走向臨床應(yīng)用,計(jì)算模...

    forsigner 評(píng)論0 收藏0
  • 為什么 kubernetes 天然適合微服務(wù) (1)

    摘要:此文已由作者劉超授權(quán)網(wǎng)易云社區(qū)發(fā)布。所以當(dāng)我們?cè)u(píng)估大數(shù)據(jù)平臺(tái)牛不牛的時(shí)候,往往以單位時(shí)間內(nèi)跑的任務(wù)數(shù)目以及能夠處理的數(shù)據(jù)量來衡量。的問題調(diào)度在大數(shù)據(jù)領(lǐng)域是核心中的核心,在容器平臺(tái)中是重要的,但不是全部。 此文已由作者劉超授權(quán)網(wǎng)易云社區(qū)發(fā)布。 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營(yíng)經(jīng)驗(yàn) 最近總在思考,為什么在支撐容器平臺(tái)和微服務(wù)的競(jìng)爭(zhēng)中,Kubernetes 會(huì)取得最終的勝出,事實(shí)...

    EastWoodYang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<