前言
在近期的工作中,我们发现 k8s 集群中有些节点资源使用率很高,有些节点资源使用率很低,我们尝试重新部署应用和驱逐 Pod,发现并不能有效解决负载不均衡问题。在学习了 Kubernetes 调度原理之后,重新调整了 Request 配置,引入了调度插件,才最终解决问题。这篇就来跟大家分享 Kubernetes 资源和调度相关知识,以及如何解决k8s调度不均衡问题。
Kubernetes 的资源模型
在 Kubernetes 里,Pod 是最小的原子调度单位。这也就意味着,所有跟调度和资源管理相关的属性都应该是属于 Pod 对象的字段。而这其中最重要的部分,就是 Pod 的 CPU 和内存配置。像 CPU 这样的资源被称作“可压缩资源”(compressible resources)。它的典型特点是,当可压缩资源不足时,Pod 只会“饥饿”,但不会退出。而像内存这样的资源,则被称作“不可压缩资源(incompressible resources)。当不可压缩资源不足时,Pod 就会因为 OOM(Out-Of-Memory)被内核杀掉。Pod 可以由多个 Container 组成,所以 CPU 和内存资源的限额,是要配置在每个 Container 的定义上的。这样,Pod 整体的资源配置,就由这些 Container 的配置值累加得到。Kubernetes 里 Pod 的 CPU 和内存资源,实际上还要分为 limits 和 requests 两种情况:
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
这两者的区别其实非常简单:在调度的时候,kube-scheduler 只会按照 requests 的值进行调度。而在真正设置 Cgroups 限制的时候,kubelet 则会按照 limits 的值来进行设置。这是因为在实际场景中,大多数作业使用到的资源其实远小于它所请求的资源限额,这种策略能有效的提高整体资源的利用率。
Kubernetes 的服务质量
服务质量 QoS 的英文全称为 Quality of Service。在 Kubernetes 中,每个 Pod 都有个 QoS 标记,通过这个 Qos 标记来对 Pod 进行服务质量管理,它确定 Pod 的调度和驱逐优先级。在 Kubernetes 中,Pod 的 QoS 服务质量一共有三个级别:
-
Guaranteed:当 Pod 里的每一个 Container 都同时设置了 requests 和 limits,并且 requests 和 limits 值相等的时候,这个 Pod 就属于 Guaranteed 类别 。
-
Burstable:而当 Pod 不满足 Guaranteed 的条件,但至少有一个 Container 设置了 requests。那么这个 Pod 就会被划分到 Burstable 类别。
-
BestEffort:而如果一个 Pod 既没有设置 requests,也没有设置 limits,那么它的 QoS 类别就是 BestEffort。
具体地说