全球超過1300萬(wàn)個(gè)活躍容器每天在跑,但生產(chǎn)環(huán)境崩潰的鍋,80%還是那幾樣老問題。你以為熟練了,其實(shí)只是熟練地踩坑。
「我本地明明是好的」——這句話值多少錢?
2023年某電商平臺(tái)大促,凌晨2點(diǎn)17分,支付鏈路突然雪崩。值班工程師盯著監(jiān)控面板,CPU、內(nèi)存、網(wǎng)絡(luò)全綠,唯獨(dú)容器健康檢查瘋狂報(bào)錯(cuò)。根因?開發(fā)環(huán)境用的Docker Desktop最新版,生產(chǎn)機(jī)還跑著18個(gè)月前的運(yùn)行時(shí),一個(gè)libc版本差異讓SSL握手直接超時(shí)。
修復(fù)花了47分鐘,訂單流失估算在八位數(shù)。事后復(fù)盤,CTO的原話是:「我們不是在用容器,是在用容器的幻覺。」
這種幻覺很普遍。Docker把環(huán)境打包得漂漂亮亮,讓人誤以為「鏡像一致=行為一致」。但鏡像只是靜態(tài)快照,底層的容器運(yùn)行時(shí)(Container Runtime)、內(nèi)核版本、系統(tǒng)調(diào)用實(shí)現(xiàn),全是變量。本地跑得好好的代碼,到生產(chǎn)環(huán)境遇到不同的seccomp(安全計(jì)算模式)配置,直接Permission Denied,這種事每周都在各大公司的故障群里上演。
更隱蔽的是資源限制的幻覺。開發(fā)者本地筆記本16核32G,隨手寫個(gè)docker run不帶內(nèi)存限制。上線后同樣配置扔到K8s集群,QoS(服務(wù)質(zhì)量等級(jí))設(shè)為Burstable,隔壁Pod一擠兌,OOM Killer(內(nèi)存溢出終止程序)進(jìn)場(chǎng),服務(wù)重啟時(shí)間剛好撞上流量高峰。AWS去年公布的客戶故障分析里,容器內(nèi)存配置不當(dāng)導(dǎo)致的驅(qū)逐事件,占所有彈性計(jì)算故障的34%。
健康檢查:從擺設(shè)到兇器
Dockerfile里抄來(lái)的HEALTHCHECK指令,很多人根本沒想明白邏輯。某金融科技公司去年的事故特別典型:他們的健康檢查是curl本地8080端口,返回200就算健康。但服務(wù)有個(gè)隱藏bug,內(nèi)存泄漏到80%時(shí),HTTP響應(yīng)延遲從50ms飆到8秒,curl還在耐心等,K8s調(diào)度器一看「健康」,繼續(xù)把流量往里灌。等最終超時(shí)崩潰,已經(jīng)積累了上千個(gè)掛起的連接,雪崩不可避免。
正確的健康檢查應(yīng)該分層。存活探針(Liveness Probe)只問「你還活著嗎」,就緒探針(Readiness Probe)要問「你能干活嗎」。但現(xiàn)實(shí)中,大量配置把兩者寫成一樣的,或者干脆只配一個(gè)。Google SRE手冊(cè)里有個(gè)數(shù)據(jù):配置雙探針的服務(wù),故障自愈時(shí)間平均縮短62%。知道這個(gè)的人不少,照做的人不多。
鏡像層緩存是另一個(gè)暗雷。Docker build的層緩存能省時(shí)間,但也能埋雷。某團(tuán)隊(duì)的基礎(chǔ)鏡像從ubuntu:20.04改成ubuntu:22.04,以為重新構(gòu)建了就行,結(jié)果上層應(yīng)用鏡像的Dockerfile寫的是FROM mybase:latest,CI系統(tǒng)沒清緩存,拉的還是舊版基礎(chǔ)鏡像。上線后OpenSSL版本不匹配,TLS 1.3握手失敗,全網(wǎng)HTTPS中斷22分鐘。這種「緩存投毒」問題,Docker官方Issue區(qū)有400多條討論,解決方案從--no-cache到多階段構(gòu)建都有,但執(zhí)行到位需要整個(gè)CI/CD鏈路的配合。
網(wǎng)絡(luò)命名空間:看不見的戰(zhàn)場(chǎng)
容器網(wǎng)絡(luò)是最容易「看起來(lái)懂了」的領(lǐng)域。bridge、host、overlay、macvlan,模式背得熟,真出問題就抓瞎。2024年初,某視頻平臺(tái)的直播推流服務(wù)出現(xiàn)詭異延遲:同機(jī)房?jī)膳_(tái)容器,ping延遲不到1ms,但應(yīng)用層RTT(往返時(shí)間)偶爾跳到200ms以上。最后定位到Docker的bridge模式默認(rèn)啟用了iptables(防火墻規(guī)則)的conntrack(連接追蹤),高并發(fā)短連接場(chǎng)景下,nf_conntrack表滿,新連接被DROP,應(yīng)用重傳等到超時(shí)。
解決方法是換host網(wǎng)絡(luò),或者調(diào)內(nèi)核參數(shù)。但問題的根源,是團(tuán)隊(duì)沒人知道默認(rèn)bridge模式的性能邊界。Docker文檔里寫得清楚,但誰(shuí)看呢?大多數(shù)人到出事了才第一次打開那頁(yè)。
日志處理是最后一個(gè)盲區(qū)。容器stdout/stderr默認(rèn)寫到JSON文件,沒配rotate(輪轉(zhuǎn)策略)的話,磁盤寫滿只是時(shí)間問題。某SaaS公司的監(jiān)控顯示,容器節(jié)點(diǎn)磁盤告警里,/var/lib/docker/overlay2占用的增長(zhǎng)曲線,和業(yè)務(wù)的日志量曲線高度吻合——他們根本沒配日志驅(qū)動(dòng),用的默認(rèn)json-file,10G磁盤三天打滿。換成fluentd或者直接輸出到外部收集器,這個(gè)問題本可以避免,但「能跑就行」的心態(tài)讓配置債越積越多。
從熟練到精通,差的不只是時(shí)間
Docker的易用性是個(gè)雙刃劍。它把底層復(fù)雜度包起來(lái),讓新手快速出活,也讓老手產(chǎn)生「我已經(jīng)懂了」的錯(cuò)覺。真正的分水嶺,是開始追問「如果這層抽象失效了怎么辦」。
Netflix的容器平臺(tái)團(tuán)隊(duì)有個(gè)內(nèi)部測(cè)試:隨機(jī)殺掉生產(chǎn)環(huán)境的容器,看服務(wù)恢復(fù)時(shí)間。這個(gè)混沌工程(Chaos Engineering)實(shí)踐逼他們搞清了每個(gè)故障域的邊界。普通團(tuán)隊(duì)沒這個(gè)條件,但至少可以做到:本地開發(fā)和生產(chǎn)用完全一致的運(yùn)行時(shí)版本,健康檢查按業(yè)務(wù)語(yǔ)義設(shè)計(jì),網(wǎng)絡(luò)模式選型時(shí)把性能基準(zhǔn)測(cè)一遍,日志和監(jiān)控當(dāng)成一等公民來(lái)配置。
這些都不難,難的是承認(rèn)「我每天用,但未必真懂」。容器技術(shù)發(fā)展了十年,生產(chǎn)環(huán)境的坑也挖了十年,地圖早就公開了,走不走得出來(lái),看的是細(xì)節(jié)執(zhí)行力。
你們團(tuán)隊(duì)的Dockerfile,最近一次全面review是什么時(shí)候?
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.