一、资源管理

当我们创建Pod时,可以对POD使用的资源做一些限制,比如CPU、Memory等。也可以从namespace维度,来对整个namespace的资源使用限制。

1、POD资源限制

通过pods.spec.containers.resources中limits和requests字段来控制Pod容器的资源分配。
requests定义Pod容器需要的最小资源量,limits定义Pod容器最大可用的资源上限。

在调度时,kube-scheduler只会按照requests的值进行计算。而在真正设置Cgroups限制时,kubelet则会按照limits的值来进行设置。

支持限制的资源类型: 

  • CPU(单位为millicore,1Core=1000millicore)
  • Memory(单位为Byte)
  • Ephemeral storage(临时存储,单位为Byte)
  • 自定义资源: 配置时必须为整数

示例:

# pod-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: zjmns
spec:
  containers:
    - image: 'test.registry.com/myns/nginx:1.7.9'
      name: myweb
      resources:
        requests:
          cpu: 100m
          memory: 200Mi
          ephemeral-storage: "2Gi"
        limits:
          cpu: 150m
          memory: 200Mi
          ephemeral-storage: "4Gi"

# kubectl create -f pod-demo.yaml

2、Pod服务质量(QoS)配置

不同的requests和limits的设置方式,会将这个Pod划分到不同的QoS类别当中,共有三种类别: Guaranteed, Burstable, BestEffort。

QOS划分作用是: 当节点主机资源紧张或不足时,kubelet会把一些低优先级的,或者说服务质量要求不高的Pod优先删除掉。
按Qos类别删除顺序是:BestEffort > Burstable > Guaranteed。若Pod的QoS类别相同时,还要根据Pod的优先级来做进一步的排序和选择。

根据不同业务的要求和属性来配置资源的Limits和Request,做到合理的规划Qos Class。因为当内存不足时,BestEffort Pod会最先被kill掉,当节点发生eviction时,也会优先考虑驱逐 BestEffort的pod。

Guaranteed: 

Pod里的每一个Container都同时设置了requests和limits,且requests和limits值相等时,这个Pod就属于Guaranteed类别。
当Pod仅设置了limits而未设置requests时,Kubernetes会自动为它设置与limits相同的requests值,所以这也属于Guaranteed情况。

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo-guaranteed
  namespace: zjmns
spec:
  containers:
  - name: myweb
    image: nginx
    resources:
      requests:
        cpu: "100m"
        memory: "200Mi"
      limits:
        cpu: "100m"
        memory: "200Mi"

Burstable: 

Pod不满足Guaranteed的条件(只要requests与limits中的CPU/Memory值不相等),但至少有一个Container设置了requests,这个Pod会被划分到Burstable类别。

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo-burstable
  namespace: zjmns
spec:
  containers:
  - name: myweb
  	image: nginx
    resources:
      requests:
        memory: "200Mi"
      limits:
        memory: "100Mi"

BestEffort: 

一个Pod既没有设置requests,也没有设置limits,则这个Pod的QoS类别就是BestEffort。

apiVersion: v1
kind: Pod
metadata:
  name: test-demo-BestEffort
  namespace: zjmns
spec:
  containers:
  - name: myweb
  	image: nginx

3、CPU管理策略

是指把Pod容器绑定到某个CPU的核上运行。能减少系统在CPU之间进行上下文切换的次数,从而提升容器里应用的性能。

条件是Pod必须是Guaranteed的QoS类型,并需要将requests和limits中的cpu设置为相同的值,且requests是一个整数值。
而非整数的Guaranteed/Burstable/BestEffort,它们的CPU会放在一块,组成一个CPU share pool,然后共享,不会绑定到CPU的某个核上。

整数Guaranteed    非整数Guaranteed/Burstable/BestEffort
 ————————————————— —————————————————————————————————————
|  CPU0  |  CPU1  |     Cpushare Pool(cpu2~cpu7)        |
 ————————————————— —————————————————————————————————————

比如一个节点的CPU有8个核,有一个Guaranteed Pod的requests设置为2,则kubelet会将CPU0和CPU1分配给Guaranteed Pod去绑定,而剩下的6个核CPU2~CPU7,会被非整数的Guaranteed/Burstable/BestEffort共享,然后它们会根据不同的权重划分时间片来使用这6个核的CPU。

示例:该Pod就会被绑定在2个独占的CPU核上,具体是哪两个CPU核,是由kubelet自动分配的。

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo-cpuset
  namespace: zjmns
spec:
  containers:
  - name: myweb
    image: nginx
    resources:
      limits:
        memory: "200Mi"
        cpu: "2"
      requests:
        memory: "200Mi"
        cpu: "2"

4、Resource Quota

ResourceQuota用于限制每个namespace的资源使用量。当K8S集群上有多个NameSapce时,很容易出现namespace之间的资源抢占。
或者说,当多用户或团队共享一个K8S系统时,一个用户对应一个namsespace,那管理员可通过设置ResourceQuota来防止用户之间的资源抢占。

当用户超过了资源使用量,在创建资源时,会提示403 FORBIDDEN。
可针对namespace下各种资源进行设置配额,如计算资源(cpu、memory),存储资源(pvc),对象数量(services、pods等)。

示例:

# rquota-demo.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: ns-quota-demo
  namespace: zjmns
spec:
  hard:
    configmaps: "100"             #最大配置文件数量限制
    limits.cpu: "4"               #最大CPU数量限制
    limits.memory: 2G             #最大内存限制
    requests.storage: 100M        #最大存储空间限制
    persistentvolumeclaims: "4"   #最大PV数量限制
    pods: "4"                     #最大Pod数量限制
    secrets: "4"                  #最大保密字典数量限制
    services: "4"                 #最大服务数量限制
    services.loadbalancers: "4"   #最大负载均衡型服务数量限制

# kubectl create -f rquota-demo.yaml
# 字段解析可参考官网:https://kubernetes.io/docs/concepts/policy/resource-quotas/

Quota Scopes: 也可以为某个Quota定义一个Scope,即作用域,定义后这个Quota只会对作用域内的资源生效。

示例:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: user1-quota
  namespace: user1
spec:
  hard:
    cpu: "10"
    memory: 20Gi
    pods: "10"
  scopeSelector:
    matchExpressions:
    - operator : Exists
      scopeName: NotBestEffort

# 参数说明:
# operator: 若scopeSelector有定义时,且scopeName值为Terminating/NotTerminating/BestEffort/NotBestEffort,则operator的值只能定义为Exists。
# scopeName:值为NotBestEffort,表示匹配所有Qos不是BestEffort的Pod。

# 示例说明:
# 这个ResourceQuota意思是,限制user1 namespace下的非BestEffort的Pod:cpu只能用10个核,memory只能用20G,pods只能创建10个。

# 查看ResourceQuota定义了哪些限制规则
kubectl get quota -n zjmns
kubectl describe quota ns-quota-demo -n zjmns

# 查看某个命名空间定义了哪些ResourceQuota(一个命名空间能有多个,但只有第一个才会起作用)
kubectl describe ns zjmns

二、总结(如何满足Pod资源要求)

Pod要配置合理的资源要求,包括:CPU/Memory/EphemeralStorage/GPU

通过Request和Limit来为不同业务特点的Pod选择不同的QoS:
Guaranteed:敏感型,需要业务保障
Burstable:次敏感型,需要弹性业务
BestEffort:可容忍性业务

为每个NameSpace配置ResourceQuota来防止过量使用,保障其他人的资源可用