TKE节点磁盘空间不足导致pod被驱逐问题

最近遇到了一个问题,TKE控制台出现了大量的failed状态的pod,查看了事件并没有明显的异常报错,这里到底是怎么回事呢?

其实这里failed状态的是因为节点的内存或者磁盘满了,导致了pod被驱逐导致,这里kubectl命令查看pod的状态是Evicted,tke控制台则显示成failed,其实节点发生驱逐一般没什么影响,节点资源不足了,将pod驱逐到其他节点运行是符合预期的。

那么到底什么是驱逐呢?

Kubelet 主动监测和防止 计算资源的全面短缺。在资源短缺时,kubelet 可以主动地结束一个或多个 Pod 以回收短缺的资源。 当 kubelet 结束一个 Pod 时,它将终止 Pod 中的所有容器,而 Pod 的 Phase 将变为 Failed。 如果被驱逐的 Pod 由 Deployment 管理,这个 Deployment 会创建另一个 Pod 给 Kubernetes 来调度。

哪些资源不足会触发驱逐策略,这里可以参考文档配置对应的参数到节点的kubelet参数中

https://kubernetes.io/zh/docs/tasks/administer-cluster/out-of-resource/

一般节点发生驱逐,主要还是因为容器存储目录占用了大量的磁盘空间导致,今天我们就讲讲由于磁盘空间不足引发的驱逐问题,说到磁盘空间不足引发驱逐,这里会出现一个问题,就是我将容器存储目录挂载在数据盘上,会出现下面2种现象:

  • 容器存储目录满了,节点没有触发驱逐
  • 容器存储目录没满,节点触发了驱逐

下面我们来讲讲tke节点磁盘满了到底在什么情况下会触发驱逐,为什么将容器存储目录挂在数据盘会出现上面现象,对于驱逐问题,我们需要如何处理。

首先我们来看下tke节点默认的kubelet驱逐配置

[root@VM-0-3-centos ~]# cat /etc/kubernetes/kubelet
SERIALIZE_IMAGE_PULLS="--serialize-image-pulls=false"
REGISTER_SCHEDULABLE="--register-schedulable=true"
V="--v=2"
CLOUD_PROVIDER="--cloud-provider=qcloud"
FAIL_SWAP_ON="--fail-swap-on=false"
AUTHORIZATION_MODE="--authorization-mode=Webhook"
CLOUD_CONFIG="--cloud-config=/etc/kubernetes/qcloud.conf"
CLUSTER_DNS="--cluster-dns=172.16.52.140"
IMAGE_PULL_PROGRESS_DEADLINE="--image-pull-progress-deadline=10m0s"
HOSTNAME_OVERRIDE="--hostname-override=10.0.0.3"
EVICTION_HARD="--eviction-hard=nodefs.available<10%,nodefs.inodesFree<5%,memory.available<100Mi"
CLIENT_CA_FILE="--client-ca-file=/etc/kubernetes/cluster-ca.crt"
NON_MASQUERADE_CIDR="--non-masquerade-cidr=0.0.0.0/0"
KUBE_RESERVED="--kube-reserved=cpu=90m,memory=1300Mi"
MAX_PODS="--max-pods=61"
AUTHENTICATION_TOKEN_WEBHOOK="--authentication-token-webhook=true"
POD_INFRA_CONTAINER_IMAGE="--pod-infra-container-image=ccr.ccs.tencentyun.com/library/pause:latest"
ANONYMOUS_AUTH="--anonymous-auth=false"
KUBECONFIG="--kubeconfig=/etc/kubernetes/kubelet-kubeconfig"
NETWORK_PLUGIN="--network-plugin=cni"
CLUSTER_DOMAIN="--cluster-domain=cluster.local"

EVICTION_HARD这个字段就是配置的驱逐策略,tke节点默认策略是磁盘空间小于10%和内存小于100Mi的时候发生驱逐,但是这里到底是指的哪个目录所在的磁盘呢?

其实在kubelet的源码里面,kubelet启动的方法里面默认配置了kubelet的root-dir就是/var/lib/kubelet,也就是说,节点磁盘空间不足发生驱逐,主要是由于/var/lib/kubelet这个目录所在的磁盘空间不足引起的。

