Kubernetes 節(jié)點(diǎn)磁盤故障排查,你學(xué)會(huì)了嗎?
通過本文,您將了解有關(guān)Kubernetes節(jié)點(diǎn)遇到磁盤壓力時(shí)的正確處理方式,包括磁盤壓力的原因以及故障排除的每一個(gè)步驟。
無論您運(yùn)行的是什么應(yīng)用程序,都需要一些基本的資源。CPU、內(nèi)存和磁盤空間是通用的,將用于所有應(yīng)用程序。大多數(shù)工程師都對如何處理CPU和內(nèi)存有著正確的理解,但并不是每個(gè)人都會(huì)花時(shí)間來理解如何正確使用磁盤。
在Kubernetes 環(huán)境中,隨著時(shí)間的推移,這可能會(huì)成為災(zāi)難性的,因?yàn)橐坏┏d,Kubernetes將開始“拯救”自己。這是通過殺死pod來實(shí)現(xiàn)的,從而減少節(jié)點(diǎn)上的負(fù)載。如果應(yīng)用程序不知道如何正確處理突然的異常,這可能會(huì)導(dǎo)致問題,或者可能導(dǎo)致沒有足夠的資源來處理給定的負(fù)載。
通過本文,我們就能很好的了解以及處理類似的磁盤故障。
什么是Node Disk Pressure
Node disk pressure,顧名思義,就是連接到節(jié)點(diǎn)的磁盤處于壓力之下。您不太可能遇到Node disk pressure,因?yàn)?Kubernetes 內(nèi)置了一些措施來避免它,但它確實(shí)會(huì)不時(shí)發(fā)生。雖然有多種因素會(huì)導(dǎo)致Node disk pressure,但您可能會(huì)遇到兩個(gè)主要原因。
您可能遇到Node disk pressure的第一個(gè)原因是 Kubernetes 沒有及時(shí)清理未使用的鏡像。默認(rèn)情況下,這不應(yīng)該發(fā)生,因?yàn)?Kubernetes 會(huì)定期檢查是否有未使用的鏡像,然后進(jìn)行刪除。這不太可能是節(jié)點(diǎn)磁盤壓力的來源;但是,應(yīng)該牢記這一點(diǎn)。
另一個(gè)你很可能遇到的問題是日志的積累問題。Kubernetes中的默認(rèn)行為是在兩種情況下保存日志:它將保存任何正在運(yùn)行的容器的日志,以及保存最近退出的容器的日志,以幫助進(jìn)行故障排除。這是一種試圖在保留重要日志和隨著時(shí)間推移刪除無用日志之間取得平衡的嘗試。但是,如果您有一個(gè)包含大量日志的長時(shí)間運(yùn)行的容器,那么這些日志可能會(huì)累積到足以使節(jié)點(diǎn)磁盤的容量過載的程度。
要弄清楚確切的問題是什么,您需要找到哪些文件占用的空間最多的詳細(xì)信息。
節(jié)點(diǎn)磁盤壓力故障排除
要解決節(jié)點(diǎn)磁盤壓力問題,您需要弄清楚哪些文件占用的空間最多。由于 Kubernetes 在 Linux 上運(yùn)行,因此可以通過運(yùn)行du命令輕松完成。您可以手動(dòng)通過 SSH 連接到每個(gè) Kubernetes 節(jié)點(diǎn),也可以使用DaemonSet(https://www.containiq.com/post/using-kubernetes-daemonsets-effectively)。
部署和理解 DaemonSet
要部署 DaemonSet,您可以直接使用 DaemonSet 的GitHub Gist(https://gist.githubusercontent.com/omerlh/cc5724ffeea17917eb06843dbff987b7/raw/1e58c8850aeeb6d22d8061338f09e5e1534ab638/daemonset.yaml) ,也可以創(chuàng)建一個(gè)包含以下內(nèi)容的文件:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: disk-checker
labels:
app: disk-checker
spec:
selector:
matchLabels:
app: disk-checker
template:
metadata:
labels:
app: disk-checker
spec:
hostPID: true
hostIPC: true
hostNetwork: true
containers:
- resources:
requests:
cpu: 0.15
securityContext:
privileged: true
image: busybox
imagePullPolicy: IfNotPresent
name: disk-checked
command: ["/bin/sh"]
args: ["-c", "du -a /host | sort -n -r | head -n 20"]
volumeMounts:
- name: host
mountPath: "/host"
volumes:
- name: host
hostPath:
path: "/"
現(xiàn)在您可以運(yùn)行以下命令:
$ kubectl apply -f https://gist.githubusercontent.com/omerlh/cc5724ffeea17917eb06843dbff987b7/raw/1e58c8850aeeb6d22d8061338f09e5e1534ab638/daemonset.yaml
在使用 DaemonSet 進(jìn)行故障排除之前,了解其中發(fā)生的事情很重要。如果您查看上面的清單文件,您會(huì)注意到它實(shí)際上是一個(gè)非常簡單的服務(wù)。其中很多是樣板文件,但要注意的重要一點(diǎn)是command和args字段。這是設(shè)置du命令運(yùn)行的地方,然后打印前 20 個(gè)結(jié)果。再往下,您還可以看到主機(jī)卷在路徑/host處綁定到容器中。
使用 DaemonSet
首先,您需要確保 DaemonSet 已正確部署,您可以通過運(yùn)行kubectl get pods -l app=disk-checker來完成。這應(yīng)該產(chǎn)生和輸出如下:
$ kubectl get pods -l app=disk-checker
NAME READY STATUS RESTARTS AGE
disk-checker-bwkbj 1/1 Running 0 2s?
您在此處看到的 pod 數(shù)量取決于集群內(nèi)運(yùn)行的節(jié)點(diǎn)數(shù)量。確認(rèn)節(jié)點(diǎn)正在運(yùn)行后,您可以通過執(zhí)行kubectl logs -l app=disk-checker開始查看正在運(yùn)行的 pod 的日志。這可能需要一些時(shí)間,但最后您應(yīng)該會(huì)看到一個(gè)文件列表及其大小,這將使您更深入地了解哪些內(nèi)容占用了節(jié)點(diǎn)上的空間。您接下來要做什么取決于占用空間的文件——您需要查看 DaemonSet 的輸出并了解正在發(fā)生的事情,以及它是否是日志文件、應(yīng)用程序文件或其他正在使用您的磁盤空間的文件。
可能的解決方案
分析和理解DaemonSet的輸出是很重要的,我們可以從中解決當(dāng)前的問題。有兩種可能的解決方案。
您可能會(huì)發(fā)現(xiàn)問題是由應(yīng)用程序數(shù)據(jù)引起的,因此無法刪除文件。在這種情況下,您將不得不增加節(jié)點(diǎn)磁盤的大小以確保有足夠的空間來存儲(chǔ)應(yīng)用程序文件。這是一個(gè)比較簡單的解決方式,但會(huì)增加運(yùn)行集群的成本。因此,更好的方式應(yīng)該是首先查看應(yīng)用程序的結(jié)構(gòu),看看是否可以找到減少對應(yīng)用程序文件的依賴的方法,從而減少對磁盤使用的總體需求。
另一方面,您可能會(huì)發(fā)現(xiàn)您的應(yīng)用程序生成了大量不再需要的文件。在這種情況下,就像刪除不必要的文件一樣簡單。根據(jù)您的應(yīng)用程序在可用性方面的設(shè)置方式,您可能只需重新啟動(dòng) pod,從而導(dǎo)致 Kubernetes 自動(dòng)清理容器中的任何文件。請注意,只有在使用臨時(shí)卷時(shí)才會(huì)這樣做,而不是在使用持久卷時(shí)。
最后
到目前為止,您應(yīng)該了解當(dāng)您遇到節(jié)點(diǎn)磁盤壓力問題時(shí)這意味著什么,以及當(dāng)您遇到問題時(shí)您的直接想法應(yīng)該是什么:收集相關(guān)的錯(cuò)誤日志。
您可能必須升級(jí)集群中磁盤的大小,或者清理未使用的文件。無論問題和解決方案如何,您現(xiàn)在都可以更好地了解遇到此問題。