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
内存压测:
yum install -y stress
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 的值基本上是一致的
节点可分配资源的计算方式为:
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
举例:
节点上有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)的影响。公式近似如下:
内存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 数量应该根据运行一段时间和压测的实际占用量来设置