自從我們的kubernetes集群部署到生產(chǎn)環(huán)境后晶衷,將流量從原有的服務(wù)器上切過來之后,部分節(jié)點(diǎn)出現(xiàn)掛載目錄容量爆滿的情況阴孟。
運(yùn)維的同事報給我們之后晌纫,我們首先想到的是節(jié)點(diǎn)鏡像過多,于是我們提供一個命令用于清理當(dāng)前節(jié)點(diǎn)上無用的永丝、報錯的锹漱、鏡像和docker資源文件
docker system prune ?命令可以用于清理磁盤,刪除關(guān)閉的容器慕嚷、無用的數(shù)據(jù)卷和網(wǎng)絡(luò)毕泌,以及dangling鏡像(即無tag的鏡像)
docker system prune -a 命令清理得更加徹底,可以將沒有容器使用Docker鏡像都刪掉嗅辣。
待運(yùn)維執(zhí)行之后撼泛,目錄存儲資源釋放了一些,我們本以為這就告一段落了澡谭。然而愿题,事與愿違,沒過多久译暂,再次容量報警抠忘。撩炊。外永。
我們開始重視起來,開始檢視節(jié)點(diǎn)上工作的容器拧咳,發(fā)現(xiàn)在日志爆炸的節(jié)點(diǎn)上運(yùn)行了定時任務(wù)伯顶,開發(fā)人員將定時任務(wù)的日志輸出到控制臺,于是我們回到節(jié)點(diǎn)docker的工作目錄骆膝,通過du -sh *方式查看每個文件夾大小祭衩,發(fā)現(xiàn)docker目錄下containers目錄占用空間巨大,進(jìn)去看原來是每個運(yùn)行的容器存放日志的目錄阅签,我們找出占用空間最大的日志目錄掐暮,發(fā)現(xiàn)容器日志特別的大
我們可使用如下命令查看各個日志的文件大小
ls -lh $(find /var/lib/docker/containers/ -name *-json.log)
那我們?nèi)绾吻謇砣罩灸兀绻鹍ocker容器正在運(yùn)行政钟,那么使用rm -rf 方式刪除日志后路克,通過df -h會發(fā)現(xiàn)磁盤空間并沒有釋放
原因:在Linux或者Unix系統(tǒng)中,通過rm或者文件管理器刪除文件將會從文件系統(tǒng)的目錄結(jié)構(gòu)上解除鏈接(unlink).然而如果文件是被打開的(有一個進(jìn)程正在使用)养交,那么進(jìn)程將仍然可以讀取該文件精算,磁盤空間也一直被占用
我們通過cat /dev/null > *-json.log來清理相應(yīng)的日志,然后重啟
systemctl daemon-reload
systemctl restart docker
然而碎连,我思考灰羽,不能每次滿的時候找運(yùn)維清理日志啊,這多麻煩鱼辙,難道docker沒有相應(yīng)的機(jī)制應(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è)置成功后怠噪,每個容器運(yùn)行的日志最多有五份每份200M大小,這樣就基本限制了容器的日志大小峭梳。
然后你覺得結(jié)束了嗎舰绘?蹂喻?并不!捂寿!
容器日志我們是限制完了口四,本以為高枕無憂,不用擔(dān)心出現(xiàn)日志爆滿的情況了秦陋,但是事與愿違蔓彩,過幾天硬盤容量又滿了。驳概。赤嚼。
我們究其原因,發(fā)現(xiàn)在docker的運(yùn)行目錄下overlay這個文件夾里存放著所有的容器掛載目錄顺又,也就是容器的系統(tǒng)文件在這里放著更卒,在容器中跑著的服務(wù)產(chǎn)生日志很可能并不是輸出到控制臺,而是保存到本地稚照,容器內(nèi)的日志文件也是會占用磁盤空間的蹂空,這就讓我們犯愁了,這個不好限制開發(fā)團(tuán)隊(duì)不存日志或者規(guī)定團(tuán)隊(duì)存放目錄啊果录,對于一個成熟的容器平臺來說上枕,海納百川那是必須的~
于是我們打起了kubelet的主意
在k8s中文社區(qū)中有詳細(xì)的限制方法?那具體做法呢,其實(shí)就是為節(jié)點(diǎn)加上驅(qū)逐策略弱恒,當(dāng)cpu或者內(nèi)存或者硬盤空間不滿足要求時辨萍,自動驅(qū)逐一些消耗資源大的容器,保證節(jié)點(diǎn)穩(wěn)定性返弹。
里面主要是有以下幾個關(guān)鍵驅(qū)逐信號
上面的每個信號都支持整數(shù)值或者百分比锈玉。百分比的分母部分就是各個信號的總量。kubelet 支持兩種文件系統(tǒng)分區(qū)琉苇。
nodefs:保存 kubelet 的卷和守護(hù)進(jìn)程日志等嘲玫。
imagefs:在容器運(yùn)行時,用于保存鏡像以及可寫入層并扇。
imagefs 是可選的去团。Kubelet 能夠利用 cAdvisor 自動發(fā)現(xiàn)這些文件系統(tǒng)。Kubelet 不關(guān)注其他的文件系統(tǒng)穷蛹。所有其他類型的配置土陪,例如保存在獨(dú)立文件系統(tǒng)的卷和日志,都不被支持肴熏。
因?yàn)榇疟P壓力已經(jīng)被驅(qū)逐策略接管鬼雀,因此未來將會停止對現(xiàn)有 垃圾收集 方式的支持。
具體的內(nèi)容大家可以詳細(xì)去看看社區(qū)里的介紹蛙吏,我這里就不再贅述了源哩,我這邊獻(xiàn)上我的驅(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é)點(diǎn)檢測為每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é)點(diǎn)鏡像存儲報警撤缴,我們可以從三個方面入手
1.容器:通過docker限制容器日志大小
2.k8s:通過kubelet來驅(qū)逐過大的容器
3.跟開發(fā)人員溝通,精簡容器叽唱,不讓內(nèi)存泄漏屈呕,不隨意使用資源(很難啦~~~)
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????祝各位新春快樂~