記一次k8s集群節(jié)點鏡像存儲容量報警問題

自從我們的kubernetes集群部署到生產(chǎn)環(huán)境后,將流量從原有的服務(wù)器上切過來之后,部分節(jié)點出現(xiàn)掛載目錄容量爆滿的情況。

運維的同事報給我們之后,我們首先想到的是節(jié)點鏡像過多,于是我們提供一個命令用于清理當(dāng)前節(jié)點上無用的、報錯的、鏡像和docker資源文件

docker system prune ?命令可以用于清理磁盤,刪除關(guān)閉的容器、無用的數(shù)據(jù)卷和網(wǎng)絡(luò),以及dangling鏡像(即無tag的鏡像)

docker system prune -a 命令清理得更加徹底,可以將沒有容器使用Docker鏡像都刪掉。

待運維執(zhí)行之后,目錄存儲資源釋放了一些,我們本以為這就告一段落了。然而,事與愿違,沒過多久,再次容量報警。。。

我們開始重視起來,開始檢視節(jié)點上工作的容器,發(fā)現(xiàn)在日志爆炸的節(jié)點上運行了定時任務(wù),開發(fā)人員將定時任務(wù)的日志輸出到控制臺,于是我們回到節(jié)點docker的工作目錄,通過du -sh *方式查看每個文件夾大小,發(fā)現(xiàn)docker目錄下containers目錄占用空間巨大,進去看原來是每個運行的容器存放日志的目錄,我們找出占用空間最大的日志目錄,發(fā)現(xiàn)容器日志特別的大

我們可使用如下命令查看各個日志的文件大小

ls -lh $(find /var/lib/docker/containers/ -name *-json.log)

那我們?nèi)绾吻謇砣罩灸?,如果docker容器正在運行,那么使用rm -rf 方式刪除日志后,通過df -h會發(fā)現(xiàn)磁盤空間并沒有釋放

原因:在Linux或者Unix系統(tǒng)中,通過rm或者文件管理器刪除文件將會從文件系統(tǒng)的目錄結(jié)構(gòu)上解除鏈接(unlink).然而如果文件是被打開的(有一個進程正在使用),那么進程將仍然可以讀取該文件,磁盤空間也一直被占用

我們通過cat /dev/null > *-json.log來清理相應(yīng)的日志,然后重啟

systemctl daemon-reload

systemctl restart docker

然而,我思考,不能每次滿的時候找運維清理日志啊,這多麻煩,難道docker沒有相應(yīng)的機制應(yīng)付輸出到控制臺的日志嗎?答案是:當(dāng)然不會

在新版的docker中我們可以通過設(shè)置vim /etc/docker/daemon.json 來限制docker的日志量

"log-driver":"json-file","log-opts":{ "max-size" :"200m","max-file":"5"}

顧名思義max-size就是每個日志文件大小,max-file是最多生成的文件數(shù),如上我設(shè)置成功后,每個容器運行的日志最多有五份每份200M大小,這樣就基本限制了容器的日志大小。

然后你覺得結(jié)束了嗎??并不?。?/p>

容器日志我們是限制完了,本以為高枕無憂,不用擔(dān)心出現(xiàn)日志爆滿的情況了,但是事與愿違,過幾天硬盤容量又滿了。。。

我們究其原因,發(fā)現(xiàn)在docker的運行目錄下overlay這個文件夾里存放著所有的容器掛載目錄,也就是容器的系統(tǒng)文件在這里放著,在容器中跑著的服務(wù)產(chǎn)生日志很可能并不是輸出到控制臺,而是保存到本地,容器內(nèi)的日志文件也是會占用磁盤空間的,這就讓我們犯愁了,這個不好限制開發(fā)團隊不存日志或者規(guī)定團隊存放目錄啊,對于一個成熟的容器平臺來說,海納百川那是必須的~

于是我們打起了kubelet的主意

k8s中文社區(qū)中有詳細的限制方法?那具體做法呢,其實就是為節(jié)點加上驅(qū)逐策略,當(dāng)cpu或者內(nèi)存或者硬盤空間不滿足要求時,自動驅(qū)逐一些消耗資源大的容器,保證節(jié)點穩(wěn)定性。

里面主要是有以下幾個關(guān)鍵驅(qū)逐信號


上面的每個信號都支持整數(shù)值或者百分比。百分比的分母部分就是各個信號的總量。kubelet 支持兩種文件系統(tǒng)分區(qū)。

nodefs:保存 kubelet 的卷和守護進程日志等。

imagefs:在容器運行時,用于保存鏡像以及可寫入層。

imagefs 是可選的。Kubelet 能夠利用 cAdvisor 自動發(fā)現(xiàn)這些文件系統(tǒng)。Kubelet 不關(guān)注其他的文件系統(tǒng)。所有其他類型的配置,例如保存在獨立文件系統(tǒng)的卷和日志,都不被支持。

因為磁盤壓力已經(jīng)被驅(qū)逐策略接管,因此未來將會停止對現(xiàn)有 垃圾收集 方式的支持。

具體的內(nèi)容大家可以詳細去看看社區(qū)里的介紹,我這里就不再贅述了,我這邊獻上我的驅(qū)逐方案~

執(zhí)行vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

在里面插入

Environment="KUBELET_OTHER_ARGS=

--eviction-hard=memory.available<2Gi,nodefs.available<5Gi,imagefs.available<5Gi?

--eviction-minimum-reclaim=memory.available=500Mi,nodefs.available=5Gi,imagefs.available=5Gi?

--node-status-update-frequency=10s?

--eviction-pressure-transition-period=30s"

解讀:內(nèi)存小于2G驅(qū)逐,root目錄磁盤空間小于5G驅(qū)逐,鏡像目錄磁盤空間小于5G驅(qū)逐,節(jié)點檢測為每10秒一次,在跳出壓力狀態(tài)之前要等待的時間為30秒。

在某些場景下,驅(qū)逐 Pod 可能只回收了很少的資源。這就導(dǎo)致了 kubelet 反復(fù)觸發(fā)驅(qū)逐閾值。另外回收資源例如磁盤資源,是需要消耗時間的。

要緩和這種狀況,Kubelet 能夠?qū)γ糠N資源定義?minimum-reclaim。kubelet 一旦發(fā)現(xiàn)了資源壓力,就會試著回收至少?minimum-reclaim?的資源,使得資源消耗量回到期望范圍。

也就是說當(dāng)內(nèi)存觸發(fā)驅(qū)逐時,kubelet至少要讓內(nèi)存有2.5G,當(dāng)root和鏡像磁盤空間發(fā)生驅(qū)逐時,kubelet至少要讓磁盤有10G的空間。

那驅(qū)逐的規(guī)則是什么呢,對什么樣的容器做驅(qū)逐呢?這個我們下回分解哈。

那總的來說,若要解決節(jié)點鏡像存儲報警,我們可以從三個方面入手

1.容器:通過docker限制容器日志大小

2.k8s:通過kubelet來驅(qū)逐過大的容器

3.跟開發(fā)人員溝通,精簡容器,不讓內(nèi)存泄漏,不隨意使用資源(很難啦~~~)

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????祝各位新春快樂~

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

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

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