优化 Kubernetes 集群节点内存不足时的 Pod 调度策略,核心在于合理配置资源请求与限制,并利用服务质量(QoS)机制保障关键业务。首先,应为每个 Pod 设置准确的 requests 和 limits,避免资源超卖导致节点过载。其次,通过配置 QoS 类(如 Guaranteed),确保重要 Pod 在资源紧缺时不易被驱逐。此外,可启用 Descheduler 工具进行定期重平衡,防止节点间负载不均。最后,调整 kubelet 的驱逐阈值(eviction threshold),在内存耗尽前提前触发驱逐,保护节点稳定性,并结合监控告警及时调整资源配额。
k8s 解决 pod 调度不均衡的问题
k8s 是通过 sceduler 来调度 pod 的,在调度过程中,由于一些原因,会出现调度不均衡的问题,例如:节点故障 新节点被加到集群中 节点资源利用不足 这些都会导致 pod 在调度过程中分配不均,例如会造成节点负载过高,引发 pod 触发 OOM 等操作造成服务不可用 其中,节点资源利用不足时是最容易出现问题的,例如,设置的 requests 和 limits 不合理,或者没有设置 requests/limits 都会造成调度不均衡 解决办法及分析 在这之前,我们需要先装一个 metrics,安装方法可参考:k8s 的 metrics 部署 Scheduler 在调度过程中,经过了预选阶段和优选阶段,选出一个可用的 node 节点,来把 pod 调度到该节点上。那么在预选阶段和优选阶段是如何选出 node 节点的呢?最根本的一个调度策略就是判断节点是否有可分配的资源,我们可以通过以下 kubectl describe node node 名来查看,现在按照这个调度策略来分析下 查看当前的节点资源占用情况 可以看到,当前的 k8s 集群共有三个 node 节点,但是节点的资源分布情况极其不均匀,而实际上,k8s 在进行调度时,计算的就是 requests 的值,不管你 limits 设置多少,k8s 都不关心。所以当这个值没有达到资源瓶颈时,理论上,该节点就会一直有 pod 调度上去。所以这个时候就会出现调度不均衡的问题。有什么解决办法?给每一个 pod 设置 requests 和 limits,如果资源充足,最好将 requests 和 limits 设置成一样的,提高 Pod 的 QoS 重平衡,采取人为介入或定时任务方式,根据多维度去对当前 pod 分布做重平衡 重平衡工具 Descheduler 工具简介 Descheduler 的出现就是为了解决 Kubernetes 自身调度 (一次性调度) 不足的问题。它以定时任务方式运行,根据已实现的策略,重新去平衡 pod 在集群中的分布。截止目前,Descheduler 已实现的策略和计划中的功能点如下:已实现的调度策略 RemoveDuplicates 移除重复 pod LowNodeUtilization 节点低度使用 RemovePodsViolatingInterPodAntiAffinity 移除违反 pod 反亲和性的 pod RemovePodsViolatingNodeAffinity 路线图中计划实现的功能点 Strategy to consider taints and tolerations 考虑污点和容忍 Consideration of pod affinity 考虑 pod 亲和性 Strategy to consider pod life time 考虑 pod 生命周期 Strategy to consider number of pending pods 考虑待定中的 pod 数量 Integration with cluster autoscaler 与集群自动伸缩集成 Integration with metrics providers for obtaining real load metrics 与监控工具集成来获取真正的负载指标(截至 2026 年 1 月 6 日)
Kubernetes 节点资源不足该怎么解决?
导读:节点资源不足 (out-of-resource) 是管理集群时经常出现的情况,本文讨论了一些实用的 Kubernetes 管理实践,可用于 Kubernetes 中节点资源不足的高效管理。kubelet 是 Kubernetes 中主要节点组件,执行许多关键任务,特别是:用 kube-apiserver 注册节点。监视 kube-apiserver 中已经调度的 Pod,通知容器运行时在调度新 Pod 之后重新启动容器。监视运行中的容器并将其状态报告给 kube-apiserver。执行 liveness 探针并在容器运行失败后重新启动容器。运行由 kubelet 直接管理的静态 Pod。与 Core Metrics Pipeline 和容器运行时进行交互以收集容器和节点度量。本文中要讨论的是 kubelet 另一个重要功能:当节点资源耗尽时,“主节点代理”驱逐 Pod 的能力。当磁盘、RAM 或 CPU 等计算资源不足时,kubelet 可以极大维护节点稳定性。对于 Kubernetes 管理员而言,了解配置资源外的处理很必要,可以保持节点资源灵活性以及系统的整体容错性和关键系统进程的稳定性。kubelet 如何确定资源不足?kubelet 可以从节点上驱逐工作负载,以释放资源来处理其他 Pod 或系统任务,例如容器运行时或 kubelet 本身,但 kubelet 是如何确定资源不足的?其实 kubelet 是通过 eviction signal(驱逐信号) 和 eviction threshold(驱逐阈值) 确定何时回收资源。驱逐信号是系统资源 (如内存或存储) 的当前容量。驱逐阈值则是 kubelet 维护的资源最小值。换句话说,每个驱逐信号都与某个驱逐阈值相关联,该驱逐阈值会告诉 kubelet 何时开始回收资源。目前,kubelet 支持以下驱逐信号::描述集群内存状态的信号。内存的默认驱逐阈值为 100Mi。换句话说,当内存下降到 100Mi 时,kubelet 就会开始驱逐 Pod。:是 kubelet 用于卷、守护进程日志等的文件系统。默认情况下,如果 :描述 nodefs 索引节点内存状态的信号。默认情况下,如果 nodefs.inodesFree :文件系统是容器运行时使用的可选文件系统,用于存储容器镜像和容器可写层。默认情况下,如果 :索引 imagefs 节点内存的状态。它没有默认驱逐阈值。上述驱逐阈值都是合理的默认值。用户可以通过在 kubelet binary 上设置适当的 flag 来配置其自定义驱逐阈值。这些用户定义的阈值可以更改默认的 kubelet 驱逐行为。目前,Kubernetes 支持硬驱和软驱逐阈值。如果达到硬驱逐阈值,kubelet 将立即开始回收资源,而没有任何宽限期。软驱逐阈值则会包含用户定义的宽限期。在超过宽限期前,kubelet 不会回收与驱逐信号关联的资源。(来自 2021 年 3 月 17 日的资料)
Kubernetes 中资源紧缺时的 Pod 驱逐机制
Kubernetes 中的 Pod 驱逐机制是通过调度器 (scheduler) 来实现的。当资源紧缺时,调度器会根据一定的策略选择需要被驱逐的 Pod。以下情况会触发 Pod 驱逐机制:节点不可用:如果某个节点发生故障或被标记为不可调度状态,其上的所有 Pod 都会被驱逐并重新调度到其他可用节点上。资源不足:当集群中的资源 (如 CPU、内存) 紧缺时,调度器会根据各个 Pod 的优先级和资源需求来选择需要驱逐的 Pod。扩容需求:当有新的 Pod 需要调度到集群中,但没有足够的资源可用时,旧的 Pod 可能会被驱逐以腾出资源给新的 Pod。调整 Pod 驱逐机制以适应特定的业务需求可以通过以下方法实现:设置 Pod 的资源请求和限制:通过合理设置 Pod 的资源请求和限制,可以影响调度器在资源紧缺时选择需要驱逐的 Pod。较高的资源请求会增加 Pod 被驱逐的概率。设置 Pod 的优先级:通过设置 Pod 的优先级,可以告诉调度器哪些 Pod 应该被优先保留,哪些 Pod 可以被驱逐。较高优先级的 Pod 将更不易被驱逐。调整 Pod 的驱逐策略:Kubernetes 提供了一些驱逐策略参数,如 terminationGracePeriodSeconds(Pod 被终止前的等待时间),通过调整这些参数可以影响驱逐的行为。使用 PodDisruptionBudget(PDB):PDB 是一种资源对象,可以限制同时被驱逐的 Pod 的数量,确保集群中总是有足够的可用 Pod。通过创建和配置 PDB,可以灵活地控制 Pod 的驱逐行为。上述方法是通过调整 Pod 的调度和资源配置来影响 Pod 驱逐机制的行为,以满足特定的业务需求。(发布时间是 2023 年 9 月 10 日)
配置 Pod 的服务质量
本页介绍怎样配置 Pod 以让其归属于特定的服务质量类 (Quality of Service class,QoS class). Kubernetes 在 Node 资源不足时使用 QoS 类来就驱逐 Pod 作出决定。Kubernetes 创建 Pod 时,会将如下 QoS 类之一设置到 Pod 上:Guaranteed Burstable BestEffort 说明:Kubernetes 在创建 Pod 时会分配 QoS 类,并且这一 QoS 类在 Pod 的整个生命周期内保持不变。如果你尝试将 Pod 资源调整为会导致不同 QoS 类的值,控制平面将拒绝你的请求并返回错误消息。准备开始 你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与集群通信。建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:iximiuz Labs Killercoda KodeKloud 你还需要能够创建和删除名字空间。创建名字空间 创建一个名字空间,以便将本练习所创建的资源与集群的其余资源相隔离。kubectl create namespace qos-example 创建一个 QoS 类为 Guaranteed 的 Pod 对于 QoS 类为 Guaranteed 的 Pod:Pod 中的每个容器都必须指定内存限制和内存请求。对于 Pod 中的每个容器,内存限制必须等于内存请求。Pod 中的每个容器都必须指定 CPU 限制和 CPU 请求。对于 Pod 中的每个容器,CPU 限制必须等于 CPU 请求。这些限制同样适用于初始化容器和应用程序容器。临时容器 (Ephemeral Container) 无法定义资源,因此不受这些约束限制。下面是包含一个 Container 的 Pod 清单。该 Container 设置了内存请求和内存限制,值都是 200 MiB。该 Container 设置了 CPU 请求和 CPU 限制,值都是 700 milliCPU:pods/qos/qos-pod.yaml apiVersion:v1kind:Podmetadata:name:qos-demonamespace:qos-examplespec:containers:-name:qos-demo-ctrimage:nginxresources:limits:memory:"200Mi"cpu:"700m"requests:memory:"200Mi"cpu:"700m" 创建 Pod:kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=qos-example 查看 Pod 详情:kubectl get pod qos-demo --namespace=qos-example --output=yaml 结果表明 Kubernetes 为 Pod 配置的 QoS 类为 Guaranteed。结果也确认了 Pod 容器设置了与内存限制匹配的内存请求,设置了与 CPU 限制匹配的 CPU 请求。spec:containers:resources:limits:cpu:700mmemory:200Mirequests:cpu:700mmemory:200Mistatus:(2026 年 2 月 23 日)
FAQ
什么是 Kubernetes 中的 QoS 类?
Kubernetes 根据 Pod 的资源请求和限制设置,将其分为 Guaranteed、Burstable 和 BestEffort 三类,用于决定资源不足时的驱逐优先级。
Descheduler 的作用是什么?
Descheduler 以定时任务方式运行,根据策略重新平衡 Pod 在集群中的分布,解决调度不均衡问题。
节点内存不足时 kubelet 如何反应?
kubelet 通过驱逐信号和阈值确定资源不足,达到硬阈值时立即回收资源,软阈值则包含宽限期。