https://kubernetes.io/zh/docs/tasks/configure-pod-container/quality-service-pod

https://www.qikqiak.com/k8strain2/maintain/reserved

https://kubernetes.io/zh/docs/tasks/administer-cluster/reserve-compute-resources

内存压测:

  1. yum install -y stress
  2. stress -i 1 --vm 1 --vm-bytes 20G
fortio load -a -c 8 -qps 500 -t 60s "http://$NodeIP:$NodePort/"
这里是用NodePort的服务发布形式,发布我们的示例程序$NodeIP $NodePort

Node Allocatable

Kubernetes 节点上的 Allocatable 被定义为 Pod 可用计算资源量,调度器不会超额申请 Allocatable,目前支持 CPU, memory 和 ephemeral-storage

kubectl describe node node02
......
Capacity:
 cpu:                4
 ephemeral-storage:  36678148Ki
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             7990056Ki
 pods:               110
Allocatable:
 cpu:                4
 ephemeral-storage:  33802581141
 hugepages-1Gi:      0
 hugepages-2Mi:      0
 memory:             7887656Ki
 pods:               110
......

没有配置资源预留,所以默认情况下 Capacity 与 Allocatable 的值基本上是一致的

kubernetes 资源配额分配-服务质量(QoS)类 - 图1

节点可分配资源的计算方式为:

Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold

ResourceQuota可以对某个命名空间下资源总量进行限制
LimitRange可以为某个命令空间下POD中容器提供资源配额的默认值,以及指定资源配额的设置范围

CPU和RAM 换算单位如下:
1) CPU
单位为m时表示毫核(1个逻辑核分1000毫核);单位为空默认单位为(逻辑)核。
2) RAM
K,M,G,T,P,E 通常这些单位是以1000为换算标准的。
Ki, Mi,Gi, Ti,Pi, Ei 这些通常是以1024为换算标准的

requests和limits

举例:
kubernetes 资源配额分配-服务质量(QoS)类 - 图2
节点上有A、B、C三个POD,现在 Pod D在调度的时候,K8s统计节点上未分配的资源量,其中CPU的未分配资源量(Unallocated)小于Pod D的CPU requests值,故Pod D仍然无法调度到该节点上。可见,K8S 调度Pod的时候并不关注在调度时节点的资源实际使用情况,而是根据现存非终止态容器的requests之和情况判断是否进行调度。(已验证,终止态容器包含初始化容器和job的业务容器)
此外, Pod实际使用量可能大于或小于设置的requests资源值。如果Kubernetes找不到满足资源请求的Node,则Pod创建会停留在Pending状态。

针对CPU和RAM,requests的作用总结如下:

  • CPU requests的作用

1) 作为k8s调度POD进行节点筛选的判断依据(绝对值)
2) 宿主机CPU资源抢占时,容器按比例分配CPU使用的依据(相对值)
CPU requests,会对应到容器内cgroup下cpu.shares属性上,当宿主机CPU资源发生抢占时,各个容器按照shares份额比例进行宿主机CPU资源的使用。

  • RAM requests的作用

1) POD作为k8s调度POD进行节点筛选的依据

CPU是一种可以压榨的资源,可以用满并且Pod之间可以共享使用。CPU limits会作用到cgroup下的cpu.cfs_quota_us(CPU切换周期内的最大使用时间,单位us)属性上,从而控制POD能使用的CPU资源的上限。
cpu.cfs_quota_us值受cpu.cfs_period_us(CPU切换周期,默认100ms)的影响。公式近似如下:
kubernetes 资源配额分配-服务质量(QoS)类 - 图3
内存limits对应cgroup下memory.limit_in_bytes属性上,当节点的RAM被使用完或者POD超过了limits上限,便会触发 OOM Killed。

  • CPU 预留显示在清单文件中的 .spec.containers[].resources.requests.cpu,实际用量可以超过 CPU 预留。
  • 内存预留显示在清单文件中的 .spec.containers[].resources.requests.memory。实际用量可以超过内存预留,但节点内存不足时可能会清理容器。

  • CPU 限制显示在清单文件中的 .spec.containers[].resources.limits.cpu。实际用量可以短时间超过 CPU 限制,容器不会被停止。

  • 内存限制显示在清单文件中的 .spec.containers[].resources.limits.memory。实际用量不能超过内存限制,如果超过了,容器可能会被停止或者被调度到其他资源充足的机器上。

requests
requests用于schedule阶段,在调度pod保证所有pod的requests总和小于node能提供的计算能力
requests.cpu被转成docker的—cpu-shares参数,与cgroup cpu.shares功能相同
设置容器的cpu的相对权重
该参数在CPU资源不足时生效,根据容器requests.cpu的比例来分配cpu资源
CPU资源充足时,requests.cpu不会限制container占用的最大值,container可以独占CPU
requests.memory没有对应的docker参数,作为k8s调度依据
使用requests来设置各容器需要的最小资源

limits
limits限制运行时容器占用的资源
limits.cpu会被转换成docker的–cpu-quota参数。与cgroup cpu.cfs_quota_us功能相同
限制容器的最大CPU使用率。
cpu.cfs_quota_us参数与cpu.cfs_period_us结合使用,后者设置时间周期
k8s将docker的–cpu-period参数设置100毫秒。对应着cgroup的cpu.cfs_period_us
limits.cpu的单位使用m,千分之一核

limits.memory会被转换成docker的–memory参数。用来限制容器使用的最大内存
当容器申请内存超过limits时会被终止

如果一个容器只指明了limit,而未指明request,则表明request的值等于limit的值

QoS Classes: Guaranteed > Burstable > Best-Effort

Guaranteed
如果Pod中所有Container的所有Resource的limit和request都相等且不为0,则这个Pod的QoS Class就是Guaranteed

Best-Effort 如果Pod中所有容器的所有Resource的request和limit都没有赋值,则这个Pod的QoS Class就是Best-Effort

Burstable 除了符合Guaranteed和Best-Effort的场景,其他场景的Pod QoS Class都属于Burstable
当limit值未指定时,其有效值其实是对应Node Resource的Capacity

如果你需要保证的你应用优先级很高,也就是资源吃紧的情况下最后再杀掉你的 Pod,那么你就把你的 requests 和 limits 的值设置成一致
具体的 limits 数量应该根据运行一段时间和压测的实际占用量来设置