一、当Kubernetes节点开始"喊饿"时
最近在维护一个生产环境的Kubernetes集群时,突然收到了一连串告警。几个工作节点纷纷报告磁盘空间不足,有些甚至已经使用了超过90%的空间。这就像家里的冰箱突然塞满了食物,新买的食材怎么也放不进去了。节点上的Pod开始被驱逐,服务出现了中断,运维群里的消息瞬间炸开了锅。
这种情况在Kubernetes环境中其实很常见。随着容器不断创建和销毁,各种日志、临时文件和未清理的镜像会慢慢蚕食节点的磁盘空间。就像我们电脑的C盘,不知不觉就变红了。不同的是,生产环境的磁盘问题会直接影响业务连续性。
二、诊断磁盘空间问题的"听诊器"
在开始治疗之前,我们需要先诊断清楚问题所在。Kubernetes提供了很多好用的工具来帮我们找出磁盘空间的"罪魁祸首"。
首先,我们可以使用kubectl describe node命令查看节点的整体状况:
# 查看节点磁盘压力情况
kubectl describe node <node-name> | grep -A 10 "Conditions"
# 示例输出:
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
DiskPressure True Mon, 12 Jun 2023 14:23:45 +0800 Mon, 12 Jun 2023 13:45:32 +0800 KubeletHasDiskPressure kubelet has disk pressure
这个命令会显示节点的各种状态条件,其中DiskPressure就是磁盘压力的指示器。如果看到Status为True,就说明该节点确实存在磁盘压力。
接下来,我们需要登录到问题节点上,使用传统的Linux命令来找出具体是哪些文件占用了大量空间:
# 查看磁盘整体使用情况
df -h
# 找出占用空间最大的目录
du -h --max-depth=1 / | sort -hr
# 查看/var/lib/docker目录大小(容器运行时存储位置)
du -sh /var/lib/docker/*
通过这些命令,我们通常能快速定位到问题的根源。常见的情况包括:
- 容器日志文件过大
- 未清理的容器镜像
- Kubernetes的临时文件堆积
- 应用程序生成的临时数据
三、清理磁盘空间的"组合拳"
找到了问题所在,接下来就是制定清理策略了。根据不同的情况,我们需要采取不同的清理方法。
3.1 清理无用的容器镜像
就像我们手机里不再使用的APP,节点上可能堆积了很多不再需要的容器镜像。我们可以使用docker命令来清理:
# 列出所有镜像
docker images
# 删除特定镜像
docker rmi <image-id>
# 自动清理未被任何容器使用的镜像
docker image prune -a
# 更激进的清理方式(慎用)
docker system prune -a --volumes
对于Kubernetes环境,我们还可以设置镜像回收策略。编辑kubelet的配置文件(通常在/var/lib/kubelet/config.yaml):
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
这样当磁盘使用率达到85%时,kubelet会自动清理镜像,直到使用率降到80%以下。
3.2 管理容器日志
容器日志是另一个常见的磁盘空间"杀手"。我们可以从几个方面入手:
首先,为容器设置日志轮转策略。在Docker中,可以修改/etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
对于Kubernetes Pod,我们可以在部署时配置日志策略:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-container
image: my-image
resources:
limits:
memory: "128Mi"
cpu: "500m"
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir:
sizeLimit: 100Mi
3.3 使用EmptyDir的正确姿势
EmptyDir是Kubernetes中常用的临时存储方式,但如果不加限制,它可能会占用大量磁盘空间。我们可以设置sizeLimit来限制其大小:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: busybox
command: ["sh", "-c", "while true; do echo hello >> /scratch/hello.txt; sleep 10; done"]
volumeMounts:
- name: scratch
mountPath: /scratch
volumes:
- name: scratch
emptyDir:
sizeLimit: 100Mi
当EmptyDir使用量超过限制时,Pod会被驱逐并重新调度。
四、预防胜于治疗的"养生之道"
解决了眼前的危机后,我们需要建立长效机制来预防问题再次发生。以下是几个实用的预防措施:
4.1 设置资源配额
我们可以使用ResourceQuota来限制命名空间的资源使用:
apiVersion: v1
kind: ResourceQuota
metadata:
name: storage-quota
spec:
hard:
requests.storage: "100Gi"
persistentvolumeclaims: "10"
4.2 监控和告警系统
部署Prometheus和Grafana来监控磁盘使用情况,并设置适当的告警规则:
# Prometheus告警规则示例
groups:
- name: node.rules
rules:
- alert: NodeDiskUsageHigh
expr: 100 - (node_filesystem_avail_bytes{mountpoint="/"} * 100 / node_filesystem_size_bytes{mountpoint="/"}) > 85
for: 10m
labels:
severity: warning
annotations:
summary: "High disk usage on {{ $labels.instance }}"
description: "{{ $labels.instance }} has disk usage above 85% for 10 minutes"
4.3 定期维护脚本
编写定期执行的维护脚本,自动清理旧日志和临时文件:
#!/bin/bash
# 清理30天前的日志文件
find /var/log -name "*.log" -type f -mtime +30 -delete
# 清理kubelet的旧检查点文件
find /var/lib/kubelet/checkpoints -type f -mtime +7 -delete
# 清理Docker构建缓存
docker builder prune -f
五、特殊情况的处理技巧
有时候我们会遇到一些特殊的情况,需要特别的处理方式。
5.1 处理被驱逐的Pod
当节点磁盘空间不足时,kubelet会开始驱逐Pod。我们可以通过以下命令查看被驱逐的Pod:
kubectl get pods --all-namespaces --field-selector=status.phase=Failed
对于重要的Pod,我们可以通过设置优先级来避免被驱逐:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for important pods only."
然后在Pod模板中引用:
apiVersion: apps/v1
kind: Deployment
metadata:
name: important-app
spec:
template:
spec:
priorityClassName: high-priority
containers:
- name: important-container
image: important-image
5.2 处理持久卷(PV)的空间问题
如果使用的是持久卷,当PV空间不足时,我们可以尝试扩展PV:
# 首先编辑PVC,增加请求的大小
kubectl edit pvc my-pvc
# 找到spec.resources.requests.storage字段并增加大小
注意:不是所有的存储类型都支持在线扩容,有些可能需要先删除并重建PVC。
六、经验总结与最佳实践
经过这次事件和处理过程,我总结了一些Kubernetes磁盘空间管理的最佳实践:
- 监控先行:建立完善的磁盘监控系统,在问题发生前就能收到预警。
- 限制为王:对所有可能占用磁盘的资源都设置合理的限制,包括容器日志、EmptyDir、镜像缓存等。
- 定期清理:建立定期维护机制,自动清理不再需要的文件和数据。
- 容量规划:根据业务需求合理规划节点磁盘容量,预留足够的缓冲空间。
- 文档记录:记录每次磁盘问题的处理过程和解决方案,形成知识库。
记住,在Kubernetes环境中,磁盘空间管理不是一次性的工作,而是需要持续关注的日常运维任务。只有建立完善的预防、监控和处理机制,才能确保集群的稳定运行。
评论