const (
   // Ports of different e2e services.
   kubeletReadOnlyPort = "10255"
   // KubeletRootDirectory specifies the directory where the kubelet runtime information is stored.
   KubeletRootDirectory = "/var/lib/kubelet"
   // Health check url of kubelet
   kubeletHealthCheckURL = "http://127.0.0.1:" + kubeletReadOnlyPort + "/healthz"
)
func (e *E2EServices) startKubelet() (*server, error) {
......
cmdArgs = append(cmdArgs,
		"--kubeconfig", kubeconfigPath,
		"--root-dir", KubeletRootDirectory,
		"--v", LogVerbosityLevel, "--logtostderr",
	)
......
}	

既然知道了由于磁盘空间不足引发驱逐的目录是哪个了,这里就可以解释上面遇到的问题了。这里我们将docker的存储目录挂载在数据盘,但是kubelet的root-dir却没有挂在数据盘,还是在默认的根目录下,也就是系统盘下,当你数据盘满了,但是系统盘没有到达驱逐条件,这里是不会触发驱逐的。

同样的道理,当你将一些日志写在节点的系统盘目录,是系统盘磁盘空间被撑满,但是数据盘空间还是充足,这样还是会触发驱逐的。

当我们没有将docker存储目录挂载在数据盘的时候,docker存储目录和kubelet的root-dir默认都是在系统盘上,所以这种情况只要系统盘满了,就会触发驱逐,通常是docker的占用了大量的磁盘空间导致的。

如果你的节点只有一个系统盘,磁盘满了,触发了驱逐,可以先清理下磁盘空间

#该指令默认会清除所有如下资源:已停止的容器(container)、未被任何容器所使用的卷(volume)、未被任何容器所关联的网络(network)、所有悬空镜像(image)。
docker system prune  -a -f  

如果上面命令无法回收磁盘空间,可以参考文档清理下占用空间的日志文件https://cloud.tencent.com/document/product/457/43126

释放了磁盘空间后,evicted状态的pod这里不会自动清理,需要手动删除下

kubectl get pods -n [xxxxx | grep Evicted |awk '{print $1}' |xargs kubectl -n xxxxx delete pod

如果你的docker存储在了数据盘上,但是还是发生了驱逐,这里只需要参考文档https://cloud.tencent.com/document/product/457/43126

释放下系统盘的磁盘空间即可,然后参考上面命令手动删除下evited状态的pod

有些人其实心中有一个疑问,就是我需要把docker存目录挂载到数据盘,但是希望触发驱逐的是docker存储目录,也是当数据盘磁盘空间不足的时候触发驱逐。

这里有2个解决方案,第一就是修改kubelet的root-dir参数,第二就是增加kubelet的驱逐参数配置

采用第一种方案,需要在节点初始化配置kubelet的自定义参数,这里需要提交工单开通自定义kubelet参数功能,开通后,你就在控制台配置kubelet的root-dir参数了

这里我们将kubelet的root-dir和docker的存储目录都挂载在数据盘的/data目录下即可,当docker数据太多导致磁盘满了,这样也会触发驱逐。

如果是第二个方案,这里其实就是需要将docker的存储数据盘添加到驱逐的范围内,我们可以配置下面镜像驱逐参数,这里镜像都是存储在数据盘,设置了这2个参数,docker存储目录所在的盘满了也会触发kubelet的驱逐

imagefs.available

imagefs.available := node.stats.runtime.imagefs.available

imagefs.inodesFree

imagefs.inodesFree := node.stats.runtime.imagefs.inodesFree

EVICTION_HARD="--eviction-hard=nodefs.available<10%,nodefs.inodesFree<5%,memory.available<100Mi,imagefs.available
<10%,imagefs.inodesFree<5%"

添加上面参数后,当docker所在数据盘可使用率小于10%的时候,kubelet就会进行驱逐。

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
TKE节点磁盘空间不足导致pod被驱逐问题
最近遇到了一个问题,TKE控制台出现了大量的failed状态的pod,查看了事件并没有明显的异常报错,这里到底是怎么回事呢?
<<上一篇
下一篇>>