资源管理

在Kubernetes中,Pod是最小的调度单元,所以跟资源和调度相关的属性都是Pod对象的字段,而其中最重要的就是CPU和内存。如下所示:

  1. ---
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: pod-demo
  6. spec:
  7. containers:
  8. - name: myweb
  9. image: wordpress
  10. imagePullPolicy: IfNotPresent
  11. resources:
  12. requests:
  13. memory: "128Mi"
  14. cpu: "250m"
  15. limits:
  16. memory: "256Mi"
  17. cpu: "500m"

其中resources就是资源限制部分。
注:由于一个Pod里可以定义多个Containers,而每个资源限制都是配置在各自的Container,所以Pod的整体配置资源是所有Containers的总和。

在Kubernetes中,CPU这样的资源被称为”可压缩资源”,所谓可压缩资源就是当可用资源不足的时候,Pod只会”饥饿”,不会退出。而向Memory这样的资源被称为”不可压缩资源”,所谓的不可压缩资源就是当资源不足的时候Pod只会OOM。

其中CPU的设置单位是CPU的个数,比如CPU=1就表示这个Pod的CPU限额是1个CPU,而到底是1个CPU核心、是1个vCPU还是1个CPU超线程,这要取决于宿主机上CPU实现方式,而Kunernetes只需要保证该Pod能够使用到1个CPU的使用能力。

Kubernetes允许将CPU的限额设置位分数,比如上面我们设置的CPU.limits的值为500m,而所谓的500m就是500milliCPU,也就是0.5个CPU,这样,这个Pod就会被分到一个CPU一半的计算能力。所以我们可以直接把配置写成cpu=0.5,不过官方推荐500m的写法,这是Kubernetes内部的CPU计算方式。

在Kubernetes中,内存资源的单位是bytes,支持使用Ei,Pi,Ti,Gi,Mi,Ki的方式作为bytes的值,其中需要注意Mi和M的区别(1Mi=10241024,1M=10001000)。

Kubernetes中Pod的CPU和内存的资源限制,实际上分为requests和limits两种情况。

  1. spec.containers[].resources.limits.cpu
  2. spec.containers[].resources.limits.memory
  3. spec.containers[].resources.requests.cpu
  4. spec.containers[].resources.requests.memory

这两者的区别如下:

  • 在调度的时候,kube-scheduler会安requests的值进行计算;
  • 在设置CGroups的时候,kubelet会安limits的值来进行设置;

QoS模型

Kubernetes中支持三种QoS模型。其分类是基于requests和limits的不同配置。

Guaranteed

当Pod里的每一个Containers都设置了requests和limits,并且其值都相等的时候,这种Pod就属于Guaranteed类别,如下:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: qos-demo
  5. namespace: qos-example
  6. spec:
  7. containers:
  8. - name: qos-demo-ctr
  9. image: nginx
  10. resources:
  11. limits:
  12. memory: "200Mi"
  13. cpu: "700m"
  14. requests:
  15. memory: "200Mi"
  16. cpu: "700m"

注意,当这Pod仅设置limits,没有设置requests的时候,系统默认为它分配于limits相等的requests值,也就会被划分为Guaranteed类别。

Burstable

而当这个Pod不满足Guaranteed条件,但至少有一个Contaienrs设置了requests,那么这个Pod就会被划分为Burstable类别。如下:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: qos-demo-2
  5. namespace: qos-example
  6. spec:
  7. containers:
  8. - name: qos-demo-2-ctr
  9. image: nginx
  10. resources:
  11. limits
  12. memory: "200Mi"
  13. requests:
  14. memory: "100Mi"

BestEffort

如果这个Pod既没有设置requests值,也没有设置limits的值的时候,那么它的QoS类别就是BestEffort类别。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: qos-demo-3
  5. namespace: qos-example
  6. spec:
  7. containers:
  8. - name: qos-demo-3-ctr
  9. image: nginx

而QoS划分的主要场景就是当宿主机资源紧张的时候,kubelet对资源进行Eviction时需要用到。目前Kubernetes设置的默认Eviction的阈值如下:

  1. memory.available<100Mi
  2. nodefs.available<10%
  3. nodefs.inodesFree<5%
  4. imagefs.available<15%

上述条件可以在kubelet中设置:

  1. kubelet --eviction-hard=imagefs.available<10%,memory.available<500Mi,nodefs.available<5%,nodefs.inodesFree<5% --eviction-soft=imagefs.available<30%,nodefs.available<10% --eviction-soft-grace-period=imagefs.available=2m,nodefs.available=2m --eviction-max-pod-grace-period=600

Kubernetes中的Eviction分为Soft Eviction和Hard Eviction两种模式。

  • Soft Eviction允许设置优雅等待时间,如上设置imagefs.available=2m,允许在Imagefs不足阈值达到2分钟之后才进行Eviction;
  • Hard Eviction在达到阈值就进行Eviction;

当宿主机的Eviction阈值达到后,就会进入MemoryPressure或者DiskPressure状态,从而避免新的Pod调度到上面去。而当Eviction发生时,kubelet删除Pod的先后顺序如下:

  1. BestEffort 类型的Pod;
  2. Burstable类别并且发生”饥饿”的资源使用量已经超出了requests的Pod;
  3. Guaranteed类别并且只有当Guaranteed类别的Pod的资源使用量超过了其limits限制,或者宿主机本身处于Memory Pressure状态时,Guaranteed才会被选中被Eviction;

cpuset

cpuset,就是把容器绑定到某个CPU核上,减少CPU的上下文切换。

  • Pod必须是Guaranteed类型;
  • 只需要将Pod的CPU资源的requests和limits设置为同一个相等的数值; ```yaml

spec: containers:

  • name: nginx image: nginx resources: limits:
    1. memory: "200Mi"
    2. cpu: "2"
    requests:
    1. memory: "200Mi"
    2. cpu: "2"
    ```