无论您运行的是什么应用程序,都需要一些基本的资源。CPU、内存和磁盘空间是通用的,将用于所有应用程序。大多数工程师都对如何处理CPU和内存有着正确的理解,但并不是每个人都会花时间来理解如何正确使用磁盘。
在Kubernetes 环境中,随着时间的推移,这可能会成为灾难性的,因为一旦超载,Kubernetes将开始“拯救”自己。这是通过杀死pod来实现的,从而减少节点上的负载。如果应用程序不知道如何正确处理突然的异常,这可能会导致问题,或者可能导致没有足够的资源来处理给定的负载。
通过本文,我们就能很好的了解以及处理类似的磁盘故障。
什么是Node Disk Pressure
Node disk pressure,顾名思义,就是连接到节点的磁盘处于压力之下。您不太可能遇到Node disk pressure,因为 Kubernetes 内置了一些措施来避免它,但它确实会不时发生。虽然有多种因素会导致Node disk pressure,但您可能会遇到两个主要原因。
您可能遇到Node disk pressure的第一个原因是 Kubernetes 没有及时清理未使用的镜像。默认情况下,这不应该发生,因为 Kubernetes 会定期检查是否有未使用的镜像,然后进行删除。这不太可能是节点磁盘压力的来源;但是,应该牢记这一点。
另一个你很可能遇到的问题是日志的积累问题。Kubernetes中的默认行为是在两种情况下保存日志:它将保存任何正在运行的容器的日志,以及保存最近退出的容器的日志,以帮助进行故障排除。这是一种试图在保留重要日志和随着时间推移删除无用日志之间取得平衡的尝试。但是,如果您有一个包含大量日志的长时间运行的容器,那么这些日志可能会累积到足以使节点磁盘的容量过载的程度。
要弄清楚确切的问题是什么,您需要找到哪些文件占用的空间最多的详细信息。
节点磁盘压力故障排除
要解决节点磁盘压力问题,您需要弄清楚哪些文件占用的空间最多。由于 Kubernetes 在 Linux 上运行,因此可以通过运行du命令轻松完成。您可以手动通过 SSH 连接到每个 Kubernetes 节点,也可以使用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) ,也可以创建一个包含以下内容的文件:
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: "/"
现在您可以运行以下命令:
$ kubectl apply -f https://gist.githubusercontent.com/omerlh/cc5724ffeea17917eb06843dbff987b7/raw/1e58c8850aeeb6d22d8061338f09e5e1534ab638/daemonset.yaml
在使用 DaemonSet 进行故障排除之前,了解其中发生的事情很重要。如果您查看上面的清单文件,您会注意到它实际上是一个非常简单的服务。其中很多是样板文件,但要注意的重要一点是command和args字段。这是设置du命令运行的地方,然后打印前 20 个结果。再往下,您还可以看到主机卷在路径/host处绑定到容器中。
使用 DaemonSet
首先,您需要确保 DaemonSet 已正确部署,您可以通过运行kubectl get pods -l app=disk-checker来完成。这应该产生和输出如下:
$ kubectl get pods -l app=disk-checker
NAME READY STATUS RESTARTS AGE
disk-checker-bwkbj 1/1 Running 0 2s
您在此处看到的 pod 数量取决于集群内运行的节点数量。确认节点正在运行后,您可以通过执行kubectl logs -l app=disk-checker开始查看正在运行的 pod 的日志。这可能需要一些时间,但最后您应该会看到一个文件列表及其大小,这将使您更深入地了解哪些内容占用了节点上的空间。您接下来要做什么取决于占用空间的文件——您需要查看 DaemonSet 的输出并了解正在发生的事情,以及它是否是日志文件、应用程序文件或其他正在使用您的磁盘空间的文件。
可能的解决方案
分析和理解DaemonSet的输出是很重要的,我们可以从中解决当前的问题。有两种可能的解决方案。
您可能会发现问题是由应用程序数据引起的,因此无法删除文件。在这种情况下,您将不得不增加节点磁盘的大小以确保有足够的空间来存储应用程序文件。这是一个比较简单的解决方式,但会增加运行集群的成本。因此,更好的方式应该是首先查看应用程序的结构,看看是否可以找到减少对应用程序文件的依赖的方法,从而减少对磁盘使用的总体需求。
另一方面,您可能会发现您的应用程序生成了大量不再需要的文件。在这种情况下,就像删除不必要的文件一样简单。根据您的应用程序在可用性方面的设置方式,您可能只需重新启动 pod,从而导致 Kubernetes 自动清理容器中的任何文件。请注意,只有在使用临时卷时才会这样做,而不是在使用持久卷时。
最后
到目前为止,您应该了解当您遇到节点磁盘压力问题时这意味着什么,以及当您遇到问题时您的直接想法应该是什么:收集相关的错误日志。
您可能必须升级集群中磁盘的大小,或者清理未使用的文件。无论问题和解决方案如何,您现在都可以更好地了解遇到此问题。