为系统守护进程预留计算资源

Kubernetes 节点可以被调度至 容量。默认情况下,Pod 可以消耗节点上的所有可用容量。这是一个问题,因为节点通常会运行相当多的系统守护进程,这些进程为操作系统和 Kubernetes 本身提供支持。除非为这些系统守护进程预留资源,否则 Pod 和系统守护进程会争夺资源,并导致节点上的资源耗尽问题。

kubelet 公开了一个名为“节点可分配资源”的功能,该功能有助于为系统守护进程保留计算资源。 Kubernetes 建议集群管理员根据每个节点上的工作负载密度配置“节点可分配资源”。

开始之前

你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具与你的集群通信。建议在至少两个不充当控制平面主机的节点上运行此教程。如果你还没有集群,可以使用 minikube 创建一个集群,或者可以使用这些 Kubernetes 游乐场之一

你可以使用 kubelet 配置文件 配置以下 kubelet 配置设置

节点可分配资源

node capacity

Kubernetes 节点上的“可分配资源”定义为可用于 Pod 的计算资源量。调度器不会过度订阅“可分配资源”。目前支持“CPU”、“内存”和“临时存储”。

节点可分配资源作为 API 中 v1.Node 对象的一部分以及 CLI 中 kubectl describe node 的一部分公开。

可以在 kubelet 中为两类系统守护进程保留资源。

启用 QoS 和 Pod 级 cgroup

为了在节点上正确强制执行节点可分配资源约束,你必须通过 cgroupsPerQOS 设置启用新的 cgroup 层次结构。默认情况下启用此设置。启用后,kubelet 会将所有最终用户 Pod 置于由 kubelet 管理的 cgroup 层次结构下。

配置 cgroup 驱动程序

kubelet 支持使用 cgroup 驱动程序操作主机上的 cgroup 层次结构。该驱动程序通过 cgroupDriver 设置配置。

支持的值如下

  • cgroupfs 是默认驱动程序,它直接操作主机上的 cgroup 文件系统以管理 cgroup 沙箱。
  • systemd 是一种替代驱动程序,它使用由该初始化系统支持的资源的瞬态切片来管理 cgroup 沙箱。

根据关联的容器运行时的配置,操作员可能必须选择特定的 cgroup 驱动程序以确保正确的系统行为。例如,如果操作员使用 containerd 运行时提供的 systemd cgroup 驱动程序,则必须将 kubelet 配置为使用 systemd cgroup 驱动程序。

Kube 保留资源

  • KubeletConfiguration 设置kubeReserved: {}。示例值 {cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000}
  • KubeletConfiguration 设置kubeReservedCgroup: ""

kubeReserved 旨在捕获 kubernetes 系统守护进程(如 kubelet容器运行时 等)的资源保留。它不旨在为作为 Pod 运行的系统守护进程保留资源。 kubeReserved 通常是节点上 Pod 密度 的函数。

除了 cpumemoryephemeral-storage 之外,还可以指定 pid 为 kubernetes 系统守护进程保留指定数量的进程 ID。

要选择性地在 kubernetes 系统守护进程上强制执行 kubeReserved,请将 Kube 守护进程的父控制组指定为 kubeReservedCgroup 设置的值,并kube-reserved 添加到 enforceNodeAllocatable

建议将 kubernetes 系统守护进程放置在顶层控制组下(例如,在 systemd 机器上为 runtime.slice)。每个系统守护进程最好在其自己的子控制组中运行。有关推荐的控制组层次结构的更多详细信息,请参阅 设计提案

请注意,如果 kubeReservedCgroup 不存在,Kubelet 不会 创建它。如果指定了无效的 cgroup,kubelet 将无法启动。对于 systemd cgroup 驱动程序,你应该遵循定义的 cgroup 名称的特定模式:名称应为你为 kubeReservedCgroup 设置的值,并附加 .slice

系统保留资源

  • KubeletConfiguration 设置systemReserved: {}。示例值 {cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000}
  • KubeletConfiguration 设置systemReservedCgroup: ""

systemReserved 旨在捕获 OS 系统守护进程(如 sshdudev 等)的资源保留。systemReserved 还应为 kernel 保留 memory,因为目前 Kubernetes 中 kernel 内存不计入 Pod。还建议为用户登录会话保留资源(systemd 世界中的 user.slice)。

除了 cpumemoryephemeral-storage 之外,还可以指定 pid 为 OS 系统守护进程保留指定数量的进程 ID。

要选择性地在系统守护进程上强制执行 systemReserved,请将 OS 系统守护进程的父控制组指定为 systemReservedCgroup 设置的值,并system-reserved 添加到 enforceNodeAllocatable

建议将 OS 系统守护进程放置在顶层控制组下(例如,在 systemd 机器上为 system.slice)。

请注意,如果 systemReservedCgroup 不存在,kubelet 不会 创建它。如果指定了无效的 cgroup,kubelet 将会失败。对于 systemd cgroup 驱动程序,你应该遵循定义的 cgroup 名称的特定模式:名称应为你为 systemReservedCgroup 设置的值,并附加 .slice

显式保留的 CPU 列表

特性状态: Kubernetes v1.17 [稳定]

KubeletConfiguration 设置reservedSystemCPUs:。示例值 0-3

