1. 前言
本文记录使用K8S过程中遇到的问题、解决办法和一些原理。
问题排查方法参考《kubectl命令——故障排查篇》。
2. kubelet不停重启
2.1. 问题描述
K8S的一个worker节点磁盘不足,关机进行磁盘扩容,物理扩容后开机,执行esize2fs /dev/vdb
,扩容完成。
docker ps
,发现没有容器被启动。kubectl status kubelet
,发现kubelet不停进行重启,每次都启动失败。kubectl status docker
,正常docker正常running。
重启机器,问题依旧。
2.2. 排查解决
1 | journalctl -xeu kubelet -r |
kubelet日志没有报错,docker日志中报错:
1 | level=error msg="xxx cleanup: failed to delete container from containerd: no such container |
FROM ChatGPT:
该错误日志表示 Docker 清理容器时失败,原因是没有找到相应的容器。
可能原因及解决方法:
- 容器不存在:检查容器是否已被删除或者已经退出,如果是则不需要处理该错误。
- 容器正在运行:如果容器正在运行,可能是由于正在执行某些任务而无法清理。此时可以尝试停止容器后再进行清理。
- Docker daemon 出现故障:在某些情况下,Docker daemon 可能会出现故障导致无法清理容器。尝试重启 Docker daemon 可能会解决问题。
- 操作系统出现故障:在某些情况下,操作系统可能会出现故障导致无法清理容器。尝试重启操作系统可能会解决问题。
解决办法:手动清理容器,然后重启机器。
1 | docker container prune |
3. 新增节点flannel启动失败
3.1. 问题描述
K8S集群新增了一个节点,flannel pod自动调度上去了,但是并没有启动成功。
查看kubelet日志,报错为:
[failed to find plugin “flannel” in path [/opt/cni/bin]]
W0523 20:49:19.343813 12586 cni.go:239] Unable to update cni config: no valid networks found in /etc/cni/net.d
3.2. 解决办法
从其他正常节点拷贝一个flannel文件到这个问题节点上的 /opt/cni/bin 目录。
4. 节点上的pod被驱逐
4.1. 问题描述
因为磁盘压力,节点上的pod被驱逐了。但是,实际上节点还有很多磁盘空间。
4.2. 解决办法
1、查找kubelet配置文件路径
1 | systemctl status kubelet -l |
找到Drop-In配置文件路径,一般为:
1 | /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf |
2、修改kubelet配置文件
配置文件中添加:
1 | KUBELET_EXTRA_ARGS="--eviction-hard=memory.available<100Mi,nodefs.available<5%,imagefs.available<15%,nodefs.inodesFree<5%" |
3、重启kubelet
1 | systemctl daemon-reload |
4.3. 扩展阅读
节点压力驱逐是 kubelet 主动终止 Pod 以回收节点上资源的过程。
kubelet 监控集群节点的内存、磁盘空间和文件系统的 inode 等资源。 当这些资源中的一个或者多个达到特定的消耗水平, kubelet 可以主动地使节点上一个或者多个 Pod 失效,以回收资源防止饥饿。
在节点压力驱逐期间,kubelet 将所选 Pod 的 PodPhase 设置为 Failed。这将终止 Pod。
我们可以为 kubelet 指定自定义驱逐条件,以便在作出驱逐决定时使用。驱逐条件分为软驱逐条件和硬驱逐条件。
软驱逐条件将驱逐条件与管理员所必须指定的宽限期配对。 在超过宽限期之前,kubelet 不会驱逐 Pod。如果没有指定的宽限期,kubelet 会在启动时返回错误。
硬驱逐条件没有宽限期。当达到硬驱逐条件时, kubelet 会立即杀死 pod,而不会正常终止以回收紧缺的资源。
kubelet 具有以下默认硬驱逐条件:
- memory.available<100Mi
- nodefs.available<10%
- imagefs.available<15%
- nodefs.inodesFree<5%(Linux 节点)
参考文档:节点压力驱逐
5. 业务服务响应很慢
5.1. 问题描述
某个业务服务的Pod响应很慢,发现它的requests资源配置很低,limits资源配置很高。
调大requests后响应速度明显变快了,是什么原理?
5.2. 原理解析
requests是长期允许,保证资源;limits是临时允许,并不保证资源。
上面的问题中,因为requests配置的很低,所以只能保证requests中配置的资源,并不能保证用到用到limits中配置的资源。
5.3. 扩展阅读
“requests”和”limits”在Kubernetes中的原理是通过Linux的cgroups(control groups)来实现资源管理和隔离。cgroups是Linux内核提供的一种机制,它允许对进程组进行资源限制、优先级调整和统计。Kubernetes利用cgroups将资源限制和隔离应用到容器级别。
“requests”定义了容器所需的最小资源数量。Kubernetes调度器使用这个值来决定在哪个节点上运行容器,并确保节点上有足够的资源满足容器的请求。”requests”的目的是为了确保容器能够正常运行而不会遇到资源不足的问题。
而”limits”定义了容器允许使用的资源的上限。Kubernetes使用这个值来监控容器的资源使用情况,并保护节点的稳定性。如果容器试图使用超过其限制的资源量,Kubernetes会采取相应的措施,如终止容器或重新调度到其他节点。”limits”的目的是为了防止容器使用过多的资源,从而保护整个集群的稳定性。
尽管可以在容器中设置超过”requests”的资源使用量,但这并不是一个推荐的做法。当容器超过其”requests”的资源使用量时,它可能会影响其他容器的性能,导致资源竞争和不稳定的情况。超过”requests”的使用量只是暂时允许,Kubernetes会尽力满足容器的需求,但不保证持续提供额外的资源。
6. 节点资源充足但是无法调度
6.1. 问题描述
某个节点CPU、内存资源充足,也没有污点和亲和性配置,但是Pod无法调度到上面。
6.2. 排查解决
除了检查资源之外,再检查下节点上Pod数量的限制。
1 | kubectl describe node node01 |
Non-terminated Pods
要小于 Allocatable.pods
,如果Pod数量已经达到了节点上Pod数量限制,那么需要调大这个上限。
1 | vim /var/lib/kubelet/config.yaml # maxPods默认110,调大它 |
7. kubectl top命令执行报错
7.1. 问题描述
执行kubectl top pod
,报错:
error: Metrics API not available
在Kubernetes Dashboard上,也发现Pod的CPU使用率和内存使用都无法显示。
7.2. 问题分析
参考kubectl top node error: metrics not available yet可知,之所以出现上面的问题,是因为K8S集群没有安装 metrics-server 。
7.3. 解决办法
解决办法:安装 metrics-server 。
通用安装方法:
1 | wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml |
如果是sealos安装的K8S集群,那么可以使用 metrics-server 集群镜像安装。
1 | sealos run labring/metrics-server:v0.6.2 --cmd="\ |
其中 /root/metrics-server/values.yaml 内容为:
1 | defaultArgs: |
8. kubectl get响应慢
8.1. 问题描述
执行 kubectl get xxx
,响应很慢,十几秒,总会几条出现提示:
1 | I0819 11:17:11.769943 2075052 request.go:668] Waited for 1.159893511s due to client-side throttling, not priority and fairness, request: GET:https://192.168.56.101:6443/apis/enterprisesearch.k8s.elastic.co/v1beta1?timeout=32s |
而且每次request后面的内容都不同。
8.2. 解决办法
解决办法:kube-apiserver 的启动参数中添加 --feature-gates=APIPriorityAndFairness=false
具体操作方法:
1 | # master节点 |
添加启动参数:
1 | spec: |
但是,上面的办法只能解决部分问题。kubectl get pod
正常了,但是kubectl get all
还是有问题。
终极解决办法:升级kubectl到v1.22版本以上。从提示其实也能看出是 client-side 侧的限流,但是 kubectl 并没有修改限流配置的方法,只能升级版本。
参考文档:
- Kubectl Error - Waited for … due to client-side throttling, not priority and fairness, request
- API Priority and Fairness
- Crossplane 支持的自定义资源数量突破了 Kubernetes 的限制
- How to avoid “Waited for Xs due to client-side throttling, not priority and fairness”
- kubectl get all - command return - Throttling request
- k8smaster-请求受到了节流
- kube-apiserver