k8s學(xué)習(xí)記錄(gpu信息采集)

首先,關(guān)于k8s的調(diào)度機(jī)制,可以看我上一篇文章:

k8s學(xué)習(xí)記錄(kube-scheduler)

而這一篇文章探討的內(nèi)容,就是關(guān)于k8s 調(diào)度器的不足之處的。我們知道,對(duì)于內(nèi)存memory,cpu的劃分,k8s已經(jīng)做得很不錯(cuò)了,但如果要追求更多,更細(xì)致的劃分,就需要自己動(dòng)手寫scheduler。

而scheduler調(diào)度是需要信息的。我們這一次準(zhǔn)備搞一個(gè)能顯示我們想要的信息的daemon,給自己寫的scheduler使用。

由于k8s的底層接口全部都是go編寫的,我們也必須用go來(lái)寫這個(gè)daemon,這就不得不學(xué)習(xí)一下需要的相關(guān)的依賴

在Go 1.11之后,Go 大力推動(dòng)Go Modules,關(guān)于這個(gè)的討論非常多,也非常激烈,在go項(xiàng)目中如何使用Go Modules也是需要了解的。

Cron

https://godoc.org/github.com/robfig/cron

import? "github.com/robfig/cron"

Cron是一個(gè)相當(dāng)優(yōu)秀的處理定時(shí)任務(wù)的工具,我們?nèi)绻f(shuō)要定時(shí)采集Pod的數(shù)據(jù),可少不了它。

c := cron.New()

c.AddFunc("30 * * * *", func() { fmt.Println("Every hour on the half hour") })

c.AddFunc("30 3-6,20-23 * * *", func() { fmt.Println(".. in the range 3-6am, 8-11pm") })

c.AddFunc("CRON_TZ=Asia/Tokyo 30 04 * * *", func() { fmt.Println("Runs at 04:30 Tokyo time every day") })

c.AddFunc("@hourly",? ? ? func() { fmt.Println("Every hour, starting an hour from now") })

c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty, starting an hour thirty from now") })

c.Start()

這里的符號(hào)特別有意思:

Field name | Mandatory? | Allowed values | Allowed special characters

----------? | ---------- | --------------? | --------------------------

Minutes? ? ? | Yes? ? ? ? | 0-59? ? ? ? ? ? | * / , -

Hours? ? ? ? | Yes? ? ? ? | 0-23? ? ? ? ? ? | * / , -

Day of month | Yes? ? ? ? | 1-31? ? ? ? ? ? | * / , - ?

Month? ? ? ? | Yes? ? ? ? | 1-12 or JAN-DEC | * / , -

Day of week? | Yes? ? ? ? | 0-6 or SUN-SAT? | * / , - ?

下面是官方的解釋:

Asterisk ( * )

The asterisk indicates that the cron expression will match for all values of the

field; e.g., using an asterisk in the 5th field (month) would indicate every

month.

Slash ( / )

Slashes are used to describe increments of ranges. For example 3-59/15 in the

1st field (minutes) would indicate the 3rd minute of the hour and every 15

minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...",

that is, an increment over the largest possible range of the field.? The form

"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the

increment until the end of that specific range.? It does not wrap around.

Comma ( , )

Commas are used to separate items of a list. For example, using "MON,WED,FRI" in

the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.

Hyphen ( - )

Hyphens are used to define ranges. For example, 9-17 would indicate every

hour between 9am and 5pm inclusive.

Question mark ( ? )

Question mark may be used instead of '*' for leaving either day-of-month or

day-of-week blank

也可以參考下文

http://www.itdecent.cn/p/fd3dda663953

https://www.cnblogs.com/jiangz222/p/12345566.html

Zap

https://github.com/uber-go/zap

import "go.uber.org/zap"

Zap是一個(gè)高性能日志庫(kù),擁有非常多優(yōu)秀的特性,參考

https://www.liwenzhou.com/posts/Go/zap/

