在Docker容器技術(shù)即將統(tǒng)治世界的趨勢(shì)下,作為地理遙感領(lǐng)域的AI處理解譯平臺(tái),華為云GeoGenius空天地平臺(tái),早已開始全面的云原生方向轉(zhuǎn)型。本文總結(jié)大規(guī)模遙感影像處理在云原生平臺(tái)的落地經(jīng)驗(yàn),期間各種性能并發(fā)等場(chǎng)景優(yōu)化經(jīng)驗(yàn)有不少借鑒意義,與各遙感同行分享。
本文作者:唐盛軍,華為云城市智能體架構(gòu)師,擁有多年開發(fā)經(jīng)驗(yàn),先后從事:網(wǎng)絡(luò)協(xié)議識(shí)別&解析、業(yè)務(wù)控制網(wǎng)關(guān)等網(wǎng)絡(luò)協(xié)議相關(guān)工作;13年開始轉(zhuǎn)戰(zhàn)云計(jì)算,熟悉OpenStack,CloudFoundry,Docker,Kubernetes實(shí)現(xiàn)原理,精通常見的物理&云網(wǎng)絡(luò)技術(shù)。目前負(fù)責(zé)容器業(yè)務(wù)產(chǎn)品化,如:遙感,基因,大數(shù)據(jù),AI等
AI牛啊,云原生牛啊,所以1+1>2?
遙感影像,作為地球自拍照,能夠從更廣闊的視角,為人們提供更多維度的輔助信息,來(lái)幫助人類感知自然資源、農(nóng)林水利、交通災(zāi)害等多領(lǐng)域信息。
AI技術(shù),可以在很多領(lǐng)域超過人類,關(guān)鍵是它是自動(dòng)的,省時(shí)又省力。可顯著提升遙感影像解譯的工作效率,對(duì)各類地物元素進(jìn)行自動(dòng)化的檢測(cè),例如建筑物,河道,道路,農(nóng)作物等。能為智慧城市發(fā)展&治理提供決策依據(jù)。
云原生技術(shù),近年來(lái)可謂是一片火熱。易構(gòu)建,可重復(fù),無(wú)依賴等優(yōu)勢(shì),無(wú)論從哪個(gè)角度看都與AI算法天生一對(duì)。所以大家也可以看到,各領(lǐng)域的AI場(chǎng)景,大都是將AI推理算法運(yùn)行在Docker容器里面的。AI+云原生這么6,那么強(qiáng)強(qiáng)聯(lián)手后,地物分類、目標(biāo)提取、變化檢測(cè)等高性能AI解譯不就手到擒來(lái)?我們也是這么認(rèn)為的,所以基于AI+Kubernetes云原生,構(gòu)建了支持遙感影像AI處理的空天地平臺(tái)。詳見:https://www.huaweicloud.com/product/geogenius.html
不過理想是好的,過程卻跟西天取經(jīng)一般,九九八十一難,最終修成正果。
業(yè)務(wù)場(chǎng)景介紹
遇到問題的業(yè)務(wù)場(chǎng)景叫影像融合(Pansharpen),也就是對(duì)地球自拍照進(jìn)行“多鏡頭合作美顏”功能。(可以理解成:手機(jī)的多個(gè)攝像頭,同時(shí)拍照,合并成一張高清彩色大圖)。
所以業(yè)務(wù)簡(jiǎn)單總結(jié)就是:讀取2張圖片,生成1張新的圖片。該功能我們放在一個(gè)容器里面執(zhí)行,每張融合后的結(jié)果圖片大約5GB。
問題的關(guān)鍵是,一個(gè)批次業(yè)務(wù)量需要處理的是3000多張衛(wèi)星影像,所以每批任務(wù)只需要同時(shí)運(yùn)行完成3000多個(gè)容器就OK啦。云原生YYDS!
業(yè)務(wù)架構(gòu)圖示
為了幫助理解,這里分解使用云原生架構(gòu)實(shí)現(xiàn)該業(yè)務(wù)場(chǎng)景的邏輯圖如下:
圖片
在云上,原始數(shù)據(jù),以及結(jié)果數(shù)據(jù),一定是要存放在對(duì)象存儲(chǔ)桶里面的。因?yàn)檫@個(gè)數(shù)據(jù)量,只有對(duì)象存儲(chǔ)的價(jià)格是合適的。(對(duì)象存儲(chǔ),1毛錢/GB。文件存儲(chǔ)則需要3毛錢/GB)
因?yàn)槿萜髦g是互相獨(dú)立無(wú)影響的,每個(gè)容器只需要處理自己的那幅影像就行。例如1號(hào)容器處理 1.tif影像;2號(hào)容器處理2.tif影像;依次類推。
所以管理程序,只需要投遞對(duì)應(yīng)數(shù)量的容器(3000+),并監(jiān)控每個(gè)容器是否成功執(zhí)行完畢就行(此處為簡(jiǎn)化說(shuō)明,實(shí)際業(yè)務(wù)場(chǎng)景是一個(gè)pipeline處理流程)。那么,需求已經(jīng)按照云原生理想的狀態(tài)分解,咱們開始起(tang)飛(keng)吧~
注:以下描述的問題,是經(jīng)過梳理后呈現(xiàn)的,實(shí)際問題出現(xiàn)時(shí)是互相穿插錯(cuò)綜復(fù)雜的。
K8s死掉了
當(dāng)作業(yè)投遞后,不多久系統(tǒng)就顯示作業(yè)紛紛失敗。查看日志報(bào)調(diào)用K8s接口失敗,再一看,K8s的Master都已經(jīng)掛了。。。
K8s-Master處理過程,總結(jié)版:
發(fā)現(xiàn)Master掛是因?yàn)镃PU爆了
所以擴(kuò)容Master節(jié)點(diǎn)(此處重復(fù)N次);
性能優(yōu)化:擴(kuò)容集群節(jié)點(diǎn)數(shù)量;
性能優(yōu)化:容器分批投放;
性能優(yōu)化:查詢?nèi)萜鲌?zhí)行進(jìn)度,少用ListPod接口;
詳細(xì)版:
看監(jiān)控Master節(jié)點(diǎn)的CPU已經(jīng)爆掉了,所以最簡(jiǎn)單粗暴的想法就是給Master擴(kuò)容呀,嘎嘎的擴(kuò)。于是從4U8G * 3 一路擴(kuò)容一路測(cè)試一路失敗,擴(kuò)到了32U64G * 3。可以發(fā)現(xiàn)CPU還是爆滿??磥?lái)簡(jiǎn)單的擴(kuò)容是行不通了。
3000多個(gè)容器,投給K8s后,大量的容器都處于Pending狀態(tài)(集群整體資源不夠,所以容器都在排隊(duì)呢)。而正在Pending的Pod,K8s的Scheduler會(huì)不停的輪訓(xùn),去判斷能否有資源可以給它安排上。所以這也會(huì)給Scheduler巨大的CPU壓力。擴(kuò)容集群節(jié)點(diǎn)數(shù)量,可以減少排隊(duì)的Pod數(shù)量。
另外,既然排隊(duì)的太多,不如就把容器分批投遞給K8s吧。于是開始分批次投遞任務(wù),想著別一次把K8s壓垮了。每次投遞數(shù)量,減少到1千,然后到500,再到100。
同時(shí),查詢Pod進(jìn)度的時(shí)候,避免使用ListPod接口,改為直接查詢具體的Pod信息。因?yàn)長(zhǎng)ist接口,在K8s內(nèi)部的處理會(huì)列出所有Pod信息,處理壓力也很大。
這一套組合拳下來(lái),Master節(jié)點(diǎn)終于不掛了。不過,一頭問題按下去了,另一頭問題就冒出來(lái)了。
容器跑一半,掛了
雖然Master不掛了,但是當(dāng)投遞1~2批次作業(yè)后,容器又紛紛失敗。
容器掛掉的處理過程,總結(jié)版:
發(fā)現(xiàn)容器掛掉是被eviction驅(qū)逐了;
Eviction驅(qū)逐,發(fā)現(xiàn)原因是節(jié)點(diǎn)報(bào)Disk Pressure(存儲(chǔ)容量滿了);
于是擴(kuò)容節(jié)點(diǎn)存儲(chǔ)容量;
延長(zhǎng)驅(qū)逐容器(主動(dòng)kill容器)前的容忍時(shí)間;
詳細(xì)版:
(注:以下問題是定位梳理后,按順序呈現(xiàn)給大家。但其實(shí)出問題的時(shí)候,順序沒有這么友好)
容器執(zhí)行失敗,首先想到的是先看看容器里面腳本執(zhí)行的日志唄:結(jié)果報(bào)日志找不到~
于是查詢Pod信息,從event事件中發(fā)現(xiàn)有些容器是被Eviction驅(qū)逐干掉了。同時(shí)也可以看到,驅(qū)逐的原因是 DiskPressure(即節(jié)點(diǎn)的存儲(chǔ)滿了)。
當(dāng)Disk Pressure發(fā)生后,節(jié)點(diǎn)被打上了驅(qū)逐標(biāo)簽,隨后啟動(dòng)主動(dòng)驅(qū)逐容器的邏輯:
由于節(jié)點(diǎn)進(jìn)入Eviction驅(qū)逐狀態(tài),節(jié)點(diǎn)上面的容器,如果在5分鐘后,還沒有運(yùn)行完,就被Kubelet主動(dòng)殺死了。(因?yàn)镵8s想通過干掉容器來(lái)騰出更多資源,從而盡快退出Eviction狀態(tài))。
這里我們假設(shè)每個(gè)容器的正常運(yùn)行時(shí)間為1~2個(gè)小時(shí),那么不應(yīng)該一發(fā)生驅(qū)動(dòng)就馬上殺死容器(因?yàn)橐呀?jīng)執(zhí)行到一半的容器,殺掉重新執(zhí)行是有成本浪費(fèi)的)。我們期望應(yīng)該盡量等待所有容器都運(yùn)行結(jié)束才動(dòng)手。所以這個(gè) pod-eviction-timeout 容忍時(shí)間,應(yīng)該設(shè)置為24小時(shí)(大于每個(gè)容器的平均執(zhí)行時(shí)間)。
Disk Pressure的直接原因就是本地盤容量不夠了。所以得進(jìn)行節(jié)點(diǎn)存儲(chǔ)擴(kuò)容,有2個(gè)選擇:1)使用云存儲(chǔ)EVS(給節(jié)點(diǎn)掛載云存儲(chǔ))。2)擴(kuò)容本地盤(節(jié)點(diǎn)自帶本地存儲(chǔ)的VM)。
由于云存儲(chǔ)(EVS)的帶寬實(shí)在太低了,350MB/s。一個(gè)節(jié)點(diǎn)咱們能同時(shí)跑30多個(gè)容器,帶寬完全滿足不了。最終選擇使用 i3類型的VM。這種VM自帶本地存儲(chǔ)。并且將8塊NVMe盤,組成Raid0,帶寬還能x8。
對(duì)象存儲(chǔ)寫入失敗
容器執(zhí)行繼續(xù)紛紛失敗。
容器往對(duì)象存儲(chǔ)寫入失敗處理過程,總結(jié)版:
不直接寫入,而是先寫到本地,然后cp過去。
將普通對(duì)象桶,改為支持文件語(yǔ)義的并行文件桶。
詳細(xì)版:
查看日志發(fā)現(xiàn),腳本在生成新的影像時(shí),往存儲(chǔ)中寫入時(shí)出錯(cuò):
我們整集群是500核的規(guī)模,同時(shí)運(yùn)行的容器數(shù)量大概在250個(gè)(每個(gè)2u2g)。這么多的容器同時(shí)往1個(gè)對(duì)象存儲(chǔ)桶里面并發(fā)追加寫入。這個(gè)應(yīng)該是導(dǎo)致該IO問題的原因。
對(duì)象存儲(chǔ)協(xié)議s3fs,本身并不適合大文件的追加寫入。因?yàn)樗鼘?duì)文件的操作都是整體的,即使你往一個(gè)文件追加寫入1字節(jié),也會(huì)導(dǎo)致整個(gè)文件重新寫一遍。
最終這里改為:先往本地生成目標(biāo)影像文件,然后腳本的最后,再拷貝到對(duì)象存儲(chǔ)上。相當(dāng)于增加一個(gè)臨時(shí)存儲(chǔ)中轉(zhuǎn)一下。
在臨時(shí)中轉(zhuǎn)存儲(chǔ)選擇中,2種本地存儲(chǔ)都試過:1)塊存儲(chǔ)帶寬太低,350MB/s影響整體作業(yè)速度。2)可以選擇帶本地存儲(chǔ)的VM,多塊本地存儲(chǔ)組成Raid陣列,帶寬速度都杠杠滴。
同時(shí),華為云在對(duì)象存儲(chǔ)協(xié)議上也有一個(gè)擴(kuò)展,使其支持追加寫入這種的POSIX語(yǔ)義,稱為并行文件桶。后續(xù)將普通的對(duì)象桶,都改為了文件語(yǔ)義桶。以此來(lái)支撐大規(guī)模的并發(fā)追加寫入文件的操作。
K8s計(jì)算節(jié)點(diǎn)掛了
So,繼續(xù)跑任務(wù)。但是這容器作業(yè),執(zhí)行又紛紛失敗鳥~
計(jì)算節(jié)點(diǎn)掛掉,定位梳理后,總結(jié)版:
計(jì)算節(jié)點(diǎn)掛掉,是因?yàn)楹镁脹]上報(bào)K8s心跳了。
沒上報(bào)心跳,是因?yàn)閗ubelet(K8s節(jié)點(diǎn)的agent)過得不太好(死掉了)。
是因?yàn)镵ubelet的資源被容器搶光了(由于不想容器經(jīng)常oom kill,并未設(shè)置limit限制)
為了保護(hù)kubelet,所有容器全都設(shè)置好limit。
詳細(xì)版,直接從各類奇葩亂象等問題入手:
1) 容器啟動(dòng)失敗,報(bào)超時(shí)錯(cuò)誤。
2) 然后,什么PVC共享存儲(chǔ)掛載失?。?img src="https://file.tuyuangis.com/uploads/20211115/10f8f4812e25320779f8b34d407c418f.jpg" />
3) 或者,又有些容器無(wú)法正常結(jié)束(刪不掉)。
4) 查詢節(jié)點(diǎn)Kubelet日志,可以看到充滿了各種超時(shí)錯(cuò)誤:
圖片
啊,這么多的底層容器超時(shí),一開始感覺的Docker的Daemon進(jìn)程掛了,通過重啟Docker服務(wù)來(lái)試圖修復(fù)問題。
后面繼續(xù)定位發(fā)現(xiàn),K8s集群顯示,好多計(jì)算節(jié)點(diǎn)Unavailable了(節(jié)點(diǎn)都死掉啦)。
圖片
繼續(xù)分析節(jié)點(diǎn)不可用(Unavailable),可以發(fā)現(xiàn)是Kubelet好久沒有給Master上報(bào)心跳了,所以Master認(rèn)為節(jié)點(diǎn)掛了。說(shuō)明不僅僅是Docker的Daemon受影響,節(jié)點(diǎn)的Kubelet也有受影響。
那什么情況會(huì)導(dǎo)致Kubelet,Docker這些主機(jī)進(jìn)程都不正常呢?這個(gè)就要提到Kubernetes在調(diào)度容器時(shí),所設(shè)計(jì)的Request和Limit這2個(gè)概念了。
Request是K8s用來(lái)調(diào)度容器到空閑計(jì)算節(jié)點(diǎn)上的。而Limit則會(huì)傳遞給Docker用于限制容器資源上限(觸發(fā)上限容易被oom killer 殺掉)。前期我們?yōu)榱朔乐棺鳂I(yè)被殺死,僅為容器設(shè)置了Request,沒有設(shè)置Limit。也就是每個(gè)容器實(shí)際可以超出請(qǐng)求的資源量,去搶占額外的主機(jī)資源。大量容器并發(fā)時(shí),主機(jī)資源會(huì)受影響。
考慮到雖然不殺死作業(yè),對(duì)用戶挺友好,但是平臺(tái)自己受不了也不是個(gè)事。于是給所有的容器都加上了Limit限制,防止容器超限使用資源,強(qiáng)制用戶進(jìn)程運(yùn)行在容器Limit資源之內(nèi),超過就Kill它。以此來(lái)確保主機(jī)進(jìn)程(如Docker,Kubelet等),一定是有足夠的運(yùn)行資源的。
K8s計(jì)算節(jié)點(diǎn),又掛了
于是,繼續(xù)跑任務(wù)。不少作業(yè)執(zhí)行又雙叒失敗鳥~
節(jié)點(diǎn)又掛了,總結(jié)版:
分析日志,這次掛是因?yàn)镻LEG(Pod Lifecycle Event Generator)失敗。
PLEG異常是因?yàn)楣?jié)點(diǎn)上面存留的歷史容器太多(>500個(gè)),查詢用時(shí)太久超時(shí)了。
及時(shí)清理已經(jīng)運(yùn)行結(jié)束的容器(即使跑完的容器,還是會(huì)占用節(jié)點(diǎn)存儲(chǔ)資源)。
容器接口各種超時(shí)(cpu+memory是有l(wèi)imit保護(hù),但是io還是會(huì)被搶占)。
提升系統(tǒng)磁盤的io性能,防止Docker容器接口(如list等)超時(shí)。
詳細(xì)版:
現(xiàn)象還是節(jié)點(diǎn)Unavailable了,查看Kubelet日志搜索心跳情況,發(fā)現(xiàn)有PLEG is not healthy 的錯(cuò)誤:
于是搜索PLEG相關(guān)的Kubelet日志,發(fā)現(xiàn)該錯(cuò)誤還挺多:
圖片
這個(gè)錯(cuò)誤,是因?yàn)閗ubelet去list當(dāng)前節(jié)點(diǎn)所有容器(包括已經(jīng)運(yùn)行結(jié)束的容器)時(shí),超時(shí)了。
看了代碼:
https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/pleg/generic.go#L203
kubelet判斷超時(shí)的時(shí)間,3分鐘的長(zhǎng)度是寫死的。所以當(dāng)pod數(shù)量越多,這個(gè)超時(shí)概率越大。很多場(chǎng)景案例表明,節(jié)點(diǎn)上的累計(jì)容器數(shù)量到達(dá)500以上,容易出現(xiàn)PLEG問題。(此處也說(shuō)明K8s可以更加Flexible一點(diǎn),超時(shí)時(shí)長(zhǎng)應(yīng)該動(dòng)態(tài)調(diào)整)。
緩解措施就是及時(shí)的清理已經(jīng)運(yùn)行完畢的容器。但是運(yùn)行結(jié)束的容器一旦清理,容器記錄以及容器日志也會(huì)被清理,所以需要有相應(yīng)的功能來(lái)彌補(bǔ)這些問題(比如日志采集系統(tǒng)等)。
List所有容器接口,除了容器數(shù)量多,IO慢的話,也會(huì)導(dǎo)致超時(shí)。
這時(shí),從后臺(tái)可以看到,在投遞作業(yè)期間,大量并發(fā)容器同時(shí)運(yùn)行時(shí),云硬盤的寫入帶寬被大量占用:
對(duì)存儲(chǔ)池的沖擊也很大:
這也導(dǎo)致了IO性能變很差,也會(huì)一定程度影響list容器接口超時(shí),從而導(dǎo)致PLEG錯(cuò)誤。
該問題的解決措施:盡量使用的帶本地高速盤的VM,并且將多塊數(shù)據(jù)盤組成Raid陣列,提高讀寫帶寬。
這樣,該VM作為K8s的節(jié)點(diǎn),節(jié)點(diǎn)上的容器都直接讀寫本地盤,io性能較好。(跟大數(shù)據(jù)集群的節(jié)點(diǎn)用法一樣了,強(qiáng)依賴本地shuffle~)。
在這多條措施實(shí)施后,后續(xù)多批次的作業(yè)都可以平穩(wěn)的運(yùn)行完。
總結(jié):“AI+云原生”這條路
云原生是趨勢(shì),已經(jīng)成為大家的共識(shí),各領(lǐng)域也都開始以云原生為底座的業(yè)務(wù)嘗試。AI是未來(lái),這也是當(dāng)前不可阻擋的力量。但是當(dāng)AI踏上這條云原生的道路卻不那么一帆風(fēng)順。至少可以看到,華為云的云原生底座(當(dāng)然,也包括存儲(chǔ)、網(wǎng)絡(luò)等周邊基礎(chǔ)設(shè)施)還可以有更多的進(jìn)步空間。
但是,大家也不用擔(dān)心太多,因?yàn)楫?dāng)前華為云的空天地平臺(tái),在經(jīng)歷了多年的AI+云原生的積累,目前可以很穩(wěn)定的處理PB級(jí)每日的遙感影像數(shù)據(jù),支撐各類空基、天基、地基等場(chǎng)景,并且在該領(lǐng)域保持絕對(duì)領(lǐng)先的戰(zhàn)斗值。雖然大家看到此間過程有點(diǎn)曲折,但是所有的困難都是涅槃的火種,克服過的困難都是今后可以對(duì)客戶做的承諾。在這里可以很明確的告訴各位:AI+云原生=真香。
寫這篇文章的目的,不是在闡述困難,而是為了總結(jié)分享。與同領(lǐng)域的人分享并促進(jìn)遙感領(lǐng)域的快速發(fā)展,共同推動(dòng)AI+云原生的落地。
來(lái)源:https://blog.csdn.net/qq_43173805/article/details/121064717成都途遠(yuǎn)GIS是一家專業(yè)致力于無(wú)人機(jī)航空攝影測(cè)繪、航空數(shù)據(jù)處理、GIS地理信息系統(tǒng)研發(fā)、數(shù)字孿生城市制作、數(shù)字沙盤模型等業(yè)務(wù)的創(chuàng)新型科技公司,為您提供一站式地理信息服務(wù)。
本文鏈接:http://www.dzac.com.cn/industry/445.html
本文標(biāo)簽:遙感