AI+云原生,把衛(wèi)星遙感虐的死去活來
AI牛啊,云原生牛啊,所以1+1>2?

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