Nvml

nvml是nvidia基于自家NVIDIA System Management Interface (nvidia-smi)的獲取顯卡信息的接口,支持go語(yǔ)言

具體參考

https://github.com/NVIDIA/gpu-monitoring-tools/blob/master/bindings/go/samples/nvml/deviceInfo/main.go

Client-go

client-go提供了容器內(nèi)應(yīng)用獲取pod信息的途徑。

https://github.com/kubernetes/client-go

例子

https://github.com/kubernetes/client-go/tree/master/examples/in-cluster-client-configuration



有了前面這些技術(shù)鋪墊,我們就可以著手開始寫我們自己的gpu scheduler了

具體代碼可以看這里:

https://github.com/hyc3z/Omaticaya

核心思想:

利用Cron創(chuàng)建一個(gè)輪詢?nèi)蝿?wù),每隔一段時(shí)間輪詢,更新緩存中的gpu信息,然后轉(zhuǎn)換成node tag標(biāo)注在node上。轉(zhuǎn)換/標(biāo)注這一塊速度很快,大約10ms就能完成。但輪詢因?yàn)閚vml的關(guān)系,少則100ms,多則500ms不等。實(shí)時(shí)性相對(duì)還較弱。


初步實(shí)現(xiàn):cron+nvml采集信息+zap實(shí)時(shí)日志+k8s client-go更新tag

后續(xù)計(jì)劃:Dcgm+prometheus+influxdb存儲(chǔ)信息,glusterfs持久化

初步實(shí)現(xiàn)最初的思想,這里還發(fā)現(xiàn)了一個(gè)坑:

vgo/Go modules

筆者這里也查閱了很多vgo相關(guān)的信息,發(fā)現(xiàn)go的包管理也是走了不少的彎路。今天,vgo是Russ Cox親手扶上寶座的Go包管理,但它真的好用嗎?

首先,第一個(gè)問(wèn)題,就是包名和源名必須相同。也就是,如果你的包是發(fā)布在github.com/username/packagename下的,你在本地的module名必須也得是github.com/username/xxx。這對(duì)于github的用戶還相對(duì)友好,對(duì)于gitlab、其他平臺(tái)的用戶,真的相當(dāng)?shù)疤邸?/p>

第二個(gè)問(wèn)題,包版本依賴。筆者在調(diào)用k8s.io/client-go時(shí),發(fā)現(xiàn)k8s接口對(duì)不上,原來(lái)在k8s上最新的tag是kubernetes-1.18.0 而go.mod居然只允許v開頭的版本號(hào)(v1.0.0等),輸入這種tag直接報(bào)錯(cuò)。真的蛋疼死了……后面直接cmd輸命令,找依賴,找關(guān)系,感覺(jué)本來(lái)應(yīng)該vgo干的事現(xiàn)在全讓程序員擦屁股。

第三個(gè)問(wèn)題,本地模組的導(dǎo)入。在vgo中,由于不支持GOPATH,導(dǎo)入本地模組也必須是使用項(xiàng)目托管上的絕對(duì)路徑。

筆者作為一個(gè)學(xué)習(xí)golang的新人,沒(méi)有用過(guò)Go dep/vendor,聽(tīng)說(shuō)是另一個(gè)社區(qū)版本的包管理,但vgo究竟怎樣,見(jiàn)仁見(jiàn)智吧。

Docker build

在運(yùn)行完go build . 之后,我們需要使用docker build -t <tagname> 進(jìn)行鏡像的制作,這里需要編寫Dockerfile文件

FROM nvidia/cuda:10.1-base

WORKDIR /

COPY Omaticaya /usr/local/bin

CMD ["Omaticaya"]

然后docker push 把鏡像上傳,供k8s使用。

目前這個(gè)版本已經(jīng)可以運(yùn)行,并采集gpu相關(guān)信息,但性能還有待優(yōu)化。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容