简单粗暴的办法
一把删除k8s集群中default命名空间下所有Evicted状态的容器的命令:
kubectl get pod -n default | grep Evicted | awk '{print $1}' | xargs kubectl delete pod -n default
注意: 此办法治标不治本。
治本的办法
首先要将本地的Docker Desktop的kubernetes context切换到出现问题的k8s集群,当然也可以在命令行终端用命令切换。
然后我们查看一个状态是Evicted的容器到底出了什么问题,在命令行终端执行如下命令:
kubectl describe pods nacos-server-test-78689747c5-26nn7
附上命令行终端的输出:
➜ ~ kubectl describe pods nacos-server-test-78689747c5-26nn7
Name: nacos-server-test-78689747c5-26nn7
Namespace: default
Priority: 0
Node: cn-beijing.xxx.xx.xx.xx/
Start Time: Sat, 30 Jul 2022 08:45:43 +0800
Labels: app=nacos-server
pod-template-hash=78689747c5
Annotations: kubernetes.io/psp: ack.privileged
Status: Failed
Reason: Evicted
Message: Pod The node had condition: [DiskPressure].
IP:
IPs: <none>
Controlled By: ReplicaSet/nacos-server-test-78689747c5
Containers:
nacos-server:
Image: registry.cn-beijing.aliyuncs.com/xxxxxx/nacos-server:v2.0.3
Port: 8848/TCP
Host Port: 0/TCP
Requests:
cpu: 500m
memory: 1Gi
Environment:
NACOS_REPLICAS: 1
MYSQL_SERVICE_DB_NAME: <set to the key 'mysql.db.name' of config map 'nacos-cm'> Optional: false
MYSQL_SERVICE_PORT: <set to the key 'mysql.port' of config map 'nacos-cm'> Optional: false
MYSQL_SERVICE_USER: <set to the key 'mysql.user' of config map 'nacos-cm'> Optional: false
NACOS_SERVER_PORT: 8848
NACOS_APPLICATION_PORT: 8848
PREFER_HOST_MODE: hostname
MODE: standalone
SPRING_DATASOURCE_PLATFORM: mysql
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-mg4b2 (ro)
Volumes:
default-token-mg4b2:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-mg4b2
Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: <none>
➜ ~
我们看一下第10~12行可知,当前这个容器的状态是失败,原因是Evicted,具体的失败原因也告诉我们了:Pod The node had condition: [DiskPressure]
,直译过来就是“这个节点出状况了:磁盘压力”,其实就是该节点的磁盘空间不足了。我们马上能想到的解决方案就是ssh登上节点清理一下垃圾文件。
还有一种可能的错误信息是:The node was low on resource: ephemeral-storage. Container NAME was using 16658224Ki, which exceeds its request of 0
。跟上面那种[DiskPressure]
的报错的根本原因是一样的,都是磁盘空间不足,但是导致的后果不太一样。上面那种是导致容器启动不了,这种报错是导致容器会在运行中被杀死。
我们通过ssh登录节点以后,输入如下命令,查看一下Docker管理的磁盘空间:
docker system df
截图中的reclaimable列的数据是可回收的空间:容器镜像可以回收3.83G的磁盘空间,容器可以回收29MB的空间。下面我们就是要把这将近4个G的空间回收掉。
回收之前,我们先用df -h
命令看一下宿主机的磁盘空间大小,到最后做对比。
可以看到目前宿主机的磁盘空间占用是70%。我们再来重点看一下/var/lib/docker/overlay2
这个文件夹的磁盘占用,输入命令du -ch -d 1
这一个文件夹占用了13个G!后面我们做的操作其实都是回收这个文件夹占用的空间。
接下来我们先排空节点,执行命令:
kubectl drain this_node --ignore-daemonsets --delete-local-data
再清空docker占用的磁盘空间:
docker system prune -af --volumes
我们删除了在这台节点上的所有的镜像、容器和volume。我们再执行命令du -ch -d 1
看一下/var/lib/docker/overlay2
文件夹的磁盘占用。
只剩下2.8G的文件了。我们继续把这些文件都删掉。执行命令rm -rf *
之后,还有一些文件夹遗留下来,暂时删除不了,因为还有容器用到,我们先放一下。
然后我们停止并删除所有的容器:
docker stop $(docker ps -q) && docker rm $(docker ps -a -q)
-q
的意思是只返回容器id。
此时再看一下/var/lib/docker/overlay2
,已经清空了。我们需要再次执行如下命令,把刚才停掉并删除的容器的垃圾清理干净:
docker system prune -af --volumes
我们执行命令df -h
看一下现在的效果:
我们成功回收了40%的磁盘空间。
最后重启该节点。等节点恢复运行后,将节点设置为可调度状态,就完成了。