reservedSystemCPUs 旨在为 OS 系统守护进程和 kubernetes 系统守护进程定义显式的 CPU 集。reservedSystemCPUs 适用于不打算在 cpuset 资源方面为 OS 系统守护进程和 kubernetes 系统守护进程定义单独的顶层 cgroup 的系统。如果 Kubelet 没有 kubeReservedCgroupsystemReservedCgroup,则由 reservedSystemCPUs 提供的显式 cpuset 将优先于由 kubeReservedCgroupsystemReservedCgroup 选项定义的 CPU。

此选项专门为 Telco/NFV 用例设计,其中不受控制的中断/计时器可能会影响工作负载性能。你可以使用此选项为系统/kubernetes 守护进程以及中断/计时器定义显式的 cpuset,以便系统上的其余 CPU 可以专门用于工作负载,从而减少不受控制的中断/计时器的影响。要将系统守护进程、kubernetes 守护进程和中断/计时器移动到此选项定义的显式 cpuset,应使用 Kubernetes 之外的其他机制。例如:在 Centos 中,你可以使用 tuned 工具集执行此操作。

驱逐阈值

KubeletConfiguration 设置evictionHard: {memory.available: "100Mi", nodefs.available: "10%", nodefs.inodesFree: "5%", imagefs.available: "15%"}。示例值: {memory.available: "<500Mi"}

节点级别的内存压力会导致系统OOM(内存溢出),这会影响整个节点及其上运行的所有Pod。节点可能会暂时离线,直到内存被回收。为了避免(或降低)系统OOM的发生概率,kubelet提供了资源耗尽管理。驱逐操作仅支持 memoryephemeral-storage。通过 evictionHard 设置预留一些内存,当节点上的可用内存低于预留值时,kubelet 会尝试驱逐Pod。理论上,如果节点上不存在系统守护进程,则Pod使用的内存不会超过 capacity - eviction-hard。因此,为驱逐预留的资源不可供Pod使用。

强制执行节点可分配资源

KubeletConfiguration 设置: enforceNodeAllocatable: [pods]。示例值:[pods,system-reserved,kube-reserved]

调度器将“Allocatable”(可分配资源)视为Pod可用的capacity(容量)。

默认情况下,kubelet 会在 Pod 之间强制执行“Allocatable”。当所有Pod的总使用量超过“Allocatable”时,将通过驱逐 Pod 来执行强制执行。有关驱逐策略的更多详细信息,请参阅节点压力驱逐页面。此强制执行由在 KubeletConfiguration 设置 enforceNodeAllocatable 中指定 pods 值来控制。

或者,可以通过在同一设置中指定 kube-reservedsystem-reserved 值,使 kubelet 强制执行 kubeReservedsystemReserved。请注意,要强制执行 kubeReservedsystemReserved,需要分别指定 kubeReservedCgroupsystemReservedCgroup

通用指南

系统守护进程预计应与Guaranteed(保证)QoS 等级的 Pod类似对待。系统守护进程可以在其边界控制组内突发,此行为需要作为 Kubernetes 部署的一部分进行管理。例如,kubelet 应该有自己的控制组,并与容器运行时共享 kubeReserved 资源。但是,如果强制执行了 kubeReserved,则 Kubelet 不能突发并耗尽所有可用的节点资源。

在强制执行 systemReserved 预留时要格外小心,因为它可能导致关键的系统服务 CPU 不足、被 OOM 杀死或无法在节点上 fork。建议仅当用户对其节点进行了详尽的分析,以得出精确的估计,并且有信心在组中的任何进程被 OOM 杀死时恢复时,才强制执行 systemReserved

  • 首先,在 pods 上强制执行“Allocatable”。
  • 一旦建立了足够的监控和警报机制来跟踪 kube 系统守护进程,请尝试根据使用情况的启发式方法强制执行 kubeReserved
  • 如果绝对必要,请随着时间的推移强制执行 systemReserved

随着越来越多的功能被添加,kube 系统守护进程的资源需求可能会随着时间的推移而增长。随着时间的推移,Kubernetes 项目将尝试降低节点系统守护进程的利用率,但这目前不是优先事项。因此,预计未来版本中的 Allocatable 容量将下降。

示例场景

这是一个说明节点可分配资源计算的示例

  • 节点有 32Gimemory16 个 CPU100GiStorage
  • kubeReserved 设置为 {cpu: 1000m, memory: 2Gi, ephemeral-storage: 1Gi}
  • systemReserved 设置为 {cpu: 500m, memory: 1Gi, ephemeral-storage: 1Gi}
  • evictionHard 设置为 {memory.available: "<500Mi", nodefs.available: "<10%"}

在这种情况下,“Allocatable”将为 14.5 个 CPU、28.5Gi 的内存和 88Gi 的本地存储。调度器确保此节点上所有 Pod 的总内存 requests 不超过 28.5Gi,并且存储不超过 88Gi。当 Pod 的总内存使用量超过 28.5Gi,或者总磁盘使用量超过 88Gi 时,Kubelet 会驱逐 Pod。如果节点上的所有进程都尽可能多地消耗 CPU,则 Pod 一起不能消耗超过 14.5 个 CPU。

如果未强制执行 kubeReserved 和/或 systemReserved,并且系统守护进程超出其预留,则当节点总内存使用量高于 31.5Gi 或 storage 大于 90Gi 时,kubelet 会驱逐 Pod。

上次修改时间:2024年6月4日,太平洋标准时间凌晨3:39:改进“为系统守护进程预留计算资源”文档 (#45771) (bc35539293)