记录下自己在使用KubeSphere过程中由于YAML中错误的配置导致Kubernetes经常资源紧张而无法创建与部署新节点的问题。

问题描述

部门在使用KubeSphere过程中经常遇到类似如下图所示的由于kubernetes无法调度而导致的无法部署的问题

kubesphere部署失败

进一步查看报错节点信息会发现提示CPU资源不足,从而导致无法部署。

内存不足导致k8s无法调度

之前自己采取的解决方案是暴力的删除一部分节点来释放CPU资源,但此种方式治标不治本,且随着KubeSphere在部门内部使用的普及,此问题发生的频率越来越高,只能想办法从根源上处理。

分析与解决

由于提示的是CPU资源不足,首先检查是否为CPU的问题,采用lscpu | egrep 'Model name|Socket|Thread|NUMA|CPU\(s\)'free -g分别查看CPU和内存信息,结果如下

服务器CPU和内存信息

从查询结果可知系统的CPU配置和内存配置都很高,而自己在KubeSphere中部署的都是一些普通的Java程序,不可能占用特别多的CPU和内存资源,Linux服务器本身的配置问题排除。

接下来利用kubectl describe node查看节点信息,输出结果如下

查看k8s节点信息

在上图中可发现相关节点汇总后的CPU和内存占用的百分比非常大,其中CPU在Requests部分占比为84%,由于Linux系统自身运行和运行KubesphereKubernetes都需要占用一定的CPU资源,从而导致当Kubersphere中部署的项目超过一定数量时,Linux系统无法给Kubernetes分配足够的CPU资源导致部署失败。至此,问题的表面原因找出来了。

进一步分析上面的问题,自己觉得很好奇的是为啥Requests部分占用的资源,自己在对应的YAML文件中压根就没指定Requests相关的参数,检查代码发现Limits配置的值比较大

1
2
3
4
resources: 
  limits: 
    cpu: 500m
    memory: 2000Mi

同时基于kubectl describe node发现相关节点的Requests和Limits的值都相同,猜测是否Kubernetes默认将Ruquests的值设置为与Limits的值相同。

k8s节点limits和requests相同

Kubernetes官网发现如下说明

Note: If you specify a limit for a resource, but do not specify any request, and no admission-time mechanism has applied a default request for that resource, then Kubernetes copies the limit you specified and uses it as the requested value for the resource.

上述文字说明当我们在YAML文件中只设置了Limits但是没有指定Requests,则Kubernetes会将Request的值默认设置为与Limits相同,从而导致CPU和内存资源占用都很高,至此问题根源找到!

解决的方式也很简单,要么移除掉Limits,让Kubernetes根据Linux系统资源和节点状况给我们动态的分配节点,或者同时指定Requests和Limits即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 屏蔽此部分代码
#resources: 
#  limits: 
#    cpu: 500m
#    memory: 2000Mi 

# 或者显示配置request和limits
resources: 
  limits: 
    cpu: 500m
    memory: 2000Mi
  requests: 
    cpu: 20m
    memory: 64Mi

经验教训: 需要对自己项目中的代码要有更深入的理解,尤其是配置文件,要做到理解每一行的作用,不能简单的复制别人的代码。


参考文档: