Kubernetes集群多租户资源管理,


1.概述

先讲解Pod的两个重要参数:CPU Request与Memory Request。在大多数情况下我们在定义Pod时并没有定义这两个参数,此时Kubernetes会认为该Pod所需的资源很少,并可以将其调度到任何可用的Node上。这样一来,当集群中的计算资源不很充足时,如果集群中的Pod负载突然加大,就会使某个Node的资源严重不足。

为了避免系统挂掉,该Node会选择“清理”某些Pod来释放资源,此时每个Pod都可能成为牺牲品。但有些Pod担负着更重要的职责,比其他Pod更重要,比如与数据存储相关的、与登录相关的、与查询余额相关的,即使系统资源严重不足,也需要保障这些Pod的存活,Kubernetes中该保障机制的核心如下。

  • 通过资源限额来确保不同的Pod只能占用指定的资源
  • 允许集群的资源被超额分配,以提高集群的资源利用率
  • 为Pod划分等级,确保不同等级的Pod有不同的服务质量(QoS),资源不足时,低等级的Pod会被清理,以确保高等级的Pod稳定运行

Kubernetes集群里的节点提供的资源主要是计算资源,计算资源是可计量的能被申请、分配和使用的基础资源,这使之区别于API资源(API Resources,例如Pod和Services等)。当前Kubernetes集群中的计算资源主要包括CPU、GPU及Memory,绝大多数常规应用是用不到GPU的,因此这里重点介绍CPU与Memory的资源管理问题

CPU与Memory是被Pod使用的,因此在配置Pod时可以通过参数CPU Request及Memory Request为其中的每个容器指定所需使用的CPU与Memory量,Kubernetes会根据Request的值去查找有足够资源的Node来调度此Pod,如果没有,则调度失败。

2.Pod资源使用规范

我们知道,一个pod所使用的CPU与Memory是一个动态的量,确切地说,是一个范围,跟它的负载密切相关:负载增加时,CPU和Memory的使用量也会增加。因此最准确的说法是,某个进程的CPU使用量为0.1个CPU~1个CPU,内存占用则为500MB~1GB。对应到Kubernetes的Pod容器上,cpu和Memory 分别有两个限制:

  • Requests 表示业务正常运行所需要资源 属于预留资源
  • Limit 表示业务最大使用资源 该值为不保障资源 资源足够情况下最大使用资源值

其中CPU 为可压缩资源 按照时间片进行调度,Memory 为不可压缩资源 属于硬限制资源类型,limits对应资源量的上限,即最多允许使用这个上限的资源量。由于CPU资源是可压缩的,进程无论如何也不可能突破上限,因此设置起来比较容易。对于Memory这种不可压缩资源来说,它的Limit设置就是一个问题了,如果设置得小了,当进程在业务繁忙期试图请求超过Limit限制的Memory时,此进程就会被Kubernetes杀掉。因此,Memory的Request与Limit的值需要结合进程的实际需求谨慎设置。如果不设置CPU或Memory的Limit值,会怎样呢?在这种情况下,该Pod的资源使用量有一个弹性范围,我们不用绞尽脑汁去思考这两个Limit的合理值,但问题也来了,考虑下面的例子:

Pod A的Memory Request被设置为1GB,Node A当时空闲的Memory为1.2GB,符合Pod A的需求,因此Pod A被调度到Node A上。运行3天后,Pod A的访问请求大增,内存需要增加到1.5GB,此时Node A的剩余内存只有200MB,由于PodA新增的内存已经超出系统资源,所以在这种情况下,Pod A就会被Kubernetes杀掉。

没有设置Limit的Pod,或者只设置了CPU Limit或者Memory Limit两者之一的Pod,表面看都是很有弹性的,但实际上,相对于4个参数都被设置的Pod,是处于一种相对不稳定的状态的,它们与4个参数都没设置的Pod相比,只是稳定一点而已。理解了这一点,就很容易理解Resource QoS问题了。

如果我们有成百上千个不同的Pod,那么先手动设置每个Pod的这4个参数,再检查并确保这些参数的设置,都是合理的。比如不能出现内存超过2GB或者CPU占据2个核心的Pod。最后还得手工检查不同租户(Namespace)下的Pod的资源使用量是否超过限额。为此,Kubernetes提供了另外两个相关对象:LimitRange及ResourceQuota,前者解决request与limit参数的默认值和合法取值范围等问题,后者则解决约束租户的资源配额问题。

  • CPU 相关规则如下:

单位m,10m=0.01核,1核=1000m

Requests 根据业务实际使用量进行预估填写

Limits = Requests * 20% + Requests

  • Memory 相关规则如下:

单位Mi 1024Mi=1G内存

Requests 根据业务实际使用量进行预估填写

Limits = Requests * 20% + Requests

3.Namespace资源管理规范

业务实际Requests Limit 不超过整体80% 防止业务滚动更新无足够资源创建Pod

3.1 多租户资源使用策略

通过ResourceQuota限制对应项目组资源用量

3.2 资源用量变更流程

4.资源监控及检查

4.1 资源使用监控

  • Namespace Reuqests资源使用率
  1. sum (kube_resourcequota{type="used",resource="requests.cpu"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.cpu"}) by (resource,namespace) * 100 
  2.  
  3. sum (kube_resourcequota{type="used",resource="requests.memory"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.memory"}) by (resource,namespace) * 100 
  • Namespace Limit资源使用率
  1. sum (kube_resourcequota{type="used",resource="limits.cpu"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.cpu"}) by (resource,namespace) * 100 
  2.  
  3. sum (kube_resourcequota{type="used",resource="limits.memory"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.memory"}) by (resource,namespace) * 100 

4.2 通过Grafana 进行查看

  • CPU请求率
  1. sum (kube_resourcequota{type="used",resource="requests.cpu",namespace=~"$NameSpace"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.cpu",namespace=~"$NameSpace"}) by (resource,namespace) 
  • 内存请求率
  1. sum (kube_resourcequota{type="used",resource="requests.memory",namespace=~"$NameSpace"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="requests.memory",namespace=~"$NameSpace"}) by (resource,namespace) 
  • CPU限制率
  1. sum (kube_resourcequota{type="used",resource="limits.cpu"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.cpu"}) by (resource,namespace) 
  • 内存限制率
  1. sum (kube_resourcequota{type="used",resource="limits.memory"}) by (resource,namespace) / sum (kube_resourcequota{type="hard",resource="limits.memory"}) by (resource,namespace) 

4.3 集群内查看资源使用

  • 查看资源使用量
  1. [root@k8s-dev-slave04 yaml]# kubectl describe resourcequotas -n cloudchain--staging 
  2.  
  3. Name:            mem-cpu-demo 
  4.  
  5. Namespace:       cloudchain--staging 
  6.  
  7. Resource         Used   Hard 
  8.  
  9. --------         ----   ---- 
  10.  
  11. limits.cpu       200m   500m 
  12.  
  13. limits.memory    200Mi  500Mi 
  14.  
  15. requests.cpu     150m   250m 
  16.  
  17. requests.memory  150Mi  250Mi 
  • 查看event事件 判断是否正常创建
  1. [root@kevin ~]# kubectl get event -n default 
  2.  
  3. LAST SEEN   TYPE      REASON         OBJECT                          MESSAGE 
  4.  
  5. 46m         Warning   FailedCreate   replicaset/hpatest-57965d8c84   Error creating: pods "hpatest-57965d8c84-s78x6" is forbidden: exceeded quota: mem-cpu-demo, requested: limits.cpu=400m,limits.memory=400Mi, used: limits.cpu=200m,limits.memory=200Mi, limited: limits.cpu=500m,limits.memory=500Mi 
  6.  
  7. 29m         Warning   FailedCreate   replicaset/hpatest-57965d8c84   Error creating: pods "hpatest-57965d8c84-5w6lk" is forbidden: exceeded quota: mem-cpu-demo, requested: limits.cpu=400m,limits.memory=400Mi, used: limits.cpu=200m,limits.memory=200Mi, limited: limits.cpu=500m,limits.memory=500Mi 
  8.  
  9. 13m         Warning   FailedCreate   replicaset/hpatest-57965d8c84   Error creating: pods "hpatest-57965d8c84-w2qvz" is forbidden: exceeded quota: mem-cpu-demo, requested: limits.cpu=400m,limits.memory=400Mi, used: limits.cpu=200m,limits.memory=200Mi, limited: limits.cpu=500m,limits.memory=500Mi 

本文转载自微信公众号「运维开发故事」

相关内容