新聞中心
linux 4.1內(nèi)核熱補(bǔ)丁成功實(shí)踐
作者:UCloud內(nèi)核團(tuán)隊(duì) 2019-01-16 10:33:41
云計(jì)算 我們詳細(xì)介紹了進(jìn)程cputime統(tǒng)計(jì)異常問題的完整分析和解決思路。該問題并非嚴(yán)重的宕機(jī)問題,但卻可能會(huì)讓用戶對(duì)監(jiān)控?cái)?shù)據(jù)產(chǎn)生困惑,誤認(rèn)為可能機(jī)器負(fù)載太高需要加資源,問題的解決會(huì)避免產(chǎn)生不必要的開支。

成都創(chuàng)新互聯(lián)IDC提供業(yè)務(wù):成都服務(wù)器托管,成都服務(wù)器租用,成都服務(wù)器托管,重慶服務(wù)器租用等四川省內(nèi)主機(jī)托管與主機(jī)租用業(yè)務(wù);數(shù)據(jù)中心含:雙線機(jī)房,BGP機(jī)房,電信機(jī)房,移動(dòng)機(jī)房,聯(lián)通機(jī)房。
最開始公司運(yùn)維同學(xué)反饋,個(gè)別宿主機(jī)上存在進(jìn)程CPU峰值使用率異常的現(xiàn)象。而數(shù)萬臺(tái)機(jī)器中只出現(xiàn)了幾例,也就是說萬分之幾的概率。監(jiān)控產(chǎn)生的些小誤差,不會(huì)造成宕機(jī)等嚴(yán)重后果,很容易就此被忽略了。
但我們考慮到這個(gè)異常轉(zhuǎn)瞬即逝、并不易被察覺,可能還存在更多這樣的機(jī)器,又或者現(xiàn)在正常將來又不正常,內(nèi)核研發(fā)本能的好奇心讓我們感到:此事必有蹊蹺!于是追查下去。
問題現(xiàn)象
現(xiàn)象一:CPU監(jiān)控非0即100%
該問題現(xiàn)象表現(xiàn)在Redis進(jìn)程CPU監(jiān)控的峰值時(shí)而100% 時(shí)而為0,有的甚至是幾十分鐘都為0,突發(fā)1秒100%后又變?yōu)?,如下圖。
而從大量機(jī)器的統(tǒng)計(jì)規(guī)律看,這個(gè)現(xiàn)象在2.6.32 內(nèi)核不存在,在4.1內(nèi)核存在幾例。2.6.32是我們較早期采用的版本,為平臺(tái)的穩(wěn)定發(fā)展做了有力支撐,4.1 可以滿足很多新技術(shù)需求,如新款CPU、新板卡、RDMA、NVMe和binlog2.0等。后臺(tái)無縫維護(hù)著兩個(gè)版本,并為了能力提升和優(yōu)化而逐步向4.1及更高版本過渡。
現(xiàn)象二:top顯示非0即300%
登錄到機(jī)器上執(zhí)行top -b -d 1 –p
問題分析
上述異常程序使用的是同樣的數(shù)據(jù)源:/proc/pid/stat中進(jìn)程運(yùn)行占用的用戶態(tài)時(shí)間utime和內(nèi)核態(tài)時(shí)間stime。我們抓取utime和stime更新情況后,發(fā)現(xiàn)utime或者stime每隔幾分鐘或者幾十分鐘才更新,更新的步進(jìn)值達(dá)到幾百到1000+,而正常進(jìn)程看到的是每幾秒更新,步進(jìn)值是幾十。
定位到異常點(diǎn)后,還要找出原因。排除了監(jiān)控邏輯、IO負(fù)載、調(diào)用瓶頸等可能后,確認(rèn)是4.1內(nèi)核的CPU時(shí)間統(tǒng)計(jì)有 bug。
cputime統(tǒng)計(jì)邏輯
檢查/proc/pid/stat中utime和stime被更新的代碼執(zhí)行路徑,在cputime_adjust()發(fā)現(xiàn)了一處可疑的地方:
當(dāng)utime+stime>=rtime的時(shí)候就直接跳出了,也就是不更新utime和stime了!這里的rtime是runtime,代表進(jìn)程運(yùn)行占用的所有CPU時(shí)長,正常應(yīng)該等于或近似進(jìn)程用戶態(tài)時(shí)間+內(nèi)核態(tài)時(shí)間。 但內(nèi)核配置了CONFIG_VIRT_CPU_ACCOUNTING_GEN選項(xiàng),這會(huì)讓utime和stime分別單調(diào)增長。而runtime是調(diào)度器里統(tǒng)計(jì)到的進(jìn)程真正運(yùn)行總時(shí)長。
內(nèi)核每次更新/proc/pid/stat的utime和stime的時(shí)候,都會(huì)跟rtime對(duì)比。如果utime+stime很長一段時(shí)間都大于rtime,那代碼直接goto out了, /proc/pid/stat就不更新了。只有當(dāng)rtime持續(xù)更新追上utime+stime后,才更新utime和stime。
冷補(bǔ)丁和熱補(bǔ)丁
***回合:冷補(bǔ)丁
出現(xiàn)問題的代碼位置已經(jīng)找到,那就先去內(nèi)核社區(qū)看看有沒有成熟補(bǔ)丁可用,看一下kernel/sched/cputime.c的 changelog,看到一個(gè)patch:確保stime+utime=rtime。再看描述:像top這樣的工具,會(huì)出現(xiàn)超過100%的利用率,之后又一段時(shí)間為0,這不就是我們遇到的問題嗎?真是踏破鐵鞋無覓處,得來全不費(fèi)工夫?。╬atch鏈接:https://lore.kernel.org/patchwork/patch/609410/)
該補(bǔ)丁在4.3內(nèi)核及以后版本才提交, 卻并未提交到4.1穩(wěn)定版分支,于是移植到4.1內(nèi)核。打上該補(bǔ)丁后進(jìn)行壓測,再?zèng)]出現(xiàn)cputime時(shí)而100%時(shí)而0%的現(xiàn)象,而是0-100%之間平滑波動(dòng)的值。
至此,你可能覺得問題已經(jīng)解決了。但是,問題才解決了一半。而往往“但是”后邊才是重點(diǎn)。
第二回合:熱補(bǔ)丁
給內(nèi)核代碼打上該冷補(bǔ)丁只能解決新增服務(wù)器的問題,但公司還有數(shù)萬存量服務(wù)器是無法升級(jí)內(nèi)核后重啟的。
如果沒有其它好選擇,那存量更新將被迫采用如下的妥協(xié)方案:監(jiān)控程序修改統(tǒng)計(jì)方式進(jìn)行規(guī)避,不再使用utime和stime,而是通過runtime來統(tǒng)計(jì)進(jìn)程的執(zhí)行時(shí)間。
雖然該方案快速可行,但也有很大的缺點(diǎn):
1. 很多業(yè)務(wù)部門都要修改統(tǒng)計(jì)程序,研發(fā)成本較高;
2. /proc/pid/stat的utime和stime是標(biāo)準(zhǔn)統(tǒng)計(jì)方式,一些第三方組件并不容易修改;
3. 并沒有根本解決utime和stime不準(zhǔn)的問題,用戶、研發(fā)、運(yùn)維使用ps、top命令時(shí)還會(huì)產(chǎn)生困惑,產(chǎn)生額外的溝通協(xié)調(diào)成本。
幸好,我們還可以依靠UCloud已多次成功應(yīng)用的技術(shù):熱補(bǔ)丁技術(shù)。
所謂熱補(bǔ)丁技術(shù),是指在有缺陷的服務(wù)器內(nèi)核或進(jìn)程正在運(yùn)行時(shí),對(duì)已經(jīng)加載到內(nèi)存的程序二進(jìn)制打上補(bǔ)丁,使得程序?qū)崟r(shí)在線狀態(tài)下執(zhí)行新的正確邏輯??梢院唵卫斫鉃橄耜P(guān)二爺那樣不打麻藥在清醒狀態(tài)下刮骨療傷。當(dāng)然,對(duì)內(nèi)核刮骨療傷內(nèi)核是不會(huì)痛的,但刮不好內(nèi)核就會(huì)直接死給你看,沒有絲毫猶豫,非常干脆利索又耿直。
熱補(bǔ)丁修復(fù)
而本次熱補(bǔ)丁修復(fù)存在兩個(gè)難點(diǎn):
難點(diǎn)一: 熱補(bǔ)丁制作
這次熱補(bǔ)丁在結(jié)構(gòu)體新增了spinlock成員變量,那就涉及新成員的內(nèi)存分配和釋放,在結(jié)構(gòu)體實(shí)例被復(fù)制和釋放時(shí),都要額外的對(duì)新成員做處理,稍有遺漏可能會(huì)造成內(nèi)存泄漏進(jìn)而導(dǎo)致宕機(jī),這就加大了風(fēng)險(xiǎn)。
再一個(gè)就是,結(jié)構(gòu)體實(shí)例是在進(jìn)程啟動(dòng)時(shí)初始化的,對(duì)于已經(jīng)存在的實(shí)例如何塞進(jìn)新的spinlock成員?所謂兵來將擋水來土掩,我們想到可以在原生補(bǔ)丁使用spinlock成員的代碼路徑上攔截,如果發(fā)現(xiàn)實(shí)例不含該成員,則進(jìn)行分配、初始化、加鎖、釋放鎖。
要解決問題,既要攀登困難的山峰,又得控制潛在的風(fēng)險(xiǎn)。團(tuán)隊(duì)編寫了腳本進(jìn)行幾百萬次的加載、卸載熱補(bǔ)丁測試,并無內(nèi)存泄漏,單機(jī)穩(wěn)定運(yùn)行,再下一城。
難點(diǎn)二:難以復(fù)現(xiàn)
另一個(gè)難題是該問題難以復(fù)現(xiàn),只有在現(xiàn)網(wǎng)生產(chǎn)環(huán)境才有幾個(gè)case可驗(yàn)證熱補(bǔ)丁,而又不可以拿用戶的環(huán)境去冒險(xiǎn)。針對(duì)這種情況我們已經(jīng)有標(biāo)準(zhǔn)化處理流程去應(yīng)對(duì),那就是設(shè)計(jì)完善的灰度策略,這也是UCloud內(nèi)部一直在強(qiáng)調(diào)的核心理念和能力。經(jīng)過分析,這個(gè)問題可以拆解為驗(yàn)證熱補(bǔ)丁穩(wěn)定性和驗(yàn)證熱補(bǔ)丁正確性。于是我們采取了如下灰度策略:
1. 穩(wěn)定性驗(yàn)證:先拿幾臺(tái)機(jī)器測試正常,再拿公司內(nèi)部500臺(tái)次級(jí)重要的機(jī)器打熱補(bǔ)丁,灰度運(yùn)行幾天正常,從而驗(yàn)證了穩(wěn)定性,風(fēng)險(xiǎn)盡在掌控之中。
2. 正確性驗(yàn)證:找到一臺(tái)出現(xiàn)問題的機(jī)器,同時(shí)打印utime+stime以及rtime,根據(jù)代碼的邏輯,當(dāng)rtime小于utime+stime時(shí)會(huì)執(zhí)行老邏輯,當(dāng)rtime大于utime+stime時(shí)會(huì)執(zhí)行新的熱補(bǔ)丁邏輯。如下圖所示,進(jìn)入熱補(bǔ)丁的新邏輯后,utime+stime打印正常且與rtime保持了同步更新,從而驗(yàn)證了熱補(bǔ)丁的正確性。
3. 全網(wǎng)變更:***再分批在現(xiàn)網(wǎng)環(huán)境機(jī)器上打熱補(bǔ)丁,執(zhí)行全網(wǎng)變更,問題得到根本解決,此處要感謝運(yùn)維同學(xué)的全力協(xié)助。
總結(jié)
綜上,我們詳細(xì)介紹了進(jìn)程cputime統(tǒng)計(jì)異常問題的完整分析和解決思路。該問題并非嚴(yán)重的宕機(jī)問題,但卻可能會(huì)讓用戶對(duì)監(jiān)控?cái)?shù)據(jù)產(chǎn)生困惑,誤認(rèn)為可能機(jī)器負(fù)載太高需要加資源,問題的解決會(huì)避免產(chǎn)生不必要的開支。此外,該問題也會(huì)讓研發(fā)、運(yùn)維和技術(shù)支持的同學(xué)們使用top和ps命令時(shí)產(chǎn)生困惑。最終我們對(duì)問題的本質(zhì)仔細(xì)分析并求證,用熱補(bǔ)丁的方式妥善的解決了問題。
網(wǎng)頁題目:Linux 4.1內(nèi)核熱補(bǔ)丁成功實(shí)踐
文章網(wǎng)址:http://m.fisionsoft.com.cn/article/cdcsejd.html


咨詢
建站咨詢
